if ($cid = CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_Contact', $params['external_identifier'], 'id', 'external_identifier')) {
$formatted['id'] = $cid;
}
+ else {
+ // CRM-17275 - External identifier is treated as a special field/
+ // Having it set will inhibit various efforts to retrieve a duplicate
+ // However, it is valid to update a contact with no external identifier to having
+ // an external identifier if they match according to the dedupe rules so
+ // we check for that possibility here.
+ // There is probably a better approach but this fix is the FIRST (!#!) time
+ /// unit tests have been added to this & we need to build those up a bit before
+ // doing much else in here. Remember when you have build a house of card the
+ // golden rule ... walk away ... carefully.
+ // (did I mention unit tests...)
+ $checkParams = array('check_permissions' => FALSE, 'match' => $params);
+ unset($checkParams['match']['external_identifier']);
+ $checkParams['match']['contact_type'] = $this->_contactType;
+ $possibleMatches = civicrm_api3('Contact', 'duplicatecheck', $checkParams);
+ foreach (array_keys($possibleMatches['values']) as $possibleID) {
+ if (!CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_Contact', $possibleID, 'external_identifier', 'id')) {
+ $formatted['id'] = $cid = $possibleID;
+ }
+ }
+ }
}
//format common data, CRM-4062
}
if ($dupeCheck) {
+ // @todo switch to using api version by uncommenting these lines & removing following 11.
+ // Any change here is too scary for a stable release.
+ // $dupes = civicrm_api3('Contact', 'duplicatecheck', (array('match' => $params, 'dedupe_rule_id' => $dedupeRuleGroupID)));
+ // $ids = $dupes['count'] ? implode(',', array_keys($dupes['values'])) : NULL;
// check for record already existing
require_once 'CRM/Dedupe/Finder.php';
$dedupeParams = CRM_Dedupe_Finder::formatParams($params, $params['contact_type']);
}
return $output;
}
+
+/**
+ * Check for duplicate contacts.
+ *
+ * @param array $params
+ * Params per getfields metadata.
+ *
+ * @return array
+ * 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));
+ $values = empty($dupes) ? array() : array_fill_keys($dupes, array());
+ return civicrm_api3_create_success($values, $params, 'Contact', 'duplicatecheck');
+}
+
+/**
+ * Declare metadata for contact dedupe function.
+ *
+ * @param $params
+ */
+function _civicrm_api3_contact_duplicatecheck_spec(&$params) {
+ $params['dedupe_rule_id'] = array(
+ 'title' => 'Dedupe Rule ID (optional)',
+ 'description' => 'This will default to the built in unsupervised rule',
+ 'type' => CRM_Utils_Type::T_INT,
+ );
+ // @todo declare 'match' parameter. We don't have a standard for type = array yet.
+}
$this->callAPISuccessGetSingle('Contact', $originalValues);
}
+ /**
+ * Test that the import parser updates when a new external identifier is set.
+ *
+ * @throws \Exception
+ */
+ public function testImportParserWithUpdateWithNewExternalIdentifier() {
+ $originalValues = array(
+ 'first_name' => 'Bill',
+ 'last_name' => 'Gates',
+ 'email' => 'bill.gates@microsoft.com',
+ 'nick_name' => 'Billy-boy',
+ );
+ $this->runImport($originalValues, CRM_Import_Parser::DUPLICATE_UPDATE, CRM_Import_Parser::VALID);
+ $result = $this->callAPISuccessGetSingle('Contact', $originalValues);
+ $originalValues['nick_name'] = 'Old Bill';
+ $originalValues['external_identifier'] = 'windows';
+ $this->runImport($originalValues, CRM_Import_Parser::DUPLICATE_UPDATE, CRM_Import_Parser::VALID);
+ $originalValues['id'] = $result['id'];
+ $this->assertEquals('Old Bill', $this->callAPISuccessGetValue('Contact', array('id' => $result['id'], 'return' => 'nick_name')));
+ $this->callAPISuccessGetSingle('Contact', $originalValues);
+ }
+
/**
* Run the import parser.
*