From 2316bfc0e6ac72743dd089b9bbd15af7e475d90f Mon Sep 17 00:00:00 2001 From: TeLiXj Date: Mon, 6 Nov 2017 16:02:26 +0100 Subject: [PATCH] Add place service --- doc/service/place/add/place_add.md | 69 +++++ doc/service/place/add/place_add_request.md | 91 ++++++ doc/service/place/add/place_add_response.md | 30 ++ src/Service/AbstractHttpService.php | 8 +- src/Service/AbstractService.php | 23 +- src/Service/Place/Add/PlaceAddService.php | 66 ++++ .../Place/Add/Request/PlaceAddRequest.php | 288 ++++++++++++++++++ .../Add/Request/PlaceAddRequestInterface.php | 21 ++ .../Place/Add/Response/PlaceAddResponse.php | 121 ++++++++ .../Place/Add/Response/PlaceAddStatus.php | 33 ++ .../Serializer/Place/Add/PlaceAddResponse.xml | 33 ++ 11 files changed, 781 insertions(+), 2 deletions(-) create mode 100644 doc/service/place/add/place_add.md create mode 100644 doc/service/place/add/place_add_request.md create mode 100644 doc/service/place/add/place_add_response.md create mode 100644 src/Service/Place/Add/PlaceAddService.php create mode 100644 src/Service/Place/Add/Request/PlaceAddRequest.php create mode 100644 src/Service/Place/Add/Request/PlaceAddRequestInterface.php create mode 100644 src/Service/Place/Add/Response/PlaceAddResponse.php create mode 100644 src/Service/Place/Add/Response/PlaceAddStatus.php create mode 100644 src/Service/Serializer/Place/Add/PlaceAddResponse.xml diff --git a/doc/service/place/add/place_add.md b/doc/service/place/add/place_add.md new file mode 100644 index 00000000..5d56f20f --- /dev/null +++ b/doc/service/place/add/place_add.md @@ -0,0 +1,69 @@ +# Place Add API + +You can complete Google Maps database sending data from your application. Doing this can help you to show to your users +real information about a place and help Google to fix errors or add a new place. + +## Dependencies + +The Place Add API requires an http client and so, the library relies on [Httplug](http://httplug.io/) which is +an http client abstraction library. It also requires the [Ivory Serializer](https://github.com/egeloen/ivory-serializer) +in order to deserialize the http response. To install them, read this [documentation](/doc/installation.md). + +## Build + +First of all, if you want to add a place, you will need to build a place add service. So let's go: + +``` php +use Ivory\GoogleMap\Service\Place\Add\PlaceAddService; +use Http\Adapter\Guzzle6\Client; +use Http\Message\MessageFactory\GuzzleMessageFactory; + +$place = new PlaceAddService(new Client(), new GuzzleMessageFactory()); +``` + +The Place Add constructor requires an `HttpClient` as first argument and a `MessageFactory` as second argument. +Here, I have chosen to use the [Guzzle6](http://docs.guzzlephp.org/en/latest/psr7.html) client as well as the Guzzle +message factory. Httplug supports the most popular http clients, so, you can choose you preferred one instead. + +The Place Add constructor also accepts a `SerializerInterface` as third argument. It is highly recommended to +use it in order to configure a PSR-6 cache pool and so avoid parsing the built-in metadata every time. + +``` php +use Ivory\GoogleMap\Service\Place\Add\PlaceAddService; +use Ivory\GoogleMap\Service\Serializer\SerializerBuilder; +use Http\Adapter\Guzzle6\Client; +use Http\Message\MessageFactory\GuzzleMessageFactory; + +$add = new PlaceAddService( + new Client(), + new GuzzleMessageFactory(), + SerializerBuilder::create($psr6Pool) +); +``` + +All services works the same way, so, if you want to learn more about it, you can read this common +[documentation](/doc/service/service.md) about services. + +## Request + +Once you have built you place add service, you can process a request: + +``` php +use Ivory\GoogleMap\Base\Coordinate; +use Ivory\GoogleMap\Service\Place\Base\PlaceType; +use Ivory\GoogleMap\Service\Place\Add\Request\PlaceAddRequest; + +$response = $place->process(new PlaceAddRequest( + new Coordinate(-33.8669710, 151.1958750), + 'Google Shoes!', + PlaceType::SHOE_STORE +); +``` + +The place add service allows you to send more information. If you want to learn more about it, you +can read its [documentation](/doc/service/place/add/place_add_request.md). + +## Response + +When you have requested the service, it gives you a response object. If you want to learn more about it, you can read +its [documentation](/doc/service/place/add/place_add_response.md). diff --git a/doc/service/place/add/place_add_request.md b/doc/service/place/add/place_add_request.md new file mode 100644 index 00000000..3b76270f --- /dev/null +++ b/doc/service/place/add/place_add_request.md @@ -0,0 +1,91 @@ +# Place Add Request + +A place add request contains all the information about a place to send it to Google Maps database. + + +## Build + +First of all, if you want to send a place, you will need to build a place add request. So let's go: + +``` php +use Ivory\GoogleMap\Base\Coordinate; +use Ivory\GoogleMap\Service\Place\Base\PlaceType; +use Ivory\GoogleMap\Service\Place\Add\Request\PlaceAddRequest; + +$response = $place->process(new PlaceAddRequest( + new Coordinate(-33.8669710, 151.1958750), + 'Google Shoes!', + PlaceType::SHOE_STORE +); +``` + +The place add request constructor requires the location of the place, a name and a type of place. + +## Configure location + +You can change the location of the place added in constructor sending the coordinates using the Coordinate class. + +``` php +$request->setLocation(new Coordinate(-33.8669710, 151.1958750))); +``` + +## Configure name + +Change the name sending in constructor. This field have a limitation to 255 characters by a Google Maps restriction. + +``` php +$request->setLocation('Google Shoes!'); +``` + +## Configure type + +To change the type sending in constructor you can use the PlaceType class constants. + +``` php +$request->setType(PlaceType::SHOE_STORE); +``` + +## Configure accuracy + +The accuracy of the location in metres + +``` php +$request->setAccuracy(50); +``` + +## Configure address + +The full address of the place it's recommended if you want to pass the moderation process for inclusion in the Google +Maps database. + +``` php +$request->setAddress('48 Pirrama Road, Pyrmont, NSW 2009, Australia'); +``` + +## Configure language + +If you want to configure the language: + +``` php +$request->setLanguage('fr'); +``` + +## Configure phone number + +Like address it's recommended to pass the moderation process + +``` php +$request->setPhoneNumber('(02) 9374 4000'); +``` + +## Configure website + +Like address and phone number it's recommended to pass the moderation process + +``` php +$request->setWebsite('http://www.google.com.au/'); +``` + +##Google Maps docs +This library contains all behaviours to add a place, but if you need extra information can check official documentation +to [Add a place](https://developers.google.com/places/web-service/add-place) in the Google Maps API site diff --git a/doc/service/place/add/place_add_response.md b/doc/service/place/add/place_add_response.md new file mode 100644 index 00000000..b0805c89 --- /dev/null +++ b/doc/service/place/add/place_add_response.md @@ -0,0 +1,30 @@ +# Place Add Response + +When you have requested to add a place, the returned object is a `PlaceAddResponse`. It wraps a place add status, the +Google Maps placeId and the scope. + +## Status + +The available status are defined by the `PlaceAddStatus` constants. + +``` php +$status = $response->getStatus(); +``` + +## PlaceId + +The Google Maps placeId of the new place. + +``` php +$placeId = $response->getPlaceId(); +``` + +## Scope + +The scope of the new place added. Always be APP because the place not yet passed the moderation process + +``` php +$scope = $response->getScope(); +``` + +If you want to learn more about the place, you can read its [documentation](/doc/service/place/base/place.md). diff --git a/src/Service/AbstractHttpService.php b/src/Service/AbstractHttpService.php index 90a629ee..acabfd45 100644 --- a/src/Service/AbstractHttpService.php +++ b/src/Service/AbstractHttpService.php @@ -77,11 +77,17 @@ public function setMessageFactory(MessageFactory $messageFactory) /** * @param RequestInterface $request + * @param string $type GET or POST * * @return PsrRequestInterface */ protected function createRequest(RequestInterface $request) { - return $this->messageFactory->createRequest('GET', $this->createUrl($request)); + return $this->messageFactory->createRequest( + $this->getMethod(), + $this->createUrl($request), + [], + $this->getMethod() == "POST" ? json_encode($request->buildQuery()) : null + ); } } diff --git a/src/Service/AbstractService.php b/src/Service/AbstractService.php index f9e9394b..323e6c3e 100644 --- a/src/Service/AbstractService.php +++ b/src/Service/AbstractService.php @@ -21,6 +21,11 @@ abstract class AbstractService */ private $url; + /** + * @var string GET or POST + */ + private $method = 'GET'; + /** * @var string|null */ @@ -55,6 +60,22 @@ public function setUrl($url) $this->url = $url; } + /** + * @return string + */ + public function getMethod() + { + return $this->method; + } + + /** + * @param string $method + */ + public function setMethod($method) + { + $this->method = $method; + } + /** * @return bool */ @@ -110,7 +131,7 @@ public function setBusinessAccount(BusinessAccount $businessAccount = null) */ protected function createUrl(RequestInterface $request) { - $query = $request->buildQuery(); + $query = $this->method == 'GET' ? $request->buildQuery() : []; if ($this->hasKey()) { $query['key'] = $this->key; diff --git a/src/Service/Place/Add/PlaceAddService.php b/src/Service/Place/Add/PlaceAddService.php new file mode 100644 index 00000000..3d8b877b --- /dev/null +++ b/src/Service/Place/Add/PlaceAddService.php @@ -0,0 +1,66 @@ + + * + * For the full copyright and license information, please read the LICENSE + * file that was distributed with this source code. + */ + +namespace Ivory\GoogleMap\Service\Place\Add; + +use Http\Client\HttpClient; +use Http\Message\MessageFactory; +use Ivory\GoogleMap\Service\AbstractSerializableService; +use Ivory\GoogleMap\Service\Place\Add\Request\PlaceAddRequestInterface; +use Ivory\GoogleMap\Service\Place\Add\Response\PlaceAddResponse; +use Ivory\Serializer\Context\Context; +use Ivory\Serializer\Naming\SnakeCaseNamingStrategy; +use Ivory\Serializer\SerializerInterface; + +/** + * @author TeLiXj + */ +class PlaceAddService extends AbstractSerializableService +{ + /** + * @param HttpClient $client + * @param MessageFactory $messageFactory + * @param SerializerInterface|null $serializer + */ + public function __construct( + HttpClient $client, + MessageFactory $messageFactory, + SerializerInterface $serializer = null + ) { + parent::__construct( + 'https://maps.googleapis.com/maps/api/place/add', + $client, + $messageFactory, + $serializer + ); + $this->setMethod('POST'); + } + + /** + * @param PlaceAddRequestInterface $request + * + * @return PlaceAddResponse + */ + public function process(PlaceAddRequestInterface $request) + { + $httpRequest = $this->createRequest($request); + $httpResponse = $this->getClient()->sendRequest($httpRequest); + $response = $this->deserialize( + $httpResponse, + PlaceAddResponse::class, + (new Context())->setNamingStrategy(new SnakeCaseNamingStrategy()) + ); + + $response->setRequest($request); + + return $response; + } +} diff --git a/src/Service/Place/Add/Request/PlaceAddRequest.php b/src/Service/Place/Add/Request/PlaceAddRequest.php new file mode 100644 index 00000000..331d8ed3 --- /dev/null +++ b/src/Service/Place/Add/Request/PlaceAddRequest.php @@ -0,0 +1,288 @@ + + * + * For the full copyright and license information, please read the LICENSE + * file that was distributed with this source code. + */ + +namespace Ivory\GoogleMap\Service\Place\Add\Request; + +use Ivory\GoogleMap\Base\Coordinate; + +/** + * @author TeLiXj + */ +class PlaceAddRequest implements PlaceAddRequestInterface +{ + /** + * @var string|null + */ + private $accuracy; + + /** + * @var string|null + */ + private $address; + + /** + * @var string|null + */ + private $language; + + /** + * @var Coordinate + */ + private $location; + + /** + * @var string + */ + private $name; + + /** + * @var string|null + */ + private $phoneNumber; + + /** + * @var array|null + */ + private $types; + + /** + * @var string|null + */ + private $website; + + /** + * @param string $location + * @param string $name + * @param string $types + */ + public function __construct($location, $name, $types) + { + $this->setLocation($location); + $this->setName($name); + $this->setTypes([$types]); + } + + /** + * @return bool + */ + public function hasAccuracy() + { + return $this->accuracy !== null; + } + + /** + * @return string + */ + public function getAccuracy() + { + return $this->accuracy; + } + + /** + * @param string $address + */ + public function setAddress($address) + { + $this->address = $address; + } + + /** + * @return bool + */ + public function hasAddress() + { + return $this->address !== null; + } + + /** + * @return string + */ + public function getAddress() + { + return $this->address; + } + + /** + * @param string $accuracy + */ + public function setAccuracy($accuracy) + { + $this->accuracy = $accuracy; + } + + /** + * @return bool + */ + public function hasLanguage() + { + return $this->language !== null; + } + + /** + * @return string|null + */ + public function getLanguage() + { + return $this->language; + } + + /** + * @param string|null $language + */ + public function setLanguage($language) + { + $this->language = $language; + } + + /** + * @return string + */ + public function getLocation() + { + return $this->location; + } + + /** + * @param Coordinate|null $location + */ + public function setLocation(Coordinate $location = null) + { + $this->location = $location; + } + + /** + * @return string + */ + public function getName() + { + return $this->name; + } + + /** + * @param string $name + */ + public function setName($name) + { + $this->name = $name; + } + + /** + * @return bool + */ + public function hasPhoneNumber() + { + return $this->phoneNumber !== null; + } + + /** + * @return string|null + */ + public function getPhoneNumber() + { + return $this->phoneNumber; + } + + /** + * @param string|null $phoneNumber + */ + public function setPhoneNumber($phoneNumber) + { + $this->phoneNumber = $phoneNumber; + } + + /** + * @return bool + */ + public function hasTypes() + { + return $this->types !== null; + } + + /** + * @return array|null + */ + public function getTypes() + { + return $this->types; + } + + /** + * @param array|null $types + */ + public function setTypes($types) + { + $this->types = $types; + } + + /** + * @return bool + */ + public function hasWebsite() + { + return $this->website !== null; + } + + /** + * @return string|null + */ + public function getWebsite() + { + return $this->website; + } + + /** + * @param string|null $website + */ + public function setWebsite($website) + { + $this->website = $website; + } + + /** + * {@inheritdoc} + */ + public function buildQuery() + { + $query = [ + 'location' => [ + "lat" => $this->location->getLatitude(), + "lng" => $this->location->getLongitude() + ], + 'name' => $this->name + ]; + + if ($this->hasAccuracy()) { + $query['accuracy'] = $this->accuracy; + } + + if ($this->hasAddress()) { + $query['address'] = $this->address; + } + + if ($this->hasLanguage()) { + $query['language'] = $this->language; + } + + if ($this->hasPhoneNumber()) { + $query['phone_number'] = $this->phoneNumber; + } + + if ($this->hasTypes()) { + $query['types'] = $this->types; + } + + if ($this->hasWebsite()) { + $query['website'] = $this->website; + } + + return $query; + } +} diff --git a/src/Service/Place/Add/Request/PlaceAddRequestInterface.php b/src/Service/Place/Add/Request/PlaceAddRequestInterface.php new file mode 100644 index 00000000..ea3f40e1 --- /dev/null +++ b/src/Service/Place/Add/Request/PlaceAddRequestInterface.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please read the LICENSE + * file that was distributed with this source code. + */ + +namespace Ivory\GoogleMap\Service\Place\Add\Request; + +use Ivory\GoogleMap\Service\RequestInterface; + +/** + * @author TeLiXj + */ +interface PlaceAddRequestInterface extends RequestInterface +{ +} diff --git a/src/Service/Place/Add/Response/PlaceAddResponse.php b/src/Service/Place/Add/Response/PlaceAddResponse.php new file mode 100644 index 00000000..ea7a0162 --- /dev/null +++ b/src/Service/Place/Add/Response/PlaceAddResponse.php @@ -0,0 +1,121 @@ + + * + * For the full copyright and license information, please read the LICENSE + * file that was distributed with this source code. + */ + +namespace Ivory\GoogleMap\Service\Place\Add\Response; + +use Ivory\GoogleMap\Service\Place\Base\Place; +use Ivory\GoogleMap\Service\Place\Add\Request\PlaceAddRequestInterface; + +/** + * @author TeLiXj + */ +class PlaceAddResponse +{ + /** + * @var string|null + */ + private $status; + + /** + * @var PlaceAddRequestInterface|null + */ + private $request; + + /** + * @var string + */ + private $placeId; + + /** + * @var string + */ + private $scope; + + /** + * @return bool + */ + public function hasStatus() + { + return $this->status !== null; + } + + /** + * @return string|null + */ + public function getStatus() + { + return $this->status; + } + + /** + * @param string|null $status + */ + public function setStatus($status) + { + $this->status = $status; + } + + /** + * @return bool + */ + public function hasRequest() + { + return $this->request !== null; + } + + /** + * @return PlaceAddRequestInterface|null + */ + public function getRequest() + { + return $this->request; + } + + /** + * @param PlaceAddRequestInterface|null $request + */ + public function setRequest(PlaceAddRequestInterface $request = null) + { + $this->request = $request; + } + + /** + * @return string + */ + public function getPlaceId() + { + return $this->placeId; + } + + /** + * @param string $placeId + */ + public function setPlaceId($placeId) + { + $this->placeId = $placeId; + } + + /** + * @return string + */ + public function getScope() + { + return $this->scope; + } + + /** + * @param string + */ + public function setScope($scope) + { + $this->scope = $scope; + } +} diff --git a/src/Service/Place/Add/Response/PlaceAddStatus.php b/src/Service/Place/Add/Response/PlaceAddStatus.php new file mode 100644 index 00000000..d8d3ddc8 --- /dev/null +++ b/src/Service/Place/Add/Response/PlaceAddStatus.php @@ -0,0 +1,33 @@ + + * + * For the full copyright and license information, please read the LICENSE + * file that was distributed with this source code. + */ + +namespace Ivory\GoogleMap\Service\Place\Add\Response; + +/** + * @author TeLiXj + */ +final class PlaceAddStatus +{ + const OK = 'OK'; + const UNKNOWN_ERROR = 'UNKNOWN_ERROR'; + const ZERO_RESULTS = 'ZERO_RESULTS'; + const OVER_QUERY_LIMIT = 'OVER_QUERY_LIMIT'; + const REQUEST_DENIED = 'REQUEST_DENIED'; + const INVALID_REQUEST = 'INVALID_REQUEST'; + const NOT_FOUND = 'NOT_FOUND'; + + /** + * @codeCoverageIgnore + */ + private function __construct() + { + } +} diff --git a/src/Service/Serializer/Place/Add/PlaceAddResponse.xml b/src/Service/Serializer/Place/Add/PlaceAddResponse.xml new file mode 100644 index 00000000..b2c8f60a --- /dev/null +++ b/src/Service/Serializer/Place/Add/PlaceAddResponse.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + +