X-Git-Url: http://git.polytechnique.org/?a=blobdiff_plain;f=classes%2Fgmapsgeocoder.php;h=ec42adfac2557fbe1a4ac5189c48d56a8e5d0ffb;hb=b7502335ed5c1f9d674a7717b28d186946bb7f39;hp=405bad1599c8e7fe141d614170d040b054cfff89;hpb=b869da13aaaaef80157a192ef240a3d364f7d4d1;p=platal.git diff --git a/classes/gmapsgeocoder.php b/classes/gmapsgeocoder.php index 405bad1..ec42adf 100644 --- a/classes/gmapsgeocoder.php +++ b/classes/gmapsgeocoder.php @@ -1,6 +1,6 @@ prepareAddress($address); $textAddress = $this->getTextToGeocode($address->text); + if (is_null($defaultLanguage)) { + $defaultLanguage = Platal::globals()->geocoder->gmaps_hl; + } // Try to geocode the full address. - if (($geocodedData = $this->getPlacemarkForAddress($textAddress))) { - $this->getUpdatedAddress($address, $geocodedData, null); + if (($geocodedData = $this->getPlacemarkForAddress($textAddress, $defaultLanguage))) { + $this->getUpdatedAddress($address, $geocodedData, null, $forceLanguage); return; } @@ -55,16 +58,15 @@ class GMapsGeocoder extends Geocoder { for ($i = max(1, $linesCount - self::MAX_GMAPS_RPC_CALLS + 1); $i < $linesCount; ++$i) { $extraLines = implode("\n", array_slice($addressLines, 0, $i)); $toGeocode = implode("\n", array_slice($addressLines, $i)); - if (($geocodedData = $this->getPlacemarkForAddress($toGeocode))) { - $this->getUpdatedAddress($address, $geocodedData, $extraLines); + if (($geocodedData = $this->getPlacemarkForAddress($toGeocode, $defaultLanguage))) { + $this->getUpdatedAddress($address, $geocodedData, $extraLines, $forceLanguage); return; } } } - public function stripGeocodingFromAddress(Address &$address) { + public function stripGeocodingFromAddress(Address $address) { $address->geocodedText = null; - $address->geocodedPostalText = null; $address->geoloc_choice = null; $address->countryId = null; $address->country = null; @@ -78,38 +80,38 @@ 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->formatAddress($address, $extraLines); + private function getUpdatedAddress(Address $address, array $geocodedData, $extraLines, $forceLanguage) { + $this->fillAddressWithGeocoding($address, $geocodedData, false); + $this->formatAddress($address, $extraLines, $forceLanguage); } // 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) { + $url = $this->getGeocodingUrl($address, $defaultLanguage); $geoData = $this->getGeoJsonFromUrl($url); return ($geoData ? $this->getPlacemarkFromJson($geoData) : null); } // Prepares address to be geocoded - private function prepareAddress(Address &$address) { + private function prepareAddress(Address $address) { $address->text = preg_replace('/\s*\n\s*/m', "\n", trim($address->text)); - $address->postalText = $this->getPostalAddress($address->text); } // 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' => $defaultLanguage, 'oe' => 'utf8', // Output encoding. 'output' => 'json', // Output format. - 'gl' => 'fr', // Location preferences (addresses are in France by default). + 'gl' => $globals->geocoder->gmaps_gl, 'q' => $address, // The queries address. ); @@ -179,38 +181,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']; @@ -237,15 +246,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; - } - $address->geocodedPostalText = $this->getPostalAddress($address->geocodedText); $geoloc = strtoupper(preg_replace(array("/[0-9,\"'#~:;_\- ]/", "/\r\n/"), array('', "\n"), $address->geocodedText)); $text = strtoupper(preg_replace(array("/[0-9,\"'#~:;_\- ]/", "/\r\n/"), @@ -271,59 +276,46 @@ class GMapsGeocoder extends Geocoder { } } - if ($same) { - $address->geocodedText = null; - $address->geocodedPostalText = null; - } else { - $address->geocodedText = str_replace("\n", "\r\n", $address->geocodedText); - $address->geocodedPostalText = str_replace("\n", "\r\n", $address->geocodedPostalText); - } - $address->text = str_replace("\n", "\r\n", $address->text); - $address->postalText = str_replace("\n", "\r\n", $address->postalText); + return $same; } - // Returns the address formated for postal use. - // The main rules are (cf AFNOR XPZ 10-011): - // -everything in upper case; - // -if there are more then than 38 characters in a line, split it; - // -if there are more then than 32 characters in the description of the "street", use abbreviations. - private function getPostalAddress($text) { - static $abbreviations = array( - 'IMPASSE' => 'IMP', - 'RUE' => 'R', - 'AVENUE' => 'AV', - 'BOULEVARD' => 'BVD', - 'ROUTE' => 'R', - 'STREET' => 'ST', - 'ROAD' => 'RD', - ); - - $text = strtoupper($text); - $arrayText = explode("\n", $text); - $postalText = ''; - - foreach ($arrayText as $i => $line) { - $postalText .= (($i == 0) ? '' : "\n"); - if (($length = strlen($line)) > 32) { - $words = explode(' ', $line); - $count = 0; - foreach ($words as $word) { - if (isset($abbreviations[$word])) { - $word = $abbreviations[$word]; + // 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, $forceLanguage) + { + if ($extraLines) { + $address->geocodedText = $extraLines . "\n" . $address->geocodedText; + } + + if ($this->compareAddress($address)) { + $address->geocodedText = null; + } elseif (!$forceLanguage) { + $languages = XDB::fetchOneCell('SELECT IF(ISNULL(gc1.belongsTo), gl1.language, gl2.language) + FROM geoloc_countries AS gc1 + INNER JOIN geoloc_languages AS gl1 ON (gc1.iso_3166_1_a2 = gl1.iso_3166_1_a2) + LEFT JOIN geoloc_countries AS gc2 ON (gc1.belongsTo = gc2.iso_3166_1_a2) + LEFT JOIN geoloc_languages AS gl2 ON (gc2.iso_3166_1_a2 = gl2.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 ($count + ($wordLength = strlen($word)) <= 38) { - $postalText .= (($count == 0) ? '' : ' ') . $word; - $count += (($count == 0) ? 0 : 1) + $wordLength; - } else { - $postalText .= "\n" . $word; - $count = strlen($word); + if ($this->compareAddress($address)) { + $this->fillAddressWithGeocoding($address, $geocodedData, true); + $address->geocodedText = null; + break; } } - } else { - $postalText .= $line; } + $address->geocodedText = str_replace("\n", "\r\n", $address->geocodedText); } - return $postalText; + $address->text = str_replace("\n", "\r\n", $address->text); } // Trims the name of the real country if it contains an ISO 3166-1 non-country @@ -331,7 +323,7 @@ class GMapsGeocoder extends Geocoder { // all non-country items of ISO 3166-1. private function getTextToGeocode($text) { - $res = XDB::iterator('SELECT country, countryFR + $res = XDB::iterator('SELECT countryEn, country FROM geoloc_countries WHERE belongsTo IS NOT NULL'); $countries = array(); @@ -343,10 +335,12 @@ class GMapsGeocoder extends Geocoder { $countLines = count($textLines); $needle = strtoupper(trim($textLines[$countLines - 2])); $isPseudoCountry = false; - foreach ($countries as $country) { - if (strtoupper($country) == $needle) { - $isPseudoCountry = true; - break; + if ($needle) { + foreach ($countries as $country) { + if (strtoupper($country) === $needle) { + $isPseudoCountry = true; + break; + } } }