From 2fc6d711572376041ba4e9bea0cb59a6694f5e79 Mon Sep 17 00:00:00 2001 From: Seamus Lee Date: Mon, 11 Sep 2017 15:54:56 +1000 Subject: [PATCH] CRM-20892 Create Oppotunitistic locking mechanism in the CiviMail API and angular content to ensure that if content is editied in a separate tab it alerts the user --- ang/crmMailing/services.js | 5 +++++ api/v3/Mailing.php | 17 +++++++++++++---- api/v3/utils.php | 17 +++++++++++++++++ 3 files changed, 35 insertions(+), 4 deletions(-) diff --git a/ang/crmMailing/services.js b/ang/crmMailing/services.js index 6c60d338b3..a4de098344 100644 --- a/ang/crmMailing/services.js +++ b/ang/crmMailing/services.js @@ -277,6 +277,7 @@ }); delete params.recipients; // the content was merged in return qApi('Mailing', 'create', params).then(function(result) { + mailing.modified_date = result.values[result.id].modified_date; // changes rolled back, so we don't care about updating mailing return result.values[result.id]['api.Mailing.preview'].values; }); @@ -304,6 +305,7 @@ delete params.recipients; // the content was merged in return qApi('Mailing', 'create', params).then(function (recipResult) { // changes rolled back, so we don't care about updating mailing + mailing.modified_date = recipResult.values[recipResult.id].modified_date; return recipResult.values[recipResult.id]['api.MailingRecipients.get'].values; }); }, @@ -323,6 +325,7 @@ delete params.recipients; // the content was merged in return qApi('Mailing', 'create', params).then(function (recipResult) { // changes rolled back, so we don't care about updating mailing + mailing.modified_date = recipResult.values[recipResult.id].modified_date; return recipResult.values[recipResult.id]['api.MailingRecipients.getcount']; }); }, @@ -354,6 +357,7 @@ mailing.id = result.id; } // no rollback, so update mailing.id // Perhaps we should reload mailing based on result? + mailing.modified_date = result.values[result.id].modified_date; return mailing; }); }, @@ -405,6 +409,7 @@ if (result.id && !mailing.id) { mailing.id = result.id; } // no rollback, so update mailing.id + mailing.modified_date = result.values[result.id].modified_date; return result.values[result.id]['api.Mailing.send_test'].values; }); } diff --git a/api/v3/Mailing.php b/api/v3/Mailing.php index a8ee98d5f8..f600b81cd5 100644 --- a/api/v3/Mailing.php +++ b/api/v3/Mailing.php @@ -66,10 +66,19 @@ function civicrm_api3_mailing_create($params) { else { $safeParams = $params; } - $safeParams['_evil_bao_validator_'] = 'CRM_Mailing_BAO_Mailing::checkSendable'; - $result = _civicrm_api3_basic_create(_civicrm_api3_get_BAO(__FUNCTION__), $safeParams); - return _civicrm_api3_mailing_get_formatResult($result); - + $timestampCheck = TRUE; + if (!empty($params['id'])) { + $timestampCheck = _civicrm_api3_compare_timestamps($safeParams['modified_date'], $safeParams['id'], 'Mailing'); + unset($safeParams['modified_date']); + } + if (!$timestampCheck) { + throw new API_Exception("Mailing has not been saved, Content maybe out of date, please refresh the page and try again"); + } + else { + $safeParams['_evil_bao_validator_'] = 'CRM_Mailing_BAO_Mailing::checkSendable'; + $result = _civicrm_api3_basic_create(_civicrm_api3_get_BAO(__FUNCTION__), $safeParams); + return _civicrm_api3_mailing_get_formatResult($result); + } } /** diff --git a/api/v3/utils.php b/api/v3/utils.php index cdbc837f2a..166f018608 100644 --- a/api/v3/utils.php +++ b/api/v3/utils.php @@ -2504,3 +2504,20 @@ function _civicrm_api3_check_edit_permissions($bao_name, $params) { } } } + +/** + * Check if an entity has been modified since the last known modified_date + * @param string $modifiedDate Last knowm modified_date + * @param int $id Id of record to check + * @param string $entity API Entity + * @return bool + */ +function _civicrm_api3_compare_timestamps($modifiedDate, $id, $entity) { + $currentDbInfo = civicrm_api3($entity, 'getsingle', array('id' => $id)); + drupal_set_message(json_encode(strtotime($currentDbInfo['modified_date']))); + drupal_set_message(json_encode(strtotime($modifiedDate))); + if (strtotime($currentDbInfo['modified_date']) <= strtotime($modifiedDate)) { + return TRUE; + } + return FALSE; +} -- 2.25.1