Skip to content

Commit

Permalink
[Ref] [Import] move metadata calculations to a trait
Browse files Browse the repository at this point in the history
A lot of the complexity of the import classes comes from complex & convoluted handling of metadata.

For reasons now obsolete the metadata is loaded & wrangled into various arrays on the first form and
then passed through storing the form in the session object to later forms (which don't have a shared parent).

We should be passing user form input around but not metadata as that can be retrieved as needed (and
cached for performance). This moves  couple of functions out to the metadata and adds a couple of calls to them
- more could be done but it would be hard going. Am also open to breaking this into more steps per
reviewer preference
  • Loading branch information
eileenmcnaughton committed Aug 12, 2019
1 parent c67a47b commit dae8945
Show file tree
Hide file tree
Showing 5 changed files with 83 additions and 40 deletions.
2 changes: 1 addition & 1 deletion CRM/Contact/BAO/Relationship.php
Original file line number Diff line number Diff line change
Expand Up @@ -537,7 +537,7 @@ public static function dataExists(&$params) {
* related relationship types get return
*
* @return array
* array reference of all relationship types with context to current contact.
* Array of all relationship types with context to current contact.
*/
public static function getContactRelationshipType(
$contactId = NULL,
Expand Down
23 changes: 9 additions & 14 deletions CRM/Contact/Import/Form/MapField.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
*/
class CRM_Contact_Import_Form_MapField extends CRM_Import_Form_MapField {


use CRM_Contact_Import_MetadataTrait;
/**
* An array of all contact fields with
* formatted custom field names.
Expand All @@ -62,20 +62,19 @@ class CRM_Contact_Import_Form_MapField extends CRM_Import_Form_MapField {
* FIXME: This is essentially the same function as parent::defaultFromHeader
*
* @param string $columnName name of column header
* @param array $patterns pattern to match for the column
*
* @return string
*/
public function defaultFromColumnName($columnName, $patterns) {
public function defaultFromColumnName($columnName) {

if (!preg_match('/^[a-z0-9 ]$/i', $columnName)) {
if ($columnKey = array_search($columnName, $this->_mapperFields)) {
if ($columnKey = array_search($columnName, $this->getFieldTitles())) {
$this->_fieldUsed[$columnKey] = TRUE;
return $columnKey;
}
}

foreach ($patterns as $key => $re) {
foreach ($this->getDataPatterns() as $key => $re) {
// Skip empty key/patterns
if (!$key || !$re || strlen("$re") < 5) {
continue;
Expand All @@ -95,7 +94,7 @@ public function defaultFromColumnName($columnName, $patterns) {
public function preProcess() {
$dataSource = $this->get('dataSource');
$skipColumnHeader = $this->get('skipColumnHeader');
$this->_mapperFields = $this->get('fields');
$this->_mapperFields = $this->getFieldTitles();
$this->_importTableName = $this->get('importTableName');
$this->_onDuplicate = $this->get('onDuplicate');
$highlightedFields = [];
Expand Down Expand Up @@ -241,7 +240,6 @@ public function buildQuickForm() {
$defaults = [];
$mapperKeys = array_keys($this->_mapperFields);
$hasColumnNames = !empty($this->_columnNames);
$columnPatterns = $this->get('columnPatterns');
$dataPatterns = $this->get('dataPatterns');
$hasLocationTypes = $this->get('fieldTypes');

Expand Down Expand Up @@ -400,7 +398,7 @@ public function buildQuickForm() {
$sel = &$this->addElement('hierselect', "mapper[$i]", ts('Mapper for Field %1', [1 => $i]), NULL);

if ($this->get('savedMapping')) {
list($mappingName, $defaults, $js) = $this->loadSavedMapping($mappingName, $i, $mappingRelation, $mappingWebsiteType, $mappingLocation, $mappingPhoneType, $mappingImProvider, $defaults, $formName, $js, $hasColumnNames, $dataPatterns, $columnPatterns);
list($mappingName, $defaults, $js) = $this->loadSavedMapping($mappingName, $i, $mappingRelation, $mappingWebsiteType, $mappingLocation, $mappingPhoneType, $mappingImProvider, $defaults, $formName, $js, $hasColumnNames, $dataPatterns);
}
else {
$js .= "swapOptions($formName, 'mapper[$i]', 0, 3, 'hs_mapper_0_');\n";
Expand All @@ -415,9 +413,7 @@ public function buildQuickForm() {
else {
// Infer the default from the column names if we have them
$defaults["mapper[$i]"] = [
$this->defaultFromColumnName($this->_columnNames[$i],
$columnPatterns
),
$this->defaultFromColumnName($this->_columnNames[$i]),
0,
];
}
Expand Down Expand Up @@ -861,11 +857,10 @@ protected function saveMappingField($mapperKeys, array $saveMapping, string $cTy
* @param string $js
* @param bool $hasColumnNames
* @param array $dataPatterns
* @param array $columnPatterns
*
* @return array
*/
protected function loadSavedMapping($mappingName, $i, $mappingRelation, $mappingWebsiteType, $mappingLocation, $mappingPhoneType, $mappingImProvider, $defaults, $formName, $js, $hasColumnNames, $dataPatterns, $columnPatterns) {
protected function loadSavedMapping($mappingName, $i, $mappingRelation, $mappingWebsiteType, $mappingLocation, $mappingPhoneType, $mappingImProvider, $defaults, $formName, $js, $hasColumnNames, $dataPatterns) {
$jsSet = FALSE;
if (isset($mappingName[$i])) {
if ($mappingName[$i] != ts('- do not import -')) {
Expand Down Expand Up @@ -995,7 +990,7 @@ protected function loadSavedMapping($mappingName, $i, $mappingRelation, $mapping
$js .= "swapOptions($formName, 'mapper[$i]', 0, 3, 'hs_mapper_0_');\n";

if ($hasColumnNames) {
$defaults["mapper[$i]"] = [$this->defaultFromColumnName($this->_columnNames[$i], $columnPatterns)];
$defaults["mapper[$i]"] = [$this->defaultFromColumnName($this->_columnNames[$i])];
}
else {
$defaults["mapper[$i]"] = [$this->defaultFromData($dataPatterns, $i)];
Expand Down
84 changes: 72 additions & 12 deletions CRM/Contact/Import/MetadataTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,20 @@ trait CRM_Contact_Import_MetadataTrait {
* @return array
*/
protected function getContactImportMetadata(): array {
$contactFields = CRM_Contact_BAO_Contact::importableFields($this->_contactType);
$cacheKey = 'importable_contact_field_metadata' . $this->getContactType() . $this->getContactSubType();
if (Civi::cache('fields')->has($cacheKey)) {
return Civi::cache('fields')->get($cacheKey);
}
$contactFields = CRM_Contact_BAO_Contact::importableFields($this->getContactType());
// exclude the address options disabled in the Address Settings
$fields = CRM_Core_BAO_Address::validateAddressOptions($contactFields);

//CRM-5125
//supporting import for contact subtypes
$csType = NULL;
if (!empty($this->_contactSubType)) {
if ($this->getContactSubType()) {
//custom fields for sub type
$subTypeFields = CRM_Core_BAO_CustomField::getFieldsForImport($this->_contactSubType);
$subTypeFields = CRM_Core_BAO_CustomField::getFieldsForImport($this->getContactSubType());

if (!empty($subTypeFields)) {
foreach ($subTypeFields as $customSubTypeField => $details) {
Expand All @@ -32,15 +36,7 @@ protected function getContactImportMetadata(): array {
}
}

//Relationship importables
$this->_relationships = $relations
= CRM_Contact_BAO_Relationship::getContactRelationshipType(
NULL, NULL, NULL, $this->_contactType,
FALSE, 'label', TRUE, $this->_contactSubType
);
asort($relations);

foreach ($relations as $key => $var) {
foreach ($this->getRelationships() as $key => $var) {
list($type) = explode('_', $key);
$relationshipType[$key]['title'] = $var;
$relationshipType[$key]['headerPattern'] = '/' . preg_quote($var, '/') . '/';
Expand All @@ -56,7 +52,71 @@ protected function getContactImportMetadata(): array {
],
], $relationshipType);
}
Civi::cache('fields')->set($cacheKey, $fields);
return $fields;
}

/**
* Get sorted available relationships.
*
* @return array
*/
protected function getRelationships(): array {
$cacheKey = 'importable_contact_relationship_field_metadata' . $this->getContactType() . $this->getContactSubType();
if (Civi::cache('fields')->has($cacheKey)) {
return Civi::cache('fields')->get($cacheKey);
}
//Relationship importables
$relations = CRM_Contact_BAO_Relationship::getContactRelationshipType(
NULL, NULL, NULL, $this->getContactType(),
FALSE, 'label', TRUE, $this->getContactSubType()
);
asort($relations);
Civi::cache('fields')->set($cacheKey, $relations);
return $relations;
}

/**
* Get an array of header patterns for importable keys.
*
* @return array
*/
public function getHeaderPatterns() {
return CRM_Utils_Array::collect('headerPattern', $this->getContactImportMetadata());
}

/**
* Get an array of header patterns for importable keys.
*
* @return array
*/
public function getDataPatterns() {
return CRM_Utils_Array::collect('dataPattern', $this->getContactImportMetadata());
}

/**
* Get an array of header patterns for importable keys.
*
* @return array
*/
public function getFieldTitles() {
return CRM_Utils_Array::collect('title', $this->getContactImportMetadata());
}

/**
* Get configured contact type.
*/
protected function getContactType() {
return $this->_contactType ?? 'Individual';
}

/**
* Get configured contact sub type.
*
* @return string
*/
protected function getContactSubType() {
return $this->_contactSubType ?? NULL;
}

}
12 changes: 0 additions & 12 deletions CRM/Contact/Import/Parser.php
Original file line number Diff line number Diff line change
Expand Up @@ -574,17 +574,6 @@ public function &getActiveFieldParams() {
return $params;
}

/**
* @return array
*/
public function getColumnPatterns() {
$values = [];
foreach ($this->_fields as $name => $field) {
$values[$name] = $field->_columnPattern;
}
return $values;
}

/**
* @param string $name
* @param $title
Expand Down Expand Up @@ -616,7 +605,6 @@ public function set($store, $mode = self::MODE_SUMMARY) {
$store->set('fields', $this->getSelectValues());
$store->set('fieldTypes', $this->getSelectTypes());

$store->set('columnPatterns', $this->getColumnPatterns());
$store->set('dataPatterns', $this->getDataPatterns());
$store->set('columnCount', $this->_activeFieldCount);

Expand Down
2 changes: 1 addition & 1 deletion CRM/Contact/Import/Parser/Contact.php
Original file line number Diff line number Diff line change
Expand Up @@ -388,7 +388,7 @@ public function summary(&$values) {
}

//checking error in custom data
$this->isErrorInCustomData($params, $errorMessage, $csType, $this->_relationships);
$this->isErrorInCustomData($params, $errorMessage, $csType, $this->getRelationships());

//checking error in core data
$this->isErrorInCoreData($params, $errorMessage);
Expand Down

0 comments on commit dae8945

Please sign in to comment.