diff --git a/.circleci/config.yml b/.circleci/config.yml index 7488ad93..df7dc433 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -54,7 +54,7 @@ jobs: - run: sed -i 's/HONEYPOT_DISABLE=.*$/HONEYPOT_DISABLE=TRUE/g' .env # Add in private values. - - run: sudo sed -ie "s/GOOGLE_MAPS_API_KEY=zzz/GOOGLE_MAPS_API_KEY=$GOOGLE_MAPS_API_KEY/g" .env + - run: sudo sed -ie "s/MAPBOX_TOKEN=zzz/MAPBOX_TOKEN=$MAPBOX_TOKEN/g" .env - run: sudo sed -ie "s/GRAVITYFORMS_KEY=zzz/GRAVITYFORMS_KEY=$GRAVITYFORMS_KEY/g" .env - run: sudo sed -ie "s/GRAVITYFORMS_SECRET=zzz/GRAVITYFORMS_SECRET=$GRAVITYFORMS_SECRET/g" .env - run: sudo sed -ie "s/GRAVITYFORMS_SUBMISSION_FORM_ID=zzz/GRAVITYFORMS_SUBMISSION_FORM_ID=$GRAVITYFORMS_SUBMISSION_FORM_ID/g" .env diff --git a/.env.example b/.env.example index 45850996..fc97b988 100644 --- a/.env.example +++ b/.env.example @@ -55,7 +55,7 @@ MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}" PHANTOM_PATH= -GOOGLE_MAPS_API_KEY=zzz +MAPBOX_TOKEN=zzz GA_TRACKING_ID= MAP_SHARE_BASE_URL=https://map.restarters.test diff --git a/app/Console/Commands/GeocodeCheck.php b/app/Console/Commands/GeocodeCheck.php index 48b7a652..8f28a42a 100644 --- a/app/Console/Commands/GeocodeCheck.php +++ b/app/Console/Commands/GeocodeCheck.php @@ -72,16 +72,15 @@ public function handle(BusinessRepository $repository, Geocoder $geocoder) if ($businesses) { foreach ($businesses as $business) { $count++; - $address = "{$business->getAddress()},{$business->getCity()},{$business->getLocalAreaName()},{$business->getPostcode()}"; - $point = $geocoder->geocode($address); + $point = $geocoder->geocode($business->getPostcode()); if (!$point) { // The address doesn't geocode. Log an error, with the expectation that the spreadsheet // will then get fixed. - $this->error("{$business->getUid()} can't geocode $address"); + $this->error("{$business->getUid()} can't geocode {$business->getPostcode()}"); $invalid++; } else { - #$this->info("{$business->getUid()} geocoded $address to " . $point->getLatitude() . "," . $point->getLongitude()); + #$this->info("{$business->getUid()} geocoded {$business->getPostcode()} to " . $point->getLatitude() . "," . $point->getLongitude()); } } } else { diff --git a/app/Console/Commands/ImportBusinessesSpreadsheet.php b/app/Console/Commands/ImportBusinessesSpreadsheet.php index 54c9f794..fe0c5055 100644 --- a/app/Console/Commands/ImportBusinessesSpreadsheet.php +++ b/app/Console/Commands/ImportBusinessesSpreadsheet.php @@ -149,12 +149,12 @@ public function handle(EntityManagerInterface $em, Geocoder $geocoder, BusinessR $point = null; try { - $point = $geocoder->geocode("$address,$city,$borough,$postcode"); + $point = $geocoder->geocode($postcode); if ($point && ($point->getLatitude() < $swlat || $point->getLatitude() > $nelat || $point->getLongitude() < $swlng || $point->getLongitude() > $nelng)) { // The address doesn't geocode. Log an error, with the expectation that the spreadsheet // will then get fixed. - $this->error("$name address $address geocodes to invalid lat/lng " . $point->getLatitude() . "," . $point->getLongitude()); + $this->error("$name address $postcode geocodes to invalid lat/lng " . $point->getLatitude() . "," . $point->getLongitude()); $point = null; } } catch (\Exception $e) { diff --git a/app/Console/Commands/ReGeocode.php b/app/Console/Commands/ReGeocode.php new file mode 100644 index 00000000..14910e46 --- /dev/null +++ b/app/Console/Commands/ReGeocode.php @@ -0,0 +1,142 @@ + 'address', + 'operator' => Operators::NOT_EQUAL, + 'value' => '' + ], + [ + 'field' => 'postcode', + 'operator' => Operators::NOT_EQUAL, + 'value' => '' + ], + [ + 'field' => 'city', + 'operator' => Operators::NOT_EQUAL, + 'value' => '' + ], + [ + 'field' => 'publishingStatus', + 'operator' => Operators::EQUAL, + 'value' => PublishingStatus::PUBLISHED + ] + ]; + + $businesses = $repository->findBy($criteria); + $count = 0; + $invalid = 0; + + if ($businesses) { + foreach ($businesses as $business) { + $count++; + $address = $business->getPostcode(); + + if ($address == 'N23 6HL') { + $address = '13 Market Street, Ebbw Vale NP23 6HL'; + } else if ($address == 'EC1 Y8QP' || $address == 'EC1Y8QP') { + $address = '195 Whitecross Street, London, EC1Y 8QP'; + } else if ($address == 'W1T 1BZ') { + $address = '38 Tottenham Court Road, London, W1T 1BZ'; + } + + $point = $geocoder->geocode($address); + + if (!$point) { + // The address doesn't geocode. Log an error, with the expectation that the spreadsheet + // will then get fixed. + $this->error("{$business->getUid()} can't geocode $address"); + $invalid++; + } else { + $geolocation = $business->getGeolocation(); + + $dist = round($this->haversineGreatCircleDistance($geolocation->getLatitude(), $geolocation->getLongitude(), $point->getLatitude(), $point->getLongitude())); + #$this->info("{$business->getUid()} geocoded $address to " . $point->getLatitude() . "," . $point->getLongitude()) . " distance $dist"; + + if ($dist > 500) { + $this->error("{$business->getUid()} was {$geolocation->getLatitude()}, {$geolocation->getLongitude()} geocoded $address to {$point->getLatitude()},{$point->getLongitude()} distance {$dist}m"); + $invalid++; + } else { + $business->setGeolocation($point); + } + } + } + } else { + $this->error("No businesses found"); + } + + $this->info("Checked $count, found $invalid invalid"); + } +} diff --git a/composer.json b/composer.json index 0f81482d..d2d0b524 100644 --- a/composer.json +++ b/composer.json @@ -9,6 +9,7 @@ "type": "project", "require": { "php": "^8.0", + "geocoder-php/mapbox-provider": "^1.4", "guzzlehttp/guzzle": "^7.2", "laracasts/utilities": "^3.2", "laravel-doctrine/migrations": "^3.0", @@ -27,7 +28,6 @@ "paquettg/php-html-parser": "^1.7", "php-coveralls/php-coveralls": "^2.5", "phpoffice/phpspreadsheet": "^1.19", - "skagarwal/google-places-api": "^2.0", "symfony/http-client": "^6.2", "symfony/mailgun-mailer": "^6.2", "toin0u/geocoder-laravel": "^4.5" diff --git a/composer.lock b/composer.lock index 3a4368ed..71dbcf71 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "b86b78f5e0a399b1692321fd0d07c024", + "content-hash": "fa6c9853ce98b2cdbf2f877f2e507e1f", "packages": [ { "name": "brick/math", @@ -1914,6 +1914,65 @@ }, "time": "2022-07-30T12:09:30+00:00" }, + { + "name": "geocoder-php/mapbox-provider", + "version": "1.4.0", + "source": { + "type": "git", + "url": "https://github.com/geocoder-php/mapbox-provider.git", + "reference": "95287b1c4724de32a1552bdaa27e53d7a9490fe8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/geocoder-php/mapbox-provider/zipball/95287b1c4724de32a1552bdaa27e53d7a9490fe8", + "reference": "95287b1c4724de32a1552bdaa27e53d7a9490fe8", + "shasum": "" + }, + "require": { + "geocoder-php/common-http": "^4.0", + "php": "^7.4 || ^8.0", + "willdurand/geocoder": "^4.0" + }, + "provide": { + "geocoder-php/provider-implementation": "1.0" + }, + "require-dev": { + "geocoder-php/provider-integration-tests": "^1.0", + "php-http/curl-client": "^2.2", + "php-http/message": "^1.0", + "phpunit/phpunit": "^9.5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "psr-4": { + "Geocoder\\Provider\\Mapbox\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fede Isas", + "email": "federicoisas@gmail.com" + } + ], + "description": "Geocoder Mapbox adapter", + "homepage": "http://geocoder-php.org/Geocoder/", + "support": { + "source": "https://github.com/geocoder-php/mapbox-provider/tree/1.4.0" + }, + "time": "2022-07-30T12:09:30+00:00" + }, { "name": "graham-campbell/result-type", "version": "v1.1.0", @@ -6170,73 +6229,6 @@ ], "time": "2023-01-12T18:13:24+00:00" }, - { - "name": "skagarwal/google-places-api", - "version": "2.1.0", - "source": { - "type": "git", - "url": "https://github.com/SachinAgarwal1337/google-places-api.git", - "reference": "75b0877ba3618168cf9ae885878cd426db17d0d7" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/SachinAgarwal1337/google-places-api/zipball/75b0877ba3618168cf9ae885878cd426db17d0d7", - "reference": "75b0877ba3618168cf9ae885878cd426db17d0d7", - "shasum": "" - }, - "require": { - "guzzlehttp/guzzle": "^6.5.7|^7.4.4|^7.2", - "illuminate/container": "^6.0|^7.0|^8.0|^9.0|^10.0", - "illuminate/support": "^6.0|^7.0|^8.0|^9.0|^10.0", - "php": "^7.2.5|^8.0" - }, - "require-dev": { - "phpunit/phpunit": "~4.0|^9.3", - "skagarwal/reflection": "~1.0" - }, - "type": "library", - "extra": { - "laravel": { - "providers": [ - "SKAgarwal\\GoogleApi\\ServiceProvider" - ], - "aliases": { - "GooglePlaces": "SKAgarwal\\GoogleApi\\Facade" - } - } - }, - "autoload": { - "files": [ - "src/helpers.php" - ], - "psr-4": { - "SKAgarwal\\GoogleApi\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Sachin Agarwal", - "email": "sachinkumaragarwal05@gmail.com" - } - ], - "description": "Google Places Api", - "keywords": [ - "Google Places Api", - "google", - "google api", - "google places", - "places" - ], - "support": { - "issues": "https://github.com/SachinAgarwal1337/google-places-api/issues", - "source": "https://github.com/SachinAgarwal1337/google-places-api/tree/2.1.0" - }, - "time": "2016-02-05T00:00:00+00:00" - }, { "name": "symfony/config", "version": "v6.2.5", diff --git a/config/app.php b/config/app.php index 0823430e..331fdc29 100644 --- a/config/app.php +++ b/config/app.php @@ -205,8 +205,51 @@ | */ - 'aliases' => Facade::defaultAliases()->merge([ + 'aliases' => [ + 'App' => Illuminate\Support\Facades\App::class, + 'Arr' => Illuminate\Support\Arr::class, + 'Artisan' => Illuminate\Support\Facades\Artisan::class, + 'Auth' => Illuminate\Support\Facades\Auth::class, + 'Blade' => Illuminate\Support\Facades\Blade::class, + 'Broadcast' => Illuminate\Support\Facades\Broadcast::class, + 'Bus' => Illuminate\Support\Facades\Bus::class, + 'Cache' => Illuminate\Support\Facades\Cache::class, + 'Config' => Illuminate\Support\Facades\Config::class, + 'Cookie' => Illuminate\Support\Facades\Cookie::class, + 'Crypt' => Illuminate\Support\Facades\Crypt::class, + 'Date' => Illuminate\Support\Facades\Date::class, + 'DB' => Illuminate\Support\Facades\DB::class, + 'Eloquent' => Illuminate\Database\Eloquent\Model::class, + 'Event' => Illuminate\Support\Facades\Event::class, + 'File' => Illuminate\Support\Facades\File::class, + 'Gate' => Illuminate\Support\Facades\Gate::class, + 'Hash' => Illuminate\Support\Facades\Hash::class, + 'Http' => Illuminate\Support\Facades\Http::class, + 'Js' => Illuminate\Support\Js::class, + 'Lang' => Illuminate\Support\Facades\Lang::class, + 'Log' => Illuminate\Support\Facades\Log::class, + 'Mail' => Illuminate\Support\Facades\Mail::class, + 'Notification' => Illuminate\Support\Facades\Notification::class, + 'Password' => Illuminate\Support\Facades\Password::class, + 'Queue' => Illuminate\Support\Facades\Queue::class, + 'RateLimiter' => Illuminate\Support\Facades\RateLimiter::class, + 'Redirect' => Illuminate\Support\Facades\Redirect::class, 'Redis' => Illuminate\Support\Facades\Redis::class, - ])->toArray(), + 'Request' => Illuminate\Support\Facades\Request::class, + 'Response' => Illuminate\Support\Facades\Response::class, + 'Route' => Illuminate\Support\Facades\Route::class, + 'Schema' => Illuminate\Support\Facades\Schema::class, + 'Session' => Illuminate\Support\Facades\Session::class, + 'Storage' => Illuminate\Support\Facades\Storage::class, + 'Str' => Illuminate\Support\Str::class, + 'URL' => Illuminate\Support\Facades\URL::class, + 'Validator' => Illuminate\Support\Facades\Validator::class, + 'View' => Illuminate\Support\Facades\View::class, + 'Drip' => wouterNL\Drip\Facades\DripFacade::class, + 'FixometerHelper' => App\Helpers\Fixometer::class, + 'Honeypot' => Msurguy\Honeypot\HoneypotFacade::class, + 'Image' => Intervention\Image\Facades\Image::class, + 'LaravelLocalization' => Mcamara\LaravelLocalization\Facades\LaravelLocalization::class, + ] ]; diff --git a/config/geocoder.php b/config/geocoder.php index e87396a0..9ac18ffe 100644 --- a/config/geocoder.php +++ b/config/geocoder.php @@ -9,14 +9,18 @@ * file that was distributed with this source code. */ -use Geocoder\Provider\GoogleMaps\GoogleMaps; +use Geocoder\Provider\Mapbox\Mapbox; +use Geocoder\Provider\Photon\Photon; return [ 'cache-duraction' => 999999999, 'providers' => [ - GoogleMaps::class => [ - null, - env('GOOGLE_MAPS_API_KEY'), + Mapbox::class => [ + env('MAPBOX_TOKEN'), + 'GB' ], +// Photon::class => [ +// 'https://photon.komoot.io/', +// ] ] ]; diff --git a/config/google.php b/config/google.php deleted file mode 100644 index 0aade306..00000000 --- a/config/google.php +++ /dev/null @@ -1,8 +0,0 @@ - [ - 'key' => env('GOOGLE_PLACES_API_KEY', 'AIzaSyCEfAuFCUd6xGwdnUny1Hk4wUwKG147rao'), - ], -]; diff --git a/src/Application/Commands/Business/ImportFromHttpRequest/ImportFromHttpRequestFactory.php b/src/Application/Commands/Business/ImportFromHttpRequest/ImportFromHttpRequestFactory.php index 0981bcc2..e0c6d1c7 100644 --- a/src/Application/Commands/Business/ImportFromHttpRequest/ImportFromHttpRequestFactory.php +++ b/src/Application/Commands/Business/ImportFromHttpRequest/ImportFromHttpRequestFactory.php @@ -117,7 +117,7 @@ protected function transformRequestData($data) protected function geocodeData($data) { if (!isset($data['geolocation']) && isset($data['address'], $data['postcode'])) { - $point = $this->geocoder->geocode($data['address'] . ', ' . $data['postcode']); + $point = $this->geocoder->geocode($data['postcode']); if ($point) { $data['geolocation'] = [ diff --git a/src/Application/Commands/Business/ImportFromHttpRequest/ImportFromHttpRequestHandler.php b/src/Application/Commands/Business/ImportFromHttpRequest/ImportFromHttpRequestHandler.php index 98822493..2df570eb 100644 --- a/src/Application/Commands/Business/ImportFromHttpRequest/ImportFromHttpRequestHandler.php +++ b/src/Application/Commands/Business/ImportFromHttpRequest/ImportFromHttpRequestHandler.php @@ -106,7 +106,7 @@ public function handle(ImportFromHttpRequestCommand $command) $business->setUpdatedAt(new \DateTime("now")); // We need to re-geocode the address in case it's changed. - $point = $this->geocoder->geocode($business->getAddress() . "," . $business->getCity() . "," . $business->getPostcode()); + $point = $this->geocoder->geocode($business->getPostcode()); if ($point) { $business->setGeolocation($point); diff --git a/src/Infrastructure/Services/GeocoderImpl.php b/src/Infrastructure/Services/GeocoderImpl.php index 64de8b00..83c356a0 100644 --- a/src/Infrastructure/Services/GeocoderImpl.php +++ b/src/Infrastructure/Services/GeocoderImpl.php @@ -6,6 +6,7 @@ use Geocoder\Laravel\ProviderAndDumperAggregator; use TheRestartProject\RepairDirectory\Domain\Models\Point; use TheRestartProject\RepairDirectory\Domain\Services\Geocoder; +use Geocoder\Query\GeocodeQuery; /** * Implements the Geocoder domain interface using the Laravel Geocoder library. @@ -39,14 +40,15 @@ public function __construct($geocoder) /** * Find the [lat, lng] of a business * - * @param string $address The address to geolocate + * @param string $address The address to geolocate. Generally this should be a postcode, since geocoders other + * than Google are not very good at handling the more flexible address formats. * * @return Point|null The location of the address, or null if not found */ public function geocode($address) { try { - $geocodeResponse = $this->geocoder->geocode($address); + $geocodeResponse = $this->geocoder->geocodeQuery(GeocodeQuery::create($address)->withData('location_type', 'postcode')); $addressCollection = $geocodeResponse->get(); $address = $addressCollection->get(0); if ($address) { @@ -55,6 +57,7 @@ public function geocode($address) } catch (ChainNoResult $e) { return null; } + return null; } }