CRM-18575 autoflip fix. Do not pass autoflip when batch merging.
authoreileen <emcnaughton@wikimedia.org>
Fri, 17 Jun 2016 23:34:03 +0000 (11:34 +1200)
committereileen <emcnaughton@wikimedia.org>
Sat, 25 Jun 2016 01:07:04 +0000 (13:07 +1200)
Fix autoflip by passing do not autoflip to respect prevnext contents & fully altering those contents.

I was going to refactor further but without an api for the entity it's a drag & there is contention
about adding apis just to help improve code quality because they aren't 'protected'

CRM/Contact/Page/AJAX.php
CRM/Contact/Page/DedupeMerge.php
CRM/Core/BAO/PrevNextCache.php
tests/phpunit/CRM/Core/BAO/PrevNextCacheTest.php [new file with mode: 0644]

index 2ff0ea6a69de1e55b553f662b9959d161ec3b976..84052e751fa49f27ab30c250eeb39a836d932a78 100644 (file)
@@ -886,22 +886,16 @@ LIMIT {$offset}, {$rowCount}
    */
   public static function flipDupePairs($prevNextId = NULL) {
     if (!$prevNextId) {
-      $prevNextId = $_REQUEST['pnid'];
+      // @todo figure out if this is always POST & specify that rather than inexact GET
+      $prevNextId = CRM_Utils_Request::retrieve('pnid', 'Integer');
     }
-    $query = "
-      UPDATE civicrm_prevnext_cache cpc
-      INNER JOIN civicrm_prevnext_cache old on cpc.id = old.id
-      SET cpc.entity_id1 = cpc.entity_id2, cpc.entity_id2 = old.entity_id1 ";
+
+    $onlySelected = FALSE;
     if (is_array($prevNextId) && !CRM_Utils_Array::crmIsEmptyArray($prevNextId)) {
-      CRM_Utils_Type::escapeAll($prevNextId, 'Positive');
-      $prevNextId = implode(', ', $prevNextId);
-      $query     .= "WHERE cpc.id IN ({$prevNextId}) AND cpc.is_selected = 1";
-    }
-    else {
-      $prevNextId = CRM_Utils_Type::escape($prevNextId, 'Positive');
-      $query     .= "WHERE cpc.id = $prevNextId";
+      $onlySelected = TRUE;
     }
-    CRM_Core_DAO::executeQuery($query);
+    $prevNextId = CRM_Utils_Type::escapeAll((array) $prevNextId, 'Positive');
+    CRM_Core_BAO_PrevNextCache::flipPair($prevNextId, $onlySelected);
     CRM_Utils_JSON::output();
   }
 
index 3c52f026839721cb8ec2c972d94e033fb8e8d93e..1bdd99c7179024af1eb6624ab229147e5150838c 100644 (file)
@@ -98,7 +98,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, TRUE, self::BATCHLIMIT, $isSelected),
+        array($rgid, $gid, $mode, FALSE, self::BATCHLIMIT, $isSelected),
         "Processed " . $i * self::BATCHLIMIT . " pair of duplicates out of " . $total
       );
 
@@ -135,9 +135,8 @@ class CRM_Contact_Page_DedupeMerge extends CRM_Core_Page {
    *
    * @return int
    */
-  public static function callBatchMerge(CRM_Queue_TaskContext $ctx, $rgid, $gid = NULL, $mode = 'safe', $autoFlip = TRUE, $batchLimit = 1, $isSelected = 2) {
-    $result = CRM_Dedupe_Merger::batchMerge($rgid, $gid, $mode, $autoFlip, $batchLimit, $isSelected);
-
+  public static function callBatchMerge(CRM_Queue_TaskContext $ctx, $rgid, $gid, $mode = 'safe', $autoFlip, $batchLimit, $isSelected) {
+    CRM_Dedupe_Merger::batchMerge($rgid, $gid, $mode, $autoFlip, $batchLimit, $isSelected);
     return CRM_Queue_Task::TASK_SUCCESS;
   }
 
index 91bb82780486be792c27e5e788fb7fa5b29d1b94..649d997e7034d45d3ae0a7b863e99c25aac5d2dc 100644 (file)
@@ -601,4 +601,35 @@ WHERE  cacheKey LIKE %1
     return $params;
   }
 
+  /**
+   * Flip 2 contacts in the prevNext cache.
+   *
+   * @param array $prevNextId
+   * @param bool $onlySelected
+   *   Only flip those which have been marked as selected.
+   */
+  public static function flipPair(array $prevNextId, $onlySelected) {
+    $dao = new CRM_Core_DAO_PrevNextCache();
+    if ($onlySelected) {
+      $dao->is_selected = 1;
+    }
+    foreach ($prevNextId as $id) {
+      $dao->id = $id;
+      if ($dao->find(TRUE)) {
+        $originalData = unserialize($dao->data);
+        $srcFields = array('ID', 'Name');
+        $swapFields = array('srcID', 'srcName', 'dstID', 'dstName');
+        $data = array_diff_assoc($originalData, array_fill_keys($swapFields, 1));
+        foreach ($srcFields as $key) {
+          $data['src' . $key] = $originalData['dst' . $key];
+          $data['dst' . $key] = $originalData['src' . $key];
+        }
+        $dao->data = serialize($data);
+        $dao->entity_id1 = $data['srcID'];
+        $dao->entity_id2 = $data['dstID'];
+        $dao->save();
+      }
+    }
+  }
+
 }
