Tidy up comments
[civicrm-core.git] / CRM / Dedupe / Merger.php
index bf42eb89e45bdbbc03b4da9831410d1bd2630896..147512875c5d7bde8eedbc82e4676c4676fc0df2 100644 (file)
@@ -1,7 +1,7 @@
 <?php
 /*
  +--------------------------------------------------------------------+
- | CiviCRM version 4.7                                                |
+ | CiviCRM version 5                                                  |
  +--------------------------------------------------------------------+
  | Copyright CiviCRM LLC (c) 2004-2018                                |
  +--------------------------------------------------------------------+
@@ -39,25 +39,25 @@ class CRM_Dedupe_Merger {
    * @return array
    */
   public static function relTables() {
-    static $relTables;
 
-    // Setting these merely prevents enotices - but it may be more appropriate not to add the user table below
-    // if the url can't be retrieved. A more standardised way to retrieve them is.
-    // CRM_Core_Config::singleton()->userSystem->getUserRecordUrl() - however that function takes a contact_id &
-    // we may need a different function when it is not known.
-    $title = $userRecordUrl = '';
+    if (!isset(Civi::$statics[__CLASS__]['relTables'])) {
 
-    $config = CRM_Core_Config::singleton();
-    if ($config->userSystem->is_drupal) {
-      $userRecordUrl = CRM_Utils_System::url('user/%ufid');
-      $title = ts('%1 User: %2; user id: %3', array(1 => $config->userFramework, 2 => '$ufname', 3 => '$ufid'));
-    }
-    elseif ($config->userFramework == 'Joomla') {
-      $userRecordUrl = $config->userSystem->getVersion() > 1.5 ? $config->userFrameworkBaseURL . "index.php?option=com_users&view=user&task=user.edit&id=" . '%ufid' : $config->userFrameworkBaseURL . "index2.php?option=com_users&view=user&task=edit&id[]=" . '%ufid';
-      $title = ts('%1 User: %2; user id: %3', array(1 => $config->userFramework, 2 => '$ufname', 3 => '$ufid'));
-    }
+      // Setting these merely prevents enotices - but it may be more appropriate not to add the user table below
+      // if the url can't be retrieved. A more standardised way to retrieve them is.
+      // CRM_Core_Config::singleton()->userSystem->getUserRecordUrl() - however that function takes a contact_id &
+      // we may need a different function when it is not known.
+      $title = $userRecordUrl = '';
+
+      $config = CRM_Core_Config::singleton();
+      if ($config->userSystem->is_drupal) {
+        $userRecordUrl = CRM_Utils_System::url('user/%ufid');
+        $title = ts('%1 User: %2; user id: %3', array(1 => $config->userFramework, 2 => '$ufname', 3 => '$ufid'));
+      }
+      elseif ($config->userFramework == 'Joomla') {
+        $userRecordUrl = $config->userSystem->getVersion() > 1.5 ? $config->userFrameworkBaseURL . "index.php?option=com_users&view=user&task=user.edit&id=" . '%ufid' : $config->userFrameworkBaseURL . "index2.php?option=com_users&view=user&task=edit&id[]=" . '%ufid';
+        $title = ts('%1 User: %2; user id: %3', array(1 => $config->userFramework, 2 => '$ufname', 3 => '$ufid'));
+      }
 
-    if (!$relTables) {
       $relTables = array(
         'rel_table_contributions' => array(
           'title' => ts('Contributions'),
@@ -155,8 +155,12 @@ class CRM_Dedupe_Merger {
 
       // Allow hook_civicrm_merge() to adjust $relTables
       CRM_Utils_Hook::merge('relTables', $relTables);
+
+      // Cache the results in a static variable
+      Civi::$statics[__CLASS__]['relTables'] = $relTables;
     }
-    return $relTables;
+
+    return Civi::$statics[__CLASS__]['relTables'];
   }
 
   /**
@@ -273,11 +277,12 @@ class CRM_Dedupe_Merger {
    * We treat multi-valued custom sets as "related tables" similar to activities, contributions, etc.
    * @param string $request
    *   'relTables' or 'cidRefs'.
+   * @return array
    * @see CRM-13836
    */
   public static function getMultiValueCustomSets($request) {
-    static $data = NULL;
-    if ($data === NULL) {
+
+    if (!isset(Civi::$statics[__CLASS__]['multiValueCustomSets'])) {
       $data = array(
         'relTables' => array(),
         'cidRefs' => array(),
@@ -296,8 +301,12 @@ class CRM_Dedupe_Merger {
           'url' => CRM_Utils_System::url('civicrm/contact/view', 'reset=1&force=1&cid=$cid' . $urlSuffix),
         );
       }
+
+      // Store the result in a static variable cache
+      Civi::$statics[__CLASS__]['multiValueCustomSets'] = $data;
     }
-    return $data[$request];
+
+    return Civi::$statics[__CLASS__]['multiValueCustomSets'][$request];
   }
 
   /**
@@ -313,6 +322,7 @@ class CRM_Dedupe_Merger {
         // Empty array == do nothing - this table is handled by mergeGroupContact
         'civicrm_subscription_history' => array(),
         'civicrm_relationship' => array('CRM_Contact_BAO_Relationship' => 'mergeRelationships'),
+        'civicrm_membership' => array('CRM_Member_BAO_Membership' => 'mergeMemberships'),
       );
     }
     return $tables;
@@ -495,18 +505,21 @@ INNER JOIN  civicrm_membership membership2 ON membership1.membership_type_id = m
 
     $mainId = (int) $mainId;
     $otherId = (int) $otherId;
+    $multi_value_tables = array_keys(CRM_Dedupe_Merger::getMultiValueCustomSets('cidRefs'));
 
     $sqls = array();
     foreach ($affected as $table) {
-      // skipping non selected custom table's value migration
-      if ($customTableToCopyFrom !== NULL && in_array($table, $customTables) && !in_array($table, $customTableToCopyFrom)) {
-        continue;
+      // skipping non selected single-value custom table's value migration
+      if (!in_array($table, $multi_value_tables)) {
+        if ($customTableToCopyFrom !== NULL && in_array($table, $customTables) && !in_array($table, $customTableToCopyFrom)) {
+          continue;
+        }
       }
 
       // Call custom processing function for objects that require it
       if (isset($cpTables[$table])) {
         foreach ($cpTables[$table] as $className => $fnName) {
-          $className::$fnName($mainId, $otherId, $sqls);
+          $className::$fnName($mainId, $otherId, $sqls, $tables, $tableOperations);
         }
         // Skip normal processing
         continue;
@@ -638,18 +651,31 @@ INNER JOIN  civicrm_membership membership2 ON membership1.membership_type_id = m
    *   mode does a force merge.
    * @param int $batchLimit number of merges to carry out in one batch.
    * @param int $isSelected if records with is_selected column needs to be processed.
+   *   Note the option of '2' is only used in conjunction with $redirectForPerformance
+   *   to determine when to reload the cache (!). The use of anything other than a boolean is being grandfathered
+   *   out in favour of explicitly passing in $reloadCacheIfEmpty
    *
    * @param array $criteria
    *   Criteria to use in the filter.
    *
    * @param bool $checkPermissions
    *   Respect logged in user permissions.
+   * @param bool|NULL $reloadCacheIfEmpty
+   *  If not set explicitly this is calculated but it is preferred that it be set
+   *  per comments on isSelected above.
    *
    * @return array|bool
    */
-  public static function batchMerge($rgid, $gid = NULL, $mode = 'safe', $batchLimit = 1, $isSelected = 2, $criteria = array(), $checkPermissions = TRUE) {
+  public static function batchMerge($rgid, $gid = NULL, $mode = 'safe', $batchLimit = 1, $isSelected = 2, $criteria = array(), $checkPermissions = TRUE, $reloadCacheIfEmpty = NULL) {
     $redirectForPerformance = ($batchLimit > 1) ? TRUE : FALSE;
-    $reloadCacheIfEmpty = (!$redirectForPerformance && $isSelected == 2);
+
+    if (!isset($reloadCacheIfEmpty)) {
+      $reloadCacheIfEmpty = (!$redirectForPerformance && $isSelected == 2);
+    }
+    if ($isSelected !== 0 && $isSelected !== 1) {
+      // explicitly set to NULL if not 1 or 0 as part of grandfathering out the mystical '2' value.
+      $isSelected = NULL;
+    }
     $dupePairs = self::getDuplicatePairs($rgid, $gid, $reloadCacheIfEmpty, $batchLimit, $isSelected, '', ($mode == 'aggressive'), $criteria, $checkPermissions);
 
     $cacheParams = array(
@@ -657,7 +683,8 @@ INNER JOIN  civicrm_membership membership2 ON membership1.membership_type_id = m
       // @todo stop passing these parameters in & instead calculate them in the merge function based
       // on the 'real' params like $isRespectExclusions $batchLimit and $isSelected.
       'join' => self::getJoinOnDedupeTable(),
-      'where' => self::getWhereString($batchLimit, $isSelected),
+      'where' => self::getWhereString($isSelected),
+      'limit' => (int) $batchLimit,
     );
     return CRM_Dedupe_Merger::merge($dupePairs, $cacheParams, $mode, $redirectForPerformance, $checkPermissions);
   }
@@ -680,21 +707,15 @@ INNER JOIN  civicrm_membership membership2 ON membership1.membership_type_id = m
   /**
    * Get where string for dedupe join.
    *
-   * @param int $batchLimit
    * @param bool $isSelected
    *
    * @return string
    */
-  protected static function getWhereString($batchLimit, $isSelected) {
+  protected static function getWhereString($isSelected) {
     $where = "de.id IS NULL";
     if ($isSelected === 0 || $isSelected === 1) {
       $where .= " AND pn.is_selected = {$isSelected}";
     }
-    // else consider all dupe pairs
-    // @todo Adding limit to Where??!!
-    if ($batchLimit) {
-      $where .= " LIMIT {$batchLimit}";
-    }
     return $where;
   }
 
@@ -845,7 +866,7 @@ INNER JOIN  civicrm_membership membership2 ON membership1.membership_type_id = m
           $cacheParams['join'],
           $cacheParams['where'],
           0,
-          0,
+          $cacheParams['limit'],
           array(),
           '',
           FALSE
@@ -1620,7 +1641,6 @@ INNER JOIN  civicrm_membership membership2 ON membership1.membership_type_id = m
             break;
 
           case 'CheckBox':
-          case 'AdvMulti-Select':
           case 'Multi-Select':
           case 'Multi-Select Country':
           case 'Multi-Select State/Province':
@@ -1654,7 +1674,6 @@ INNER JOIN  civicrm_membership membership2 ON membership1.membership_type_id = m
                   if (in_array($htmlType, array(
                     'CheckBox',
                     'Multi-Select',
-                    'AdvMulti-Select',
                   ))) {
                     $submitted[$key] = CRM_Core_DAO::VALUE_SEPARATOR . implode(CRM_Core_DAO::VALUE_SEPARATOR,
                         $mergeValue
@@ -1981,16 +2000,16 @@ INNER JOIN  civicrm_membership membership2 ON membership1.membership_type_id = m
    *    Array of matches meeting the criteria.
    */
   public static function getDuplicatePairs($rule_group_id, $group_id, $reloadCacheIfEmpty, $batchLimit, $isSelected, $orderByClause = '', $includeConflicts = TRUE, $criteria = array(), $checkPermissions = TRUE, $searchLimit = 0) {
-    $where = self::getWhereString($batchLimit, $isSelected);
+    $where = self::getWhereString($isSelected);
     $cacheKeyString = self::getMergeCacheKeyString($rule_group_id, $group_id, $criteria, $checkPermissions);
     $join = self::getJoinOnDedupeTable();
-    $dupePairs = CRM_Core_BAO_PrevNextCache::retrieve($cacheKeyString, $join, $where, 0, 0, array(), $orderByClause, $includeConflicts);
+    $dupePairs = CRM_Core_BAO_PrevNextCache::retrieve($cacheKeyString, $join, $where, 0, $batchLimit, array(), $orderByClause, $includeConflicts);
     if (empty($dupePairs) && $reloadCacheIfEmpty) {
       // If we haven't found any dupes, probably cache is empty.
       // Try filling cache and give another try. We don't need to specify include conflicts here are there will not be any
       // until we have done some processing.
       CRM_Core_BAO_PrevNextCache::refillCache($rule_group_id, $group_id, $cacheKeyString, $criteria, $checkPermissions, $searchLimit);
-      $dupePairs = CRM_Core_BAO_PrevNextCache::retrieve($cacheKeyString, $join, $where, 0, 0, array(), $orderByClause, $includeConflicts);
+      $dupePairs = CRM_Core_BAO_PrevNextCache::retrieve($cacheKeyString, $join, $where, 0, $batchLimit, array(), $orderByClause, $includeConflicts);
       return $dupePairs;
     }
     return $dupePairs;