Skip to content

Commit

Permalink
[Import] Apply the same contact validation to related contacts as the…
Browse files Browse the repository at this point in the history
… main contact
  • Loading branch information
eileenmcnaughton committed May 13, 2022
1 parent 7e56b83 commit 7d2012d
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 74 deletions.
108 changes: 40 additions & 68 deletions CRM/Contact/Import/Parser/Contact.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,6 @@ class CRM_Contact_Import_Parser_Contact extends CRM_Import_Parser {
use CRM_Contact_Import_MetadataTrait;

protected $_mapperKeys = [];
protected $_mapperRelated;
protected $_mapperRelatedContactDetails;
protected $_relationships;

/**
Expand Down Expand Up @@ -112,19 +110,10 @@ class CRM_Contact_Import_Parser_Contact extends CRM_Import_Parser {
* Class constructor.
*
* @param array $mapperKeys
* @param array $mapperLocType
* @param array $mapperPhoneType
* @param array $mapperImProvider
* @param array $mapperRelated
* @param array $mapperRelatedContactType
* @param array $mapperRelatedContactDetails
*/
public function __construct(
$mapperKeys = [], $mapperLocType = [], $mapperPhoneType = [], $mapperImProvider = [], $mapperRelated = [], $mapperRelatedContactType = [], $mapperRelatedContactDetails = []) {
public function __construct($mapperKeys = []) {
parent::__construct();
$this->_mapperKeys = $mapperKeys;
$this->_mapperRelated = &$mapperRelated;
$this->_mapperRelatedContactDetails = &$mapperRelatedContactDetails;
}

/**
Expand Down Expand Up @@ -644,15 +633,6 @@ public function import($onDuplicate, &$values) {
//format common data, CRM-4062
$this->formatCommonData($field, $formatting, $contactFields);

//do we have enough fields to create related contact.
$allowToCreate = $this->checkRelatedContactFields($key, $formatting);

if (!$allowToCreate) {
$errorMessage = ts('Related contact required fields are missing.');
array_unshift($values, $errorMessage);
return CRM_Import_Parser::NO_MATCH;
}

//fixed for CRM-4148
if (!empty($params[$key]['id'])) {
$contact = [
Expand Down Expand Up @@ -1929,50 +1909,6 @@ public function processMessage(&$values, $statusFieldName, $returnCode) {
return $returnCode;
}

/**
* @param $relKey
* @param array $params
*
* @return bool
*/
public function checkRelatedContactFields($relKey, $params) {
//avoid blank contact creation.
$allowToCreate = FALSE;

//build the mapper field array.
static $relatedContactFields = [];
if (!isset($relatedContactFields[$relKey])) {
foreach ($this->_mapperRelated as $key => $name) {
if (!$name) {
continue;
}

if (!empty($relatedContactFields[$name]) && !is_array($relatedContactFields[$name])) {
$relatedContactFields[$name] = [];
}
$fldName = $this->_mapperRelatedContactDetails[$key] ?? NULL;
if ($fldName == 'url') {
$fldName = 'website';
}
if ($fldName) {
$relatedContactFields[$name][] = $fldName;
}
}
}

//validate for passed data.
if (is_array($relatedContactFields[$relKey])) {
foreach ($relatedContactFields[$relKey] as $fld) {
if (!empty($params[$fld])) {
$allowToCreate = TRUE;
break;
}
}
}

return $allowToCreate;
}

/**
* get subtypes given the contact type
*
Expand Down Expand Up @@ -3091,6 +3027,15 @@ public function getMappedRow(array $values): array {
public function validateValues(array $values): void {
$params = $this->getMappedRow($values);
$this->validateRequiredContactFields($params['contact_type'], $params, $this->isUpdateExistingContacts());
foreach ($params as $key => $value) {
// If the key is a relationship key - eg. 5_a_b or 10_b_a
// then the value is an array that describes an existing contact.
// We need to check the fields are present to identify or create this
// contact.
if (preg_match('/^\d+_[a|b]_[a|b]$/', $key)) {
$this->validateRequiredContactFields($value['contact_type'], $value, TRUE, '(' . $this->getRelatedContactLabel(substr($key, 0, -4), substr($key, -3)) . ')');
}
}

//check for duplicate external Identifier
$externalID = $params['external_identifier'] ?? NULL;
Expand Down Expand Up @@ -3164,12 +3109,39 @@ protected function getRelatedContactType($relationshipTypeID, $relationshipDirec
if (!$relationshipTypeID) {
return NULL;
}
$cacheKey = $relationshipTypeID . $relationshipDirection;
$relationshipField = 'contact_type_' . substr($relationshipDirection, -1);
return $this->getRelationshipType($relationshipTypeID, $relationshipDirection)[$relationshipField];
}

/**
* Get the related contact type.
*
* @param int|null $relationshipTypeID
* @param int|string $relationshipDirection
*
* @return null|string
*
* @throws \API_Exception
*/
protected function getRelatedContactLabel($relationshipTypeID, $relationshipDirection): ?string {
$relationshipField = 'label_' . $relationshipDirection;
return $this->getRelationshipType($relationshipTypeID, $relationshipDirection)[$relationshipField];
}

/**
* Get the relationship type.
*
* @param int $relationshipTypeID
*
* @return string[]
* @throws \API_Exception
*/
protected function getRelationshipType(int $relationshipTypeID): array {
$cacheKey = 'relationship_type' . $relationshipTypeID;
if (!isset(Civi::$statics[__CLASS__][$cacheKey])) {
$relationshipField = 'contact_type_' . substr($relationshipDirection, -1);
Civi::$statics[__CLASS__][$cacheKey] = RelationshipType::get(FALSE)
->addWhere('id', '=', $relationshipTypeID)
->addSelect($relationshipField)->execute()->first()[$relationshipField];
->addSelect('*')->execute()->first();
}
return Civi::$statics[__CLASS__][$cacheKey];
}
Expand Down
17 changes: 11 additions & 6 deletions CRM/Import/Parser.php
Original file line number Diff line number Diff line change
Expand Up @@ -512,11 +512,16 @@ public function setMaxLinesToProcess($max) {
* @param string $contactType
* @param array $params
* @param bool $isPermitExistingMatchFields
* True if the it is enough to have fields which will enable us to find
* an existing contact (eg. external_identifier).
* @param string $prefixString
* String to include in the exception (e.g '(Child of)' if we are validating
* a related contact.
*
* @return void
* @throws \CRM_Core_Exception
*/
protected function validateRequiredContactFields(string $contactType, array $params, bool $isPermitExistingMatchFields = TRUE): void {
protected function validateRequiredContactFields(string $contactType, array $params, bool $isPermitExistingMatchFields = TRUE, $prefixString = ''): void {
if (!empty($params['id'])) {
return;
}
Expand All @@ -536,7 +541,7 @@ protected function validateRequiredContactFields(string $contactType, array $par
// specified dedupe rule (or the default Unsupervised if not specified).
$requiredFields['email'] = ts('Email Address');
}
$this->validateRequiredFields($requiredFields, $params);
$this->validateRequiredFields($requiredFields, $params, $prefixString);
}

/**
Expand Down Expand Up @@ -1127,11 +1132,11 @@ protected function getIdsOfMatchingContacts(array $formatted):array {
* ['first_name' => ts('First Name'), 'last_name' => ts('Last Name')]
* ]
* Means 'email' OR 'first_name AND 'last_name'.
* @param string $prefixString
*
* @throws \CRM_Core_Exception
* Exception thrown if field requirements are not met.
* @throws \CRM_Core_Exception Exception thrown if field requirements are not met.
*/
protected function validateRequiredFields(array $requiredFields, array $params): void {
protected function validateRequiredFields(array $requiredFields, array $params, $prefixString): void {
$missingFields = [];
foreach ($requiredFields as $key => $required) {
if (!is_array($required)) {
Expand Down Expand Up @@ -1163,7 +1168,7 @@ protected function validateRequiredFields(array $requiredFields, array $params):
$missingFields[$key] = implode(' ' . ts('and') . ' ', $missing);
}
}
throw new CRM_Core_Exception(ts('Missing required fields:') . ' ' . implode(' ' . ts('OR') . ' ', $missingFields));
throw new CRM_Core_Exception(($prefixString ? ($prefixString . ' ') : '') . ts('Missing required fields:') . ' ' . implode(' ' . ts('OR') . ' ', $missingFields));
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Player First Name,Player Last name,Mother – phone
Susie,Jones,911
10 changes: 10 additions & 0 deletions tests/phpunit/CRM/Contact/Import/Parser/ContactTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -755,6 +755,16 @@ public function validateDataProvider(): array {
'mapper' => [['last_name']],
'expected_error' => 'Missing required fields: First Name OR Email Address',
],
'individual_related_required_met' => [
'csv' => 'individual_valid_with_related_email.csv',
'mapper' => [['first_name'], ['last_name'], ['1_a_b', 'email']],
'expected_error' => '',
],
'individual_related_required_not_met' => [
'csv' => 'individual_invalid_with_related_phone.csv',
'mapper' => [['first_name'], ['last_name'], ['1_a_b', 'phone', 1, 2]],
'expected_error' => '(Child of) Missing required fields: First Name and Last Name OR Email Address OR External Identifier',
],
'individual_bad_email' => [
'csv' => 'individual_invalid_email.csv',
'mapper' => [['email', 1], ['first_name'], ['last_name']],
Expand Down

0 comments on commit 7d2012d

Please sign in to comment.