From 9690742769ae7a4bb28b9b885457b01614d85eee Mon Sep 17 00:00:00 2001 From: Eileen McNaughton Date: Sat, 23 Apr 2022 08:02:42 +1200 Subject: [PATCH] Upgrade saved import names for contacts style --- CRM/Import/ImportProcessor.php | 55 +++++ CRM/Upgrade/Incremental/php/FiveFifty.php | 24 +++ .../CRM/Contact/Import/Form/MapFieldTest.php | 202 +++++++++++------- 3 files changed, 208 insertions(+), 73 deletions(-) diff --git a/CRM/Import/ImportProcessor.php b/CRM/Import/ImportProcessor.php index 52357e2899..12b38d6b53 100644 --- a/CRM/Import/ImportProcessor.php +++ b/CRM/Import/ImportProcessor.php @@ -1,5 +1,8 @@ $this->getMappingID(), + 'options' => ['limit' => 0], + ])['values']; + foreach ($fields as $index => $field) { + $fieldSpec = $this->getMetadata()[$fields[$index]['name']]; + $fields[$index]['label'] = $fieldSpec['title']; + if (empty($field['location_type_id']) && !empty($fieldSpec['hasLocationType'])) { + $fields[$index]['location_type_id'] = 'Primary'; + } + } + $this->mappingFields = $this->rekeyBySortedColumnNumbers($fields); + } + + /** + * Load the mapping from the database into the pre-5.50 format. + * + * This is preserved as a copy the upgrade script can use - since the + * upgrade allows the other to be 'fixed'. + * + * @throws \CiviCRM_API3_Exception + */ + protected function legacyLoadSavedMapping() { $fields = civicrm_api3('MappingField', 'get', [ 'mapping_id' => $this->getMappingID(), 'options' => ['limit' => 0], @@ -589,4 +615,33 @@ class CRM_Import_ImportProcessor { return [(string) $this->getFieldName($column), $this->getLocationTypeID($column), $this->getPhoneOrIMTypeID($column)]; } + /** + * This exists for use in the FiveFifty Upgrade + * + * @throws \API_Exception|\CiviCRM_API3_Exception + */ + public static function convertSavedFields(): void { + $mappings = Mapping::get(FALSE) + ->setSelect(['id', 'contact_type']) + ->addWhere('mapping_type_id:name', '=', 'Import Contact') + ->execute(); + + foreach ($mappings as $mapping) { + $processor = new CRM_Import_ImportProcessor(); + $processor->setMappingID($mapping['id']); + $processor->setMetadata(CRM_Contact_BAO_Contact::importableFields('All')); + $processor->legacyLoadSavedMapping();; + foreach ($processor->getMappingFields() as $field) { + // The if is mostly precautionary against running this more than once + // - which is common in dev if not live... + if ($field['name']) { + MappingField::update(FALSE) + ->setValues(['name' => $field['name']]) + ->addWhere('id', '=', $field['id']) + ->execute(); + } + } + } + } + } diff --git a/CRM/Upgrade/Incremental/php/FiveFifty.php b/CRM/Upgrade/Incremental/php/FiveFifty.php index e6d115c79c..00fbbbdde5 100644 --- a/CRM/Upgrade/Incremental/php/FiveFifty.php +++ b/CRM/Upgrade/Incremental/php/FiveFifty.php @@ -29,6 +29,30 @@ class CRM_Upgrade_Incremental_php_FiveFifty extends CRM_Upgrade_Incremental_Base */ public function upgrade_5_50_alpha1($rev): void { $this->addTask(ts('Upgrade DB to %1: SQL', [1 => $rev]), 'runSql', $rev); + $this->addTask(ts('Convert import mappings to use names'), 'convertMappingFieldLabelsToNames', $rev); + + } + + /** + * Convert saved mapping fields for contact imports to use name rather than + * label. + * + * Currently the 'name' column in civicrm_mapping_field holds names like + * 'First Name' or, more tragically 'Contact ID (match to contact)'. + * + * This updates them to hold the name - eg. 'first_name' in conjunction with + * a + * change in the contact import. + * + * (Getting the other entities done is a stretch goal). + * + * @return bool + * @throws \API_Exception + * @throws \CiviCRM_API3_Exception + */ + public static function convertMappingFieldLabelsToNames(): bool { + CRM_Import_ImportProcessor::convertSavedFields(); + return TRUE; } } diff --git a/tests/phpunit/CRM/Contact/Import/Form/MapFieldTest.php b/tests/phpunit/CRM/Contact/Import/Form/MapFieldTest.php index c4e236b9ba..b112e2a8c9 100644 --- a/tests/phpunit/CRM/Contact/Import/Form/MapFieldTest.php +++ b/tests/phpunit/CRM/Contact/Import/Form/MapFieldTest.php @@ -14,6 +14,7 @@ * File for the CRM_Contact_Import_Form_MapFieldTest class. */ +use Civi\Api4\MappingField; use Civi\Api4\UserJob; /** @@ -27,6 +28,14 @@ class CRM_Contact_Import_Form_MapFieldTest extends CiviUnitTestCase { use CRM_Contact_Import_MetadataTrait; use CRMTraits_Custom_CustomDataTrait; + /** + * Cleanup mappings in DB. + */ + public function tearDown(): void { + $this->quickCleanup(['civicrm_mapping', 'civicrm_mapping_field'], TRUE); + parent::tearDown(); + } + /** * Map field form. * @@ -58,7 +67,8 @@ class CRM_Contact_Import_Form_MapFieldTest extends CiviUnitTestCase { * @throws \CiviCRM_API3_Exception */ public function testSubmit(array $params, array $mapper, array $expecteds = []): void { - $form = $this->getMapFieldFormObject(); + $form = $this->getMapFieldFormObject(['mapper' => $mapper]); + /* @var CRM_Contact_Import_Form_MapField $form */ $form->set('contactType', CRM_Import_Parser::CONTACT_INDIVIDUAL); $form->preProcess(); $form->submit($params, $mapper); @@ -204,83 +214,12 @@ class CRM_Contact_Import_Form_MapFieldTest extends CiviUnitTestCase { * In conjunction with testing our existing function this tests the methods we want to migrate to * to clean it up. * - * @throws \API_Exception * @throws \CRM_Core_Exception * @throws \CiviCRM_API3_Exception */ public function testLoadSavedMappingDirect(): void { - $this->entity = 'Contact'; - $this->createCustomGroupWithFieldOfType(['title' => 'My Field']); + $mapping = $this->storeComplexMapping(); $this->setUpMapFieldForm(); - $mapping = $this->callAPISuccess('Mapping', 'create', ['name' => 'my test', 'label' => 'Special custom']); - foreach ([ - [ - 'name' => 'Addressee', - 'column_number' => '0', - ], - [ - 'name' => 'Postal Greeting', - 'column_number' => '1', - ], - [ - 'name' => 'Phone', - 'column_number' => '2', - 'location_type_id' => '1', - 'phone_type_id' => '1', - ], - [ - 'name' => 'Street Address', - 'column_number' => '3', - ], - [ - 'name' => 'Enter text here :: My Field', - 'column_number' => '4', - ], - [ - 'name' => 'Street Address', - 'column_number' => '5', - 'location_type_id' => '1', - ], - [ - 'name' => 'City', - 'column_number' => '6', - 'location_type_id' => '1', - ], - [ - 'name' => 'State Province', - 'column_number' => '7', - 'relationship_type_id' => 4, - 'relationship_direction' => 'a_b', - 'location_type_id' => '1', - ], - [ - 'name' => 'Url', - 'column_number' => '8', - 'relationship_type_id' => 4, - 'relationship_direction' => 'a_b', - 'website_type_id' => 2, - ], - [ - 'name' => 'Phone', - 'column_number' => '9', - 'relationship_type_id' => 4, - 'location_type_id' => '1', - 'relationship_direction' => 'a_b', - 'phone_type_id' => 2, - ], - [ - 'name' => 'Phone', - 'column_number' => '10', - 'location_type_id' => '1', - 'phone_type_id' => '3', - ], - ] as $mappingField) { - $this->callAPISuccess('MappingField', 'create', array_merge([ - 'mapping_id' => $mapping['id'], - 'grouping' => 1, - 'contact_type' => 'Individual', - ], $mappingField)); - } $processor = new CRM_Import_ImportProcessor(); $processor->setMappingID($mapping['id']); $processor->setMetadata($this->getContactImportMetadata()); @@ -438,4 +377,121 @@ document.forms.MapField['mapper[0][3]'].style.display = 'none';\n", $this->form->set('contactType', CRM_Import_Parser::CONTACT_INDIVIDUAL); } + /** + * Tests the routing used in the 5.50 upgrade script to stop using labels... + * + * @throws \API_Exception + * @throws \CiviCRM_API3_Exception + */ + public function testConvertFields(): void { + $mapping = $this->storeComplexMapping(TRUE); + CRM_Import_ImportProcessor::convertSavedFields(); + $updatedMapping = MappingField::get() + ->addWhere('mapping_id', '=', $mapping['id']) + ->addSelect('id', 'name')->execute(); + + $expected = [ + 0 => 'addressee', + 1 => 'postal_greeting', + 2 => 'phone', + 3 => 'street_address', + 4 => 'custom_1', + 5 => 'street_address', + 6 => 'city', + 7 => 'state_province', + 8 => 'url', + 9 => 'phone', + 10 => 'phone', + ]; + foreach ($updatedMapping as $index => $mappingField) { + $this->assertEquals($expected[$index], $mappingField['name']); + } + } + + /** + * Store a mapping with a complex set of fields. + * + * @param bool $legacyMode + * + * @return array + */ + private function storeComplexMapping(bool $legacyMode = FALSE): array { + $this->createCustomGroupWithFieldOfType(['title' => 'My Field']); + $mapping = $this->callAPISuccess('Mapping', 'create', [ + 'name' => 'my test', + 'label' => 'Special custom', + 'mapping_type_id' => 'Import Contact', + ]); + foreach ( + [ + [ + 'name' => $legacyMode ? 'Addressee' : 'addressee', + 'column_number' => '0', + ], + [ + 'name' => $legacyMode ? 'Postal Greeting' : 'postal_greeting', + 'column_number' => '1', + ], + [ + 'name' => $legacyMode ? 'Phone' : 'phone', + 'column_number' => '2', + 'location_type_id' => '1', + 'phone_type_id' => '1', + ], + [ + 'name' => $legacyMode ? 'Street Address' : 'street_address', + 'column_number' => '3', + ], + [ + 'name' => $legacyMode ? 'Enter text here :: My Field' : $this->getCustomFieldName('text'), + 'column_number' => '4', + ], + [ + 'name' => $legacyMode ? 'Street Address' : 'street_address', + 'column_number' => '5', + 'location_type_id' => '1', + ], + [ + 'name' => $legacyMode ? 'City' : 'city', + 'column_number' => '6', + 'location_type_id' => '1', + ], + [ + 'name' => $legacyMode ? 'State Province' : 'state_province', + 'column_number' => '7', + 'relationship_type_id' => 4, + 'relationship_direction' => 'a_b', + 'location_type_id' => '1', + ], + [ + 'name' => $legacyMode ? 'Url' : 'url', + 'column_number' => '8', + 'relationship_type_id' => 4, + 'relationship_direction' => 'a_b', + 'website_type_id' => 2, + ], + [ + 'name' => $legacyMode ? 'Phone' : 'phone', + 'column_number' => '9', + 'relationship_type_id' => 4, + 'location_type_id' => '1', + 'relationship_direction' => 'a_b', + 'phone_type_id' => 2, + ], + [ + 'name' => $legacyMode ? 'Phone' : 'phone', + 'column_number' => '10', + 'location_type_id' => '1', + 'phone_type_id' => '3', + ], + ] as $mappingField) { + $this->callAPISuccess('MappingField', 'create', array_merge([ + 'mapping_id' => $mapping['id'], + 'grouping' => 1, + 'contact_type' => 'Individual', + ], $mappingField)); + } + return $mapping; + } + } -- 2.25.1