Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[REF] Move function from static class to OO class #19955

Merged
merged 1 commit into from
Mar 31, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
109 changes: 109 additions & 0 deletions CRM/Dedupe/MergeHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -359,4 +359,113 @@ protected function getSelectedType($entity, $blockIndex) {
return $this->getMigrationInfo()['location_blocks'][$entity][$blockIndex]['typeTypeId'] ?? NULL;
}

/**
* Merge location.
*
* Based on the data in the $locationMigrationInfo merge the locations for 2 contacts.
*
* The data is in the format received from the merge form (which is a fairly confusing format).
*
* It is converted into an array of DAOs which is passed to the alterLocationMergeData hook
* before saving or deleting the DAOs. A new hook is added to allow these to be altered after they have
* been calculated and before saving because
* - the existing format & hook combo is so confusing it is hard for developers to change & inherently fragile
* - passing to a hook right before save means calculations only have to be done once
* - the existing pattern of passing dissimilar data to the same (merge) hook with a different 'type' is just
* ugly.
*
* The use of the new hook is tested, including the fact it is called before contributions are merged, as this
* is likely to be significant data in merge hooks.
*
* @throws \CRM_Core_Exception
*/
public function mergeLocations(): void {
$mergeHandler = $this;
$locBlocks = $mergeHandler->getLocationBlocksToMerge();
$blocksDAO = [];
$migrationInfo = $mergeHandler->getMigrationInfo();

// @todo Handle OpenID (not currently in API).
if (!empty($locBlocks)) {
$locationBlocks = CRM_Dedupe_Merger::getLocationBlockInfo();

$primaryBlockIds = CRM_Contact_BAO_Contact::getLocBlockIds($mergeHandler->getToKeepID(), ['is_primary' => 1]);
$billingBlockIds = CRM_Contact_BAO_Contact::getLocBlockIds($mergeHandler->getToKeepID(), ['is_billing' => 1]);

foreach ($locBlocks as $name => $block) {
$blocksDAO[$name] = ['delete' => [], 'update' => []];
$daoName = 'CRM_Core_DAO_' . $locationBlocks[$name]['label'];
$changePrimary = FALSE;
$primaryDAOId = (array_key_exists($name, $primaryBlockIds)) ? array_pop($primaryBlockIds[$name]) : NULL;
$billingDAOId = (array_key_exists($name, $billingBlockIds)) ? array_pop($billingBlockIds[$name]) : NULL;

foreach ($block as $blkCount => $values) {
$otherBlockId = $migrationInfo['other_details']['location_blocks'][$name][$blkCount]['id'] ?? NULL;
$mainBlockId = CRM_Utils_Array::value('mainContactBlockId', $migrationInfo['location_blocks'][$name][$blkCount], 0);
if (!$otherBlockId) {
continue;
}
$otherBlockDAO = $mergeHandler->copyDataToNewBlockDAO($otherBlockId, $name, $blkCount);

// If we're deliberately setting this as primary then add the flag
// and remove it from the current primary location (if there is one).
// But only once for each entity.
$set_primary = $migrationInfo['location_blocks'][$name][$blkCount]['set_other_primary'] ?? NULL;
if (!$changePrimary && $set_primary == "1") {
$otherBlockDAO->is_primary = 1;
if ($primaryDAOId) {
$removePrimaryDAO = $mergeHandler->getDAOForLocationEntity($name);
$removePrimaryDAO->id = $primaryDAOId;
$removePrimaryDAO->is_primary = 0;
$blocksDAO[$name]['update'][$primaryDAOId] = $removePrimaryDAO;
}
$changePrimary = TRUE;
}
// Otherwise, if main contact already has primary, set it to 0.
elseif ($primaryDAOId) {
$otherBlockDAO->is_primary = 0;
}

// If the main contact already has a billing location, set this to 0.
if ($billingDAOId) {
$otherBlockDAO->is_billing = 0;
}

// overwrite - need to delete block which belongs to main-contact.
if (!empty($mainBlockId) && $values['is_replace']) {
$deleteDAO = $mergeHandler->getDAOForLocationEntity($name);
$deleteDAO->id = $mainBlockId;
$deleteDAO->find(TRUE);

// if we about to delete a primary / billing block, set the flags for new block
// that we going to assign to main-contact
if ($primaryDAOId && ($primaryDAOId == $deleteDAO->id)) {
$otherBlockDAO->is_primary = 1;
}
if ($billingDAOId && ($billingDAOId == $deleteDAO->id)) {
$otherBlockDAO->is_billing = 1;
}
$blocksDAO[$name]['delete'][$deleteDAO->id] = $deleteDAO;
}
$blocksDAO[$name]['update'][$otherBlockDAO->id] = $otherBlockDAO;
}
$blocksDAO[$name]['update'] += $mergeHandler->getBlocksToUpdateForDeletedContact($name);
}
}

CRM_Utils_Hook::alterLocationMergeData($blocksDAO, $mergeHandler->getToKeepID(), $mergeHandler->getToRemoveID(), $migrationInfo);
foreach ($blocksDAO as $blockDAOs) {
if (!empty($blockDAOs['update'])) {
foreach ($blockDAOs['update'] as $blockDAO) {
$blockDAO->save();
}
}
if (!empty($blockDAOs['delete'])) {
foreach ($blockDAOs['delete'] as $blockDAO) {
$blockDAO->delete();
}
}
}
}

}
110 changes: 1 addition & 109 deletions CRM/Dedupe/Merger.php
Original file line number Diff line number Diff line change
Expand Up @@ -1401,7 +1401,7 @@ public static function moveAllBelongings($mainId, $otherId, $migrationInfo, $che
}
$mergeHandler = new CRM_Dedupe_MergeHandler((int) $mainId, (int) $otherId);
$mergeHandler->setMigrationInfo($migrationInfo);
self::mergeLocations($mergeHandler);
$mergeHandler->mergeLocations();

