I never check the geocode box when importing. Yet, I found that even small imports were taking a long time. I ran strace on the php process and saw lots of lookups to google. So I disabled both the mapping provider and geocoding provider globally, re-ran the import and it went through in a fraction of the time.

Next, I took a closer look at the code that is triggered based on the geo coding checkbox:

The file: Contact/Import/Parser/Contact.php contains:

 public function import($onDuplicate, &$values, $doGeocodeAddress = FALSE) {
    $config = CRM_Core_Config::singleton();
    $this->_unparsedStreetAddressContacts = array();
    if (!$doGeocodeAddress) {
      // CRM-5854, reset the geocode method to null to prevent geocoding
      $config->geocodeMethod = NULL;

In other words, if geo code checkbox is unchecked, the $doGeocodeAddress is set to false. If it is set to false, then we set $config->geocodeMethod = NULL;

Hm. Could this possibly work? If you set a property on a singleton locally in a function, it seems like it would not be available outside the function.

However, this "fix" has been in place for years so I'm asking this question as a sanity check before opening a ticket.

Maybe something changed in the behavior of PHP?


The answer is bug, but not for the reasons I thought.

In short: the addition of MagicMerge seems to be the culprit, resulting in changed behavior when geocodeMethod is set to NULL.

Long answer:

First, setting the property of a singleton in one function, does result in it persisting even in other functions. The singleton really does act like a global variable. That's how this has worked all the way up to 4.7.

However, in 4.7 MagicMerge was introduced to streamline the configuration object.

This approach added __get and __set functions to handle properties that are not defined.

Now, if a property (like geocodeMethod) is set, it is added to the cache ($this->cache[$name] = $v;). So far so good.

However, when it is retrieved, it only comes from the cache if it is set:

if (isset($this->cache[$k])) {
  return $this->cache[$k];

Oops. If we set it to NULL it will never be retrieved from the cache and will always be retrieved using the function CRM_Utils_Geocode::getProviderClass

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.