Skip to content

Commit ab44d63

Browse files
committed
updated client section for conflict resolution; refactoring
1 parent 43c3174 commit ab44d63

5 files changed

Lines changed: 260 additions & 179 deletions

File tree

admin/forms/edit_submission.php

Lines changed: 2 additions & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -52,88 +52,10 @@
5252
// determine whether the page contains any editable fields
5353
$editable_field_ids = ViewFields::getEditableViewFields($view_id);
5454

55-
// update the submission
5655
$failed_validation = false;
5756
$changed_fields = array();
58-
59-
6057
if (isset($_POST) && !empty($_POST)) {
61-
62-
if (isset($_POST["core__reconcile_changed_fields"])) {
63-
$state = Sessions::get("last_edit_submission_state");
64-
65-
// filter out anything with "db value" - we don't care about them any more: the user has indicated they want the
66-
// value from the DB, so even if it's changed again, just use it
67-
$new_values = array();
68-
$keys = array_keys($state["data"]);
69-
$fields_to_update = array();
70-
$user_values = Sessions::get("conflicted_user_values");
71-
72-
$view_fields = Submissions::getSubmissionByField($form_id, $submission_id, $view_id);
73-
foreach ($keys as $field_name) {
74-
if ($request[$field_name] == "user_value") {
75-
$fields_to_update[] = $field_name;
76-
$request[$field_name] = $user_values[$field_name]["user_value"];
77-
} else {
78-
$request[$field_name] = $view_fields[$field_name];
79-
}
80-
}
81-
82-
if (empty($fields_to_update)) {
83-
$success = true;
84-
$message = "The differences have been resolved.";
85-
} else {
86-
$changed_fields = Submissions::getChangedFieldsSinceLastRender($form_id, $view_id, $submission_id, $request["tab"], $request);
87-
88-
// now if the old DB values are the same as what they already reviewed, that's fine, we can just update the record.
89-
// But if it changed again, display the conflict resolution page with the latest info.
90-
$db_values_same = true;
91-
foreach ($changed_fields as $field_name => $changes) {
92-
if ($user_values[$field_name]["db_value"] !== $changes["db_value"]) {
93-
$db_values_same = false;
94-
} else {
95-
$request[$field_name] = $changes["user_value"];
96-
}
97-
}
98-
99-
if ($db_values_same) {
100-
$changed_fields = array();
101-
Sessions::set("new_search", "yes");
102-
$request["view_id"] = $view_id;
103-
$request["editable_field_ids"] = $editable_field_ids;
104-
list($success, $message) = Submissions::updateSubmission($form_id, $submission_id, $request, false);
105-
}
106-
}
107-
108-
} else {
109-
// see if any of the fields have been already updated
110-
$changed_fields = Submissions::getChangedFieldsSinceLastRender($form_id, $view_id, $submission_id, $_POST["tab"], $_POST);
111-
Sessions::set("new_search", "yes");
112-
$request["view_id"] = $view_id;
113-
$request["editable_field_ids"] = $editable_field_ids;
114-
115-
// if the DB had more up-to-date values, reset all the conflicting fields to save the last value in the DB before updating
116-
// the database. We'll then present the conflicts to the user to choose whether to pick their new values or the existing
117-
// ones
118-
if (!empty($changed_fields)) {
119-
foreach ($changed_fields as $field_name => $value) {
120-
$request[$field_name] = $changed_fields[$field_name]["db_value"];
121-
}
122-
}
123-
list($success, $message) = Submissions::updateSubmission($form_id, $submission_id, $request);
124-
125-
if (!empty($changed_fields)) {
126-
$success = false;
127-
$message = "The data for these fields changed while you were editing the submission. Please select the value you would like to use.";
128-
}
129-
130-
// if there was any problem updating this submission, make a special note of it: we'll use that info to merge the
131-
// current POST request info with the original field values to ensure the page contains the latest data (i.e. for
132-
// cases where they fail server-side validation)
133-
if (!$success) {
134-
$failed_validation = true;
135-
}
136-
}
58+
list($success, $message, $changed_fields, $failed_validation) = Submissions::updateSubmissionWithConflictDetection($form_id, $submission_id, $view_id, $editable_field_ids, $request);
13759
}
13860

