dev/core#3132 Ensure that contacts are not placed in null island if geocoders return...
authorSeamus Lee <seamuslee001@gmail.com>
Tue, 22 Mar 2022 23:19:35 +0000 (10:19 +1100)
committerSeamus Lee <seamuslee001@gmail.com>
Tue, 22 Mar 2022 23:20:21 +0000 (10:20 +1100)
CRM/Core/BAO/Address.php
tests/phpunit/CRM/Utils/Geocode/TestProvider.php [new file with mode: 0644]
tests/phpunit/api/v3/AddressTest.php

index 09e45a24c0ec6065174ab23a3ef7c5fc404d1926..aa23c3d0fec604cf840b77f4963c335babeb7b89 100644 (file)
@@ -1313,7 +1313,10 @@ SELECT is_primary,
     // core#2379 - Limit geocode length to 14 characters to avoid validation error on save in UI.
     foreach (['geo_code_1', 'geo_code_2'] as $geocode) {
       if ($params[$geocode] ?? FALSE) {
-        $params[$geocode] = (float) substr($params[$geocode], 0, 14);
+        // ensure that if the geocoding provider (Google, OSM etc) has returned the string 'null' because they can't geocode, ensure that contacts are not placed on null island 0,0
+        if ($params[$geocode] !== 'null') {
+          $params[$geocode] = (float) substr($params[$geocode], 0, 14);
+        }
       }
     }
     return $providerExists;
diff --git a/tests/phpunit/CRM/Utils/Geocode/TestProvider.php b/tests/phpunit/CRM/Utils/Geocode/TestProvider.php
new file mode 100644 (file)
index 0000000..fca9ec3
--- /dev/null
@@ -0,0 +1,11 @@
+<?php
+
+class CRM_Utils_Geocode_TestProvider {
+
+  public static function format(&$values, $stateName = FALSE) {
+    if ($values['street_address'] == 'Does not exist') {
+      $values['geo_code_1'] = $values['geo_code_2'] = 'null';
+    }
+  }
+
+}
index 66e2f1c7c60b2e84e0729970623432ce4f0cf22c..f8a55cde2aad150185df9b2244ba882c9eba764a 100644 (file)
@@ -627,4 +627,27 @@ class api_v3_AddressTest extends CiviUnitTestCase {
     $this->callAPISuccess('Address', 'create', ['id' => $secondAddress['id'], 'contact_id' => $contactIdB, 'master_id' => $firstAddress['id']]);
   }
 
+  /**
+   * Ensure that when geocoding fails and geocoders return the string 'null' that it is not translated into int 0 for geo_code_1 and geo_code_2 which would place the contact on null island (0,0)
+   */
+  public function testGeocodingAddress(): void {
+    $this->callAPISuccess('Setting', 'create', ['geoProvider' => 'TestProvider']);
+    $cid = $this->individualCreate();
+    $r = $this->callAPISuccess('Address', 'create', [
+      'contact_id' => $cid,
+      'location_type_id' => 1,
+      // Trigger geocoding to return 'null's for geo_code_1 and geo_code_2
+      'street_address' => 'Does not exist',
+      'city' => 'Hereville',
+      //'US',
+      'country_id' => 'US',
+      // 'California',
+      'state_province_id' => 'California',
+      'postal_code' => '94100',
+    ]);
+    $createdAddress = $this->callAPISuccess('Address', 'get', ['id' => $r['id']])['values'][$r['id']];
+    // If we have stored NULL values, then geo_code_1 should not be returned.
+    $this->assertFalse(isset($createdAddress['geo_code_1']));
+  }
+
 }