Skip to content

Commit

Permalink
Merge pull request #31336 from johntwyman/api4/contact-mergedtofrom
Browse files Browse the repository at this point in the history
Add APIv4 Contact.getMergedTo/getMergedFrom actions
  • Loading branch information
colemanw authored Nov 15, 2024
2 parents b8e97de + 5075881 commit d755914
Show file tree
Hide file tree
Showing 3 changed files with 193 additions and 0 deletions.
73 changes: 73 additions & 0 deletions Civi/Api4/Action/Contact/GetMergedFrom.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
<?php

/*
+--------------------------------------------------------------------+
| Copyright CiviCRM LLC. All rights reserved. |
| |
| This work is published under the GNU AGPLv3 license with some |
| permitted exceptions and without any warranty. For full license |
| and copyright information, see https://civicrm.org/licensing |
+--------------------------------------------------------------------+
*/

namespace Civi\Api4\Action\Contact;

use Civi\Api4\Generic\Result;

/**
* Get the prior contact a contact was merged from.
*
* @method $this setContactId(int $cid) Set contact ID (required)
* @method int getContactId() Get contact ID param
* @method $this setIsTest(bool $isTest) Set isTest param
* @method bool getIsTest() Get isTest param
*/
class GetMergedFrom extends \Civi\Api4\Generic\AbstractAction {

/**
* ID of contact to find prior contact for
*
* @var int
* @required
*/
protected $contactId;

/**
* Get test deletions rather than live?
* @var bool
*/
protected $isTest = FALSE;

/**
* @param \Civi\Api4\Generic\Result $result
*/
public function _run(Result $result): void {
$activities = [];
$deleteActivities = \Civi\Api4\ActivityContact::get(FALSE)
->addSelect('activity_id')
->addWhere('contact_id', '=', $this->contactId)
->addWhere('activity_id.activity_type_id:name', '=', 'Contact Merged')
->addWhere('activity_id.is_deleted', '=', FALSE)
->addWhere('activity_id.is_test', '=', $this->isTest)
->addWhere('record_type_id:name', '=', 'Activity Targets')
->execute();
foreach ($deleteActivities as $deleteActivity) {
$activities[] = $deleteActivity['activity_id'];
}
if (empty($activities)) {
$result[] = $activities;
return;
}

$activityContacts = \Civi\Api4\ActivityContact::get(FALSE)
->addSelect('contact_id')
->addWhere('activity_id.parent_id', 'IN', $activities)
->addWhere('record_type_id:name', '=', 'Activity Targets')
->execute();
$contacts = [];
foreach ($activityContacts as $activityContact) {
$result[] = ['id' => $activityContact['contact_id']];
}
}

}
68 changes: 68 additions & 0 deletions Civi/Api4/Action/Contact/GetMergedTo.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
<?php

/*
+--------------------------------------------------------------------+
| Copyright CiviCRM LLC. All rights reserved. |
| |
| This work is published under the GNU AGPLv3 license with some |
| permitted exceptions and without any warranty. For full license |
| and copyright information, see https://civicrm.org/licensing |
+--------------------------------------------------------------------+
*/

namespace Civi\Api4\Action\Contact;

use Civi\Api4\Generic\Result;

/**
* Get the ultimate contact a contact was merged to.
*
* @method $this setContactId(int $cid) Set contact ID (required)
* @method int getContactId() Get contact ID param
* @method $this setIsTest(bool $isTest) Set isTest param
* @method bool getIsTest() Get isTest param
*/
class GetMergedTo extends \Civi\Api4\Generic\AbstractAction {

/**
* ID of contact to find ultimate contact for
*
* @var int
* @required
*/
protected $contactId;

/**
* Get test deletions rather than live?
* @var bool
*/
protected $isTest = FALSE;

/**
* @param \Civi\Api4\Generic\Result $result
*/
public function _run(Result $result): void {
$returnId = [];
$deleteActivity = \Civi\Api4\ActivityContact::get(FALSE)
->addSelect('activity_id.parent_id')
->addWhere('contact_id', '=', $this->contactId)
->addWhere('activity_id.activity_type_id:name', '=', 'Contact Deleted by Merge')
->addWhere('activity_id.is_deleted', '=', FALSE)
->addWhere('activity_id.is_test', '=', $this->isTest)
->addWhere('record_type_id:name', '=', 'Activity Targets')
->addOrderBy('activity_id.activity_date_time', 'DESC')
->setLimit(1)
->execute()
->first();
if (!empty($deleteActivity)) {
$returnId = \Civi\Api4\ActivityContact::get(FALSE)
->addSelect('contact_id')
->addWhere('activity_id', '=', $deleteActivity['activity_id.parent_id'])
->addWhere('record_type_id:name', '=', 'Activity Targets')
->execute()
->first()['contact_id'];
}
$result[] = ['id' => $returnId];
}

}
52 changes: 52 additions & 0 deletions tests/phpunit/api/v4/Action/ContactDuplicatesTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -179,4 +179,56 @@ public function testMergeDuplicates():void {
$this->assertEquals('Jo', $check[0]['first_name']);
}

public function testGetMergedToFrom(): void {
$email = uniqid('test@');

$testContacts = $this->saveTestRecords('Contact', [
'records' => [['first_name' => 'MergeDown'], ['first_name' => 'MergeDown']],
'defaults' => ['email_primary.email' => $email],
])->column('id');

// Test merge "down" to lower ID
// which is the usual way merges are conducted
$result = Contact::mergeDuplicates(FALSE)
->setContactId($testContacts[0])
->setDuplicateId($testContacts[1])
->execute();

$mergedToID = Contact::getMergedTo(FALSE)
->setContactId($testContacts[1])
->execute()
->first()['id'];
$this->assertEquals($testContacts[0], $mergedToID);

$mergedFromID = Contact::getMergedFrom(FALSE)
->setContactId($testContacts[0])
->execute()
->first()['id'];
$this->assertEquals($testContacts[1], $mergedFromID);

// Set up new test contacts
$testContacts = $this->saveTestRecords('Contact', [
'records' => [['first_name' => 'MergeUp'], ['first_name' => 'MergeUp']],
'defaults' => ['email_primary.email' => $email],
])->column('id');

// Test merge "up" to higher ID
$result = Contact::mergeDuplicates(FALSE)
->setContactId($testContacts[1])
->setDuplicateId($testContacts[0])
->execute();

$mergedToID = Contact::getMergedTo(FALSE)
->setContactId($testContacts[0])
->execute()
->first()['id'];
$this->assertEquals($testContacts[1], $mergedToID);

$mergedFromID = Contact::getMergedFrom(FALSE)
->setContactId($testContacts[1])
->execute()
->first()['id'];
$this->assertEquals($testContacts[0], $mergedFromID);
}

}

0 comments on commit d755914

Please sign in to comment.