diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..09a492f
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+_notes/
+.vscode/
\ No newline at end of file
diff --git a/changelog.md b/changelog.md
index 7e6cdf2..a2d4a51 100644
--- a/changelog.md
+++ b/changelog.md
@@ -1,4 +1,34 @@
# CHANGE LOG
+**7 September 2016
+
+* Fix: Issue handling illegal characters in group names
+* Fix: Better handling of authorization when attempting to edit a workorder.
+* Fix: Corrent some spelling errors.
+* Improvement: Current approver can add collaborator to a workorder. * db changes see _update.
+* Improvement: Sends update email to workorder creator when something changes.
+* Improvement: Move workorder approve/edit into page_content and dbquery routing structure.
+* Improvement: Refactor php/html in several places for greater clarity.
+* Improvement: Add simple pubsub javascript library for easy frontend ui eventing.
+* Improvement: Move appconfig.php to /config/appconfig.php * just makes sense.
+* Improvement: Bump minor version
+
+**6 August 2016**
+
+* Fix: Pay engineering debt. forms_db_controller.php better follows data adapter pattern used in other classes.
+* Fix: classes/login.php now including user fname and lname in query.
+* Fix: XDebug with PHP on Windows showing multiple undefined variables. Fixed by initializing vars to null in multiple pages.
+* Fix: Form preview on workorder forms list page now working. Added header_forms_admin.php to include JS code.
+* Fix: Remove old db conn info in appconfig.php Not needed any longer.
+* Fix: UserDataAdapter AdminUpdate function protected against SQL injection.
+* Fix: Update .gitignore to ignore Visual Studio Code IDE config files in .vscode folder.
+* Improvement: Supports using environment variables for db connection. See config/db.php for details.
+
+**4 August 2016**
+
+* Fix: #7 district level approver list can now be left blank if needed. Final will be handled by last group level approver.
+* Fix: #10 Special characters in goup name can now include / char.
+* Fix: #11 If forms fields have identical label text they will now render correctly in email and when viewing/editing.
+
**16 July 2016**
* Fix: Fixed the query section of the update user page. Now you can update user information
diff --git a/readme.md b/readme.md
index c197aca..970bca6 100644
--- a/readme.md
+++ b/readme.md
@@ -1,4 +1,4 @@
-# Workorders v2.0.0
+# Workorders v2.1.0
A simple way for large groups to organize work using custom forms!
@@ -14,4 +14,5 @@ A simple way for large groups to organize work using custom forms!
* User permission levels.
* User registration can be limited based on domain.
* Users can view work orders that need their approval.
-* Users can view work orders they have submitted.
\ No newline at end of file
+* Users can view work orders they have submitted.
+* Collaboration feature allows including others in the workflow process as needed.
\ No newline at end of file
diff --git a/src/_page_processor.php b/src/_page_processor.php
index 1657742..37df502 100644
--- a/src/_page_processor.php
+++ b/src/_page_processor.php
@@ -2,7 +2,7 @@
require_once("config/db.php");
require_once("classes/Login.php");
-require_once('./resources/appconfig.php');
+require_once('config/appconfig.php');
require_once "./resources/library/appinfo.php";
$appInfoDbAdapter = new AppInfo($dsn, $user_name, $pass_word);
@@ -87,8 +87,8 @@
*/
-
- if($include_address == ""){
+ $folder = null; // set default value or error in navbar. XDebug
+ if(isset($include_address) == false || $include_address == ""){
$include_address = "page_content/index.php";
}
if(isset($_GET['I'])){
@@ -158,12 +158,12 @@
- ALERT Your are on the local server
+ ALERT You are on the local server
db_connection->query($sql);
@@ -88,7 +88,6 @@ private function dologinWithPostData()
$_SESSION['user_lname'] = $result_row->user_lname;
$_SESSION['user_email'] = $result_row->user_email;
$_SESSION['user_group'] = $result_row->user_group;
- $_SESSION['form_manager'] = $result_row->form_manager;
$_SESSION['user_perms'] = $result_row->user_perms;
$_SESSION['user_login_status'] = 1;
diff --git a/src/classes/_notes/dwsync.xml b/src/classes/_notes/dwsync.xml
deleted file mode 100644
index c41608b..0000000
--- a/src/classes/_notes/dwsync.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-
-
-
-
\ No newline at end of file
diff --git a/src/resources/appconfig.php b/src/config/appconfig.php
similarity index 83%
rename from src/resources/appconfig.php
rename to src/config/appconfig.php
index 8fbc1a9..b174afc 100644
--- a/src/resources/appconfig.php
+++ b/src/config/appconfig.php
@@ -10,11 +10,7 @@ abstract class Config {
const BaseUrl = "http://www.example.com/";
const SiteTitleShort = "FLOW";
const SiteTitleLong = "Work Flow";
- const DbDsn = "mysql:host=localhost;dbname=formsdb";
- const DbUsername = "";
- const DbPassword = "";
const WorkorderApproverScript = "workorderview.php";
const WorkorderViewOnlyScript = "workorderview.php";
}
-
?>
\ No newline at end of file
diff --git a/src/config/db.php b/src/config/db.php
index 5b7c6de..3114aef 100644
--- a/src/config/db.php
+++ b/src/config/db.php
@@ -3,6 +3,15 @@
/**
* Configuration for: Database Connection
*
+ * NOTE: There are two ways to configure the DB connection.
+ * 1) Environment variables
+ * WO_ENV_ENABLED=1
+ * WO_DB_NAME=yourDBname
+ * WO_DB_USERNAME=yourDBusername
+ * WO_DB_PASSWORD=yourDBpassword
+ * 2) Modify values in this config file below
+ * Change DB_NAME, DB_USERNAME_HERE, and DB_PASSWORD_HERE
+ *
* For more information about constants please @see http://php.net/manual/en/function.define.php
* If you want to know why we use "define" instead of "const" @see http://stackoverflow.com/q/2447791/1114320
*
@@ -11,13 +20,24 @@
* DB_USER: user for your database. the user needs to have rights for SELECT, UPDATE, DELETE and INSERT.
* DB_PASS: the password of the above user
*/
- $database_name = "DB_NAME";
- $dsn = 'mysql:host=localhost;dbname='.$database_name;
- $user_name = 'DB_USERNAME_HERE'; //DEFUAULT DB_USERNAME_HERE
- $pass_word = 'DB_PASSWORD_HERE';
+ if(getenv("WO_ENV_ENABLED") == 1)
+ {
+ // Set these in your local environment
+ $database_name = getenv("WO_DB_NAME"); // DO NOT MODIFY HERE
+ $dsn = 'mysql:host=localhost;dbname='.$database_name;
+ $user_name = getenv('WO_DB_USERNAME'); // DO NOT MODIFY HERE
+ $pass_word = getenv('WO_DB_PASSWORD'); // DO NOT MODIFY HERE
+ } else {
+ // Modify the values below IF you are NOT using environment variables for config.
+ $database_name = "DB_NAME"; // SET DB NAME HERE
+ $dsn = 'mysql:host=localhost;dbname='.$database_name;
+ $user_name = 'DB_USERNAME_HERE'; // SET DB USERNAME HERE
+ $pass_word = 'DB_PASSWORD_HERE'; // SET DB PASSWORD HERE
- if($user_name == 'DB_USERNAME_HERE'){
- echo "
Woah!!! Hold on there Sparky, you need to update the util/forms_db_info.php befor running this program!
Woah!!! Hold on there Sparky, you need to update the config/db.php before running this program!
";
+ die();
+ }
}
define("DB_HOST", "127.0.0.1");
diff --git a/src/dbquery/_notes/dwsync.xml b/src/dbquery/_notes/dwsync.xml
deleted file mode 100644
index d0995bc..0000000
--- a/src/dbquery/_notes/dwsync.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-
-
-
-
\ No newline at end of file
diff --git a/src/dbquery/qryADMIN/formbuild_qry.php b/src/dbquery/qryADMIN/formbuild_qry.php
index e37ec98..e83fa04 100644
--- a/src/dbquery/qryADMIN/formbuild_qry.php
+++ b/src/dbquery/qryADMIN/formbuild_qry.php
@@ -10,13 +10,13 @@
$formAvailable = 0;
if (isset($_POST["formAvailable"])) { $formAvailable = 1; }
if (isset($_POST["updateform"])){
- $fdc = new FormsDataController();
+ $fdc = new FormsDataController($dsn, $user_name, $pass_word);
$QUERY_PROCESS = $fdc->updateForm($_POST["id"], $_POST["formname"], $_POST["formdesc"], $_POST["xmldata"], $_POST["workflow"], $_POST["notifyOnFinalApproval"], $formAvailable, $_POST["groupWorkflows"]);
} elseif (isset($_POST["deleteform"])) {
- $fdc = new FormsDataController();
+ $fdc = new FormsDataController($dsn, $user_name, $pass_word);
$QUERY_PROCESS = $fdc->deleteForm($_POST["id"]);
} elseif (isset($_POST["addform"])) {
- $fdc = new FormsDataController();
+ $fdc = new FormsDataController($dsn, $user_name, $pass_word);
$QUERY_PROCESS = $fdc->addForm($_POST["formname"], $_POST["formdesc"], $_POST["xmldata"], $_POST["workflow"], $_POST["notifyOnFinalApproval"], $formAvailable, $_POST["groupWorkflows"]);
if (!$QUERY_PROCESS){
echo "
All fields are required. Keep calm and try again...
";
diff --git a/src/dbquery/qryGROUP/_notes/dwsync.xml b/src/dbquery/qryGROUP/_notes/dwsync.xml
deleted file mode 100644
index 73bb1e4..0000000
--- a/src/dbquery/qryGROUP/_notes/dwsync.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-
-
-
-
\ No newline at end of file
diff --git a/src/dbquery/qryUSER/_notes/dwsync.xml b/src/dbquery/qryUSER/_notes/dwsync.xml
deleted file mode 100644
index db1e8f0..0000000
--- a/src/dbquery/qryUSER/_notes/dwsync.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-
-
-
-
\ No newline at end of file
diff --git a/src/dbquery/qryUSER/edit_user_qry.php b/src/dbquery/qryUSER/edit_user_qry.php
index 6a16cbd..2254b09 100644
--- a/src/dbquery/qryUSER/edit_user_qry.php
+++ b/src/dbquery/qryUSER/edit_user_qry.php
@@ -2,7 +2,7 @@
require_once "./resources/library/user.php";
-$usrDbAdapter = new UserDataAdapter($dsn, $user_name, $pass_word, $currentUserEmail);
+$usrDbAdapter = new UserDataAdapter($dsn, $user_name, $pass_word);
$element = "User";
diff --git a/src/dbquery/qryWORKORDER/add_collab_qry.php b/src/dbquery/qryWORKORDER/add_collab_qry.php
new file mode 100644
index 0000000..a2f0cfb
--- /dev/null
+++ b/src/dbquery/qryWORKORDER/add_collab_qry.php
@@ -0,0 +1,37 @@
+AddCollaborator($id, $comment, $collabUser);
+
+$wo = $workorderDataAdapter->Select($id);
+$woViewModel = new WorkorderViewModel($wo, $key, $currentUserEmail);
+// send emails.
+$fromEmailAddress = 'noreply@dumasisd.org';
+$emailAdapter = new WorkorderEmailAdapter($fromEmailAddress);
+$emailAdapter->SendAddCollab($wo, $woViewModel);
+?>
\ No newline at end of file
diff --git a/src/dbquery/qryWORKORDER/add_comment_qry.php b/src/dbquery/qryWORKORDER/add_comment_qry.php
new file mode 100644
index 0000000..42c7773
--- /dev/null
+++ b/src/dbquery/qryWORKORDER/add_comment_qry.php
@@ -0,0 +1,24 @@
+AddComment($id, $comment);
+?>
\ No newline at end of file
diff --git a/src/dbquery/qryWORKORDER/end_collab_qry.php b/src/dbquery/qryWORKORDER/end_collab_qry.php
new file mode 100644
index 0000000..d9f8d56
--- /dev/null
+++ b/src/dbquery/qryWORKORDER/end_collab_qry.php
@@ -0,0 +1,36 @@
+Select($id);
+$woViewModel = new WorkorderViewModel($wo, $key, $currentUserEmail);
+
+$QUERY_PROCESS = $workorderDataAdapter->EndCollaboration($id, $comment);
+
+// send emails.
+$fromEmailAddress = 'noreply@dumasisd.org';
+$emailAdapter = new WorkorderEmailAdapter($fromEmailAddress);
+$emailAdapter->SendEndCollab($wo, $woViewModel);
+?>
\ No newline at end of file
diff --git a/src/dbquery/qryWORKORDER/update_approve_qry.php b/src/dbquery/qryWORKORDER/update_approve_qry.php
new file mode 100644
index 0000000..bbb399d
--- /dev/null
+++ b/src/dbquery/qryWORKORDER/update_approve_qry.php
@@ -0,0 +1,110 @@
+Select($id);
+ /**
+ * Updates occur without a user logged in as long as the update key is valid.
+ * We need to use the current approvers email address.
+ * NOTE: WorkorderDataAdapter will throw when updating if currentUserEmail is not set.
+ */
+ $userEmailAddress = $wo->currentApprover;
+ $woDbAdapter->currentUserEmail = $userEmailAddress;
+ // WorkorderViewModel is used to validate the key.
+ $woViewModel = new WorkorderViewModel($wo, $key);
+ if ($woViewModel->valid != true || $woDbAdapter->currentUserEmail == null)
+ {
+ die("Invalid request. Required data not provided or you are authorized to make changes.");
+ }
+ // Update the comments
+ $comments = json_decode($wo->comments, true);
+ if ($comments == null) {
+ $comments = array();
+ }
+ $woComment = new WorkorderComment();
+ $woComment->commentData = $comment;
+ $woComment->createdAt = date('Y-m-d H:i:s');
+ $woComment->createdBy = $userEmailAddress;
+ array_push($comments, $woComment);
+ $wo->comments = json_encode($comments);
+ // Must decode the workflow in order to manipulate approvers. Must encode back before saving to DB
+ $workflow = json_decode($wo->workflow, true);
+ $approvers = ApproverHelper::toApproverArray($workflow);
+ // some default flags
+ $fromEmailAddress = 'noreply@dumasisd.org';
+ $isFinalApprover = false;
+ $sendFinalApproveNotifications = false;
+ $newApproverKey = generateApproverKey(); // Change the approver key as needed.
+ // Check if approver is final
+ if ($wo->currentApprover == ApproverHelper::getFinal($approvers)->email) {
+ $isFinalApprover = true;
+ }
+ // Update approve status, keys, and current approver.
+ if ($approve == "true") {
+ if ($isFinalApprover == true){
+ $wo->approveState = ApproveState::ApproveClosed; // Final. Work is now completed
+ $sendFinalApproveNotifications = true;
+ $wo->approverKey = ""; // No more access as approver.
+ $newApproverKey = ""; // viewmodel will need this in order to work.
+ } else {
+ $wo->approveState = ApproveState::PendingApproval; // waiting on more approvers
+ $wo->approverKey = $newApproverKey;
+ $nextApprover = ApproverHelper::getNext($approvers);
+ ApproverHelper::setCurrent($approvers, $nextApprover);
+ $wo->currentApprover = ApproverHelper::getCurrent($approvers)->email;
+ }
+ } else {
+ // rejected by the current approver.
+ if ($isFinalApprover == true){
+ $wo->approveState = ApproveState::RejectClosed; // Final approver. Closed as rejected
+ $sendFinalApproveNotifications = false; // do not notify final approval contacts
+ $wo->approverKey = ""; // No more access as approver.
+ $newApproverKey = ""; // viewmodel will need this in order to work.
+ } else {
+ $wo->approveState = ApproveState::RejectClosed; // Closed as rejected
+ $sendFinalApproveNotifications = false; // do not notify final approval contacts
+ $wo->approverKey = ""; // No more access as approver.
+ $newApproverKey = ""; // viewmodel will need this in order to work.
+ }
+ }
+ // Must encode workflow back before saving to DB
+ $updatedWorkflow = new Workflow($workflow['name'], $approvers);
+ $wo->workflow = json_encode($updatedWorkflow);
+ $woDbAdapter->Update($id, $wo);
+ $woViewModel = new WorkorderViewModel($wo, $newApproverKey); // update the viewmodel since the comments have been updated.
+
+ // send notifications
+ $emailAdapter = new WorkorderEmailAdapter($fromEmailAddress);
+ if ($approve == "true") {
+ if ($isFinalApprover != true) {
+ $emailAdapter->SendNeedsApprovalToCurrentApprover($wo, $woViewModel);
+ $emailAdapter->SendUpdatedDetailsToCreator($wo, $woViewModel);
+ }
+ if ($sendFinalApproveNotifications == true) {
+ $emailAdapter->SendViewOnlyFinalApprovalNotifications($wo, $woViewModel);
+ }
+ } else {
+ $emailAdapter->SendViewOnlyRejectedToCreator($wo, $woViewModel);
+ }
+
+?>
diff --git a/src/includes/navbar.php b/src/includes/navbar.php
index ae4b7f8..7572159 100644
--- a/src/includes/navbar.php
+++ b/src/includes/navbar.php
@@ -1,4 +1,4 @@
-
+