From 0a680298f4284581b2fdc90e5c04c15ef9af6eed Mon Sep 17 00:00:00 2001 From: Eileen McNaughton Date: Tue, 23 Aug 2022 16:13:07 +1200 Subject: [PATCH] Switch Membership form to use Select two --- CRM/Import/Form/MapField.php | 45 +++++++++++++++++++++++++ CRM/Import/Forms.php | 23 ++++++++++++- CRM/Import/Parser.php | 15 ++++++++- CRM/Member/Import/Form/MapField.php | 21 +++--------- CRM/Member/Import/Parser/Membership.php | 12 +++++++ 5 files changed, 98 insertions(+), 18 deletions(-) diff --git a/CRM/Import/Form/MapField.php b/CRM/Import/Form/MapField.php index 35a61eff1d..71d606647a 100644 --- a/CRM/Import/Form/MapField.php +++ b/CRM/Import/Form/MapField.php @@ -456,4 +456,49 @@ abstract class CRM_Import_Form_MapField extends CRM_Import_Forms { return empty($errors) ? TRUE : $errors; } + /** + * This transforms the lists of fields for each contact type & component + * into a single unified list suitable for select2. + * + * @return array + */ + public function getFieldOptions(): array { + $fields = $this->getFields(); + $entity = $this->getBaseEntity(); + $categories = $this->getImportEntities(); + $highlightedFields = $this->getHighlightedFields(); + foreach ($fields as $fieldName => $field) { + if ($fieldName === '') { + // @todo stop setting 'do not import' in the first place. + continue; + } + if ($field['name'] === 'id' && $entity === $field['entity'] && !$this->isUpdateExisting()) { + continue; + } + $childField = [ + 'text' => $field['title'], + 'id' => $fieldName, + 'has_location' => !empty($field['hasLocationType']), + ]; + if (in_array($fieldName, $highlightedFields, TRUE)) { + $childField['text'] .= '*'; + } + $category = ($childField['has_location'] || $field['name'] === 'contact_id') ? 'Contact' : ($field['entity'] ?? $entity); + if (empty($categories[$category])) { + $category = $entity; + } + $categories[$category]['children'][$fieldName] = $childField; + } + + foreach ($categories as $index => $category) { + if (empty($category['children'])) { + unset($categories[$index]); + } + else { + $categories[$index]['children'] = array_values($category['children']); + } + } + return array_values($categories); + } + } diff --git a/CRM/Import/Forms.php b/CRM/Import/Forms.php index d9112f233e..83259b2766 100644 --- a/CRM/Import/Forms.php +++ b/CRM/Import/Forms.php @@ -601,6 +601,17 @@ class CRM_Import_Forms extends CRM_Core_Form { return $this->getParser()->getFieldsMetadata(); } + /** + * Get the fields available for import selection. + * + * @return array + * e.g ['first_name' => 'First Name', 'last_name' => 'Last Name'.... + * + */ + protected function getImportEntities(): array { + return $this->getParser()->getImportEntities(); + } + /** * Get an instance of the parser class. * @@ -631,7 +642,7 @@ class CRM_Import_Forms extends CRM_Core_Form { $mapper = []; $parser = $this->getParser(); foreach ($this->getSubmittedValue('mapper') as $columnNumber => $mappedField) { - $mapper[$columnNumber] = $parser->getMappedFieldLabel($parser->getMappingFieldFromMapperInput($mappedField, 0, $columnNumber)); + $mapper[$columnNumber] = $parser->getMappedFieldLabel($parser->getMappingFieldFromMapperInput((array) $mappedField, 0, $columnNumber)); } return $mapper; } @@ -713,4 +724,14 @@ class CRM_Import_Forms extends CRM_Core_Form { return (bool) $this->getRowCount(['new']); } + /** + * Get the base entity for the import. + * + * @return string + */ + protected function getBaseEntity(): string { + $info = $this->getParser()->getUserJobInfo(); + return reset($info)['entity']; + } + } diff --git a/CRM/Import/Parser.php b/CRM/Import/Parser.php index 02a7ce57c1..a7326203cf 100644 --- a/CRM/Import/Parser.php +++ b/CRM/Import/Parser.php @@ -1743,6 +1743,17 @@ abstract class CRM_Import_Parser implements UserJobInterface { return $this->importableFieldsMetadata; } + /** + * Get a list of entities this import supports. + * + * @return array + */ + public function getImportEntities() : array { + return [ + 'Contact' => ['text' => ts('Contact Fields'), 'is_contact' => TRUE], + ]; + } + /** * @param array $mappedField * Field detail as would be saved in field_mapping table @@ -1796,7 +1807,9 @@ abstract class CRM_Import_Parser implements UserJobInterface { $mappedFields = []; $mapper = $this->getSubmittedValue('mapper'); foreach ($mapper as $i => $mapperRow) { - $mappedField = $this->getMappingFieldFromMapperInput($mapperRow, 0, $i); + // Cast to an array as it will be a string for membership + // and any others we simplify away from using hierselect for a single option. + $mappedField = $this->getMappingFieldFromMapperInput((array) $mapperRow, 0, $i); // Just for clarity since 0 is a pseudo-value unset($mappedField['mapping_id']); $mappedFields[] = $mappedField; diff --git a/CRM/Member/Import/Form/MapField.php b/CRM/Member/Import/Form/MapField.php index 5c5d04e535..ba6145ee0e 100644 --- a/CRM/Member/Import/Form/MapField.php +++ b/CRM/Member/Import/Form/MapField.php @@ -29,20 +29,9 @@ class CRM_Member_Import_Form_MapField extends CRM_Import_Form_MapField { $this->buildSavedMappingFields($this->getSubmittedValue('savedMapping')); $this->addFormRule(array('CRM_Member_Import_Form_MapField', 'formRule'), $this); - //-------- end of saved mapping stuff --------- - - // For most fields using the html label is a good thing - // but for contact ID we really want to specify ID. - $this->_mapperFields['membership_contact_id'] = ts('Contact ID'); - $sel1 = $this->_mapperFields; - if (!$this->getSubmittedValue('onDuplicate')) { - // If not updating then do not allow membership id. - unset($sel1['membership_id']); - } - + $options = $this->getFieldOptions(); foreach ($this->getColumnHeaders() as $i => $columnHeader) { - $sel = &$this->addElement('hierselect', "mapper[$i]", ts('Mapper for Field %1', [1 => $i]), NULL); - $sel->setOptions([$sel1]); + $this->add('select2', "mapper[$i]", ts('Mapper for Field %1', [1 => $i]), $options, FALSE, ['class' => 'big', 'placeholder' => ts('- do not import -')]); } $this->assign('initHideBoxes'); @@ -68,7 +57,7 @@ class CRM_Member_Import_Form_MapField extends CRM_Import_Form_MapField { $importKeys = []; foreach ($fields['mapper'] as $mapperPart) { - $importKeys[] = $mapperPart[0]; + $importKeys[] = $mapperPart; } // FIXME: should use the schema titles, not redeclare them $requiredFields = array( @@ -226,11 +215,11 @@ class CRM_Member_Import_Form_MapField extends CRM_Import_Form_MapField { if ($this->getSubmittedValue('savedMapping')) { $fieldMapping = $fieldMappings[$i] ?? NULL; if (isset($fieldMappings[$i])) { - $defaults["mapper[$i]"] = ($fieldMapping['name'] !== 'do_not_import') ? [$fieldMapping['name']] : []; + $defaults["mapper[$i]"] = ($fieldMapping['name'] !== 'do_not_import') ? $fieldMapping['name'] : NULL; } } if (!isset($defaults["mapper[$i]"]) && $this->getSubmittedValue('skipColumnHeader')) { - $defaults["mapper[$i]"] = [$this->defaultFromHeader($columnHeader, $headerPatterns)]; + $defaults["mapper[$i]"] = $this->defaultFromHeader($columnHeader, $headerPatterns); } } return $defaults; diff --git a/CRM/Member/Import/Parser/Membership.php b/CRM/Member/Import/Parser/Membership.php index 6ee7ce8076..bdd66664c5 100644 --- a/CRM/Member/Import/Parser/Membership.php +++ b/CRM/Member/Import/Parser/Membership.php @@ -75,6 +75,18 @@ class CRM_Member_Import_Parser_Membership extends CRM_Import_Parser { ]; } + /** + * Get a list of entities this import supports. + * + * @return array + */ + public function getImportEntities() : array { + return [ + 'Membership' => ['text' => ts('Membership Fields'), 'is_contact' => FALSE], + 'Contact' => ['text' => ts('Contact Fields'), 'is_contact' => TRUE], + ]; + } + /** * Validate the values. * -- 2.25.1