Skip to content

Commit

Permalink
Handle error when creating related contact
Browse files Browse the repository at this point in the history
This addresses the e-notice identified here
#23643 (comment)

I believe the bug report in that thread was a variant of the e-notice. Ie the import()
function was failing to catch an exception & it was bubbling up to run()

While there is no support currently for calling import()
outside of run() - the intent is to replace run() with something
more sane - which WILL be callable from the outside (likely
via api).

The right behaviour for import() is to catch all errors
  • Loading branch information
eileenmcnaughton committed Jun 2, 2022
1 parent 4bd5bf7 commit 9bd3911
Show file tree
Hide file tree
Showing 3 changed files with 15 additions and 67 deletions.
2 changes: 1 addition & 1 deletion CRM/Contact/BAO/Contact.php
Original file line number Diff line number Diff line change
Expand Up @@ -799,7 +799,7 @@ public static function resolveDefaults(&$defaults, $reverse = FALSE) {
*
* @return CRM_Contact_BAO_Contact
*/
public static function &retrieve(&$params, &$defaults, $microformat = FALSE) {
public static function &retrieve(&$params, &$defaults = [], $microformat = FALSE) {
if (array_key_exists('contact_id', $params)) {
$params['id'] = $params['contact_id'];
}
Expand Down
70 changes: 7 additions & 63 deletions CRM/Contact/Import/Parser/Contact.php
Original file line number Diff line number Diff line change
Expand Up @@ -400,77 +400,21 @@ public function import($onDuplicate, &$values) {
//format common data, CRM-4062
$this->formatCommonData($field, $formatting, $contactFields);

//fixed for CRM-4148
if (!empty($formatting['id'])) {
$contact = [
'contact_id' => $formatting['id'],
];
$defaults = [];
$relatedNewContact = CRM_Contact_BAO_Contact::retrieve($contact, $defaults);
}
else {
$relatedNewContact = $this->createContact($formatting, $contactFields, $onDuplicate, NULL, FALSE);
}

if (is_object($relatedNewContact) || ($relatedNewContact instanceof CRM_Contact_BAO_Contact)) {
$relatedNewContact = clone($relatedNewContact);
}

$matchedIDs = [];
// To update/fill contact, get the matching contact Ids if duplicate contact found
// otherwise get contact Id from object of related contact
if (is_array($relatedNewContact)) {
$matchedIDs = $relatedNewContact;
}
else {
$matchedIDs[] = $relatedNewContact->id;
}
// update/fill related contact after getting matching Contact Ids, CRM-4424
if (in_array($onDuplicate, [
CRM_Import_Parser::DUPLICATE_UPDATE,
CRM_Import_Parser::DUPLICATE_FILL,
])) {
//validation of related contact subtype for update mode
//CRM-5125
$relatedCsType = NULL;
if (!empty($formatting['contact_sub_type'])) {
$relatedCsType = CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_Contact', $matchedIDs[0], 'contact_sub_type');
if (empty($formatting['id']) || $this->isUpdateExistingContacts()) {
try {
$relatedNewContact = $this->createContact($formatting, $contactFields, $onDuplicate, $formatting['id']);
}

if (!empty($relatedCsType) && (!CRM_Contact_BAO_ContactType::isAllowEdit($matchedIDs[0], $relatedCsType) && $relatedCsType != CRM_Utils_Array::value('contact_sub_type', $formatting))) {
$this->setImportStatus((int) $values[count($values) - 1], 'invalid_no_match', 'Mismatched or Invalid contact subtype found for this related contact.');
catch (CiviCRM_API3_Exception $e) {
$this->setImportStatus($rowNumber, 'ERROR', $e->getMessage());
return FALSE;
}
else {
$this->createContact($formatting, $contactFields, $onDuplicate, $matchedIDs[0]);
}
}
static $relativeContact = [];
if (is_array($relatedNewContact)) {
if (count($matchedIDs) >= 1) {
$relContactId = $matchedIDs[0];
//add relative contact to count during update & fill mode.
//logic to make count distinct by contact id.
if ($this->_newRelatedContacts || !empty($relativeContact)) {
$reContact = array_keys($relativeContact, $relContactId);

if (empty($reContact)) {
$this->_newRelatedContacts[] = $relativeContact[] = $relContactId;
}
}
else {
$this->_newRelatedContacts[] = $relativeContact[] = $relContactId;
}
}
}
else {
$relContactId = $relatedNewContact->id;
$this->_newRelatedContacts[] = $relativeContact[] = $relContactId;
$this->_newRelatedContacts[$relContactId] = $relContactId;
}

if (1) {
//fix for CRM-1993.Checks for duplicate related contacts
if (count($matchedIDs) >= 1) {
if (1) {
//if more than one duplicate contact
//found, create relationship with first contact
// now create the relationship record
Expand Down
10 changes: 7 additions & 3 deletions tests/phpunit/CRM/Contact/Import/Parser/ContactTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2111,16 +2111,20 @@ public function getImportedContacts(): array {
/**
* Test that import parser will not throw error if Related Contact is not found via passed in External ID.
*
* If the organization is present it will create it - otherwise fail without error.
*
* @dataProvider getBooleanDataProvider
*
* @throws \API_Exception
* @throws \CRM_Core_Exception
* @throws \CiviCRM_API3_Exception
*/
public function testImportParserWithExternalIdForRelationship(): void {
public function testImportParserWithExternalIdForRelationship(bool $isOrganizationProvided): void {
$contactImportValues = [
'first_name' => 'Alok',
'last_name' => 'Patel',
'Employee of' => 'related external identifier',
'organization_name' => 'Big shop',
'organization_name' => $isOrganizationProvided ? 'Big shop' : '',
];

$mapper = [
Expand All @@ -2140,7 +2144,7 @@ public function testImportParserWithExternalIdForRelationship(): void {
$parser->init();

$parser->import(CRM_Import_Parser::DUPLICATE_UPDATE, $values);
$this->callAPISuccessGetCount('Contact', ['organization_name' => 'Big shop'], 2);
$this->callAPISuccessGetCount('Contact', ['organization_name' => 'Big shop'], $isOrganizationProvided ? 2 : 0);
}

}

0 comments on commit 9bd3911

Please sign in to comment.