diff --git a/tests/phpunit/CRM/Core/BAO/PrevNextCacheTest.php b/tests/phpunit/CRM/Core/BAO/PrevNextCacheTest.php
new file mode 100644 (file)
index 0000000..4883618
--- /dev/null
@@ -0,0 +1,65 @@
+<?php
+/*
+ +--------------------------------------------------------------------+
+ | CiviCRM version 4.7                                                |
+ +--------------------------------------------------------------------+
+ | Copyright CiviCRM LLC (c) 2004-2016                                |
+ +--------------------------------------------------------------------+
+ | This file is a part of CiviCRM.                                    |
+ |                                                                    |
+ | CiviCRM is free software; you can copy, modify, and distribute it  |
+ | under the terms of the GNU Affero General Public License           |
+ | Version 3, 19 November 2007 and the CiviCRM Licensing Exception.   |
+ |                                                                    |
+ | CiviCRM is distributed in the hope that it will be useful, but     |
+ | WITHOUT ANY WARRANTY; without even the implied warranty of         |
+ | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.               |
+ | See the GNU Affero General Public License for more details.        |
+ |                                                                    |
+ | You should have received a copy of the GNU Affero General Public   |
+ | License and the CiviCRM Licensing Exception along                  |
+ | with this program; if not, contact CiviCRM LLC                     |
+ | at info[AT]civicrm[DOT]org. If you have questions about the        |
+ | GNU Affero General Public License or the licensing of CiviCRM,     |
+ | see the CiviCRM license FAQ at http://civicrm.org/licensing        |
+ +--------------------------------------------------------------------+
+ */
+
+/**
+ * Class CRM_Core_BAO_PrevNextCacheTest
+ * @group headless
+ */
+class CRM_Core_BAO_PrevNextCacheTest extends CiviUnitTestCase {
+
+  public function testFlipData() {
+    $dao = new CRM_Core_BAO_PrevNextCache();
+    $dao->entity_id1 = 1;
+    $dao->entity_id2 = 2;
+    $dao->data = serialize(array(
+      'srcID' => 1,
+      'srcName' => 'Ms. Meliissa Mouse II',
+      'dstID' => 2,
+      'dstName' => 'Mr. Maurice Mouse II',
+      'weight' => 20,
+      'canMerge' => TRUE,
+    ));
+    $dao->save();
+    $dao = new CRM_Core_BAO_PrevNextCache();
+    $dao->id = 1;
+    CRM_Core_BAO_PrevNextCache::flipPair(array(1), 0);
+    $dao->find(TRUE);
+    $this->assertEquals(2, $dao->entity_id1);
+    $this->assertEquals(1, $dao->entity_id2);
+    $this->assertEquals(serialize(array(
+      'srcName' => 'Mr. Maurice Mouse II',
+      'dstID' => 1,
+      'dstName' => 'Ms. Meliissa Mouse II',
+      'weight' => 20,
+      'canMerge' => TRUE,
+      'srcID' => 2,
+    )), $dao->data);
+
+    $this->quickCleanup(array('civicrm_prevnext_cache'));
+  }
+
+}