event_forum = ""
event_reply = ""
-[Geoloc]
-webservice_url = ""
+[Geocoder]
+email = ""
+gmaps_key = ""
+gmaps_url = "http://maps.google.com/maps/geo"
[Lists]
rpchost = "localhost"
--- /dev/null
+<?php
+/***************************************************************************
+ * Copyright (C) 2003-2009 Polytechnique.org *
+ * http://opensource.polytechnique.org/ *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the Free Software *
+ * Foundation, Inc., *
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *
+ ***************************************************************************/
+
+// Interface for an address geocoder. It provides support for transforming a free
+// form address into a fully structured one.
+// TODO: define and use an Address object instead of a key-value map.
+abstract class Geocoder {
+ // Geocodes @p the address, and returns the corresponding updated address.
+ // Unknown key-value pairs available in the input map are retained as-is.
+ abstract public function getGeocodedAddress(array $address);
+
+ // Updates geoloc_administrativeareas, geoloc_subadministrativeareas and
+ // geoloc_localities databases with new geocoded data and returns the
+ // corresponding id.
+ static public function getAreaId(array &$address, $area)
+ {
+ static $databases = array(
+ 'administrativeArea' => 'geoloc_administrativeareas',
+ 'subAdministrativeArea' => 'geoloc_subadministrativeareas',
+ 'locality' => 'geoloc_localities',
+ );
+
+ if (isset($address[$area . 'Name']) && isset($databases[$area])) {
+ $res = XDB::query("SELECT id
+ FROM " . $databases[$area] . "
+ WHERE name = {?}",
+ $address[$area . 'Name']);
+ if ($res->numRows() == 0) {
+ $address[$area . 'Id'] = XDB::execute("INSERT INTO " . $databases[$area] . " (name, country)
+ VALUES ({?}, {?})",
+ $address[$area . 'Name'], $address['countryId']);
+ } else {
+ $address[$area . 'Id'] = $res->fetchOneCell();
+ }
+ }
+ }
+}
+
+// Implementation of a Geocoder using the Google Maps API. Please refer to
+// the following links for details:
+// http://code.google.com/apis/maps/documentation/services.html#Geocoding
+// http://code.google.com/intl/en/apis/maps/documentation/geocoding/
+// http://code.google.com/apis/maps/documentation/reference.html#GGeoAddressAccuracy
+//
+// It requires the properties gmaps_key and gmaps_url to be defined in section
+// Geocoder in plat/al's configuration (platal.ini & platal.conf).
+class GMapsGeocoder extends Geocoder {
+
+ // Maximum number of Geocoding calls to the Google Maps API.
+ const MAX_GMAPS_RPC_CALLS = 5;
+
+ public function getGeocodedAddress(array $address) {
+ $address = $this->prepareAddress($address);
+ $textAddress = $address['text'];
+
+ // Try to geocode the full address.
+ if (($geocodedData = $this->getPlacemarkForAddress($textAddress))) {
+ return $this->getUpdatedAddress($address, $geocodedData, null);
+ }
+
+ // If the full geocoding failed, try to geocode only the final part of the address.
+ // We start by geocoding everything but the first line, and continue until we get
+ // a result. To respect the limit of GMaps calls, we ignore the first few lines
+ // if there are too many address lines.
+ $addressLines = explode("\n", $textAddress);
+ $linesCount = count($addressLines);
+ 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))) {
+ return $this->getUpdatedAddress($address, $geocodedData, $extraLines);
+ }
+ }
+
+ // No geocoding could be done, the initial address is returned as-is.
+ return $address;
+ }
+
+ // Updates the address with the geocoded information from Google Maps. Also
+ // cleans up the final informations.
+ private function getUpdatedAddress(array $address, array $geocodedData, $extraLines) {
+ $this->fillAddressWithGeocoding(&$address, $geocodedData);
+
+ // If the accuracy is 6, it means only the street has been gecoded
+ // but not the number, thus we need to fix it.
+ if ($address['accuracy'] == 6) {
+ $this->fixStreetNumber($address);
+ }
+
+ // We can now format the address.
+ $this->formatAddress($address, $extraLines);
+
+ // Some entities in ISO 3166 are not countries, thus they have to be replaced
+ // by the country they belong to.
+ // TODO: fixCountry($address);
+
+ return $address;
+ }
+
+ // 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);
+ $geoData = $this->getGeoJsonFromUrl($url);
+
+ return ($geoData ? $this->getPlacemarkFromJson($geoData) : null);
+ }
+
+ // Prepares address to be geocoded
+ private function prepareAddress($address) {
+ $address['text'] = preg_replace('/\s*\n\s*/m', "\n", trim($address['text']));
+ // TODO: $address['postalAddress'] = getPostalAddress($address['text']);
+ $address['updateTime'] = time();
+ unset($address['changed']);
+ return $address;
+ }
+
+ // Builds the Google Maps geocoder url to fetch information about @p address.
+ // Returns the built url.
+ private function getGeocodingUrl($address) {
+ global $globals;
+
+ $parameters = array(
+ 'key' => $globals->geocoder->gmaps_key,
+ 'sensor' => 'false', // The queried address wasn't obtained from a GPS sensor.
+ 'hl' => 'fr', // Output langage.
+ 'oe' => 'utf8', // Output encoding.
+ 'output' => 'json', // Output format.
+ 'gl' => 'fr', // Location preferences (addresses are in France by default).
+ 'q' => $address, // The queries address.
+ );
+
+ return $globals->geocoder->gmaps_url . '?' . http_build_query($parameters);
+ }
+
+ // Fetches JSON-encoded data from a Google Maps API url, and decode them.
+ // Returns the json array on success, and null otherwise.
+ private function getGeoJsonFromUrl($url) {
+ global $globals;
+
+ // Prepare a backtrace object to log errors.
+ $bt = null;
+ if ($globals->debug & DEBUG_BT) {
+ if (!isset(PlBacktrace::$bt['Geoloc'])) {
+ new PlBacktrace('Geoloc');
+ }
+ $bt = &PlBacktrace::$bt['Geoloc'];
+ $bt->start($url);
+ }
+
+ // Fetch the geocoding data.
+ $rawData = file_get_contents($url);
+ if (!$rawData) {
+ if ($bt) {
+ $bt->stop(0, "Could not retrieve geocoded address from GoogleMaps.");
+ }
+ return null;
+ }
+
+ // Decode the JSON-encoded data, and check for their validity.
+ $data = json_decode($rawData, true);
+ if ($bt) {
+ $bt->stop(count($data), null, $data);
+ }
+
+ return $data;
+ }
+
+ // Extracts the most appropriate placemark from the JSON data fetched from
+ // Google Maps. Returns a Placemark array on success, and null otherwise. See
+ // http://code.google.com/apis/maps/documentation/services.html#Geocoding_Structured
+ // for details on the Placemark structure.
+ private function getPlacemarkFromJson(array $data) {
+ // Check for geocoding failures.
+ if (!isset($data['Status']['code']) || $data['Status']['code'] != 200) {
+ // TODO: handle non-200 codes in a better way, since the code might
+ // indicate a temporary error on Google's side.
+ return null;
+ }
+
+ // Check that at least one placemark was found.
+ if (count($data['Placemark']) == 0) {
+ return null;
+ }
+
+ // Extract the placemark with the best accuracy. This is not always the
+ // best result (since the same address may yield two different placemarks).
+ $result = $data['Placemark'][0];
+ foreach ($data['Placemark'] as $place) {
+ if ($place['AddressDetails']['Accuracy'] > $result['AddressDetails']['Accuracy']) {
+ $result = $place;
+ }
+ }
+
+ return $result;
+ }
+
+ // Fills the address with the geocoded data
+ private function fillAddressWithGeocoding(&$address, $geocodedData) {
+ // 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['geoloc'] = str_replace(", ", "\n", $geocodedData['address']);
+ if (isset($geocodedData['AddressDetails']['Accuracy'])) {
+ $address['accuracy'] = $geocodedData['AddressDetails']['Accuracy'];
+ }
+
+ $currentPosition = $geocodedData['AddressDetails'];
+ if (isset($currentPosition['Country'])) {
+ $currentPosition = $currentPosition['Country'];
+ $address['countryId'] = $currentPosition['CountryNameCode'];
+ $address['country'] = $currentPosition['CountryName'];
+ }
+ if (isset($currentPosition['AdministrativeArea'])) {
+ $currentPosition = $currentPosition['AdministrativeArea'];
+ $address['administrativeAreaName'] = $currentPosition['AdministrativeAreaName'];
+ }
+ if (isset($currentPosition['SubAdministrativeArea'])) {
+ $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'];
+ }
+ if (isset($currentPosition['PostalCode'])) {
+ $address['postalCode'] = $currentPosition['PostalCode']['PostalCodeNumber'];
+ }
+
+ // Gets coordinates.
+ if (isset($geocodedData['Point']['coordinates'][0])) {
+ $address['latitude'] = $geocodedData['Point']['coordinates'][0];
+ }
+ if (isset($geocodedData['Point']['coordinates'][1])) {
+ $address['longitude'] = $geocodedData['Point']['coordinates'][1];
+ }
+ if (isset($geocodedData['ExtendedData']['LatLonBox']['north'])) {
+ $address['north'] = $geocodedData['ExtendedData']['LatLonBox']['north'];
+ }
+ if (isset($geocodedData['ExtendedData']['LatLonBox']['south'])) {
+ $address['south'] = $geocodedData['ExtendedData']['LatLonBox']['south'];
+ }
+ if (isset($geocodedData['ExtendedData']['LatLonBox']['east'])) {
+ $address['east'] = $geocodedData['ExtendedData']['LatLonBox']['east'];
+ }
+ if (isset($geocodedData['ExtendedData']['LatLonBox']['west'])) {
+ $address['west'] = $geocodedData['ExtendedData']['LatLonBox']['west'];
+ }
+ }
+
+ // 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, $extraLines) {
+ $same = true;
+ if ($extraLines) {
+ $address['geoloc'] = $extraLines . "\n" . $address['geoloc'];
+ }
+ $geoloc = strtoupper(preg_replace(array("/[0-9,\"'#~:;_\- ]/", "/\r\n/"),
+ array("", "\n"), $address['geoloc']));
+ $text = strtoupper(preg_replace(array("/[0-9,\"'#~:;_\- ]/", "/\r\n/"),
+ array("", "\n"), $address['text']));
+ $arrayGeoloc = explode("\n", $geoloc);
+ $arrayText = explode("\n", $text);
+ $countGeoloc = count($arrayGeoloc);
+ $countText = count($arrayText);
+
+ if (($countText > $countGeoloc) || ($countText < $countGeoloc - 1)
+ || (($countText == $countGeoloc - 1)
+ && ($arrayText[$countText - 1] == strtoupper($address['country'])))) {
+ $same = false;
+ } else {
+ for ($i = 0; $i < $countGeoloc && $i < $countText; ++$i) {
+ if (levenshtein($arrayText[$i], trim($arrayGeoloc[$i])) > 3) {
+ $same = false;
+ }
+ }
+ }
+ if ($same) {
+ $address['text'] = $address['geoloc'];
+ unset($address['geoloc']);
+ }
+ }
+
+ // Search for the lign from the given address that is the closest to the geocoded thoroughfareName
+ // and replaces the corresponding lign in the geocoded text by it.
+ static protected function fixStreetNumber(&$address)
+ {
+ if (isset($address['thoroughfareName'])) {
+ $thoroughfareName = $address['thoroughfareName'];
+ $thoroughfareToken = strtoupper(trim(preg_replace(array("/[,\"'#~:;_\-]/", "/\r\n/"),
+ array("", "\n"), $thoroughfareName)));
+ $geolocLines = explode("\n", $address['geoloc']);
+ $textLines = explode("\n", $address['text']);
+ $mindist = strlen($thoroughfareToken);
+ $minpos = 0;
+ $pos = 0;
+ foreach ($textLines as $i => $token) {
+ if (($l = levenshtein(strtoupper(trim(preg_replace(array("/[,\"'#~:;_\-]/", "/\r\n/"),
+ array("", "\n"), $token))),
+ $thoroughfareToken)) < $mindist) {
+ $mindist = $l;
+ $minpos = $i;
+ }
+ }
+ foreach ($geolocLines as $i => $line) {
+ if (strtoupper(trim($thoroughfareName)) == strtoupper(trim($line))) {
+ $pos = $i;
+ break;
+ }
+ }
+ $geolocLines[$pos] = $textLines[$minpos];
+ $address['geoloc'] = implode("\n", $geolocLines);
+ }
+ }
+}
+
+// vim:set et sw=4 sts=4 sws=4 foldmethod=marker enc=utf-8:
+?>
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *
***************************************************************************/
-// {{{ geoloc_country($current, $avail_only = false)
-/** donne la liste déroulante des pays
- * @param $current pays actuellement selectionné
- */
-function geoloc_country($current, $avail_only = false)
-{
- if ($avail_only) {
- $res = XDB::iterRow('SELECT g.a2, g.pays
- FROM geoloc_pays AS g
- INNER JOIN adresses AS a ON(a.country = g.a2)
- GROUP BY g.a2
- ORDER BY g.pays');
- } else {
- $res = XDB::iterRow('SELECT a2,pays FROM geoloc_pays ORDER BY pays');
- }
- $html = "";
- while (list($my_id, $my_pays) = $res->next()) {
- $html .= sprintf("<option value=\"%s\" %s>%s</option>\n",
- $my_id, ($current==$my_id?"selected='selected'":""), $my_pays);
- }
- return $html;
-}
-
-// }}}
-// {{{ geoloc_region($country, $current, $avail_only = false)
-/** donne la liste deroulante des regions pour un pays
- * @param $pays le pays dont on veut afficher les regions
- * @param $current la region actuellement selectionnee
- */
-function geoloc_region($country, $current, $avail_only = false)
-{
- if ($avail_only) {
- $res = XDB::iterRow('SELECT r.region, r.name
- FROM geoloc_region AS r
- INNER JOIN adresses AS a ON (a.country = r.a2 AND a.region = r.region)
- WHERE r.a2 = {?}
- GROUP BY r.region
- ORDER BY r.name', $country);
- } else {
- $res = XDB::iterRow('SELECT region,name
- FROM geoloc_region
- WHERE a2 = {?}
- ORDER BY name', $country);
- }
- $html = "<option value=\"\"></option>";
- while (list($regid, $regname) = $res->next()) {
- $html .= sprintf("<option value=\"%s\" %s>%s</option>\n",
- $regid, ($current==$regid?"selected='selected'":""), $regname);
- }
- return $html;
-}
-// }}}
-// {{{ get_cities_maps($array)
-/* get all the maps id of the cities contained in an array */
-function get_cities_maps($array)
-{
- global $globals;
- implode("\n",$array);
- $url = $globals->geoloc->webservice_url."findMaps.php?datatext=".urlencode(implode("\n", $array));
- if (!($f = @fopen($url, 'r'))) return false;
- $maps = array();
- while (!feof($f))
- {
- $l = trim(fgets($f));
- $tab = explode(';', $l);
- $i = $tab[0];
- unset($tab[0]);
- $maps[$i] = $tab;
- }
- return $maps;
-}
-// }}}
-// {{{ get_new_maps($url)
-/** set new maps from url **/
-function get_new_maps($url)
-{
- if (!($f = @fopen($url, 'r'))) {
- return false;
- }
- XDB::query('TRUNCATE TABLE geoloc_maps');
- $s = '';
- while (!feof($f)) {
- $l = fgetcsv($f, 1024, ';', '"');
- foreach ($l as $i => $val) {
- if ($val != 'NULL') {
- $l[$i] = '\''.addslashes($val).'\'';
- }
- }
- $s .= ',('.implode(',',$l).')';
- }
- XDB::execute('INSERT INTO geoloc_maps VALUES '.substr($s, 1));
- return true;
-}
-// }}}
-// {{{ geolocGoogle (array $address)
-// retrieve the infos on a text address
-
-function geolocGoogle (array &$address)
-{
- /* keys
- * www.polytechnique.org:
- * ABQIAAAAIlFNe1A494mwR9Zf4R3t0xRsw9kzQBeaENRP66lRw7Ru3uVJcRR73lY1tmAdYGqw-pyHTdynmicz0w
- * www.polytechnique.net and dev.polytechnique.net:
- * ABQIAAAAIlFNe1A494mwR9Zf4R3t0xT8SmDPc83znji5QwIVTgAvxgX5zRRMagHx_rmGeQF5SnCzmyqiSeSAxA
- * dev.m4x.org:
- * ABQIAAAAIlFNe1A494mwR9Zf4R3t0xQ31muaRX97DHXrOFfMwMMCxEnhaxQIPDe9Ct3D6ZvWuGiWllkGAP3IqA
- *
- * Documentation:
- * http://code.google.com/intl/fr/apis/maps/documentation/geocoding/
- * http://code.google.com/apis/maps/documentation/reference.html#GGeoAddressAccuracy */
-
- $success = true;
- $key = 'ABQIAAAAIlFNe1A494mwR9Zf4R3t0xQ31muaRX97DHXrOFfMwMMCxEnhaxQIPDe9Ct3D6ZvWuGiWllkGAP3IqA';
- $webservice = "http://maps.google.com/maps/geo?";
- $baseurl = $webservice . "&key=$key" . "&sensor=false&output=json&oe=utf8&gl=fr&hl=fr&q=";
-
- $url = $baseurl . urlencode($address['text']);
- if (!geolocalizeAddress($url, $gAddress)) {
- $addressLines = explode("\n", $address['text']);
- $nbLines = count($addressLines);
- $currentState = array();
- $success = false;
- for ($i = 1; !$success && ($i < $nbLines); $i++) {
- for ($j = 0; $j < $i; $j++) {
- $currentState[$j] = 0;
- }
- while($j < $nbLines) {
- $currentState[$j] = 1;
- $j++;
- }
- do {
- $partialAddress = "";
- for ($j = 0; $j < $nbLines; $j++) {
- if ($currentState[$j] == 1) {
- $partialAddress .= $addressLines[$j] . " ";
- }
- }
- $url = $baseurl . urlencode(trim($partialAddress));
- $success = geolocalizeAddress($url, $gAddress);
- } while (!$success && nextCurrentState($currentState, $nbLines));
- }
- if ($success) {
- $extras = "";
- for ($i = 0; $i < $nbLines; $i++) {
- if ($currentState[$i] == 0) {
- $extras .= $addressLines[$i] . ", ";
- }
- }
- trim($extras, ", ");
- $address['extras'] = $extras;
- }
- }
- if ($success) {
- fillAddress($address, $gAddress);
- formatAddress($address);
- }
- return $success;
-}
-
-// }}}
-// {{{ nextCurrentState(&$currentState, $nbLines)
-
-function nextCurrentState(&$currentState, $nbLines)
-{
- $lastOne = 0;
- $nbZeros = 2;
- for ($i = 0; $i < $nbLines; $i++) {
- if ($currentState[$i] == 1) {
- $lastOne = $i;
- $nbZeros = 2;
- } else {
- $nbZeros++;
- }
- }
- if ($lastOne == 0) {
- return false;
- } elseif ($currentState[$lastOne - 1] == 0) {
- $currentState[$lastOne - 1] = 1;
- $currentState[$lastOne] = 0;
- return true;
- } else {
- $lastZero = -1;
- for ($j = 0; $j < $lastOne; $j++) {
- if ($currentState[$j] == 0) {
- $lastZero = $j;
- }
- }
- if ($lastZero == -1) {
- return false;
- } else {
- $currentState[$lastZero] = 1;
- for ($k = $lastZero + 1; $k < $lastZero + $nbZeros; $k++) {
- $currentState[$k] = 0;
- }
- for ($k = $lastZero + $nbZeros; $k < $nbLines; $k++) {
- $currentState[$k] = 1;
- }
- return true;
- }
- }
-}
-
-// }}}
-// {{{ geolocalizeAddress ($url, &$result)
-
-function geolocalizeAddress ($url, &$result = array())
-{
- global $globals;
-
- if ($globals->debug & DEBUG_BT) {
- if (!isset(PlBacktrace::$bt['Geoloc'])) {
- new PlBacktrace('Geoloc');
- }
- PlBacktrace::$bt['Geoloc']->start($url);
- }
-
- if ($f = file_get_contents($url, 'r')) {
- $data = json_decode($f, true);
- if ($globals->debug & DEBUG_BT) {
- PlBacktrace::$bt['Geoloc']->stop(count($data), null, $data);
- }
- if ($data['Status']['code'] != 200) {
- return false;
- }
- $nbResults = count($data['Placemark']);
- $idAccuracy = 0;
- if ($nbResults > 1) {
- $bestAccuracy = $data['Placemark'][0]['AddressDetails']['Accuracy'];
- for ($i = 1; $i < $nbResults; $i++) {
- if ($data['Placemark'][$i]['AddressDetails']['Accuracy'] > $bestAccuracy) {
- unset($data['Placemark'][$idAccuracy]);
- $bestAccuracy = $data['Placemark'][$i]['AddressDetails']['Accuracy'];
- $idAccuracy = $i;
- } else {
- unset($data['Placemark'][$i]);
- }
- }
- }
- $result = $data['Placemark'][$idAccuracy];
- return true;
- }
- if ($globals->debug & DEBUG_BT) {
- PlBacktrace::$bt['Geoloc']->stop(0, "Can't fetch result.");
- }
- return false;
-}
-
-// }}}
-// {{{ fillAddress(array &$address, $gAddress)
-
-function fillAddress(array &$address, array $gAddress)
-{
- // An address is Country -> AdministrativeArea -> SubAdministrativeArea -> Locality -> Thoroughfare
- // with all the shortcuts possible
-
- // postalText
- $address['geoloc'] = str_replace(", ", "\n", $gAddress['address']);
- if (isset($gAddress['AddressDetails']['Accuracy'])) {
- $address['accuracy'] = $gAddress['AddressDetails']['Accuracy'];
- }
- $currentPosition = $gAddress['AddressDetails'];
- if (isset($currentPosition['Country'])) {
- $currentPosition = $currentPosition['Country'];
- $address['countryId'] = $currentPosition['CountryNameCode'];
- $address['country'] = $currentPosition['CountryName'];
- }
- if (isset($currentPosition['AdministrativeArea'])) {
- $currentPosition = $currentPosition['AdministrativeArea'];
- $address['administrativeAreaName'] = $currentPosition['AdministrativeAreaName'];
- }
- if (isset($currentPosition['SubAdministrativeArea'])) {
- $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'];
- }
- if (isset($currentPosition['PostalCode'])) {
- $address['postalCode'] = $currentPosition['PostalCode']['PostalCodeNumber'];
- }
-
- // Coordinates
- if (isset($gAddress['Point']['coordinates'][0])) {
- $address['latitude'] = $gAddress['Point']['coordinates'][0];
- }
- if (isset($gAddress['Point']['coordinates'][1])) {
- $address['longitude'] = $gAddress['Point']['coordinates'][1];
- }
- if (isset($gAddress['ExtendedData']['LatLonBox']['north'])) {
- $address['north'] = $gAddress['ExtendedData']['LatLonBox']['north'];
- }
- if (isset($gAddress['ExtendedData']['LatLonBox']['south'])) {
- $address['south'] = $gAddress['ExtendedData']['LatLonBox']['south'];
- }
- if (isset($gAddress['ExtendedData']['LatLonBox']['east'])) {
- $address['east'] = $gAddress['ExtendedData']['LatLonBox']['east'];
- }
- if (isset($gAddress['ExtendedData']['LatLonBox']['west'])) {
- $address['west'] = $gAddress['ExtendedData']['LatLonBox']['west'];
- }
-}
-
-// }}}
-// {{{ formatAddress(array &$address)
-
-function formatAddress(array &$address)
-{
- $same = true;
- $text = strtoupper(preg_replace(array("/[0-9,\"'#~:;_\- ]/", "/\r\n/"),
- array("", "\n"), $address['text']));
- $geoloc = strtoupper(preg_replace(array("/[0-9,\"'#~:;_\- ]/", "/\r\n/"),
- array("", "\n"), $address['geoloc']));
- if (isset($address['extras']) && $address['extras']) {
- $address['geoloc'] = $address['extras'] . "\n" . $address['geoloc'];
- $extras = strtoupper(preg_replace(array("/[0-9,\"'#~:;_\- ]/", "/\r\n/"),
- array("", "\n"), $address['extras']));
- $geoloc = $extras . $geoloc;
- unset($address['extras']);
- }
-
- $arrayText = explode("\n", $text);
- $arrayGeoloc = explode("\n", $geoloc);
- $nbText = count($arrayText);
- $nbGeoloc = count($arrayGeoloc);
-
- if ((($nbText > $nbGeoloc) || ($nbText < $nbGeoloc - 1))
- || (($nbText == $nbGeoloc - 1) && ($arrayText[$nbText - 1] == strtoupper($address['country'])))) {
- $same = false;
- } else {
- foreach ($arrayText as $i => $lignText) {
- if (levenshtein($lignText, trim($arrayGeoloc[$i])) > 3) {
- $same = false;
- }
- }
- }
- if ($same) {
- $address['text'] = $address['geoloc'];
- unset($address['geoloc']);
- }
-}
-
-// }}}
-// {{{ cleanText(&$text)
-
-function cleanText(&$text)
-{
- $lines = explode("\n", $text);
- $n = count($lines);
- $text = "";
- for ($i = 0; $i < $n; $i++) {
- if (trim($lines[$i])) {
- $text .= trim($lines[$i]) . "\n";
- }
- }
- $text = trim($text);
-}
-
-// }}}
-// {{{ getAreaId(array &$address, $area)
-
-function getAreaId(array &$address, $area)
-{
- if (isset($address[$area . 'Name'])) {
- $res = XDB::query("SELECT id
- FROM geoloc_" . $area . "
- WHERE name = {?}",
- $address[$area . 'Name']);
- if ($res->numRows() == 0) {
- $address[$area . 'Id'] = XDB::execute("INSERT INTO geoloc_" . $area . " (name, country)
- VALUES ({?}, {?})",
- $address[$area . 'Name'], $address['countryId']);
- } else {
- $address[$area . 'Id'] = $res->fetchOneCell();
- }
- }
-}
-
-// }}}
// {{{ get_address_text($adr)
/** make the text of an address that can be read by a mailman
* @param $adr an array with all the usual fields
}
// }}}
-// {{{ fixNumber($oldtext, &$new)
-
-function fixNumber($oldtext, &$new)
-{
- $ThoroughfareName = $new['AddressDetails']['Country']['AdministrativeArea']['SubAdministrativeArea']['Locality']['Thoroughfare']['ThoroughfareName'];
- $ThoroughfareName = trim(strtoupper(preg_replace(array("/[,\"'#~:;_\-]/", "/\r\n/"),
- array("", "\n"), $ThoroughfareName)));
- $oldarray = explode("\n", trim(strtoupper(preg_replace(array("/[,\"'#~:;_\-]/", "/\r\n/"),
- array("", "\n"), $oldtext))));
- $mindist = strlen($ThoroughfareName);
- $minpos = 0;
- foreach ($oldarray as $i => $oldline) {
- if (($l = levenshtein(trim($oldline), $ThoroughfareName)) < $mindist) {
- $mindist = $l;
- $minpos = $i;
- }
- }
- $nb = explode(" ", $oldarray[$minpos]);
- $new['text'] = $nb[0] . " " . $new['text'];
-}
-
-// }}}
// {{{ localize_addresses($uid)
/* localize all the address of a user and modify the database
* if the new address match with the old one
return true;
}
// }}}
+// {{{ geoloc_country($current, $avail_only = false)
+/** donne la liste déroulante des pays
+ * @param $current pays actuellement selectionné
+ */
+function geoloc_country($current, $avail_only = false)
+{
+ if ($avail_only) {
+ $res = XDB::iterRow('SELECT g.a2, g.pays
+ FROM geoloc_pays AS g
+ INNER JOIN adresses AS a ON(a.country = g.a2)
+ GROUP BY g.a2
+ ORDER BY g.pays');
+ } else {
+ $res = XDB::iterRow('SELECT a2,pays FROM geoloc_pays ORDER BY pays');
+ }
+ $html = "";
+ while (list($my_id, $my_pays) = $res->next()) {
+ $html .= sprintf("<option value=\"%s\" %s>%s</option>\n",
+ $my_id, ($current==$my_id?"selected='selected'":""), $my_pays);
+ }
+ return $html;
+}
+
+// }}}
+// {{{ geoloc_region($country, $current, $avail_only = false)
+/** donne la liste deroulante des regions pour un pays
+ * @param $pays le pays dont on veut afficher les regions
+ * @param $current la region actuellement selectionnee
+ */
+function geoloc_region($country, $current, $avail_only = false)
+{
+ if ($avail_only) {
+ $res = XDB::iterRow('SELECT r.region, r.name
+ FROM geoloc_region AS r
+ INNER JOIN adresses AS a ON (a.country = r.a2 AND a.region = r.region)
+ WHERE r.a2 = {?}
+ GROUP BY r.region
+ ORDER BY r.name', $country);
+ } else {
+ $res = XDB::iterRow('SELECT region,name
+ FROM geoloc_region
+ WHERE a2 = {?}
+ ORDER BY name', $country);
+ }
+ $html = "<option value=\"\"></option>";
+ while (list($regid, $regname) = $res->next()) {
+ $html .= sprintf("<option value=\"%s\" %s>%s</option>\n",
+ $regid, ($current==$regid?"selected='selected'":""), $regname);
+ }
+ return $html;
+}
+// }}}
+// {{{ get_cities_maps($array)
+/* get all the maps id of the cities contained in an array */
+function get_cities_maps($array)
+{
+ global $globals;
+ implode("\n",$array);
+ $url = $globals->geoloc->webservice_url."findMaps.php?datatext=".urlencode(implode("\n", $array));
+ if (!($f = @fopen($url, 'r'))) return false;
+ $maps = array();
+ while (!feof($f))
+ {
+ $l = trim(fgets($f));
+ $tab = explode(';', $l);
+ $i = $tab[0];
+ unset($tab[0]);
+ $maps[$i] = $tab;
+ }
+ return $maps;
+}
+// }}}
+// {{{ get_new_maps($url)
+/** set new maps from url **/
+function get_new_maps($url)
+{
+ if (!($f = @fopen($url, 'r'))) {
+ return false;
+ }
+ XDB::query('TRUNCATE TABLE geoloc_maps');
+ $s = '';
+ while (!feof($f)) {
+ $l = fgetcsv($f, 1024, ';', '"');
+ foreach ($l as $i => $val) {
+ if ($val != 'NULL') {
+ $l[$i] = '\''.addslashes($val).'\'';
+ }
+ }
+ $s .= ',('.implode(',',$l).')';
+ }
+ XDB::execute('INSERT INTO geoloc_maps VALUES '.substr($s, 1));
+ return true;
+}
+// }}}
function geoloc_to_x($lon, $lat)
{
private function saveAddress($addrid, array &$address)
{
- require_once "geoloc.inc.php";
+ require_once "geocoding.inc.php";
$flags = new PlFlagSet();
if ($address['current']) {
array("", "\n"), $address['text'])), 'CEDEX')) !== false) {
$flags->addFlag('cedex');
}
- getAreaId($address, "administrativeArea");
- getAreaId($address, "subAdministrativeArea");
- getAreaId($address, "locality");
+ Geocoder::getAreaId($address, "administrativeArea");
+ Geocoder::getAreaId($address, "subAdministrativeArea");
+ Geocoder::getAreaId($address, "locality");
XDB::execute("INSERT INTO profile_addresses (pid, type, id, flags, accuracy,
text, postalText, postalCode, localityId,
subAdministrativeAreaId, administrativeAreaId,
{
protected function geolocAddress(array &$address, &$success)
{
- require_once 'geoloc.inc.php';
+ require_once 'geocoding.inc.php';
$success = true;
if ($address['changed'] == 1) {
- cleanText($address['text']);
- geolocGoogle($address);
- $address['updateTime'] = time();
- // postalAddress
+ $gmapsGeocoder = new GMapsGeocoder();
+ $address = $gmapsGeocoder->getGeocodedAddress($address);
if (isset($address['geoloc'])) {
$success = false;
}
- unset($address['changed']);
}
if (isset($address['geoloc_choice']) && $address['geoloc_choice'] == 0) {
$mailer = new PlMailer('geoloc/geoloc.mail.tpl');
SELECT a2, a3, n3, worldrgn, pays, country, capital, nat, phoneprf, phoneformat, license_plate
FROM geoloc_pays;
-CREATE TABLE IF NOT EXISTS geoloc_administrativeArea (
+CREATE TABLE IF NOT EXISTS geoloc_administrativeareas (
id INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
name VARCHAR(255) NOT NULL,
country CHAR(2) NOT NULL,
INDEX(country)
) CHARSET=utf8;
-CREATE TABLE IF NOT EXISTS geoloc_subAdministrativeArea (
+CREATE TABLE IF NOT EXISTS geoloc_subadministrativeareas (
id INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
name VARCHAR(255) NOT NULL,
country CHAR(2) NOT NULL,
INDEX(country)
) CHARSET=utf8;
-CREATE TABLE IF NOT EXISTS geoloc_locality (
+CREATE TABLE IF NOT EXISTS geoloc_localities (
id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
name VARCHAR(255) NOT NULL,
country CHAR(2) NOT NULL,