CRM-21753 add pass-through support for criteria in urls on dedupe pages
authoreileen <emcnaughton@wikimedia.org>
Thu, 15 Feb 2018 04:55:46 +0000 (17:55 +1300)
committereileen <emcnaughton@wikimedia.org>
Wed, 4 Apr 2018 09:54:26 +0000 (21:54 +1200)
This permits urls such as
 civicrm/contact/dedupefind?reset=1&rgid=4&gid=&limit=&criteria={"contact":{"contact_id":205}}&action=update

The contents of $criteria['contact'] are passed to the contact api to get a list of contacts to find possible
matches for (acls are applied when generating the match list to both the matched & match list in the next step).

Note that the urls are urlencoded & hence will have %22 rather than a quote so that feels xss safe but I added some
validation before I figured that part out & I think it still makes sense to keep it.

CRM/Contact/Form/Merge.php
CRM/Contact/Page/AJAX.php
CRM/Contact/Page/DedupeFind.php
CRM/Contact/Page/DedupeMerge.php
templates/CRM/Contact/Page/DedupeFind.tpl

index 53045ac9712f3db2bb8e3f6f82490de3beb2999e..ba9cfce432262c099f83075baf0f8e4bb354f569 100644 (file)
@@ -44,6 +44,11 @@ class CRM_Contact_Form_Merge extends CRM_Core_Form {
 
   var $_contactType = NULL;
 
+  /**
+   * @var array
+   */
+  public $criteria = array();
+
   /**
    * Query limit to be retained in the urls.
    *
@@ -74,8 +79,9 @@ class CRM_Contact_Form_Merge extends CRM_Core_Form {
       $this->_gid = $gid = CRM_Utils_Request::retrieve('gid', 'Positive', $this, FALSE);
       $this->_mergeId = CRM_Utils_Request::retrieve('mergeId', 'Positive', $this, FALSE);
       $this->limit = CRM_Utils_Request::retrieve('limit', 'Positive', $this, FALSE);
+      $this->criteria = CRM_Utils_Request::retrieve('criteria', 'Json', $this, FALSE, '{}');
 
-      $urlParams = ['reset' => 1, 'rgid' => $this->_rgid, 'gid' => $this->_gid, 'limit' => $this->limit];
+      $urlParams = ['reset' => 1, 'rgid' => $this->_rgid, 'gid' => $this->_gid, 'limit' => $this->limit, 'criteria' => $this->criteria];
 
       $this->bounceIfInvalid($this->_cid, $this->_oid);
 
@@ -100,7 +106,7 @@ class CRM_Contact_Form_Merge extends CRM_Core_Form {
         CRM_Core_Session::singleton()->pushUserContext($browseUrl);
       }
 
-      $cacheKey = CRM_Dedupe_Merger::getMergeCacheKeyString($this->_rgid, $gid);
+      $cacheKey = CRM_Dedupe_Merger::getMergeCacheKeyString($this->_rgid, $gid, json_decode($this->criteria, TRUE));
 
       $join = CRM_Dedupe_Merger::getJoinOnDedupeTable();
       $where = "de.id IS NULL";
@@ -300,7 +306,7 @@ class CRM_Contact_Form_Merge extends CRM_Core_Form {
     $message = '<ul><li>' . ts('%1 has been updated.', array(1 => $name)) . '</li><li>' . ts('Contact ID %1 has been deleted.', array(1 => $this->_oid)) . '</li></ul>';
     CRM_Core_Session::setStatus($message, ts('Contacts Merged'), 'success');
 
-    $urlParams = ['reset' => 1, 'cid' => $this->_cid, 'rgid' => $this->_rgid, 'gid' => $this->_gid, 'limit' => $this->limit];
+    $urlParams = ['reset' => 1, 'cid' => $this->_cid, 'rgid' => $this->_rgid, 'gid' => $this->_gid, 'limit' => $this->limit, 'criteria' => $this->criteria];
     $contactViewUrl = CRM_Utils_System::url('civicrm/contact/view', ['reset' => 1, 'cid' => $this->_cid]);
 
     if (!empty($formValues['_qf_Merge_submit'])) {
@@ -314,7 +320,7 @@ class CRM_Contact_Form_Merge extends CRM_Core_Form {
     }
 
     if ($this->next && $this->_mergeId) {
-      $cacheKey = CRM_Dedupe_Merger::getMergeCacheKeyString($this->_rgid, $this->_gid);
+      $cacheKey = CRM_Dedupe_Merger::getMergeCacheKeyString($this->_rgid, $this->_gid, json_decode($this->criteria, TRUE));
 
       $join = CRM_Dedupe_Merger::getJoinOnDedupeTable();
       $where = "de.id IS NULL";
index acd0d3d7a72019b8e70518b930d4630cca304085..830d7db1439981a7eb2f7ffbe1716f21eaf378ec 100644 (file)
@@ -646,13 +646,16 @@ LIMIT {$offset}, {$rowCount}
 
     $gid = CRM_Utils_Request::retrieve('gid', 'Positive');
     $rgid = CRM_Utils_Request::retrieve('rgid', 'Positive');
+    $null = NULL;
+    $criteria = CRM_Utils_Request::retrieve('criteria', 'Json', $null, FALSE, '{}');
     $selected    = isset($_REQUEST['selected']) ? CRM_Utils_Type::escape($_REQUEST['selected'], 'Integer') : 0;
     if ($rowCount < 0) {
       $rowCount = 0;
     }
 
     $whereClause = $orderByClause = '';
-    $cacheKeyString   = CRM_Dedupe_Merger::getMergeCacheKeyString($rgid, $gid);
+    $cacheKeyString   = CRM_Dedupe_Merger::getMergeCacheKeyString($rgid, $gid, json_decode($criteria, TRUE));
+
     $searchRows       = array();
 
     $searchParams = self::getSearchOptionsFromRequest();
@@ -814,6 +817,7 @@ LIMIT {$offset}, {$rowCount}
             'oid' => $pairInfo['entity_id2'],
             'action' => 'update',
             'rgid' => $rgid,
+            'criteria' => $criteria,
             'limit' => CRM_Utils_Request::retrieve('limit', 'Integer'),
           ];
         if ($gid) {
@@ -1014,8 +1018,9 @@ LIMIT {$offset}, {$rowCount}
     $gid  = CRM_Utils_Type::escape($_REQUEST['gid'], 'Integer');
     $pnid = $_REQUEST['pnid'];
     $isSelected = CRM_Utils_Type::escape($_REQUEST['is_selected'], 'Boolean');
+    $criteria = CRM_Utils_Request::retrieve('criteria', 'Json', $null, FALSE, '{}');
 
-    $cacheKeyString = CRM_Dedupe_Merger::getMergeCacheKeyString($rgid, $gid);
+    $cacheKeyString = CRM_Dedupe_Merger::getMergeCacheKeyString($rgid, $gid, json_decode($criteria, TRUE));
 
     $params = array(
       1 => array($isSelected, 'Boolean'),
index 3eacb5f91d117dd1be2b19123c2d95dd4c962579..9726f9f46f1cb6112de306282af64c9c48d61c6a 100644 (file)
@@ -63,7 +63,8 @@ class CRM_Contact_Page_DedupeFind extends CRM_Core_Page_Basic {
     $limit = CRM_Utils_Request::retrieve('limit', 'Integer', $this);
     $rgid = CRM_Utils_Request::retrieve('rgid', 'Positive', $this);
     $cid = CRM_Utils_Request::retrieve('cid', 'Positive', $this, FALSE, 0);
-    $criteria = CRM_Utils_Request::retrieve('criteria', 'Json', $this, FALSE);
+
+    $criteria = CRM_Utils_Request::retrieve('criteria', 'Json', $this, FALSE, '{}');
     $this->assign('criteria', $criteria);
 
     $isConflictMode = ($context == 'conflicts');
index d006a725bee3acf21cd23dfc4b09c9c29a55b260..83f01aa7600854fa7b8329c914adcd9333aff4f4 100644 (file)
@@ -52,13 +52,13 @@ class CRM_Contact_Page_DedupeMerge extends CRM_Core_Page {
    * Build a queue of tasks by dividing dupe pairs in batches.
    */
   public static function getRunner() {
+
     $rgid = CRM_Utils_Request::retrieveValue('rgid', 'Positive');
     $gid  = CRM_Utils_Request::retrieveValue('gid', 'Positive');
     $limit = CRM_Utils_Request::retrieveValue('limit', 'Positive');
     $action = CRM_Utils_Request::retrieveValue('action', 'String');
     $mode = CRM_Utils_Request::retrieveValue('mode', 'String', 'safe');
-
-    $cacheKeyString = CRM_Dedupe_Merger::getMergeCacheKeyString($rgid, $gid);
+    $criteria = CRM_Utils_Request::retrieve('criteria', 'Json', $null, FALSE, '{}');
 
     $urlQry = array(
       'reset' => 1,
@@ -66,8 +66,12 @@ class CRM_Contact_Page_DedupeMerge extends CRM_Core_Page {
       'rgid' => $rgid,
       'gid' => $gid,
       'limit' => $limit,
+      'criteria' => $criteria,
     );
 
+    $criteria = json_decode($criteria, TRUE);
+    $cacheKeyString = CRM_Dedupe_Merger::getMergeCacheKeyString($rgid, $gid, $criteria);
+
     if ($mode == 'aggressive' && !CRM_Core_Permission::check('force merge duplicate contacts')) {
       CRM_Core_Session::setStatus(ts('You do not have permission to force merge duplicate contact records'), ts('Permission Denied'), 'error');
       CRM_Utils_System::redirect(CRM_Utils_System::url('civicrm/contact/dedupefind', $urlQry));
@@ -101,7 +105,7 @@ class CRM_Contact_Page_DedupeMerge extends CRM_Core_Page {
     for ($i = 1; $i <= ceil($total / self::BATCHLIMIT); $i++) {
       $task  = new CRM_Queue_Task(
         array('CRM_Contact_Page_DedupeMerge', 'callBatchMerge'),
-        array($rgid, $gid, $mode, self::BATCHLIMIT, $isSelected),
+        array($rgid, $gid, $mode, self::BATCHLIMIT, $isSelected, $criteria),
         "Processed " . $i * self::BATCHLIMIT . " pair of duplicates out of " . $total
       );
 
@@ -131,11 +135,12 @@ class CRM_Contact_Page_DedupeMerge extends CRM_Core_Page {
    *   'safe' mode or 'force' mode.
    * @param int $batchLimit
    * @param int $isSelected
+   * @param array $criteria
    *
    * @return int
    */
-  public static function callBatchMerge(CRM_Queue_TaskContext $ctx, $rgid, $gid, $mode = 'safe', $batchLimit, $isSelected) {
-    CRM_Dedupe_Merger::batchMerge($rgid, $gid, $mode, $batchLimit, $isSelected);
+  public static function callBatchMerge(CRM_Queue_TaskContext $ctx, $rgid, $gid, $mode = 'safe', $batchLimit, $isSelected, $criteria) {
+    CRM_Dedupe_Merger::batchMerge($rgid, $gid, $mode, $batchLimit, $isSelected, $criteria);
     return CRM_Queue_Task::TASK_SUCCESS;
   }
 
index 7e3a10d6a14a97d1c02d860ea24ea1999a6f3606..663eeea53a820a7cfb887be7a22e400da4ed92c0 100644 (file)
       var is_selected = CRM.$('.crm-dedupe-select-all').prop('checked') ? 1 : 0;
     }
 
+    var criteria = {/literal}'{$criteria|escape}'{literal};
+    criteria  = criteria.length > 0 ? criteria : 0;
+
     var dataUrl = {/literal}"{crmURL p='civicrm/ajax/toggleDedupeSelect' h=0 q='snippet=4'}"{literal};
     var rgid = {/literal}"{$rgid}"{literal};
     var gid = {/literal}"{$gid}"{literal};
     rgid = rgid.length > 0 ? rgid : 0;
     gid  = gid.length > 0 ? gid : 0;
 
-    CRM.$.post(dataUrl, {pnid: id, rgid: rgid, gid: gid, is_selected: is_selected}, function (data) {
+    CRM.$.post(dataUrl, {pnid: id, rgid: rgid, gid: gid, is_selected: is_selected, criteria : criteria}, function (data) {
       // nothing to do for now
     }, 'json');
   }