diff --git a/CRM/Contact/Import/Parser.php b/CRM/Contact/Import/Parser.php index ba2056171553..0a85acd50c9f 100644 --- a/CRM/Contact/Import/Parser.php +++ b/CRM/Contact/Import/Parser.php @@ -1000,9 +1000,6 @@ protected function formatContactParameters(&$values, &$params) { // Note // Custom - // Cache the various object fields - static $fields = []; - // first add core contact values since for other Civi modules they are not added $contactFields = CRM_Contact_DAO_Contact::fields(); _civicrm_api3_store_values($contactFields, $values, $params); @@ -1016,6 +1013,10 @@ protected function formatContactParameters(&$values, &$params) { return TRUE; } + // Cache the various object fields + // @todo - remove this after confirming this is just a compilation of other-wise-cached fields. + static $fields = []; + if (isset($values['individual_prefix'])) { if (!empty($params['prefix_id'])) { $prefixes = CRM_Core_PseudoConstant::get('CRM_Contact_DAO_Contact', 'prefix_id'); @@ -1164,18 +1165,15 @@ protected function formatContactParameters(&$values, &$params) { } // Check for custom field values - - if (empty($fields['custom'])) { - $fields['custom'] = &CRM_Core_BAO_CustomField::getFields(CRM_Utils_Array::value('contact_type', $values), - FALSE, FALSE, NULL, NULL, FALSE, FALSE, FALSE - ); - } + $customFields = CRM_Core_BAO_CustomField::getFields(CRM_Utils_Array::value('contact_type', $values), + FALSE, FALSE, NULL, NULL, FALSE, FALSE, FALSE + ); foreach ($values as $key => $value) { if ($customFieldID = CRM_Core_BAO_CustomField::getKeyID($key)) { // check if it's a valid custom field id - if (!array_key_exists($customFieldID, $fields['custom'])) { + if (!array_key_exists($customFieldID, $customFields)) { return civicrm_api3_create_error('Invalid custom field ID'); } else { diff --git a/CRM/Contact/Import/Parser/Contact.php b/CRM/Contact/Import/Parser/Contact.php index 5981a5fab58b..f8b543c6c5d8 100644 --- a/CRM/Contact/Import/Parser/Contact.php +++ b/CRM/Contact/Import/Parser/Contact.php @@ -477,6 +477,9 @@ public function getAllFields() { * * @return bool * the result of this processing + * + * @throws \CiviCRM_API3_Exception + * @throws \CRM_Core_Exception */ public function import($onDuplicate, &$values, $doGeocodeAddress = FALSE) { $config = CRM_Core_Config::singleton(); @@ -505,10 +508,7 @@ public function import($onDuplicate, &$values, $doGeocodeAddress = FALSE) { 'contact_type' => $this->_contactType, ]; - static $contactFields = NULL; - if ($contactFields == NULL) { - $contactFields = CRM_Contact_DAO_Contact::import(); - } + $contactFields = CRM_Contact_DAO_Contact::import(); //check if external identifier exists in database if (!empty($params['external_identifier']) && (!empty($params['id']) || in_array($onDuplicate, [ diff --git a/tests/phpunit/CRM/Contact/Import/Parser/ContactTest.php b/tests/phpunit/CRM/Contact/Import/Parser/ContactTest.php index 835f393f2754..ff4e11c6c9ef 100644 --- a/tests/phpunit/CRM/Contact/Import/Parser/ContactTest.php +++ b/tests/phpunit/CRM/Contact/Import/Parser/ContactTest.php @@ -37,7 +37,14 @@ * @group headless */ class CRM_Contact_Import_Parser_ContactTest extends CiviUnitTestCase { - protected $_tablesToTruncate = ['civicrm_address', 'civicrm_phone', 'civicrm_email']; + use CRMTraits_Custom_CustomDataTrait; + + /** + * Main entity for the class. + * + * @var string + */ + protected $entity = 'Contact'; /** * Setup function. @@ -46,6 +53,16 @@ public function setUp() { parent::setUp(); } + /** + * Tear down after test. + * + * @throws \CRM_Core_Exception + */ + public function tearDown() { + $this->quickCleanup(['civicrm_address', 'civicrm_phone', 'civicrm_email'], TRUE); + parent::tearDown(); + } + /** * Test that import parser will add contact with employee of relationship. * @@ -316,6 +333,44 @@ public function testGenderLabel() { $this->callAPISuccessGetSingle('Contact', $contactValues); } + /** + * Test that labels work for importing custom data. + * + * @throws \CRM_Core_Exception + */ + public function testCustomDataLabel() { + $this->createCustomGroupWithFieldOfType([], 'select'); + $contactValues = [ + 'first_name' => 'Bill', + 'last_name' => 'Gates', + 'email' => 'bill.gates@microsoft.com', + 'nick_name' => 'Billy-boy', + $this->getCustomFieldName('select') => 'Yellow', + ]; + $this->runImport($contactValues, CRM_Import_Parser::DUPLICATE_UPDATE, CRM_Import_Parser::VALID, [NULL, NULL, 'Primary', NULL, NULL]); + $contact = $this->callAPISuccessGetSingle('Contact', array_merge($contactValues, ['return' => $this->getCustomFieldName('select')])); + $this->assertEquals('Y', $contact[$this->getCustomFieldName('select')]); + } + + /** + * Test that names work for importing custom data. + * + * @throws \CRM_Core_Exception + */ + public function testCustomDataName() { + $this->createCustomGroupWithFieldOfType([], 'select'); + $contactValues = [ + 'first_name' => 'Bill', + 'last_name' => 'Gates', + 'email' => 'bill.gates@microsoft.com', + 'nick_name' => 'Billy-boy', + $this->getCustomFieldName('select') => 'Y', + ]; + $this->runImport($contactValues, CRM_Import_Parser::DUPLICATE_UPDATE, CRM_Import_Parser::VALID, [NULL, NULL, 'Primary', NULL, NULL]); + $contact = $this->callAPISuccessGetSingle('Contact', array_merge($contactValues, ['return' => $this->getCustomFieldName('select')])); + $this->assertEquals('Y', $contact[$this->getCustomFieldName('select')]); + } + /** * Test that the import parser adds the address to the primary location. * @@ -464,20 +519,16 @@ public function testCustomFieldValidation() { */ public function testImportFill() { // Create a custom field group for testing. - $custom_group_name = 'importFillGroup'; - $results = $this->callAPISuccess('customGroup', 'get', ['title' => $custom_group_name]); - if ($results['count'] == 0) { - $api_params = [ - 'title' => $custom_group_name, - 'extends' => 'Individual', - 'is_active' => TRUE, - ]; - $customGroup = $this->callAPISuccess('customGroup', 'create', $api_params); - } + $this->createCustomGroup([ + 'title' => 'importFillGroup', + 'extends' => 'Individual', + 'is_active' => TRUE, + ]); + $customGroupID = $this->ids['CustomGroup']['importFillGroup']; // Add two custom fields. $api_params = [ - 'custom_group_id' => $customGroup['id'], + 'custom_group_id' => $customGroupID, 'label' => 'importFillField1', 'html_type' => 'Select', 'data_type' => 'String', @@ -490,7 +541,7 @@ public function testImportFill() { $customField1 = $result['id']; $api_params = [ - 'custom_group_id' => $customGroup['id'], + 'custom_group_id' => $customGroupID, 'label' => 'importFillField2', 'html_type' => 'Select', 'data_type' => 'String', @@ -505,8 +556,6 @@ public function testImportFill() { // Now set up values. $original_gender = 'Male'; $original_custom1 = 'foo'; - $original_job_title = ''; - $original_custom2 = ''; $original_email = 'test-import-fill@example.org'; $import_gender = 'Female'; diff --git a/tests/phpunit/CRMTraits/Custom/CustomDataTrait.php b/tests/phpunit/CRMTraits/Custom/CustomDataTrait.php index af0e1936840d..963daae894a2 100644 --- a/tests/phpunit/CRMTraits/Custom/CustomDataTrait.php +++ b/tests/phpunit/CRMTraits/Custom/CustomDataTrait.php @@ -72,12 +72,21 @@ public function createCustomGroup($params = []) { * @throws \CRM_Core_Exception */ public function createCustomGroupWithFieldOfType($groupParams = [], $customFieldType = 'text', $identifier = '') { - if ($customFieldType !== 'text') { + $supported = ['text', 'select']; + if (!in_array($customFieldType, $supported)) { throw new CRM_Core_Exception('we have not yet extracted other custom field types from createCustomFieldsOfAllTypes, Use consistent syntax when you do'); } $groupParams['title'] = empty($groupParams['title']) ? $identifier . 'Group with field ' . $customFieldType : $groupParams['title']; $this->createCustomGroup($groupParams); - $customField = $this->createTextCustomField(['custom_group_id' => $this->ids['CustomGroup'][$groupParams['title']]]); + switch ($customFieldType) { + case 'text': + $customField = $this->createTextCustomField(['custom_group_id' => $this->ids['CustomGroup'][$groupParams['title']]]); + break; + + case 'select': + $customField = $this->createSelectCustomField(['custom_group_id' => $this->ids['CustomGroup'][$groupParams['title']]]); + break; + } $this->ids['CustomField'][$identifier . $customFieldType] = $customField['id']; } @@ -90,38 +99,7 @@ public function createCustomFieldsOfAllTypes() { $customField = $this->createTextCustomField(['custom_group_id' => $customGroupID]); $ids['text'] = $customField['id']; - $optionValue[] = [ - 'label' => 'Red', - 'value' => 'R', - 'weight' => 1, - 'is_active' => 1, - ]; - $optionValue[] = [ - 'label' => 'Yellow', - 'value' => 'Y', - 'weight' => 2, - 'is_active' => 1, - ]; - $optionValue[] = [ - 'label' => 'Green', - 'value' => 'G', - 'weight' => 3, - 'is_active' => 1, - ]; - - $params = [ - 'label' => 'Pick Color', - 'html_type' => 'Select', - 'data_type' => 'String', - 'weight' => 2, - 'is_required' => 1, - 'is_searchable' => 0, - 'is_active' => 1, - 'option_values' => $optionValue, - 'custom_group_id' => $customGroupID, - ]; - - $customField = $this->callAPISuccess('custom_field', 'create', $params); + $customField = $this->createSelectCustomField(['custom_group_id' => $customGroupID]); $ids['select_string'] = $customField['id']; $params = [ @@ -229,4 +207,49 @@ protected function createTextCustomField($params = []) { return $this->callAPISuccess('CustomField', 'create', $params)['values'][0]; } + /** + * Create custom select field. + * + * @param array $params + * Parameter overrides, must include custom_group_id. + * + * @return array + */ + protected function createSelectCustomField(array $params): array { + $optionValue = [ + [ + 'label' => 'Red', + 'value' => 'R', + 'weight' => 1, + 'is_active' => 1, + ], + [ + 'label' => 'Yellow', + 'value' => 'Y', + 'weight' => 2, + 'is_active' => 1, + ], + [ + 'label' => 'Green', + 'value' => 'G', + 'weight' => 3, + 'is_active' => 1, + ], + ]; + + $params = array_merge([ + 'label' => 'Pick Color', + 'html_type' => 'Select', + 'data_type' => 'String', + 'weight' => 2, + 'is_required' => 1, + 'is_searchable' => 0, + 'is_active' => 1, + 'option_values' => $optionValue, + ], $params); + + $customField = $this->callAPISuccess('custom_field', 'create', $params); + return $customField['values'][$customField['id']]; + } + }