// **** Do contact related migrations
// @todo - move all custom field processing to the move class & eventually have an
Expand Down Expand Up @@ -1770,114 +1770,6 @@ public static function getMergeContactDetails($contact_id) {
return $result['values'][$contact_id];
}

/**
* Merge location.
*
* Based on the data in the $locationMigrationInfo merge the locations for 2 contacts.
*
* The data is in the format received from the merge form (which is a fairly confusing format).
*
* It is converted into an array of DAOs which is passed to the alterLocationMergeData hook
* before saving or deleting the DAOs. A new hook is added to allow these to be altered after they have
* been calculated and before saving because
* - the existing format & hook combo is so confusing it is hard for developers to change & inherently fragile
* - passing to a hook right before save means calculations only have to be done once
* - the existing pattern of passing dissimilar data to the same (merge) hook with a different 'type' is just
* ugly.
*
* The use of the new hook is tested, including the fact it is called before contributions are merged, as this
* is likely to be significant data in merge hooks.
*
* @param \CRM_Dedupe_MergeHandler $mergeHandler
*/
public static function mergeLocations($mergeHandler) {
$locBlocks = $mergeHandler->getLocationBlocksToMerge();
$blocksDAO = [];
$migrationInfo = $mergeHandler->getMigrationInfo();

// @todo Handle OpenID (not currently in API).
if (!empty($locBlocks)) {
$locationBlocks = self::getLocationBlockInfo();

$primaryBlockIds = CRM_Contact_BAO_Contact::getLocBlockIds($mergeHandler->getToKeepID(), ['is_primary' => 1]);
$billingBlockIds = CRM_Contact_BAO_Contact::getLocBlockIds($mergeHandler->getToKeepID(), ['is_billing' => 1]);

foreach ($locBlocks as $name => $block) {
$blocksDAO[$name] = ['delete' => [], 'update' => []];
$daoName = 'CRM_Core_DAO_' . $locationBlocks[$name]['label'];
$changePrimary = FALSE;
$primaryDAOId = (array_key_exists($name, $primaryBlockIds)) ? array_pop($primaryBlockIds[$name]) : NULL;
$billingDAOId = (array_key_exists($name, $billingBlockIds)) ? array_pop($billingBlockIds[$name]) : NULL;

foreach ($block as $blkCount => $values) {
$otherBlockId = $migrationInfo['other_details']['location_blocks'][$name][$blkCount]['id'] ?? NULL;
$mainBlockId = CRM_Utils_Array::value('mainContactBlockId', $migrationInfo['location_blocks'][$name][$blkCount], 0);
if (!$otherBlockId) {
continue;
}
$otherBlockDAO = $mergeHandler->copyDataToNewBlockDAO($otherBlockId, $name, $blkCount);

// If we're deliberately setting this as primary then add the flag
// and remove it from the current primary location (if there is one).
// But only once for each entity.
$set_primary = $migrationInfo['location_blocks'][$name][$blkCount]['set_other_primary'] ?? NULL;
if (!$changePrimary && $set_primary == "1") {
$otherBlockDAO->is_primary = 1;
if ($primaryDAOId) {
$removePrimaryDAO = $mergeHandler->getDAOForLocationEntity($name);
$removePrimaryDAO->id = $primaryDAOId;
$removePrimaryDAO->is_primary = 0;
$blocksDAO[$name]['update'][$primaryDAOId] = $removePrimaryDAO;
}
$changePrimary = TRUE;
}
// Otherwise, if main contact already has primary, set it to 0.
elseif ($primaryDAOId) {
$otherBlockDAO->is_primary = 0;
}

// If the main contact already has a billing location, set this to 0.
if ($billingDAOId) {
$otherBlockDAO->is_billing = 0;
}

// overwrite - need to delete block which belongs to main-contact.
if (!empty($mainBlockId) && $values['is_replace']) {
$deleteDAO = $mergeHandler->getDAOForLocationEntity($name);
$deleteDAO->id = $mainBlockId;
$deleteDAO->find(TRUE);

// if we about to delete a primary / billing block, set the flags for new block
// that we going to assign to main-contact
if ($primaryDAOId && ($primaryDAOId == $deleteDAO->id)) {
$otherBlockDAO->is_primary = 1;
}
if ($billingDAOId && ($billingDAOId == $deleteDAO->id)) {
$otherBlockDAO->is_billing = 1;
}
$blocksDAO[$name]['delete'][$deleteDAO->id] = $deleteDAO;
}
$blocksDAO[$name]['update'][$otherBlockDAO->id] = $otherBlockDAO;
}
$blocksDAO[$name]['update'] += $mergeHandler->getBlocksToUpdateForDeletedContact($name);
}
}

CRM_Utils_Hook::alterLocationMergeData($blocksDAO, $mergeHandler->getToKeepID(), $mergeHandler->getToRemoveID(), $migrationInfo);
foreach ($blocksDAO as $blockDAOs) {
if (!empty($blockDAOs['update'])) {
foreach ($blockDAOs['update'] as $blockDAO) {
$blockDAO->save();
}
}
if (!empty($blockDAOs['delete'])) {
foreach ($blockDAOs['delete'] as $blockDAO) {
$blockDAO->delete();
}
}
}
}

/**
* Dedupe a pair of contacts.
*
Expand Down