13961
$form_info = Forms::getForm($form_id);
@@ -157,37 +79,7 @@
15779
Sessions::clear("conflicted_user_values");
15880
Submissions::trackCurrentEditSubmissionFields($grouped_fields, $submission_id, $view_id, $tab_number);
15981
} else {
160-
$user_values = array();
161-
foreach ($changed_fields as $changed_field_name => $changed_info) {
162-
foreach ($grouped_fields as $group) {
163-
foreach ($group["fields"] as $field) {
164-
if ($field["field_name"] !== $changed_field_name) {
165-
continue;
166-
}
167-
168-
$db_value = $field;
169-
$db_value["is_editable"] = "no";
170-
$db_value["submission_value"] = $changed_info["db_value"];
171-
172-
$user_value = $field;
173-
$user_value["is_editable"] = "no";
174-
$user_value["submission_value"] = $changed_info["user_value"];
175-
176-
$reconcile_changed_fields[] = array(
177-
"field_name" => $changed_field_name,
178-
"field_id" => $field["field_id"],
179-
"field_title" => $field["field_title"],
180-
"db_value" => $db_value,
181-
"user_value" => $user_value
182-
);
183-
$user_values[$changed_field_name] = array(
184-
"db_value" => $changed_info["db_value"],
185-
"user_value" => $changed_info["user_value"]
186-
);
187-
}
188-
}
189-
}
190-
Sessions::set("conflicted_user_values", $user_values);
82+
$reconcile_changed_fields = Submissions::getChangedFieldsToReconcile($grouped_fields, $changed_fields);
19183
}
19284

19385
$page_field_ids = array();

clients/forms/edit_submission.php

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -71,23 +71,10 @@
7171
// for the update function and to determine whether the page contains any editable fields
7272
$editable_field_ids = ViewFields::getEditableViewFields($view_id);
7373

74-
// handle POST requests
7574
$failed_validation = false;
75+
$changed_fields = array();
7676
if (isset($_POST) && !empty($_POST)) {
77-
// add the view ID to the request hash, for use by the Submissions::updateSubmission method
78-
$request["view_id"] = $view_id;
79-
$request["editable_field_ids"] = $editable_field_ids;
80-
list($success, $message) = Submissions::updateSubmission($form_id, $submission_id, $request);
81-
82-
// if there was any problem udpating this submission, make a special note of it: we'll use that info to merge the current POST request
83-
// info with the original field values to ensure the page contains the latest data (i.e. for cases where they fail server-side validation)
84-
if (!$success) {
85-
$failed_validation = true;
86-
}
87-
88-
// required. The reason being, this setting determines whether the submission IDs in the current form-view-search
89-
// are cached. Any time the data changes, the submission may then belong to different Views, so we need to re-cache it
90-
Sessions::set("new_search", "yes");
77+
list($success, $message, $changed_fields, $failed_validation) = Submissions::updateSubmissionWithConflictDetection($form_id, $submission_id, $view_id, $editable_field_ids, $request);
9178
}
9279

9380
// this is crumby
@@ -109,6 +96,14 @@
10996
$grouped_fields = FieldValidation::mergeFormSubmission($grouped_fields, $_POST);
11097
}
11198

