11<?php
22namespace PHPFacile \Geocoding \Db \Service ;
33
4+ use PHPFacile \Openstreetmap \Service \OpenstreetmapServiceInterface ;
5+
46use Zend \Db \Adapter \AdapterInterface ;
57use Zend \Db \Sql \Sql ;
68
9+ use Exceptions \Data \NotFoundException ;
10+ use Exceptions \Data \FoundTooManyException ;
11+
712class LocationService
813{
914 /**
10- * @var Adapater
15+ * @var Adapter
1116 */
1217 protected $ adapter ;
1318
@@ -25,7 +30,7 @@ public function __construct(AdapterInterface $adapter)
2530 $ this ->adapter = $ adapter ;
2631 }
2732
28- public function setOpenstreetmapService ($ openstreetmapService )
33+ public function setOpenstreetmapService (OpenstreetmapServiceInterface $ openstreetmapService )
2934 {
3035 $ this ->openstreetmapService = $ openstreetmapService ;
3136 }
@@ -35,14 +40,15 @@ public function setOpenstreetmapService($openstreetmapService)
3540 *
3641 * @param StdClass $geocodedLocation Geocoded location as returned by phpfacile/geocoding
3742 *
38- * @throws Exception In case the geocoded location is not found or if there are several matches
43+ * @throws NotFoundException In case the geocoded location is not found
44+ * @throws FoundTooManyException If there are several matches
3945 *
4046 * @return string Id in the database
4147 */
4248 public function getGeocoderLocationIdFromGeocodedPlaceStdClass ($ geocodedLocation )
4349 {
4450 $ where = [
45- 'geocoding_provider ' => $ geocodedLocation ->geocoding ->provider ,
51+ 'geocoding_provider ' => $ geocodedLocation ->geocoding ->provider ,
4652 'geocoder_object_id ' => $ geocodedLocation ->geocoding ->idProvider ,
4753 ];
4854
@@ -55,10 +61,10 @@ public function getGeocoderLocationIdFromGeocodedPlaceStdClass($geocodedLocation
5561 $ rows = $ stmt ->execute ();
5662 if (false === ($ row = $ rows ->current ())) {
5763 // TODO replace with a NotFoundException
58- throw new \ Exception ( ' Not found ' );
64+ throw new NotFoundException ( ' Geocoder location [ ' . $ geocodedLocation -> geocoding -> provider . ' : ' . $ geocodedLocation -> geocoding -> idProvider . ' ] not found ' );
5965 } else if (false !== $ rows ->next ()) {
6066 // TODO replace with a TooManyHitsException
61- throw new \ Exception ('Too many hits ' );
67+ throw new FoundTooManyException ('Too many geocoder locations found for [ ' . $ geocodedLocation -> geocoding -> provider . ' : ' . $ geocodedLocation -> geocoding -> idProvider . ' ] ' );
6268 }
6369
6470 return $ row ['id ' ];
@@ -79,13 +85,13 @@ public function insertGeocoderLocationOfGeocodedPlaceStdClass($geocodedLocation)
7985 1st step - Actually store the geocoder location data
8086 */
8187 $ geocoding = $ geocodedLocation ->geocoding ;
82- $ values ['geocoding_datetime_utc ' ] = $ geocoding ->geocodingDateTimeUTC ;
83- $ values ['geocoding_provider ' ] = $ geocoding ->provider ;
84- $ values ['geocoder_object_id ' ] = $ geocoding ->idProvider ;
85- $ values ['geocoded_latitude ' ] = $ geocoding ->coordinates ->latitude ;
86- $ values ['geocoded_longitude ' ] = $ geocoding ->coordinates ->longitude ;
87- $ values ['geocoded_country_code ' ] = $ geocoding ->country ->isoCode ;
88- $ values ['geocoded_timezone ' ] = $ geocoding ->timezone ;
88+ $ values ['geocoding_datetime_utc ' ] = $ geocoding ->geocodingDateTimeUTC ;
89+ $ values ['geocoding_provider ' ] = $ geocoding ->provider ;
90+ $ values ['geocoder_object_id ' ] = $ geocoding ->idProvider ;
91+ $ values ['geocoded_latitude ' ] = $ geocoding ->coordinates ->latitude ;
92+ $ values ['geocoded_longitude ' ] = $ geocoding ->coordinates ->longitude ;
93+ $ values ['geocoded_country_code ' ] = $ geocoding ->country ->isoCode ;
94+ $ values ['geocoded_timezone ' ] = $ geocoding ->timezone ;
8995
9096 $ sql = new Sql ($ this ->adapter );
9197 $ query = $ sql
@@ -101,16 +107,18 @@ public function insertGeocoderLocationOfGeocodedPlaceStdClass($geocodedLocation)
101107 in future. So as to be able to geocode places with (almost) no more
102108 external geocoder API call.
103109 */
110+ $ placeNames = [];
111+ $ postalCodes = [];
104112 switch ($ geocodedLocation ->geocoding ->provider ) {
105113 case 'nominatim ' :
106- $ relation = $ this ->openstreetmapService ->getRelationById ($ geocodedLocation ->geocoding ->idProvider );
107- $ officialName = $ relation ->getOfficialName ();
108- $ placeNames = $ relation ->getNames ();
109- $ placePostalCodes = $ relation ->getPostalCodes ();
110- // TODO Not sure this is the best way to retrieve the country code
114+ $ relation = $ this ->openstreetmapService ->getRelationById ($ geocodedLocation ->geocoding ->idProvider );
115+ $ officialName = $ relation ->getOfficialName ();
116+ $ placeNames = $ relation ->getNames ();
117+ $ postalCodes = $ relation ->getPostalCodes ();
118+ // FIXME Not sure this is the best way to retrieve the country code
111119 $ countryCode = $ geocodedLocation ->country ->code ;
112- if (1 === count ($ placePostalCodes )) {
113- $ keptPostalCode = $ placePostalCodes [0 ];
120+ if (1 === count ($ postalCodes )) {
121+ $ keptPostalCode = $ postalCodes [0 ];
114122 } else {
115123 // probably several postal codes for the same area
116124 $ keptPostalCode = null ;
@@ -124,32 +132,59 @@ public function insertGeocoderLocationOfGeocodedPlaceStdClass($geocodedLocation)
124132 // or with same name and postal code in the same country?
125133 try {
126134 $ placeId = $ this ->getIdOfPlaceByNamePostalCodeCountryCodeEtc ($ officialName , $ keptPostalCode , $ countryCode , $ geocodedLocation ->geocoding ->provider , $ geocodedLocation ->geocoding ->idProvider );
127- } catch (\Exception $ e ) {
128- // TODO replace with a NotFoundException
129- if ('Not found ' === $ e ->getMessage ()) {
130- // Ok insert
131- $ values = [];
132- $ values ['name ' ] = $ officialName ;
133- $ values ['postal_code ' ] = $ keptPostalCode ;
134- $ values ['country_code ' ] = $ countryCode ;
135- $ values ['best_geocoder_location_id ' ] = $ geocoderDataId ;
136-
137- $ sql = new Sql ($ this ->adapter );
135+ } catch (NotFoundException $ e ) {
136+ // Ok insert
137+ $ values = [];
138+ $ values ['name ' ] = $ officialName ;
139+ $ values ['postal_code ' ] = $ keptPostalCode ;
140+ $ values ['country_code ' ] = $ countryCode ;
141+ $ values ['best_geocoder_location_id ' ] = $ geocoderDataId ;
142+
143+ $ sql = new Sql ($ this ->adapter );
144+ $ query = $ sql
145+ ->insert ('places ' )
146+ ->values ($ values );
147+ $ stmt = $ sql ->prepareStatementForSqlObject ($ query );
148+ $ stmt ->execute ();
149+
150+ $ placeId = $ this ->adapter ->getDriver ()->getLastGeneratedValue ();
151+
152+ // Store alternative names
153+ foreach ($ placeNames as $ locale => $ name )
154+ {
155+ if (2 === strlen ($ locale )) {
156+ // Huho... I really need to find the right way to use prepared statements
157+ $ query = $ sql
158+ ->insert ('place_names ' )
159+ ->values (
160+ [
161+ 'place_id ' => $ placeId ,
162+ 'locale ' => $ locale ,
163+ 'name ' => $ name ,
164+ ]
165+ );
166+ $ stmt = $ sql ->prepareStatementForSqlObject ($ query );
167+ $ stmt ->execute ();
168+ }
169+ }
170+
171+ // Store all postal codes
172+ foreach ($ postalCodes as $ postalCode )
173+ {
174+ // Huho... I really need to find the right way to use prepared statements
138175 $ query = $ sql
139- ->insert ('places ' )
140- ->values ($ values );
176+ ->insert ('place_postal_codes ' )
177+ ->values (
178+ [
179+ 'place_id ' => $ placeId ,
180+ 'postal_code ' => $ postalCode ,
181+ ]
182+ );
141183 $ stmt = $ sql ->prepareStatementForSqlObject ($ query );
142184 $ stmt ->execute ();
143-
144- $ placeId = $ this ->adapter ->getDriver ()->getLastGeneratedValue ();
145- } else {
146- throw new \Exception ('Failure ' , 0 , $ e );
147185 }
148186 }
149187
150- // TODO Store alternative names
151- // TODO Store all zipcodes
152-
153188 $ sql = new Sql ($ this ->adapter );
154189 $ query = $ sql
155190 ->update ('geocoder_locations ' )
@@ -177,14 +212,9 @@ public function getGeocoderLocationIdFromGeocodedPlaceStdClassAfterInsertIfNeede
177212 {
178213 try {
179214 $ id = $ this ->getGeocoderLocationIdFromGeocodedPlaceStdClass ($ geocodedLocation );
180- } catch (\Exception $ e ) {
181- // TODO replace with a NotFoundException
182- if ('Not found ' === $ e ->getMessage ()) {
183- // Ok insert
184- $ id = $ this ->insertGeocoderLocationOfGeocodedPlaceStdClass ($ geocodedLocation );
185- } else {
186- throw new \Exception ('Failure ' , 0 , $ e );
187- }
215+ } catch (NotFoundException $ e ) {
216+ // Ok insert
217+ $ id = $ this ->insertGeocoderLocationOfGeocodedPlaceStdClass ($ geocodedLocation );
188218 }
189219
190220 return $ id ;
@@ -230,6 +260,6 @@ public function getIdOfPlaceByNamePostalCodeCountryCodeEtc($officialName, $keptP
230260 return $ row ['place_id ' ];
231261 }
232262
233- throw new \ Exception ( ' Not found ' );
263+ throw new NotFoundException ( ' Place [ ' . $ officialName . ' ] not found ' );
234264 }
235265}
0 commit comments