Also tries to geocode in the country's languages if geocoded and given text don't...
authorStéphane Jacob <sj@m4x.org>
Thu, 23 Dec 2010 20:04:13 +0000 (21:04 +0100)
committerStéphane Jacob <sj@m4x.org>
Tue, 28 Dec 2010 10:53:19 +0000 (11:53 +0100)
Signed-off-by: Stéphane Jacob <sj@m4x.org>
classes/address.php
classes/geocoder.php
classes/gmapsgeocoder.php

index 0ba8f93..d7f7970 100644 (file)
@@ -298,6 +298,9 @@ class Address
     public $localityName = null;
     public $subAdministrativeAreaName = null;
     public $administrativeAreaName = null;
+    public $localityNameLocal = null;
+    public $subAdministrativeAreaNameLocal = null;
+    public $administrativeAreaNameLocal = null;
     public $countryId = null;
     public $latitude = null;
     public $longitude = null;
@@ -609,26 +612,29 @@ class Address
     public function toFormArray()
     {
         $address = array(
-            'accuracy'                  => $this->accuracy,
-            'text'                      => $this->text,
-            'postalText'                => $this->postalText,
-            'postalCode'                => $this->postalCode,
-            'localityId'                => $this->localityId,
-            'subAdministrativeAreaId'   => $this->subAdministrativeAreaId,
-            'administrativeAreaId'      => $this->administrativeAreaId,
-            'countryId'                 => $this->countryId,
-            'localityName'              => $this->localityName,
-            'subAdministrativeAreaName' => $this->subAdministrativeAreaName,
-            'administrativeAreaName'    => $this->administrativeAreaName,
-            'latitude'                  => $this->latitude,
-            'longitude'                 => $this->longitude,
-            'north'                     => $this->north,
-            'south'                     => $this->south,
-            'east'                      => $this->east,
-            'west'                      => $this->west,
-            'error'                     => $this->error,
-            'changed'                   => $this->changed,
-            'removed'                   => $this->removed,
+            'accuracy'                       => $this->accuracy,
+            'text'                           => $this->text,
+            'postalText'                     => $this->postalText,
+            'postalCode'                     => $this->postalCode,
+            'localityId'                     => $this->localityId,
+            'subAdministrativeAreaId'        => $this->subAdministrativeAreaId,
+            'administrativeAreaId'           => $this->administrativeAreaId,
+            'countryId'                      => $this->countryId,
+            'localityName'                   => $this->localityName,
+            'subAdministrativeAreaName'      => $this->subAdministrativeAreaName,
+            'administrativeAreaName'         => $this->administrativeAreaName,
+            'localityNameLocal'              => $this->localityNameLocal,
+            'subAdministrativeAreaNameLocal' => $this->subAdministrativeAreaNameLocal,
+            'administrativeAreaNameLocal'    => $this->administrativeAreaNameLocal,
+            'latitude'                       => $this->latitude,
+            'longitude'                      => $this->longitude,
+            'north'                          => $this->north,
+            'south'                          => $this->south,
+            'east'                           => $this->east,
+            'west'                           => $this->west,
+            'error'                          => $this->error,
+            'changed'                        => $this->changed,
+            'removed'                        => $this->removed,
         );
         if (!is_null($this->geocodedText)) {
             $address['geocodedText'] = $this->geocodedText;
index 425b017..0808f4e 100644 (file)
@@ -41,9 +41,10 @@ abstract class Geocoder {
         );
 
         $areaName = $area . 'Name';
+        $areaNameLocal = $areaName . 'Local';
         $areaId = $area . 'Id';
         if (!is_null($address->$areaName) && isset($databases[$area])) {
-            $res = XDB::query('SELECT  id
+            $res = XDB::query('SELECT  id, nameLocal
                                  FROM  ' . $databases[$area] . '
                                 WHERE  name = {?}',
                               $address->$areaName);
index 38eff81..d8fad1f 100644 (file)
@@ -78,15 +78,19 @@ class GMapsGeocoder extends Geocoder {
     // Updates the address with the geocoded information from Google Maps. Also
     // cleans up the final informations.
     private function getUpdatedAddress(Address &$address, array $geocodedData, $extraLines) {
-        $this->fillAddressWithGeocoding($address, $geocodedData);
+        $this->fillAddressWithGeocoding($address, $geocodedData, false);
         $this->formatAddress($address, $extraLines);
     }
 
     // Retrieves the Placemark object (see #getPlacemarkFromJson()) for the @p
     // address, by querying the Google Maps API. Returns the array on success,
     // and null otherwise.
-    private function getPlacemarkForAddress($address) {
-        $url     = $this->getGeocodingUrl($address);
+    private function getPlacemarkForAddress($address, $defaultLanguage = null) {
+        if (is_null($defaultLanguage)) {
+            $defaultLanguage = Platal::globals()->geocoder->gmaps_hl;
+        }
+
+        $url     = $this->getGeocodingUrl($address, $defaultLanguage);
         $geoData = $this->getGeoJsonFromUrl($url);
 
         return ($geoData ? $this->getPlacemarkFromJson($geoData) : null);
@@ -99,13 +103,13 @@ class GMapsGeocoder extends Geocoder {
 
     // Builds the Google Maps geocoder url to fetch information about @p address.
     // Returns the built url.
-    private function getGeocodingUrl($address) {
+    private function getGeocodingUrl($address, $defaultLanguage) {
         global $globals;
 
         $parameters = array(
             'key'    => $globals->geocoder->gmaps_key,
             'sensor' => 'false',   // The queried address wasn't obtained from a GPS sensor.
-            'hl'     => $globals->geocoder->gmaps_hl,
+            'hl'     => $defaultLanguage,
             'oe'     => 'utf8',    // Output encoding.
             'output' => 'json',    // Output format.
             'gl'     => $globals->geocoder->gmaps_gl,
@@ -178,38 +182,45 @@ class GMapsGeocoder extends Geocoder {
     }
 
     // Fills the address with the geocoded data
-    private function fillAddressWithGeocoding(Address &$address, $geocodedData) {
+    private function fillAddressWithGeocoding(Address &$address, $geocodedData, $isLocal) {
         // The geocoded address three is
         // Country -> AdministrativeArea -> SubAdministrativeArea -> Locality -> Thoroughfare
         // with all the possible shortcuts
         // The address is formatted as xAL, or eXtensible Address Language, an international
         // standard for address formatting.
         // xAL documentation: http://www.oasis-open.org/committees/ciq/ciq.html#6
-        $address->geocodedText = str_replace(', ', "\n", $geocodedData['address']);
+        if ($isLocal) {
+            $ext = 'Local';
+        } else {
+            $ext = ucfirst(Platal::globals()->geocoder->gmaps_hl);
+            $address->geocodedText = str_replace(', ', "\n", $geocodedData['address']);
+        }
+
         if (isset($geocodedData['AddressDetails']['Accuracy'])) {
             $address->accuracy = $geocodedData['AddressDetails']['Accuracy'];
         }
 
         $currentPosition = $geocodedData['AddressDetails'];
         if (isset($currentPosition['Country'])) {
+            $country = 'country' . $ext;
             $currentPosition    = $currentPosition['Country'];
             $address->countryId = $currentPosition['CountryNameCode'];
-            $address->country   = $currentPosition['CountryName'];
+            $address->$country  = $currentPosition['CountryName'];
         }
         if (isset($currentPosition['AdministrativeArea'])) {
-            $currentPosition                 = $currentPosition['AdministrativeArea'];
-            $address->administrativeAreaName = $currentPosition['AdministrativeAreaName'];
+            $administrativeAreaName = 'administrativeAreaName' . $ext;
+            $currentPosition                  = $currentPosition['AdministrativeArea'];
+            $address->$administrativeAreaName = $currentPosition['AdministrativeAreaName'];
         }
         if (isset($currentPosition['SubAdministrativeArea'])) {
-            $currentPosition                    = $currentPosition['SubAdministrativeArea'];
-            $address->subAdministrativeAreaName = $currentPosition['SubAdministrativeAreaName'];
+            $subAdministrativeAreaName = 'subAdministrativeAreaName' . $ext;
+            $currentPosition                     = $currentPosition['SubAdministrativeArea'];
+            $address->$subAdministrativeAreaName = $currentPosition['SubAdministrativeAreaName'];
         }
         if (isset($currentPosition['Locality'])) {
-            $currentPosition       = $currentPosition['Locality'];
-            $address->localityName = $currentPosition['LocalityName'];
-        }
-        if (isset($currentPosition['Thoroughfare'])) {
-            $address->thoroughfareName = $currentPosition['Thoroughfare']['ThoroughfareName'];
+            $localityName = 'localityName' . $ext;
+            $currentPosition        = $currentPosition['Locality'];
+            $address->$localityName = $currentPosition['LocalityName'];
         }
         if (isset($currentPosition['PostalCode'])) {
             $address->postalCode = $currentPosition['PostalCode']['PostalCodeNumber'];
@@ -236,14 +247,11 @@ class GMapsGeocoder extends Geocoder {
         }
     }
 
-    // Formats the text of the geocoded address using the unused data and
-    // compares it to the given address. If they are too different, the user
-    // will be asked to choose between them.
-    private function formatAddress(Address &$address, $extraLines) {
+    // Compares the geocoded address with the given address and returns true
+    // iff their are close enough to be considered as equals or not.
+    private function compareAddress($address)
+    {
         $same = true;
-        if ($extraLines) {
-            $address->geocodedText = $extraLines . "\n" . $address->geocodedText;
-        }
         $geoloc = strtoupper(preg_replace(array("/[0-9,\"'#~:;_\- ]/", "/\r\n/"),
                                           array('', "\n"), $address->geocodedText));
         $text   = strtoupper(preg_replace(array("/[0-9,\"'#~:;_\- ]/", "/\r\n/"),
@@ -269,9 +277,41 @@ class GMapsGeocoder extends Geocoder {
             }
         }
 
-        if ($same) {
+        return $same;
+    }
+
+    // Formats the text of the geocoded address using the unused data and
+    // compares it to the given address. If they are too different, the user
+    // will be asked to choose between them.
+    private function formatAddress(Address &$address, $extraLines)
+    {
+        if ($extraLines) {
+            $address->geocodedText = $extraLines . "\n" . $address->geocodedText;
+        }
+
+        if ($this->compareAddress($address)) {
             $address->geocodedText = null;
         } else {
+            $languages = XDB::fetchOneCell('SELECT  IF(ISNULL(gc1.belongsTo), gc1.languages, gc2.languages)
+                                              FROM  geoloc_countries AS gc1
+                                         LEFT JOIN  geoloc_countries AS gc2 ON (gc1.belongsTo = gc2.iso_3166_1_a2)
+                                             WHERE  gc1.iso_3166_1_a2 = {?}',
+                                           $address->countryId);
+            $toGeocode = substr($address->text, strlen($extraLines));
+            foreach (explode(',', $languages) as $language) {
+                if ($language != Platal::globals()->geocoder->gmaps_hl) {
+                    $geocodedData = $this->getPlacemarkForAddress($toGeocode, $language);
+                    $address->geocodedText = str_replace(', ', "\n", $geocodedData['address']);
+                    if ($extraLines) {
+                        $address->geocodedText = $extraLines . "\n" . $address->geocodedText;
+                    }
+                    if ($this->compareAddress($address)) {
+                        $this->fillAddressWithGeocoding($address, $geocodedData, true);
+                        $address->geocodedText = null;
+                        break;
+                    }
+                }
+            }
             $address->geocodedText = str_replace("\n", "\r\n", $address->geocodedText);
         }
         $address->text = str_replace("\n", "\r\n", $address->text);