99+
$reconcile_changed_fields = array();
100+
if (empty($changed_fields)) {
101+
Sessions::clear("conflicted_user_values");
102+
Submissions::trackCurrentEditSubmissionFields($grouped_fields, $submission_id, $view_id, $tab_number);
103+
} else {
104+
$reconcile_changed_fields = Submissions::getChangedFieldsToReconcile($grouped_fields, $changed_fields);
105+
}
106+
112107
$page_field_ids = array();
113108
$page_field_type_ids = array();
114109
foreach ($grouped_fields as $group) {
@@ -186,6 +181,7 @@
186181
"settings" => $settings,
187182
"page_field_ids" => $page_field_ids,
188183
"grouped_fields" => $grouped_fields,
184+
"changed_fields" => $reconcile_changed_fields,
189185
"field_types" => $page_field_types,
190186
"head_title" => $edit_submission_page_label,
191187
"submission_id" => $submission_id,

global/code/Submissions.class.php

Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1581,6 +1581,8 @@ public static function getChangedFieldsSinceLastRender($form_id, $view_id, $subm
15811581
break;
15821582
}
15831583
}
1584+
1585+
// currently file conficts are ignored: the latest file is always overridden
15841586
list ($user_value, $file_field) = self::getSaveFieldValueFromUpdateRequest($post, $form_field, $field_settings, $field_types_processing_info);
15851587

