Merge pull request #19067 from eileenmcnaughton/weight
[civicrm-core.git] / CRM / Dedupe / MergeHandler.php
index f67371d6e081be3b7e3e336cf06b5fd7ba14706a..cb0d64ebacdc9c8dbe4d5e615a590e23aa663be9 100644 (file)
@@ -196,33 +196,167 @@ class CRM_Dedupe_MergeHandler {
    * This is intended as a refactoring step - not the long term function. Do not
    * call from any function other than the one it is taken from (Merger::mergeLocations).
    *
-   * @param string $daoName
    * @param int $otherBlockId
    * @param string $name
    * @param int $blkCount
    *
-   * @return mixed
+   * @return CRM_Core_DAO_Address|CRM_Core_DAO_Email|CRM_Core_DAO_IM|CRM_Core_DAO_Phone|CRM_Core_DAO_Website
+   *
+   * @throws \CRM_Core_Exception
    */
-  public function copyDataToNewBlockDAO(string $daoName, $otherBlockId, $name, $blkCount) {
-    $locationBlocks = CRM_Dedupe_Merger::getLocationBlockInfo();
-    $migrationInfo = $this->getMigrationInfo();
+  public function copyDataToNewBlockDAO($otherBlockId, $name, $blkCount) {
     // For the block which belongs to other-contact, link the location block to main-contact
-    $otherBlockDAO = new $daoName();
+    $otherBlockDAO = $this->getDAOForLocationEntity($name, $this->getSelectedLocationType($name, $blkCount), $this->getSelectedType($name, $blkCount));
     $otherBlockDAO->contact_id = $this->getToKeepID();
-
     // Get the ID of this block on the 'other' contact, otherwise skip
     $otherBlockDAO->id = $otherBlockId;
+    return $otherBlockDAO;
+  }
 
-    // Add/update location and type information from the form, if applicable
-    if ($locationBlocks[$name]['hasLocation']) {
-      $locTypeId = $migrationInfo['location_blocks'][$name][$blkCount]['locTypeId'] ?? NULL;
-      $otherBlockDAO->location_type_id = $locTypeId;
+  /**
+   * Get blocks, if any, to update for the deleted contact.
+   *
+   * If the deleted contact no longer has a primary address but still has
+   * one or more blocks we want to ensure the remaining block is updated
+   * to have is_primary = 1 in case the contact is ever undeleted.
+   *
+   * @param string $entity
+   *
+   * @return array
+   * @throws \CRM_Core_Exception
+   */
+  public function getBlocksToUpdateForDeletedContact($entity) {
+    $movedBlocks = $this->getLocationBlocksToMerge()[$entity];
+    $deletedContactsBlocks = $this->getLocationBlocksForContactToRemove()[$entity];
+    $unMovedBlocks = array_values(array_diff_key($deletedContactsBlocks, $movedBlocks));
+    if (empty($unMovedBlocks) || empty($movedBlocks)) {
+      return [];
     }
-    if ($locationBlocks[$name]['hasType']) {
-      $typeTypeId = $migrationInfo['location_blocks'][$name][$blkCount]['typeTypeId'] ?? NULL;
-      $otherBlockDAO->{$locationBlocks[$name]['hasType']} = $typeTypeId;
+    foreach (array_keys($movedBlocks) as $index) {
+      if ($deletedContactsBlocks[$index]['is_primary']) {
+        // We have moved the primary - change any other block to be primary.
+        $newPrimaryBlock = $this->getDAOForLocationEntity($entity);
+        $newPrimaryBlock->id = $unMovedBlocks[0]['id'];
+        $newPrimaryBlock->is_primary = 1;
+        return [$newPrimaryBlock->id => $newPrimaryBlock];
+      }
     }
-    return $otherBlockDAO;
+    return [];
+  }
+
+  /**
+   * Get the details of the blocks to be transferred over for the given entity.
+   *
+   * @param string $entity
+   *
+   * @return array
+   */
+  protected function getLocationBlocksToMoveForEntity($entity) {
+    $movedBlocks = $this->getLocationBlocksToMerge()[$entity];
+    $blockDetails = $this->getLocationBlocksForContactToRemove()[$entity];
+    return array_intersect_key($blockDetails, $movedBlocks);
+  }
+
+  /**
+   * Does the contact to keep have location blocks for the given entity.
+   *
+   * @param string $entity
+   *
+   * @return bool
+   */
+  public function contactToKeepHasLocationBlocksForEntity($entity) {
+    return !empty($this->getLocationBlocksForContactToKeep()[$entity]);
+  }
+
+  /**
+   * Get the location blocks for the contact to be kept.
+   *
+   * @return array
+   */
+  public function getLocationBlocksForContactToKeep() {
+    return $this->getMigrationInfo()['main_details']['location_blocks'];
+  }
+
+  /**
+   * Get the location blocks for the contact to be deleted.
+   *
+   * @return array
+   */
+  public function getLocationBlocksForContactToRemove() {
+    return $this->getMigrationInfo()['other_details']['location_blocks'];
+  }
+
+  /**
+   * Get the DAO object appropriate to the location entity.
+   *
+   * @param string $entity
+   *
+   * @param int|null $locationTypeID
+   * @param int|null $typeID
+   *
+   * @return CRM_Core_DAO_Address|CRM_Core_DAO_Email|CRM_Core_DAO_IM|CRM_Core_DAO_Phone|CRM_Core_DAO_Website
+   * @throws \CRM_Core_Exception
+   */
+  public function getDAOForLocationEntity($entity, $locationTypeID = NULL, $typeID = NULL) {
+    switch ($entity) {
+      case 'email':
+        $dao = new CRM_Core_DAO_Email();
+        $dao->location_type_id = $locationTypeID;
+        return $dao;
+
+      case 'address':
+        $dao = new CRM_Core_DAO_Address();
+        $dao->location_type_id = $locationTypeID;
+        return $dao;
+
+      case 'phone':
+        $dao = new CRM_Core_DAO_Phone();
+        $dao->location_type_id = $locationTypeID;
+        $dao->phone_type_id = $typeID;
+        return $dao;
+
+      case 'website':
+        $dao = new CRM_Core_DAO_Website();
+        $dao->website_type_id = $typeID;
+        return $dao;
+
+      case 'im':
+        $dao = new CRM_Core_DAO_IM();
+        $dao->location_type_id = $locationTypeID;
+        return $dao;
+
+      default:
+        // Mostly here, along with the switch over a more concise format, to help IDEs understand the possibilities.
+        throw new CRM_Core_Exception('Unsupported entity');
+    }
+  }
+
+  /**
+   * Get the selected location type for the given location block.
+   *
+   * This will retrieve any user selection if they specified which location to move a block to.
+   *
+   * @param string $entity
+   * @param int $blockIndex
+   *
+   * @return int|null
+   */
+  protected function getSelectedLocationType($entity, $blockIndex) {
+    return $this->getMigrationInfo()['location_blocks'][$entity][$blockIndex]['locTypeId'] ?? NULL;
+  }
+
+  /**
+   * Get the selected type for the given location block.
+   *
+   * This will retrieve any user selection if they specified which type to move a block to (e.g 'Mobile' for phone).
+   *
+   * @param string $entity
+   * @param int $blockIndex
+   *
+   * @return int|null
+   */
+  protected function getSelectedType($entity, $blockIndex) {
+    return $this->getMigrationInfo()['location_blocks'][$entity][$blockIndex]['typeTypeId'] ?? NULL;
   }
 
 }