From fedc34282dbad5d2af77cb28585bae41eeb7d1c0 Mon Sep 17 00:00:00 2001 From: eileen Date: Thu, 23 Mar 2017 15:18:17 +1300 Subject: [PATCH] Towards CRM-20155 remove duplicate calls to dedupe functions. This is a partial commit which covers the best tested section of these & establishes the new functions. I didn't want to make the commit too daunting. The bin file probably has not been used in years hence all the require_once calls :-) --- CRM/Contact/BAO/Contact.php | 49 +++++++++++++++ api/v3/Contact.php | 61 ++++++------------- bin/ContributionProcessor.php | 40 +++++------- tests/phpunit/CRM/Dedupe/DedupeFinderTest.php | 3 +- tests/phpunit/api/v3/ContactTest.php | 13 ++-- 5 files changed, 91 insertions(+), 75 deletions(-) diff --git a/CRM/Contact/BAO/Contact.php b/CRM/Contact/BAO/Contact.php index ff9301f1fd..e057dafd4a 100644 --- a/CRM/Contact/BAO/Contact.php +++ b/CRM/Contact/BAO/Contact.php @@ -3426,4 +3426,53 @@ LEFT JOIN civicrm_address add2 ON ( add1.master_id = add2.id ) return $clauses; } + /** + * Get any existing duplicate contacts based on the input parameters. + * + * @param array $input + * Input parameters to be matched. + * @param string $contactType + * @param string $rule + * - Supervised + * - Unsupervised + * @param $excludedContactIDs + * An array of ids not to be included in the results. + * @param bool $checkPermissions + * @param int $ruleGroupID + * ID of the rule group to be used if an override is desirable. + * + * @return array + */ + public static function getDuplicateContacts($input, $contactType, $rule = 'Unsupervised', $excludedContactIDs = array(), $checkPermissions = TRUE, $ruleGroupID = NULL) { + $dedupeParams = CRM_Dedupe_Finder::formatParams($input, $contactType); + $dedupeParams['check_permission'] = $checkPermissions; + $ids = CRM_Dedupe_Finder::dupesByParams($dedupeParams, $contactType, $rule, $excludedContactIDs, $ruleGroupID); + return $ids; + } + + /** + * Get the first duplicate contacts based on the input parameters. + * + * @param array $input + * Input parameters to be matched. + * @param string $contactType + * @param string $rule + * - Supervised + * - Unsupervised + * @param $excludedContactIDs + * An array of ids not to be included in the results. + * @param bool $checkPermissions + * @param int $ruleGroupID + * ID of the rule group to be used if an override is desirable. + * + * @return int|NULL + */ + public static function getFirstDuplicateContact($input, $contactType, $rule = 'Unsupervised', $excludedContactIDs = array(), $checkPermissions = TRUE, $ruleGroupID = NULL) { + $ids = self::getDuplicateContacts($input, $contactType, $rule, $excludedContactIDs, $checkPermissions, $ruleGroupID); + if (empty($ids)) { + return NULL; + } + return $ids[0]; + } + } diff --git a/api/v3/Contact.php b/api/v3/Contact.php index 773068f4bb..e09fc91ee1 100644 --- a/api/v3/Contact.php +++ b/api/v3/Contact.php @@ -55,8 +55,14 @@ function civicrm_api3_contact_create($params) { throw new \Civi\API\Exception\UnauthorizedException('Permission denied to modify contact record'); } - $dupeCheck = CRM_Utils_Array::value('dupe_check', $params, FALSE); - $values = _civicrm_api3_contact_check_params($params, $dupeCheck); + if (!empty($params['dupe_check'])) { + $ids = CRM_Contact_BAO_Contact::getDuplicateContacts($params, $params['contact_type'], 'Unsupervised', array(), $params['check_permission']); + if (count($ids) > 0) { + throw new API_Exception("Found matching contacts: " . implode(',', $ids), "duplicate", array("ids" => $ids)); + } + } + + $values = _civicrm_api3_contact_check_params($params); if ($values) { return $values; } @@ -455,13 +461,12 @@ function civicrm_api3_contact_delete($params) { * This function is on it's way out. * * @param array $params - * @param bool $dupeCheck * * @return null * @throws API_Exception * @throws CiviCRM_API3_Exception */ -function _civicrm_api3_contact_check_params(&$params, $dupeCheck) { +function _civicrm_api3_contact_check_params(&$params) { switch (strtolower(CRM_Utils_Array::value('contact_type', $params))) { case 'household': @@ -494,35 +499,13 @@ function _civicrm_api3_contact_check_params(&$params, $dupeCheck) { } } - if ($dupeCheck) { - // check for record already existing - $dedupeParams = CRM_Dedupe_Finder::formatParams($params, $params['contact_type']); - - // CRM-6431 - // setting 'check_permission' here means that the dedupe checking will be carried out even if the - // person does not have permission to carry out de-dupes - // this is similar to the front end form - if (isset($params['check_permission'])) { - $dedupeParams['check_permission'] = $params['check_permission']; - } - - $ids = CRM_Dedupe_Finder::dupesByParams($dedupeParams, $params['contact_type'], 'Unsupervised', array()); - - if (count($ids) > 0) { - throw new API_Exception("Found matching contacts: " . implode(',', $ids), "duplicate", array("ids" => $ids)); - } - } - // The BAO no longer supports the legacy param "current_employer" so here is a shim for api backward-compatability if (!empty($params['current_employer'])) { $organizationParams = array( 'organization_name' => $params['current_employer'], ); - $dedupParams = CRM_Dedupe_Finder::formatParams($organizationParams, 'Organization'); - - $dedupParams['check_permission'] = FALSE; - $dupeIds = CRM_Dedupe_Finder::dupesByParams($dedupParams, 'Organization', 'Supervised'); + $dupeIds = CRM_Contact_BAO_Contact::getDuplicateContacts($organizationParams, 'Organization', 'Supervised', array(), FALSE); // check for mismatch employer name and id if (!empty($params['employer_id']) && !in_array($params['employer_id'], $dupeIds)) { @@ -1104,11 +1087,10 @@ function _civicrm_api3_contact_deprecation() { * -int main_id: main contact id with whom merge has to happen * -int other_id: duplicate contact which would be deleted after merge operation * -string mode: "safe" skips the merge if there are no conflicts. Does a force merge otherwise. - * -boolean auto_flip: whether to let api decide which contact to retain and which to delete. * * @return array * API Result Array - * @throws CiviCRM_API3_Exception + * @throws API_Exception */ function civicrm_api3_contact_merge($params) { if (($result = CRM_Dedupe_Merger::merge(array( @@ -1119,7 +1101,7 @@ function civicrm_api3_contact_merge($params) { ), array(), $params['mode'])) != FALSE) { return civicrm_api3_create_success($result, $params); } - throw new CiviCRM_API3_Exception('Merge failed'); + throw new API_Exception('Merge failed'); } /** @@ -1333,17 +1315,14 @@ function _civicrm_api3_contact_getlist_output($result, $request) { * API formatted array */ function civicrm_api3_contact_duplicatecheck($params) { - $dedupeParams = CRM_Dedupe_Finder::formatParams($params['match'], $params['match']['contact_type']); - - // CRM-6431 - // setting 'check_permission' here means that the dedupe checking will be carried out even if the - // person does not have permission to carry out de-dupes - // this is similar to the front end form - if (isset($params['check_permission'])) { - $dedupeParams['check_permission'] = $params['check_permission']; - } - - $dupes = CRM_Dedupe_Finder::dupesByParams($dedupeParams, $params['match']['contact_type'], 'Unsupervised', array(), CRM_Utils_Array::value('dedupe_rule_id', $params)); + $dupes = CRM_Contact_BAO_Contact::getDuplicateContacts( + $params['match'], + $params['match']['contact_type'], + 'Unsupervised', + array(), + CRM_Utils_Array::value('check_permissions', $params), + CRM_Utils_Array::value('dedupe_rule_id', $params) + ); $values = empty($dupes) ? array() : array_fill_keys($dupes, array()); return civicrm_api3_create_success($values, $params, 'Contact', 'duplicatecheck'); } diff --git a/bin/ContributionProcessor.php b/bin/ContributionProcessor.php index 2481fb2304..5432bc045f 100644 --- a/bin/ContributionProcessor.php +++ b/bin/ContributionProcessor.php @@ -188,10 +188,15 @@ class CiviContributeProcessor { $params['transaction']['is_test'] = 0; } - if (self::processAPIContribution($params)) { - CRM_Core_Error::debug_log_message("Processed - {$trxnDetails['email']}, {$trxnDetails['amt']}, {$value} ..

", TRUE); + try { + if (self::processAPIContribution($params)) { + CRM_Core_Error::debug_log_message("Processed - {$trxnDetails['email']}, {$trxnDetails['amt']}, {$value} ..

", TRUE); + } + else { + CRM_Core_Error::debug_log_message("Skipped - {$trxnDetails['email']}, {$trxnDetails['amt']}, {$value} ..

", TRUE); + } } - else { + catch (CiviCRM_API3_Exception $e) { CRM_Core_Error::debug_log_message("Skipped - {$trxnDetails['email']}, {$trxnDetails['amt']}, {$value} ..

", TRUE); } } @@ -399,6 +404,10 @@ class CiviContributeProcessor { } /** + * @deprecated function. + * + * This function has probably been defunct for quite a long time. + * * @param array $params * * @return bool @@ -408,33 +417,16 @@ class CiviContributeProcessor { return FALSE; } - // add contact using dedupe rule - $dedupeParams = CRM_Dedupe_Finder::formatParams($params, 'Individual'); - $dedupeParams['check_permission'] = FALSE; - $dupeIds = CRM_Dedupe_Finder::dupesByParams($dedupeParams, 'Individual'); - // if we find more than one contact, use the first one - if (!empty($dupeIds[0])) { - $params['contact_id'] = $dupeIds[0]; - } - $contact = CRM_Contact_BAO_Contact::create($params); - if (!$contact->id) { - return FALSE; - } + $params['contact_id'] = CRM_Contact_BAO_Contact::getFirstDuplicateContact($params, 'Individual', 'Unsupervised', array(), FALSE); + + $contact = civicrm_api3('Contact', 'create', $params); // only pass transaction params to contribution::create, if available if (array_key_exists('transaction', $params)) { $params = $params['transaction']; - $params['contact_id'] = $contact->id; + $params['contact_id'] = $contact['id']; } - // handle contribution custom data - $customFields = CRM_Core_BAO_CustomField::getFields('Contribution', - FALSE, - FALSE, - CRM_Utils_Array::value('financial_type_id', - $params - ) - ); $params['custom'] = CRM_Core_BAO_CustomField::postProcess($params, CRM_Utils_Array::value('id', $params, NULL), 'Contribution' diff --git a/tests/phpunit/CRM/Dedupe/DedupeFinderTest.php b/tests/phpunit/CRM/Dedupe/DedupeFinderTest.php index 7bc6779599..417fb63f79 100644 --- a/tests/phpunit/CRM/Dedupe/DedupeFinderTest.php +++ b/tests/phpunit/CRM/Dedupe/DedupeFinderTest.php @@ -203,8 +203,7 @@ class CRM_Dedupe_DedupeFinderTest extends CiviUnitTestCase { 'street_address' => 'Ambachtstraat 23', ); CRM_Core_TemporaryErrorScope::useException(); - $dedupeParams = CRM_Dedupe_Finder::formatParams($fields, 'Individual'); - $ids = CRM_Dedupe_Finder::dupesByParams($dedupeParams, 'Individual', 'General'); + $ids = CRM_Contact_BAO_Contact::getDuplicateContacts($fields, 'Individual', 'General'); // Check with default Individual-General rule $this->assertEquals(count($ids), 2, 'Check Individual-General rule for dupesByParams().'); diff --git a/tests/phpunit/api/v3/ContactTest.php b/tests/phpunit/api/v3/ContactTest.php index e793746180..406d328fbb 100644 --- a/tests/phpunit/api/v3/ContactTest.php +++ b/tests/phpunit/api/v3/ContactTest.php @@ -2991,19 +2991,15 @@ class api_v3_ContactTest extends CiviUnitTestCase { * Test the duplicate check function. */ public function testDuplicateCheck() { - $this->callAPISuccess('Contact', 'create', array( + $harry = array( 'first_name' => 'Harry', 'last_name' => 'Potter', 'email' => 'harry@hogwarts.edu', 'contact_type' => 'Individual', - )); + ); + $this->callAPISuccess('Contact', 'create', $harry); $result = $this->callAPISuccess('Contact', 'duplicatecheck', array( - 'match' => array( - 'first_name' => 'Harry', - 'last_name' => 'Potter', - 'email' => 'harry@hogwarts.edu', - 'contact_type' => 'Individual', - ), + 'match' => $harry, )); $this->assertEquals(1, $result['count']); @@ -3016,6 +3012,7 @@ class api_v3_ContactTest extends CiviUnitTestCase { ), )); $this->assertEquals(0, $result['count']); + $this->callAPIFailure('Contact', 'create', array_merge($harry, array('dupe_check' => 1))); } public function testGetByContactType() { -- 2.25.1