|
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 } |