Skip to content

Commit

Permalink
Merge pull request #62 from sherlockode/feature/place_finders
Browse files Browse the repository at this point in the history
Add Nominatim place search for Open Street Map
  • Loading branch information
Vowow authored Mar 14, 2023
2 parents 74a851c + 0ced02e commit 1213972
Show file tree
Hide file tree
Showing 11 changed files with 209 additions and 34 deletions.
37 changes: 25 additions & 12 deletions src/Controller/Shop/CheckoutController.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
namespace Sherlockode\SyliusMondialRelayPlugin\Controller\Shop;

use Sherlockode\SyliusMondialRelayPlugin\Form\Type\Shop\SearchPickupPointType;
use Sherlockode\SyliusMondialRelayPlugin\Google\Place;
use Sherlockode\SyliusMondialRelayPlugin\MondialRelay\MondialRelay;
use Sherlockode\SyliusMondialRelayPlugin\PlaceFinder\PlaceFinderRegistry;
use Sherlockode\SyliusMondialRelayPlugin\Serializer\PointSerializer;
use Sylius\Component\Order\Context\CartContextInterface;
use Sylius\Component\Shipping\Model\ShipmentInterface;
Expand Down Expand Up @@ -50,15 +50,20 @@ class CheckoutController
private $apiClient;

/**
* @var Place
* @var PlaceFinderRegistry
*/
private $googlePlace;
private $placeFinderRegistry;

/**
* @var PointSerializer
*/
private $pointSerializer;

/**
* @var string
*/
private $mapProvider;

/**
* CheckoutController constructor.
*
Expand All @@ -67,25 +72,28 @@ class CheckoutController
* @param CartContextInterface $cartContext
* @param Environment $twig
* @param MondialRelay $apiClient
* @param Place $googlePlace
* @param PlaceFinderRegistry $placeFinderRegistry
* @param PointSerializer $pointSerializer
* @param string $mapProvider
*/
public function __construct(
UrlGeneratorInterface $urlGenerator,
FormFactoryInterface $formFactory,
CartContextInterface $cartContext,
Environment $twig,
MondialRelay $apiClient,
Place $googlePlace,
PointSerializer $pointSerializer
PlaceFinderRegistry $placeFinderRegistry,
PointSerializer $pointSerializer,
?string $mapProvider
) {
$this->urlGenerator = $urlGenerator;
$this->formFactory = $formFactory;
$this->cartContext = $cartContext;
$this->twig = $twig;
$this->apiClient = $apiClient;
$this->googlePlace = $googlePlace;
$this->placeFinderRegistry = $placeFinderRegistry;
$this->pointSerializer = $pointSerializer;
$this->mapProvider = $mapProvider;
}

/**
Expand Down Expand Up @@ -155,10 +163,14 @@ public function searchPickupPoints(Request $request): JsonResponse
$actions = $form->get('types')->getData();

if ($suggestion) {
$suggestedZipCode = $this->googlePlace->retrieveSuggestionZipCode($suggestion);
$finder = $this->placeFinderRegistry->getFinder($this->mapProvider);

if ($finder) {
$suggestedZipCode = $finder->find($suggestion);

if ($suggestedZipCode) {
$zipCode = $suggestedZipCode;
if ($suggestedZipCode) {
$zipCode = $suggestedZipCode;
}
}
}

Expand Down Expand Up @@ -215,12 +227,13 @@ public function getPickupPoint(Request $request): Response
public function autocomplete(Request $request): JsonResponse
{
$query = $request->query->get('query');
$finder = $this->placeFinderRegistry->getFinder($this->mapProvider);

if (!$query) {
if (!$query || !$finder) {
return new JsonResponse();
}

return new JsonResponse($this->googlePlace->getPlaces($query));
return new JsonResponse($finder->search($query));
}

/**
Expand Down
32 changes: 23 additions & 9 deletions src/Google/Place.php → src/PlaceFinder/GooglePlaceFinder.php
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
<?php

namespace Sherlockode\SyliusMondialRelayPlugin\Google;
namespace Sherlockode\SyliusMondialRelayPlugin\PlaceFinder;

class Place
use Sherlockode\SyliusMondialRelayPlugin\Manager\MapProviderManager;

class GooglePlaceFinder implements PlaceFinderInterface
{
/**
* @var string|null
Expand All @@ -17,12 +19,22 @@ public function __construct(?string $apiKey)
$this->apiKey = $apiKey;
}

/**
* @param string|null $type
*
* @return bool
*/
public function supports(?string $type): bool
{
return MapProviderManager::MAP_PROVIDER_GOOGLE === $type;
}

