From 4352bd7284bcc5ba5a49d13f0ad343262fe5f1a7 Mon Sep 17 00:00:00 2001 From: eileen Date: Mon, 24 Jul 2017 17:12:35 +1200 Subject: [PATCH] CRM-19888 fix import to prefer default country when resolving states. The example given is the abbreviation UT is used in muliple countries and if US is the default country it should resolve to UTAH --- CRM/Contact/BAO/Contact.php | 74 ++++++++++++++----- CRM/Core/PseudoConstant.php | 26 +++++++ .../CRM/Contact/Import/Parser/ContactTest.php | 36 +++++++++ 3 files changed, 116 insertions(+), 20 deletions(-) diff --git a/CRM/Contact/BAO/Contact.php b/CRM/Contact/BAO/Contact.php index 93275ced6e..449ff4f92e 100644 --- a/CRM/Contact/BAO/Contact.php +++ b/CRM/Contact/BAO/Contact.php @@ -551,30 +551,64 @@ WHERE civicrm_contact.id = " . CRM_Utils_Type::escape($id, 'Integer'); if ($countryID) { $stateProvinceList = CRM_Core_PseudoConstant::stateProvinceForCountry($countryID); - } - else { - $stateProvinceList = CRM_Core_PseudoConstant::stateProvince(); - } - if (CRM_Utils_Array::lookupValue($values, - 'state_province', - $stateProvinceList, - TRUE - )) { - return $values['state_province_id']; - } - - if (!empty($countryID)) { + if (CRM_Utils_Array::lookupValue($values, + 'state_province', + $stateProvinceList, + TRUE + )) { + return $values['state_province_id']; + } $stateProvinceList = CRM_Core_PseudoConstant::stateProvinceForCountry($countryID, 'abbreviation'); + if (CRM_Utils_Array::lookupValue($values, + 'state_province', + $stateProvinceList, + TRUE + )) { + return $values['state_province_id']; + } + return NULL; } else { + // The underlying lookupValue function needs some de-fanging. Until that has been unravelled we + // continue to resolve stateprovince lists in descending order of preference & just 'keep trying'. + // prefer matching country.. + $stateProvinceList = CRM_Core_BAO_Address::buildOptions('state_province_id', NULL, array('country_id' => Civi::settings()->get('defaultContactCountry'))); + if (CRM_Utils_Array::lookupValue($values, + 'state_province', + $stateProvinceList, + TRUE + )) { + return $values['state_province_id']; + } + + $stateProvinceList = CRM_Core_PseudoConstant::stateProvince(); + if (CRM_Utils_Array::lookupValue($values, + 'state_province', + $stateProvinceList, + TRUE + )) { + return $values['state_province_id']; + } + + $stateProvinceList = CRM_Core_PseudoConstant::stateProvinceAbbreviationForDefaultCountry(); + if (CRM_Utils_Array::lookupValue($values, + 'state_province', + $stateProvinceList, + TRUE + )) { + return $values['state_province_id']; + } $stateProvinceList = CRM_Core_PseudoConstant::stateProvinceAbbreviation(); + if (CRM_Utils_Array::lookupValue($values, + 'state_province', + $stateProvinceList, + TRUE + )) { + return $values['state_province_id']; + } } - CRM_Utils_Array::lookupValue($values, - 'state_province', - $stateProvinceList, - TRUE - ); - return CRM_Utils_Array::value('state_province_id', $values); + + return NULL; } /** @@ -685,7 +719,7 @@ WHERE civicrm_contact.id = " . CRM_Utils_Type::escape($id, 'Integer'); $reverse ); } - $stateProvinceID = self::resolveStateProvinceID($values, CRM_Utils_Array::value('country_id', $values), $reverse); + $stateProvinceID = self::resolveStateProvinceID($values, CRM_Utils_Array::value('country_id', $values)); if ($stateProvinceID) { $values['state_province_id'] = $stateProvinceID; } diff --git a/CRM/Core/PseudoConstant.php b/CRM/Core/PseudoConstant.php index 4196644418..75793c800c 100644 --- a/CRM/Core/PseudoConstant.php +++ b/CRM/Core/PseudoConstant.php @@ -780,6 +780,32 @@ WHERE id = %1"; return self::$stateProvinceAbbreviation; } + /** + * Get all the State/Province abbreviations from the database for the specified country. + * + * @param int $countryID + * + * @return array + * array of all State/Province abbreviations for the given country. + */ + public static function stateProvinceAbbreviationForCountry($countryID) { + if (!isset(\Civi::$statics[__CLASS__]['stateProvinceAbbreviationForCountry'][$countryID])) { + \Civi::$statics[__CLASS__]['stateProvinceAbbreviationForCountry'][$countryID] = array(); + } + self::populate(\Civi::$statics[__CLASS__]['stateProvinceAbbreviationForCountry'][$countryID], 'CRM_Core_DAO_StateProvince', TRUE, 'abbreviation', 'is_active', "country_id = " . (int) $countryID, 'abbreviation'); + return \Civi::$statics[__CLASS__]['stateProvinceAbbreviationForCountry'][$countryID]; + } + + /** + * Get all the State/Province abbreviations from the database for the default country. + * + * @return array + * array of all State/Province abbreviations for the given country. + */ + public static function stateProvinceAbbreviationForDefaultCountry() { + return CRM_Core_PseudoConstant::stateProvinceAbbreviationForCountry(Civi::settings()->get('defaultContactCountry')); + } + /** * Get all the countries from database. * diff --git a/tests/phpunit/CRM/Contact/Import/Parser/ContactTest.php b/tests/phpunit/CRM/Contact/Import/Parser/ContactTest.php index 2890a7be35..9bf670cf43 100644 --- a/tests/phpunit/CRM/Contact/Import/Parser/ContactTest.php +++ b/tests/phpunit/CRM/Contact/Import/Parser/ContactTest.php @@ -453,6 +453,42 @@ class CRM_Contact_Imports_Parser_ContactTest extends CiviUnitTestCase { } } + /** + * CRM-19888 default country should be used if ambigous. + */ + public function testImportAmbiguousStateCountry() { + $countries = CRM_Core_PseudoConstant::country(FALSE, FALSE); + $this->callAPISuccess('Setting', 'create', array('countryLimit' => array(array_search('United States', $countries), array_search('Guyana', $countries), array_search('Netherlands', $countries)))); + $this->callAPISuccess('Setting', 'create', array('provinceLimit' => array(array_search('United States', $countries), array_search('Guyana', $countries), array_search('Netherlands', $countries)))); + $mapper = array(0 => NULL, 1 => NULL, 2 => 'Primary', 3 => NULL); + list($contactValues) = $this->setUpBaseContact(); + $fields = array_keys($contactValues); + $addressValues = array( + 'street_address' => 'PO Box 2716', + 'city' => 'Midway', + 'state_province' => 'UT', + 'postal_code' => 84049, + 'country' => 'United States', + ); + $locationTypes = $this->callAPISuccess('Address', 'getoptions', array('field' => 'location_type_id')); + $locationTypes = $locationTypes['values']; + foreach ($addressValues as $field => $value) { + $contactValues['home_' . $field] = $value; + $mapper[] = array_search('Home', $locationTypes); + $contactValues['work_' . $field] = $value; + $mapper[] = array_search('Work', $locationTypes); + $fields[] = $field; + $fields[] = $field; + } + $contactValues['work_country'] = ''; + + $this->runImport($contactValues, CRM_Import_Parser::DUPLICATE_UPDATE, CRM_Import_Parser::VALID, $mapper, $fields); + $addresses = $this->callAPISuccess('Address', 'get', array('contact_id' => array('>' => 2), 'sequential' => 1)); + $this->assertEquals(2, $addresses['count']); + $this->assertEquals(array_search('United States', $countries), $addresses['values'][0]['country_id']); + $this->assertEquals(array_search('United States', $countries), $addresses['values'][1]['country_id']); + } + /** * Run the import parser. * -- 2.25.1