server/src/app/Services/GeonamesResolver.php
changeset 304 20071981ba2a
child 308 e032d686d88e
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/app/Services/GeonamesResolver.php	Tue Sep 27 23:43:29 2016 +0200
@@ -0,0 +1,123 @@
+<?php
+namespace CorpusParole\Services;
+
+use CorpusParole\Services\GeonamesResolverInterface;
+
+use Cache;
+use Config;
+use EasyRdf\Graph;
+use GuzzleHttp\Client;
+use GuzzleHttp\Exception\RequestException;
+use GuzzleHttp\Exception\ClientException;
+use GuzzleHttp\Exception\GuzzleException;
+use Illuminate\Contracts\Cache\Repository as CacheRepository;
+
+class GeonamesResolver implements GeonamesResolverInterface {
+
+    private $client = null;
+
+    public function __construct(Client $httpClient) {
+        $this->client = $httpClient;
+    }
+
+    /**
+     * make the Geonames query.
+     */
+    public function queryLabel($id) {
+
+        $url = config('corpusparole.geonames_base_url').$id."/";
+
+        try {
+            $response = $this->client->get($url, ['headers'=>['Accept' => 'application/rdf+xml'],]);
+        }
+        catch(ClientException $e) {
+            if($e->getResponse()->getStatusCode() === 404) {
+                return null;
+            } else {
+                throw new GeonamesResolverException(
+                    $e->getMessage(),
+                    $e->getResponse()->getStatusCode(),
+                    $e
+                );
+            }
+        }
+        catch(RequestException $e) {
+            throw new GeonamesResolverException(
+                $e->getMessage(),
+                $e->hasResponse()?$e->getResponse()->getStatusCode():500,
+                $e
+            );
+        }
+
+        $graph = new Graph($url, $response->getBody());
+        $labels = [];
+        // search First offficial name in fr then name
+        foreach ($graph->allLiterals("<$url>", "<http://www.geonames.org/ontology#officialName>") as $labelLit) {
+            $lang = $labelLit->getLang();
+            if(!$lang && !isset($labels[''])) {
+                $labels[''] = $labelLit->getvalue();
+            }
+            elseif (strpos($lang, 'fr') === 0 && !isset($labels['fr'])) {
+                $labels['fr'] = $labelLit->getvalue();
+            }
+        }
+
+        $label = isset($labels['fr']) ? $labels['fr'] : ( isset($labels[''])? $labels['']: null) ;
+
+        if(is_null($label)) {
+            $labelLit = $graph->getLiteral("<$url>", "<http://www.geonames.org/ontology#name>");            
+            $label = (!is_null($labelLit)) ? $labelLit->getValue() : null;
+        }
+
+        return $label;
+    }
+
+    /**
+     * Check Geonames id format
+     */
+    private function checkGeonamesIdFormat($geonamesid) {
+        return ctype_digit($geonamesid);
+    }
+
+    /**
+     * Get name from Geonames id
+     * @param string $id The id to resolve. Can be an url starting with http://sws.geonames.org/
+     * @return a string with the name
+     */
+    public function getLabel($id) {
+        $geonamesid = $id;
+        if(strpos($id, config('corpusparole.geonames_base_url')) === 0) {
+            $geonamesid = substr($id, strlen(config('corpusparole.geonames_base_url')));
+        }
+        $geonamesid = rtrim($geonamesid, '/');
+
+        if(!$this->checkGeonamesIdFormat($geonamesid)) {
+            throw new GeonamesResolverException("GeonamesId not in correct format", 400);
+        }
+
+        $that = $this;
+
+        return Cache::remember("geonames:$geonamesid", config('corpusparole.geonames_cache_expiration'), function() use ($that, $geonamesid)  {
+
+            return $that->queryLabel($geonamesid);
+
+        });
+
+    }
+
+    /**
+     * Get a list of names from an array of geonames ids.
+     * @param array $ids The array of ids to resolve.
+     *                   Each id can be an url starting with http://geonames.org/geonames/
+     */
+    public function getLabels(array $ids) {
+
+        if(count($ids) > config('corpusparole.geonames_max_ids')) {
+            throw new GeonamesResolverException("Too manys ids provided");
+        }
+
+        return array_combine($ids, array_map([$this,'getLabel'], $ids));
+    }
+
+
+}