15861588
$changed[$field_name] = array(
@@ -1594,6 +1596,155 @@ public static function getChangedFieldsSinceLastRender($form_id, $view_id, $subm
15941596
}
15951597

15961598

1599+
/**
1600+
* Used for clients and administrators when updating a submission. This checks the specific submission data hadn't
1601+
* changed while they were editing (i.e. the actual changed fields, not the general submission itself). If it does
1602+
* it handles returning the list of changed fields for users to reconcile the conflicts manually.
1603+
* @param $form_id
1604+
* @param $submission_id
1605+
* @param $view_id
1606+
* @param $editable_field_ids
1607+
* @param $request
1608+
* @return array
1609+
*/
1610+
public static function updateSubmissionWithConflictDetection($form_id, $submission_id, $view_id, $editable_field_ids, $request)
1611+
{
1612+
$L = Core::$L;
1613+
1614+
$success = true;
1615+
$message = "";
1616+
$changed_fields = array();
1617+
$failed_validation = false;
1618+
1619+
if (isset($_POST["core__reconcile_changed_fields"])) {
1620+
$state = Sessions::get("last_edit_submission_state");
1621+
1622+
// filter out anything with "db value" - we don't care about them any more: the user has indicated they want the
1623+
// value from the DB, so even if it's changed again, just use it
1624+
$keys = array_keys($state["data"]);
1625+
$fields_to_update = array();
1626+
$user_values = Sessions::get("conflicted_user_values");
1627+
1628+
$view_fields = Submissions::getSubmissionByField($form_id, $submission_id, $view_id);
1629+
foreach ($keys as $field_name) {
1630+
if ($request[$field_name] == "user_value") {
1631+
$fields_to_update[] = $field_name;
1632+
$request[$field_name] = $user_values[$field_name]["user_value"];
1633+
} else {
1634+
$request[$field_name] = $view_fields[$field_name];
1635+
}
1636+
}
1637+
1638+
if (empty($fields_to_update)) {
1639+
$success = true;
1640+
$message = $L["notify_differences_resolved"];
1641+
} else {
1642+
$changed_fields = Submissions::getChangedFieldsSinceLastRender($form_id, $view_id, $submission_id, $request["tab"], $request);
1643+
1644+
// now if the old DB values are the same as what they already reviewed, that's fine, we can just update the record.
1645+
// But if it changed again, display the conflict resolution page with the latest info.
1646+
$db_values_same = true;
1647+
foreach ($changed_fields as $field_name => $changes) {
1648+
if ($user_values[$field_name]["db_value"] !== $changes["db_value"]) {
1649+
$db_values_same = false;
1650+
} else {
1651+
$request[$field_name] = $changes["user_value"];
1652+
}
1653+
}
1654+
1655+
if ($db_values_same) {
1656+
$changed_fields = array();
1657+
Sessions::set("new_search", "yes");
1658+
$request["view_id"] = $view_id;
1659+
$request["editable_field_ids"] = $editable_field_ids;
1660+
list($success, $message) = Submissions::updateSubmission($form_id, $submission_id, $request, false);
1661+
}
1662+
}
1663+
1664+
} else {
1665+
// see if any of the fields have been already updated
1666+
$changed_fields = Submissions::getChangedFieldsSinceLastRender($form_id, $view_id, $submission_id, $_POST["tab"], $_POST);
1667+
Sessions::set("new_search", "yes");
1668+
$request["view_id"] = $view_id;
1669+
$request["editable_field_ids"] = $editable_field_ids;
1670+
1671+
// if the DB had more up-to-date values, reset all the conflicting fields to save the last value in the DB before updating
1672+
// the database. We'll then present the conflicts to the user to choose whether to pick their new values or the existing
1673+
// ones
1674+
if (!empty($changed_fields)) {
1675+
foreach ($changed_fields as $field_name => $value) {
1676+
$request[$field_name] = $changed_fields[$field_name]["db_value"];
1677+
}
1678+
}
1679+
list($success, $message) = Submissions::updateSubmission($form_id, $submission_id, $request);
1680+
1681+
if (!empty($changed_fields)) {
1682+
$success = false;
1683+
$message = $L["notify_conflicts_detected"];
1684+
}
1685+
1686+
// if there was any problem updating this submission, make a special note of it: we'll use that info to merge the
1687+
// current POST request info with the original field values to ensure the page contains the latest data (i.e. for
1688+
// cases where they fail server-side validation)
1689+
if (!$success) {
1690+
$failed_validation = true;
1691+
}
1692+
}
1693+
1694+
return array(
1695+
$success,
1696+
$message,
1697+
$changed_fields,
1698+
$failed_validation
1699+
);
1700+
}
1701+
1702+
1703+
/**
1704+
* Used on the edit submission page to figure out what field are changed and return a list of DB + user values
1705+
* to present to the user.
1706+
* @param $grouped_fields
1707+
* @param $changed_fields
1708+
* @return array
1709+
*/
1710+
public static function getChangedFieldsToReconcile($grouped_fields, $changed_fields)
1711+
{
1712+
$reconcile_changed_fields = array();
1713+
$user_values = array();
1714+
foreach ($changed_fields as $changed_field_name => $changed_info) {
1715+
foreach ($grouped_fields as $group) {
1716+
foreach ($group["fields"] as $field) {
1717+
if ($field["field_name"] !== $changed_field_name) {
1718+
continue;
1719+
}
1720+
1721+
$db_value = $field;
1722+
$db_value["is_editable"] = "no";
1723+
$db_value["submission_value"] = $changed_info["db_value"];
1724+
1725+
$user_value = $field;
1726+
$user_value["is_editable"] = "no";
1727+
$user_value["submission_value"] = $changed_info["user_value"];
1728+
1729+
$reconcile_changed_fields[] = array(
1730+
"field_name" => $changed_field_name,
1731+
"field_id" => $field["field_id"],
1732+
"field_title" => $field["field_title"],
1733+
"db_value" => $db_value,
1734+
"user_value" => $user_value
1735+
);
1736+
$user_values[$changed_field_name] = array(
1737+
"db_value" => $changed_info["db_value"],
1738+
"user_value" => $changed_info["user_value"]
1739+
);
1740+
}
1741+
}
1742+
}
1743+
Sessions::set("conflicted_user_values", $user_values);
1744+
1745+
return $reconcile_changed_fields;
1746+
}
1747+
15971748
// -----------------------------------------------------------------------------------------------------------------
15981749

15991750

global/lang/en_us.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1279,3 +1279,5 @@
12791279
$LANG["processing_no_redirect_url"] = "The submission was processed correctly, but you haven't specified a redirect URL for this form! Edit your form in the Form Tools UI and add the redirect URL.";
12801280

12811281

1282+
$LANG["notify_differences_resolved"] = "The differences have been resolved.";
1283+
$LANG["notify_conflicts_detected"] = "The data for these fields changed while you were editing the submission. Please select the value you would like to use.";

0 commit comments

Comments
 (0)