/** * Based on the provided two contact_ids and a set of tables, move the * belongings of the other contact to the main one. * */ public static function moveContactBelongings($mainId, $otherId, $tables = FALSE, $tableOperations = array()) { $cidRefs = self::cidRefs(); $eidRefs = self::eidRefs(); $cpTables = self::cpTables(); $paymentTables = self::paymentTables(); $membershipMerge = FALSE; // CRM-12695 $affected = array_merge(array_keys($cidRefs), array_keys($eidRefs)); if ($tables !== FALSE) { // if there are specific tables, sanitize the list $affected = array_unique(array_intersect($affected, $tables)); } else { // if there aren't any specific tables, don't affect the ones handled by relTables() // also don't affect tables in locTables() CRM-15658 $relTables = self::relTables(); $handled = self::locTables(); foreach ($relTables as $params) { $handled = array_merge($handled, $params['tables']); } $affected = array_diff($affected, $handled); /** * CRM-12695 * Set $membershipMerge flag only once * while doing contact related migration * to call addMembershipToRealtedContacts() * function only once. * Since the current function (moveContactBelongings) is called twice * with & without parameters $tables & $tableOperations */ // retrieve main contact's related table(s) $activeMainRelTables = CRM_Dedupe_Merger::getActiveRelTables($mainId); // check if membership table exists in main contact's related table(s) if (in_array('rel_table_memberships', $activeMainRelTables)) { $membershipMerge = TRUE; // set membership flag - CRM-12695 } } $mainId = (int) $mainId; $otherId = (int) $otherId; $sqls = array(); foreach ($affected as $table) { // Call custom processing function for objects that require it if (isset($cpTables[$table])) { foreach ($cpTables[$table] as $className => $fnName) { $className::$fnName($mainId, $otherId, $sqls); } // Skip normal processing continue; } // use UPDATE IGNORE + DELETE query pair to skip on situations when // there's a UNIQUE restriction on ($field, some_other_field) pair if (isset($cidRefs[$table])) { foreach ($cidRefs[$table] as $field) { // carry related contributions CRM-5359 if (in_array($table, $paymentTables)) { $paymentSqls = self::paymentSql($table, $mainId, $otherId); $sqls = array_merge($sqls, $paymentSqls); if (!empty($tables) && !in_array('civicrm_contribution', $tables)) { $payOprSqls = self::operationSql($mainId, $otherId, $table, $tableOperations, 'payment'); $sqls = array_merge($sqls, $payOprSqls); } } $preOperationSqls = self::operationSql($mainId, $otherId, $table, $tableOperations); $sqls = array_merge($sqls, $preOperationSqls); $sqls[] = "UPDATE IGNORE {$table} SET {$field} = {$mainId} WHERE {$field} = {$otherId}"; $sqls[] = "DELETE FROM {$table} WHERE {$field} = {$otherId}"; } } if (isset($eidRefs[$table])) { foreach ($eidRefs[$table] as $entityTable => $entityId) { $sqls[] = "UPDATE IGNORE {$table} SET {$entityId} = {$mainId} WHERE {$entityId} = {$otherId} AND {$entityTable} = 'civicrm_contact'"; $sqls[] = "DELETE FROM {$table} WHERE {$entityId} = {$otherId} AND {$entityTable} = 'civicrm_contact'"; } } } // Allow hook_civicrm_merge() to add SQL statements for the merge operation. CRM_Utils_Hook::merge('sqls', $sqls, $mainId, $otherId, $tables); // call the SQL queries in one transaction $transaction = new CRM_Core_Transaction(); foreach ($sqls as $sql) { CRM_Core_DAO::executeQuery($sql, array(), TRUE, NULL, TRUE); } // CRM-12695 if ($membershipMerge) { // call to function adding membership to related contacts CRM_Dedupe_Merger::addMembershipToRealtedContacts($mainId); } $transaction->commit(); }