server/src/app/Services/GeonamesResolver.php
changeset 314 f5690d918358
parent 308 e032d686d88e
child 550 fbd1bfc9f963
equal deleted inserted replaced
313:706f10bcdc3c 314:f5690d918358
       
     1 <?php
       
     2 namespace CorpusParole\Services;
       
     3 
       
     4 use CorpusParole\Services\GeonamesResolverInterface;
       
     5 
       
     6 use Cache;
       
     7 use Config;
       
     8 use EasyRdf\Graph;
       
     9 use GuzzleHttp\Client;
       
    10 use GuzzleHttp\Exception\RequestException;
       
    11 use GuzzleHttp\Exception\ClientException;
       
    12 use GuzzleHttp\Exception\GuzzleException;
       
    13 use Illuminate\Contracts\Cache\Repository as CacheRepository;
       
    14 
       
    15 class GeonamesResolver implements GeonamesResolverInterface {
       
    16 
       
    17     private $client = null;
       
    18 
       
    19     public function __construct(Client $httpClient) {
       
    20         $this->client = $httpClient;
       
    21     }
       
    22 
       
    23     /**
       
    24      * make the Geonames query.
       
    25      */
       
    26     public function queryLabel($id) {
       
    27 
       
    28         $url = config('corpusparole.geonames_base_url').$id."/";
       
    29 
       
    30         try {
       
    31             $response = $this->client->get($url, ['headers'=>['Accept' => 'application/rdf+xml'],]);
       
    32         }
       
    33         catch(ClientException $e) {
       
    34             if($e->getResponse()->getStatusCode() === 404) {
       
    35                 return null;
       
    36             } else {
       
    37                 throw new GeonamesResolverException(
       
    38                     $e->getMessage(),
       
    39                     $e->getResponse()->getStatusCode(),
       
    40                     $e
       
    41                 );
       
    42             }
       
    43         }
       
    44         catch(RequestException $e) {
       
    45             throw new GeonamesResolverException(
       
    46                 $e->getMessage(),
       
    47                 $e->hasResponse()?$e->getResponse()->getStatusCode():500,
       
    48                 $e
       
    49             );
       
    50         }
       
    51 
       
    52         $graph = new Graph($url, $response->getBody());
       
    53         $labels = [];
       
    54         // search First offficial name in fr then name
       
    55         foreach ($graph->allLiterals("<$url>", "<http://www.geonames.org/ontology#officialName>") as $labelLit) {
       
    56             $lang = $labelLit->getLang();
       
    57             if(!$lang && !isset($labels[''])) {
       
    58                 $labels[''] = $labelLit->getvalue();
       
    59             }
       
    60             elseif (strpos($lang, 'fr') === 0 && !isset($labels['fr'])) {
       
    61                 $labels['fr'] = $labelLit->getvalue();
       
    62             }
       
    63         }
       
    64 
       
    65         $label = isset($labels['fr']) ? $labels['fr'] : ( isset($labels[''])? $labels['']: null) ;
       
    66 
       
    67         if(is_null($label)) {
       
    68             $labelLit = $graph->getLiteral("<$url>", "<http://www.geonames.org/ontology#name>");
       
    69             $label = (!is_null($labelLit)) ? $labelLit->getValue() : null;
       
    70         }
       
    71 
       
    72         return $label;
       
    73     }
       
    74 
       
    75     /**
       
    76      * Check Geonames id format
       
    77      */
       
    78     private function checkGeonamesIdFormat($geonamesid) {
       
    79         return ctype_digit($geonamesid);
       
    80     }
       
    81 
       
    82     /**
       
    83      * Get name from Geonames id
       
    84      * @param string $id The id to resolve. Can be an url starting with http://sws.geonames.org/
       
    85      * @return a string with the name
       
    86      */
       
    87     public function getLabel($id) {
       
    88         $geonamesid = $id;
       
    89         $matches = [];
       
    90         if( preg_match(config('corpusparole.geonames_url_regexp'), $id, $matches) === 1) {
       
    91             $geonamesid = $matches[1];
       
    92         }
       
    93         $geonamesid = rtrim($geonamesid, '/');
       
    94 
       
    95         if(!$this->checkGeonamesIdFormat($geonamesid)) {
       
    96             throw new GeonamesResolverException("GeonamesId not in correct format", 400);
       
    97         }
       
    98 
       
    99         $that = $this;
       
   100 
       
   101         return Cache::remember("geonames:$geonamesid", config('corpusparole.geonames_cache_expiration'), function() use ($that, $geonamesid)  {
       
   102 
       
   103             return $that->queryLabel($geonamesid);
       
   104 
       
   105         });
       
   106 
       
   107     }
       
   108 
       
   109     /**
       
   110      * Get a list of names from an array of geonames ids.
       
   111      * @param array $ids The array of ids to resolve.
       
   112      *                   Each id can be an url starting with http://geonames.org/geonames/
       
   113      */
       
   114     public function getLabels(array $ids) {
       
   115 
       
   116         if(count($ids) > config('corpusparole.geonames_max_ids')) {
       
   117             throw new GeonamesResolverException("Too manys ids provided");
       
   118         }
       
   119 
       
   120         return array_combine($ids, array_map([$this,'getLabel'], $ids));
       
   121     }
       
   122 
       
   123 
       
   124 }