/**
* @param string $query
*
* @return string[]
* @return array
*/
public function getPlaces(string $query): array
public function search(string $query): array
{
$url = 'https://maps.googleapis.com/maps/api/place/autocomplete/json?' . http_build_query([
'input' => $query,
Expand All @@ -41,16 +53,16 @@ public function getPlaces(string $query): array
}

/**
* @param string $placeId
* @param string $id
*
* @return string|null
*/
public function retrieveSuggestionZipCode(string $placeId): ?string
public function find(string $id): ?string
{
$url = 'https://maps.googleapis.com/maps/api/place/details/json?' . http_build_query([
'place_id' => $placeId,
'key' => $this->apiKey,
]);
'place_id' => $id,
'key' => $this->apiKey,
]);
$response = $this->get($url);

foreach ($response['result']['address_components'] ?? [] as $component) {
Expand All @@ -75,7 +87,9 @@ private function get(string $url): array
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, false);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
curl_setopt($ch, CURLOPT_USERAGENT, 'Curl');

$raw = curl_exec($ch);
$response = json_decode($raw, true);
Expand Down
78 changes: 78 additions & 0 deletions src/PlaceFinder/NominatimPlaceFinder.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
<?php

namespace Sherlockode\SyliusMondialRelayPlugin\PlaceFinder;

use Sherlockode\SyliusMondialRelayPlugin\Manager\MapProviderManager;

class NominatimPlaceFinder implements PlaceFinderInterface
{
/**
* @param string|null $type
*
* @return bool
*/
public function supports(?string $type): bool
{
return MapProviderManager::MAP_PROVIDER_OSM === $type;
}

/**
* @param string $query
*
* @return array
*/
public function search(string $query): array
{
$places = $this->get(sprintf(
'https://nominatim.openstreetmap.org/search?q=%s&format=jsonv2&countrycodes=FR',
$query
));

return array_values(array_map(function ($place) {
return [
'id' => $place['place_id'],
'label' => $place['display_name'],
];
}, $places));
}

/**
* @param string $id
*
* @return string|null
*/
public function find(string $id): ?string
{
$place = $this->get(sprintf('https://nominatim.openstreetmap.org/details?place_id=%s&format=json', $id));

return $place['addresstags']['postcode'] ?? null;
}

/**
* @param string $url
*
* @return array
*/
private function get(string $url): array
{
$ch = curl_init();

try {
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, false);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
curl_setopt($ch, CURLOPT_USERAGENT, 'Curl');

$raw = curl_exec($ch);
$response = json_decode($raw, true);
} catch (\Exception $exception) {
$response = [];
} finally {
curl_close($ch);
}

return $response;
}
}
27 changes: 27 additions & 0 deletions src/PlaceFinder/PlaceFinderInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

namespace Sherlockode\SyliusMondialRelayPlugin\PlaceFinder;

interface PlaceFinderInterface
{
/**
* @param string|null $type
*
* @return bool
*/
public function supports(?string $type): bool;

/**
* @param string $query
*
* @return array
*/
public function search(string $query): array;

/**
* @param string $id
*
* @return string|null
*/
public function find(string $id): ?string;
}
35 changes: 35 additions & 0 deletions src/PlaceFinder/PlaceFinderRegistry.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?php

namespace Sherlockode\SyliusMondialRelayPlugin\PlaceFinder;

class PlaceFinderRegistry
{
/**
* @var PlaceFinderInterface[]
*/
private $finders;

/**
* @param iterable $finders
*/
public function __construct(iterable $finders)
{
$this->finders = $finders;
}

/**
* @param string|null $type
*
* @return PlaceFinderInterface|null
*/
public function getFinder(?string $type): ?PlaceFinderInterface
{
foreach ($this->finders as $finder) {
if ($finder->supports($type)) {
return $finder;
}
}

return null;
}
}
2 changes: 1 addition & 1 deletion src/Resources/config/services.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@
<import resource="services/controller.xml"/>
<import resource="services/event_listener.xml"/>
<import resource="services/form.xml"/>
<import resource="services/google.xml"/>
<import resource="services/manager.xml"/>
<import resource="services/mondial_relay.xml"/>
<import resource="services/place_finder.xml"/>
<import resource="services/serializer.xml"/>
<import resource="services/twig.xml"/>
</imports>
Expand Down
3 changes: 2 additions & 1 deletion src/Resources/config/services/controller.xml
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,9 @@
<argument type="service" id="sylius.context.cart.composite" />
<argument type="service" id="twig" />
<argument type="service" id="sherlockode.sylius_mondial_relay_plugin.mondial_relay.bridge" />
<argument type="service" id="sherlockode.sylius_mondial_relay_plugin.google.place" />
<argument type="service" id="sherlockode.sylius_mondial_relay_plugin.place_finder.registry" />
<argument type="service" id="sherlockode.sylius_mondial_relay_plugin.serializer.point" />
<argument>%sherlockode_sylius_mondial_relay.map_provider%</argument>
<tag name="controller.service_arguments" />
</service>
</services>
Expand Down
9 changes: 0 additions & 9 deletions src/Resources/config/services/google.xml

This file was deleted.

16 changes: 16 additions & 0 deletions src/Resources/config/services/place_finder.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8" ?>

<container xmlns="http://symfony.com/schema/dic/services" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
<services>
<service id="sherlockode.sylius_mondial_relay_plugin.place_finder.registry" class="Sherlockode\SyliusMondialRelayPlugin\PlaceFinder\PlaceFinderRegistry">
<argument type="tagged_iterator" tag="sherlockode.sylius_mondial_relay_plugin.place_finder" />
</service>
<service id="sherlockode.sylius_mondial_relay_plugin.place_finder.google" class="Sherlockode\SyliusMondialRelayPlugin\PlaceFinder\GooglePlaceFinder">
<argument>%sherlockode_sylius_mondial_relay.google_api_key%</argument>
<tag name="sherlockode.sylius_mondial_relay_plugin.place_finder" />
</service>
<service id="sherlockode.sylius_mondial_relay_plugin.place_finder.nominatim" class="Sherlockode\SyliusMondialRelayPlugin\PlaceFinder\NominatimPlaceFinder">
<tag name="sherlockode.sylius_mondial_relay_plugin.place_finder" />
</service>
</services>
</container>
2 changes: 1 addition & 1 deletion src/Resources/public/css/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@
display: none;
right: 0;
top: 45px;
z-index: 2;
z-index: 1500;
box-shadow: rgba(149, 157, 165, 0.5) 0 8px 24px;
}

Expand Down
2 changes: 1 addition & 1 deletion src/Resources/public/js/shop.js
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ export default class MondialRelay
if (event.target.getAttribute('data-mr-autocomplete')) {
this.debounce(function () {
this.autocomplete();
}.bind(this), 100)();
}.bind(this), 300)();
}
}.bind(this));
}
Expand Down

0 comments on commit 1213972

Please sign in to comment.