From d494a70be178f48e93b5707277f2507a7035e4b4 Mon Sep 17 00:00:00 2001 From: Tobias Nyholm Date: Sat, 15 Jul 2017 14:24:39 +0200 Subject: [PATCH 1/5] Adding Plugin support --- src/Plugin/.gitattributes | 4 + src/Plugin/.travis.yml | 15 ++ src/Plugin/CHANGELOG.md | 13 ++ src/Plugin/Exception/LoopException.php | 37 +++++ src/Plugin/LICENSE | 21 +++ src/Plugin/Plugin.php | 33 ++++ src/Plugin/Plugin/BoundsPlugin.php | 47 ++++++ src/Plugin/Plugin/CachePlugin.php | 66 ++++++++ src/Plugin/Plugin/LimitPlugin.php | 41 +++++ src/Plugin/Plugin/LocalePlugin.php | 41 +++++ src/Plugin/Plugin/LoggerPlugin.php | 50 ++++++ src/Plugin/Plugin/QueryDataPlugin.php | 51 ++++++ src/Plugin/PluginProvider.php | 153 ++++++++++++++++++ .../Promise/GeocoderFulfilledPromise.php | 62 +++++++ .../Promise/GeocoderRejectedPromise.php | 61 +++++++ src/Plugin/Readme.md | 21 +++ src/Plugin/Tests/Plugin/BoundsPluginTest.php | 48 ++++++ src/Plugin/Tests/Plugin/CachePluginTest.php | 72 +++++++++ src/Plugin/Tests/Plugin/LimitPluginTest.php | 27 ++++ src/Plugin/Tests/Plugin/LocalePluginTest.php | 29 ++++ src/Plugin/Tests/Plugin/LoggerPluginTest.php | 80 +++++++++ .../Tests/Plugin/QueryDataPluginTest.php | 48 ++++++ src/Plugin/Tests/PluginProviderTest.php | 138 ++++++++++++++++ src/Plugin/composer.json | 43 +++++ src/Plugin/phpunit.xml.dist | 28 ++++ 25 files changed, 1229 insertions(+) create mode 100644 src/Plugin/.gitattributes create mode 100644 src/Plugin/.travis.yml create mode 100644 src/Plugin/CHANGELOG.md create mode 100644 src/Plugin/Exception/LoopException.php create mode 100644 src/Plugin/LICENSE create mode 100644 src/Plugin/Plugin.php create mode 100644 src/Plugin/Plugin/BoundsPlugin.php create mode 100644 src/Plugin/Plugin/CachePlugin.php create mode 100644 src/Plugin/Plugin/LimitPlugin.php create mode 100644 src/Plugin/Plugin/LocalePlugin.php create mode 100644 src/Plugin/Plugin/LoggerPlugin.php create mode 100644 src/Plugin/Plugin/QueryDataPlugin.php create mode 100644 src/Plugin/PluginProvider.php create mode 100644 src/Plugin/Promise/GeocoderFulfilledPromise.php create mode 100644 src/Plugin/Promise/GeocoderRejectedPromise.php create mode 100644 src/Plugin/Readme.md create mode 100644 src/Plugin/Tests/Plugin/BoundsPluginTest.php create mode 100644 src/Plugin/Tests/Plugin/CachePluginTest.php create mode 100644 src/Plugin/Tests/Plugin/LimitPluginTest.php create mode 100644 src/Plugin/Tests/Plugin/LocalePluginTest.php create mode 100644 src/Plugin/Tests/Plugin/LoggerPluginTest.php create mode 100644 src/Plugin/Tests/Plugin/QueryDataPluginTest.php create mode 100644 src/Plugin/Tests/PluginProviderTest.php create mode 100644 src/Plugin/composer.json create mode 100644 src/Plugin/phpunit.xml.dist diff --git a/src/Plugin/.gitattributes b/src/Plugin/.gitattributes new file mode 100644 index 000000000..d04504afd --- /dev/null +++ b/src/Plugin/.gitattributes @@ -0,0 +1,4 @@ +.gitattributes export-ignore +.travis.yml export-ignore +phpunit.xml.dist export-ignore +Tests/ export-ignore diff --git a/src/Plugin/.travis.yml b/src/Plugin/.travis.yml new file mode 100644 index 000000000..d2b93dcb7 --- /dev/null +++ b/src/Plugin/.travis.yml @@ -0,0 +1,15 @@ +language: php +sudo: false + +php: 7.0 + +install: + - composer update --prefer-stable --prefer-dist + +script: + - composer test-ci + +after_success: + - wget https://scrutinizer-ci.com/ocular.phar + - php ocular.phar code-coverage:upload --format=php-clover build/coverage.xml + diff --git a/src/Plugin/CHANGELOG.md b/src/Plugin/CHANGELOG.md new file mode 100644 index 000000000..9148ad9ef --- /dev/null +++ b/src/Plugin/CHANGELOG.md @@ -0,0 +1,13 @@ +# Change Log + +The change log describes what is "Added", "Removed", "Changed" or "Fixed" between each release. + +## 4.0.0-beta2 + +- Removed `AbstractHttpProvider::setMessageFactory`. +- Removed `AbstractHttpProvider::getHttpClient`. +- Make sure we have a `MessageFactory` in the constructor of `AbstractHttpProvider`. + +## 4.0.0-beta1 + +First release of this library. diff --git a/src/Plugin/Exception/LoopException.php b/src/Plugin/Exception/LoopException.php new file mode 100644 index 000000000..56632479a --- /dev/null +++ b/src/Plugin/Exception/LoopException.php @@ -0,0 +1,37 @@ + + */ +class LoopException extends \RuntimeException implements Exception +{ + /** + * @var Query + */ + private $query; + + public static function create($message, Query $query) + { + $ex = new self($message); + $ex->query = $query; + + return $ex; + } + + /** + * @return Query + */ + public function getQuery(): Query + { + return $this->query; + } +} diff --git a/src/Plugin/LICENSE b/src/Plugin/LICENSE new file mode 100644 index 000000000..8aa8246ef --- /dev/null +++ b/src/Plugin/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2011 — William Durand + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/src/Plugin/Plugin.php b/src/Plugin/Plugin.php new file mode 100644 index 000000000..c8e36b62a --- /dev/null +++ b/src/Plugin/Plugin.php @@ -0,0 +1,33 @@ + + * @author Tobias Nyholm + */ +interface Plugin +{ + /** + * Handle the Query and return the Collection coming from the next callable. + * + * @param Query $query + * @param callable $next Next middleware in the chain, the query is passed as the first argument + * @param callable $first First middleware in the chain, used to to restart a request + * + * @return Promise Resolves a Collection or fails with an Geocoder\Exception\Exception + */ + public function handleQuery(Query $query, callable $next, callable $first); +} diff --git a/src/Plugin/Plugin/BoundsPlugin.php b/src/Plugin/Plugin/BoundsPlugin.php new file mode 100644 index 000000000..fbe00c33d --- /dev/null +++ b/src/Plugin/Plugin/BoundsPlugin.php @@ -0,0 +1,47 @@ + + */ +class BoundsPlugin implements Plugin +{ + /** + * @var Bounds + */ + private $bounds; + + /** + * @param Bounds $bounds + */ + public function __construct(Bounds $bounds) + { + $this->bounds = $bounds; + } + + /** + * {@inheritdoc} + */ + public function handleQuery(Query $query, callable $next, callable $first) + { + if (!$query instanceof GeocodeQuery) { + return $next($query); + } + + if (empty($query->getBounds())) { + $query = $query->withBounds($this->bounds); + } + + return $next($query); + } +} diff --git a/src/Plugin/Plugin/CachePlugin.php b/src/Plugin/Plugin/CachePlugin.php new file mode 100644 index 000000000..f9c5423f8 --- /dev/null +++ b/src/Plugin/Plugin/CachePlugin.php @@ -0,0 +1,66 @@ + + */ +class CachePlugin implements Plugin +{ + /** + * @var CacheInterface + */ + private $cache; + + /** + * How log a result is going to be cached. + * + * @var int|null + */ + private $lifetime; + + /** + * @param CacheInterface $cache + * @param int $lifetime + */ + public function __construct(CacheInterface $cache, int $lifetime = null) + { + $this->cache = $cache; + $this->lifetime = $lifetime; + } + + /** + * {@inheritdoc} + */ + public function handleQuery(Query $query, callable $next, callable $first) + { + $cacheKey = $this->getCacheKey($query); + if (null !== $cachedResult = $this->cache->get($cacheKey)) { + return $cachedResult; + } + + $result = $next($query); + $this->cache->set($cacheKey, $result, $this->lifetime); + + return $result; + } + + /** + * @param Query $query + * + * @return string + */ + private function getCacheKey(Query $query): string + { + // Include the major version number of the geocoder to avoid issues unserializing. + return 'v4'.sha1((string) $query); + } +} diff --git a/src/Plugin/Plugin/LimitPlugin.php b/src/Plugin/Plugin/LimitPlugin.php new file mode 100644 index 000000000..aed0cafbb --- /dev/null +++ b/src/Plugin/Plugin/LimitPlugin.php @@ -0,0 +1,41 @@ + + */ +class LimitPlugin implements Plugin +{ + /** + * @var int + */ + private $limit; + + /** + * @param int $limit + */ + public function __construct(int $limit) + { + $this->limit = $limit; + } + + /** + * {@inheritdoc} + */ + public function handleQuery(Query $query, callable $next, callable $first) + { + if (empty($query->getLocale())) { + $query = $query->withLimit($this->limit); + } + + return $next($query); + } +} diff --git a/src/Plugin/Plugin/LocalePlugin.php b/src/Plugin/Plugin/LocalePlugin.php new file mode 100644 index 000000000..a8a19822e --- /dev/null +++ b/src/Plugin/Plugin/LocalePlugin.php @@ -0,0 +1,41 @@ + + */ +class LocalePlugin implements Plugin +{ + /** + * @var string + */ + private $locale; + + /** + * @param string $locale + */ + public function __construct(string $locale) + { + $this->locale = $locale; + } + + /** + * {@inheritdoc} + */ + public function handleQuery(Query $query, callable $next, callable $first) + { + if (empty($query->getLocale())) { + $query = $query->withLocale($this->locale); + } + + return $next($query); + } +} diff --git a/src/Plugin/Plugin/LoggerPlugin.php b/src/Plugin/Plugin/LoggerPlugin.php new file mode 100644 index 000000000..e90cc1121 --- /dev/null +++ b/src/Plugin/Plugin/LoggerPlugin.php @@ -0,0 +1,50 @@ + + */ +class LoggerPlugin +{ + /** + * @var LoggerInterface + */ + private $logger; + + /** + * @param LoggerInterface $logger + */ + public function __construct(LoggerInterface $logger) + { + $this->logger = $logger; + } + + public function handleQuery(Query $query, callable $next, callable $first) + { + $startTime = microtime(true); + $logger = $this->logger; + + return $next($query)->then(function (Collection $result) use ($logger, $query, $startTime) { + $duration = (microtime(true) - $startTime) * 1000; + $this->logger->info(sprintf('[Geocoder] Got %d results in %0.2f ms for query %s', count($result), $duration, $query->__toString())); + + return $result; + }, function (Exception $exception) use ($logger, $query, $startTime) { + $duration = (microtime(true) - $startTime) * 1000; + $this->logger->error(sprintf('[Geocoder] Failed with %s after %0.2f ms for query %s', get_class($exception), $duration, $query->__toString())); + + throw $exception; + }); + } +} diff --git a/src/Plugin/Plugin/QueryDataPlugin.php b/src/Plugin/Plugin/QueryDataPlugin.php new file mode 100644 index 000000000..c9b849933 --- /dev/null +++ b/src/Plugin/Plugin/QueryDataPlugin.php @@ -0,0 +1,51 @@ + + */ +class QueryDataPlugin implements Plugin +{ + /** + * @var array + */ + private $data; + + /** + * @var bool + */ + private $force; + + /** + * @param array $data + * @param bool $force If true we overwrite existing values + */ + public function __construct(array $data, $force = false) + { + $this->data = $data; + $this->force = $force; + } + + /** + * {@inheritdoc} + */ + public function handleQuery(Query $query, callable $next, callable $first) + { + $queryData = $query->getAllData(); + foreach ($this->data as $key => $value) { + if ($this->force || !array_key_exists($key, $queryData)) { + $query = $query->withData($key, $value); + } + } + + return $next($query); + } +} diff --git a/src/Plugin/PluginProvider.php b/src/Plugin/PluginProvider.php new file mode 100644 index 000000000..46543af59 --- /dev/null +++ b/src/Plugin/PluginProvider.php @@ -0,0 +1,153 @@ + + * @author Tobias Nyholm + */ +class PluginProvider implements Provider +{ + /** + * @var Provider + */ + private $provider; + + /** + * @var Plugin[] + */ + private $plugins; + + /** + * A list of options. + * + * @var array + */ + private $options; + + /** + * @param Provider $provider + * @param Plugin[] $plugins + * @param array $options { + * + * @var int $max_restarts + * } + */ + public function __construct(Provider $provider, array $plugins = [], array $options = []) + { + $this->provider = $provider; + $this->plugins = $plugins; + $this->options = $this->configure($options); + } + + /** + * @inheritdoc + */ + public function geocodeQuery(GeocodeQuery $query): Collection + { + $pluginChain = $this->createPluginChain($this->plugins, function (GeocodeQuery $query) { + try { + return new GeocoderFulfilledPromise($this->provider->geocodeQuery($query)); + } catch (Exception $exception) { + return new GeocoderRejectedPromise($exception); + } + }); + + return $pluginChain($query)->wait(); + } + + /** + * @inheritdoc + */ + public function reverseQuery(ReverseQuery $query): Collection + { + $pluginChain = $this->createPluginChain($this->plugins, function (ReverseQuery $query) { + try { + return new GeocoderFulfilledPromise($this->provider->reverseQuery($query)); + } catch (Exception $exception) { + return new GeocoderRejectedPromise($exception); + } + }); + + return $pluginChain($query)->wait(); + } + + /** + * @inheritdoc + */ + public function getName(): string + { + return $this->provider->getName(); + } + + /** + * Configure the plugin provider. + * + * @param array $options + * + * @return array + */ + private function configure(array $options = []): array + { + $defaults = [ + 'max_restarts' => 10, + ]; + + $config = array_merge($defaults, $options); + + // Make sure no invalid values are provided + if (count($config) !== count($defaults)) { + throw new LogicException(sprintf('Valid options to the PluginProviders are: %s', implode(', ', array_values($defaults)))); + } + + return $config; + } + + /** + * Create the plugin chain. + * + * @param Plugin[] $pluginList A list of plugins + * @param callable $clientCallable Callable making the HTTP call + * + * @return callable + */ + private function createPluginChain(array $pluginList, callable $clientCallable) + { + $firstCallable = $lastCallable = $clientCallable; + + while ($plugin = array_pop($pluginList)) { + $lastCallable = function (Query $query) use ($plugin, $lastCallable, &$firstCallable) { + return $plugin->handleQuery($query, $lastCallable, $firstCallable); + }; + + $firstCallable = $lastCallable; + } + + $firstCalls = 0; + $firstCallable = function (Query $query) use ($lastCallable, &$firstCalls) { + if ($firstCalls > $this->options['max_restarts']) { + throw LoopException::create('Too many restarts in plugin provider', $query); + } + + ++$firstCalls; + + return $lastCallable($query); + }; + + return $firstCallable; + } +} diff --git a/src/Plugin/Promise/GeocoderFulfilledPromise.php b/src/Plugin/Promise/GeocoderFulfilledPromise.php new file mode 100644 index 000000000..86f61acb0 --- /dev/null +++ b/src/Plugin/Promise/GeocoderFulfilledPromise.php @@ -0,0 +1,62 @@ + + * @author Tobias Nyholm + */ +final class GeocoderFulfilledPromise implements Promise +{ + /** + * @var Collection + */ + private $collection; + + /** + * @param Collection $collection + */ + public function __construct(Collection $collection) + { + $this->collection = $collection; + } + + /** + * {@inheritdoc} + */ + public function then(callable $onFulfilled = null, callable $onRejected = null) + { + if (null === $onFulfilled) { + return $this; + } + + try { + return new self($onFulfilled($this->collection)); + } catch (Exception $e) { + return new GeocoderRejectedPromise($e); + } + } + + /** + * {@inheritdoc} + */ + public function getState() + { + return Promise::FULFILLED; + } + + /** + * {@inheritdoc} + */ + public function wait($unwrap = true) + { + if ($unwrap) { + return $this->collection; + } + } +} diff --git a/src/Plugin/Promise/GeocoderRejectedPromise.php b/src/Plugin/Promise/GeocoderRejectedPromise.php new file mode 100644 index 000000000..5ea27d3e4 --- /dev/null +++ b/src/Plugin/Promise/GeocoderRejectedPromise.php @@ -0,0 +1,61 @@ + + * @author Tobias Nyholm + */ +final class GeocoderRejectedPromise implements Promise +{ + /** + * @var Exception + */ + private $exception; + + /** + * @param Exception $exception + */ + public function __construct(Exception $exception) + { + $this->exception = $exception; + } + + /** + * {@inheritdoc} + */ + public function then(callable $onFulfilled = null, callable $onRejected = null) + { + if (null === $onRejected) { + return $this; + } + + try { + return new GeocoderFulfilledPromise($onRejected($this->exception)); + } catch (Exception $e) { + return new self($e); + } + } + + /** + * {@inheritdoc} + */ + public function getState() + { + return Promise::REJECTED; + } + + /** + * {@inheritdoc} + */ + public function wait($unwrap = true) + { + if ($unwrap) { + throw $this->exception; + } + } +} diff --git a/src/Plugin/Readme.md b/src/Plugin/Readme.md new file mode 100644 index 000000000..137a4def3 --- /dev/null +++ b/src/Plugin/Readme.md @@ -0,0 +1,21 @@ +# Geocoder plugin + +[![Build Status](https://travis-ci.org/geocoder-php/plugin.svg?branch=master)](http://travis-ci.org/geocoder-php/plugin) +[![Latest Stable Version](https://poser.pugx.org/geocoder-php/plugin/v/stable)](https://packagist.org/packages/geocoder-php/plugin) +[![Total Downloads](https://poser.pugx.org/geocoder-php/plugin/downloads)](https://packagist.org/packages/geocoder-php/plugin) +[![Monthly Downloads](https://poser.pugx.org/geocoder-php/plugin/d/monthly.png)](https://packagist.org/packages/geocoder-php/plugin) +[![Code Coverage](https://img.shields.io/scrutinizer/coverage/g/geocoder-php/plugin.svg?style=flat-square)](https://scrutinizer-ci.com/g/geocoder-php/plugin) +[![Quality Score](https://img.shields.io/scrutinizer/g/geocoder-php/plugin.svg?style=flat-square)](https://scrutinizer-ci.com/g/geocoder-php/plugin) +[![Software License](https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat-square)](LICENSE) + + +### Install + +```bash +composer require geocoder-php/plugin +``` + +### Contribute + +Contributions are very welcome! Send a pull request to the [main repository](https://github.com/geocoder-php/Geocoder) or +report any issues you find on the [issue tracker](https://github.com/geocoder-php/Geocoder/issues). diff --git a/src/Plugin/Tests/Plugin/BoundsPluginTest.php b/src/Plugin/Tests/Plugin/BoundsPluginTest.php new file mode 100644 index 000000000..305246a85 --- /dev/null +++ b/src/Plugin/Tests/Plugin/BoundsPluginTest.php @@ -0,0 +1,48 @@ +fail('Plugin should not restart the chain'); + }; + $next = function(GeocodeQuery $query) use ($bounds) { + $this->assertEquals($bounds, $query->getBounds()); + }; + + $plugin = new BoundsPlugin($bounds); + $plugin->handleQuery($query, $next, $first); + } + + public function testReverse() + { + $bounds = new Bounds(4,7,1,1); + $query = ReverseQuery::fromCoordinates(71,11); + $first = function(Query $query) { + $this->fail('Plugin should not restart the chain'); + }; + $next = function(Query $query) use ($bounds) { + $this->assertTrue(true, 'We should not fail on ReverseQuery'); + }; + + $plugin = new BoundsPlugin($bounds); + $plugin->handleQuery($query, $next, $first); + } +} diff --git a/src/Plugin/Tests/Plugin/CachePluginTest.php b/src/Plugin/Tests/Plugin/CachePluginTest.php new file mode 100644 index 000000000..31855e1c0 --- /dev/null +++ b/src/Plugin/Tests/Plugin/CachePluginTest.php @@ -0,0 +1,72 @@ +__toString(); + $cache = $this->getMockBuilder(VoidCachePool::class) + ->disableOriginalConstructor() + ->setMethods(['get', 'set']) + ->getMock(); + + $cache->expects($this->once()) + ->method('get') + ->with('v4'.$queryString) + ->willReturn(null); + $cache->expects($this->once()) + ->method('set') + ->with('v4'.$queryString, 'result', $ttl) + ->willReturn(true); + + $first = function(Query $query) { + $this->fail('Plugin should not restart the chain'); + }; + $next = function(Query $query) { + return 'result'; + }; + + $plugin = new CachePlugin($cache, $ttl); + $this->assertEquals('result', $plugin->handleQuery($query, $next, $first)); + } + public function testPluginHit() + { + $query = GeocodeQuery::create('foo'); + $queryString = $query->__toString(); + $cache = $this->getMockBuilder(VoidCachePool::class) + ->disableOriginalConstructor() + ->setMethods(['get', 'set']) + ->getMock(); + + $cache->expects($this->once()) + ->method('get') + ->with('v4'.$queryString) + ->willReturn('result'); + $cache->expects($this->never())->method('set'); + + $first = function(Query $query) { + $this->fail('Plugin should not restart the chain'); + }; + $next = function(Query $query) { + $this->fail('Plugin not call $next on cache hit'); + }; + + $plugin = new CachePlugin($cache); + $this->assertEquals('result', $plugin->handleQuery($query, $next, $first)); + } +} diff --git a/src/Plugin/Tests/Plugin/LimitPluginTest.php b/src/Plugin/Tests/Plugin/LimitPluginTest.php new file mode 100644 index 000000000..b8fc6fd9a --- /dev/null +++ b/src/Plugin/Tests/Plugin/LimitPluginTest.php @@ -0,0 +1,27 @@ +fail('Plugin should not restart the chain'); + }; + $next = function(Query $query) { + $this->assertEquals(4711, $query->getLimit()); + }; + + $plugin = new LimitPlugin(4711); + $plugin->handleQuery($query, $next, $first); + } +} diff --git a/src/Plugin/Tests/Plugin/LocalePluginTest.php b/src/Plugin/Tests/Plugin/LocalePluginTest.php new file mode 100644 index 000000000..8db9645dc --- /dev/null +++ b/src/Plugin/Tests/Plugin/LocalePluginTest.php @@ -0,0 +1,29 @@ +fail('Plugin should not restart the chain'); + }; + $next = function(Query $query) { + $this->assertEquals('sv', $query->getLocale()); + }; + + $plugin = new LocalePlugin('sv'); + $plugin->handleQuery($query, $next, $first); + } +} diff --git a/src/Plugin/Tests/Plugin/LoggerPluginTest.php b/src/Plugin/Tests/Plugin/LoggerPluginTest.php new file mode 100644 index 000000000..7e0472573 --- /dev/null +++ b/src/Plugin/Tests/Plugin/LoggerPluginTest.php @@ -0,0 +1,80 @@ +getMockBuilder(AbstractLogger::class) + ->disableOriginalConstructor() + ->setMethods(['log']) + ->getMock(); + $logger->expects($this->once()) + ->method('log') + ->with('info', $this->callback(function($message) { + return false !== strstr($message, 'Got 0 results'); + })); + + $geocodeQuery = GeocodeQuery::create('foo'); + $collection = new AddressCollection([]); + + $provider = $this->getMockBuilder(Provider::class) + ->disableOriginalConstructor() + ->setMethods(['geocodeQuery', 'reverseQuery', 'getName']) + ->getMock(); + $provider->expects($this->once()) + ->method('geocodeQuery') + ->with($geocodeQuery) + ->willReturn($collection); + $provider->expects($this->never())->method('reverseQuery'); + $provider->expects($this->never())->method('getName'); + + $pluginProvider = new PluginProvider($provider, [new LoggerPlugin($logger)]); + $this->assertSame($collection, $pluginProvider->geocodeQuery($geocodeQuery)); + } + + public function testPluginException() + { + $this->expectException(QuotaExceeded::class); + $logger = $this->getMockBuilder(AbstractLogger::class) + ->disableOriginalConstructor() + ->setMethods(['log']) + ->getMock(); + $logger->expects($this->once()) + ->method('log') + ->with('error', $this->callback(function($message) { + return false !== strstr($message, 'QuotaExceeded'); + })); + + $geocodeQuery = GeocodeQuery::create('foo'); + $provider = $this->getMockBuilder(Provider::class) + ->disableOriginalConstructor() + ->setMethods(['geocodeQuery', 'reverseQuery', 'getName']) + ->getMock(); + $provider->expects($this->once()) + ->method('geocodeQuery') + ->willThrowException(new QuotaExceeded()); + $provider->expects($this->never())->method('reverseQuery'); + $provider->expects($this->never())->method('getName'); + + $pluginProvider = new PluginProvider($provider, [new LoggerPlugin($logger)]); + $pluginProvider->geocodeQuery($geocodeQuery); + } +} diff --git a/src/Plugin/Tests/Plugin/QueryDataPluginTest.php b/src/Plugin/Tests/Plugin/QueryDataPluginTest.php new file mode 100644 index 000000000..7e45410a7 --- /dev/null +++ b/src/Plugin/Tests/Plugin/QueryDataPluginTest.php @@ -0,0 +1,48 @@ +withData('default', 'value'); + $first = function(Query $query) { + $this->fail('Plugin should not restart the chain'); + }; + $next = function(Query $query) { + $this->assertEquals('bar', $query->getData('foo')); + $this->assertEquals('value', $query->getData('default')); + }; + + $plugin = new QueryDataPlugin(['foo'=>'bar', 'default'=>'new value']); + $plugin->handleQuery($query, $next, $first); + } + + public function testPluginForce() + { + $query = GeocodeQuery::create('xxx'); + $query = $query->withData('default', 'value'); + $first = function(Query $query) { + $this->fail('Plugin should not restart the chain'); + }; + $next = function(Query $query) { + $this->assertEquals('bar', $query->getData('foo')); + $this->assertEquals('new value', $query->getData('default')); + }; + + $plugin = new QueryDataPlugin(['foo'=>'bar', 'default'=>'new value'], true); + $plugin->handleQuery($query, $next, $first); + } +} diff --git a/src/Plugin/Tests/PluginProviderTest.php b/src/Plugin/Tests/PluginProviderTest.php new file mode 100644 index 000000000..edd92dfe3 --- /dev/null +++ b/src/Plugin/Tests/PluginProviderTest.php @@ -0,0 +1,138 @@ +getMockBuilder(Provider::class) + ->disableOriginalConstructor() + ->setMethods(['geocodeQuery', 'reverseQuery', 'getName']) + ->getMock(); + $provider->expects($this->once()) + ->method('geocodeQuery') + ->with($geocodeQuery) + ->willReturn($collection); + $provider->expects($this->once()) + ->method('reverseQuery') + ->with($reverseQuery) + ->willReturn($collection); + $provider->expects($this->never())->method('getName'); + + $pluginProvider = new PluginProvider($provider); + $this->assertSame($collection, $pluginProvider->geocodeQuery($geocodeQuery)); + $this->assertSame($collection, $pluginProvider->reverseQuery($reverseQuery)); + } + + public function testPluginsIsBeingUsedWhenGeocoding() + { + $geocodeQuery = GeocodeQuery::create('foo'); + $collection = new AddressCollection([]); + + $provider = $this->getMockBuilder(Provider::class) + ->disableOriginalConstructor() + ->setMethods(['geocodeQuery', 'reverseQuery', 'getName']) + ->getMock(); + $provider->expects($this->once()) + ->method('geocodeQuery') + ->with($geocodeQuery) + ->willReturn($collection); + $provider->expects($this->never())->method('reverseQuery'); + $provider->expects($this->never())->method('getName'); + + $pluginA = $this->getMockBuilder(Plugin::class) + ->disableOriginalConstructor() + ->setMethods(['handleQuery']) + ->getMock(); + $pluginA->expects($this->once()) + ->method('handleQuery') + ->with($geocodeQuery, $this->isType('callable'), $this->isType('callable')) + ->willReturnCallback(function(Query $query, callable $next, callable $first) { + return $next($query); + }); + + $pluginProvider = new PluginProvider($provider, [$pluginA]); + $this->assertSame($collection, $pluginProvider->geocodeQuery($geocodeQuery)); + } + + + public function testPluginsIsBeingUsedWhenReverse() + { + $reverseQuery = ReverseQuery::fromCoordinates(47,11); + $collection = new AddressCollection([]); + + $provider = $this->getMockBuilder(Provider::class) + ->disableOriginalConstructor() + ->setMethods(['geocodeQuery', 'reverseQuery', 'getName']) + ->getMock(); + $provider->expects($this->never())->method('geocodeQuery'); + $provider->expects($this->never())->method('getName'); + $provider->expects($this->once()) + ->method('reverseQuery') + ->with($reverseQuery) + ->willReturn($collection); + + $pluginA = $this->getMockBuilder(Plugin::class) + ->disableOriginalConstructor() + ->setMethods(['handleQuery']) + ->getMock(); + $pluginA->expects($this->once()) + ->method('handleQuery') + ->with($reverseQuery, $this->isType('callable'), $this->isType('callable')) + ->willReturnCallback(function(Query $query, callable $next, callable $first) { + return $next($query); + }); + + $pluginProvider = new PluginProvider($provider, [$pluginA]); + $this->assertSame($collection, $pluginProvider->reverseQuery($reverseQuery)); + } + + public function testLoopException() + { + $this->expectException(LoopException::class); + $geocodeQuery = GeocodeQuery::create('foo'); + $collection = new AddressCollection([]); + + $provider = $this->getMockBuilder(Provider::class) + ->disableOriginalConstructor() + ->setMethods(['geocodeQuery', 'reverseQuery', 'getName']) + ->getMock(); + $provider->expects($this->once()) + ->method('geocodeQuery') + ->with($geocodeQuery) + ->willReturn($collection); + $provider->expects($this->never())->method('reverseQuery'); + $provider->expects($this->never())->method('getName'); + + $pluginA = $this->getMockBuilder(Plugin::class) + ->disableOriginalConstructor() + ->setMethods(['handleQuery']) + ->getMock(); + $pluginA->expects($this->any()) + ->method('handleQuery') + ->with($geocodeQuery, $this->isType('callable'), $this->isType('callable')) + ->willReturnCallback(function(Query $query, callable $next, callable $first) { + return $first($query); + }); + + $pluginProvider = new PluginProvider($provider, [$pluginA]); + $pluginProvider->geocodeQuery($geocodeQuery); + } +} diff --git a/src/Plugin/composer.json b/src/Plugin/composer.json new file mode 100644 index 000000000..a78f5c131 --- /dev/null +++ b/src/Plugin/composer.json @@ -0,0 +1,43 @@ +{ + "name": "geocoder-php/plugin", + "type": "library", + "description": "Plugins to Geocoder providers", + "keywords": ["http geocoder"], + "homepage": "http://geocoder-php.org", + "license": "MIT", + "authors": [ + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com" + } + ], + "require": { + "php": "^7.0", + "willdurand/geocoder": "^4.0", + "psr/log": "^1.0", + "psr/simple-cache": "^1.0", + "php-http/promise": "^1.0" + + }, + "require-dev": { + "phpunit/phpunit": "^6.1", + "cache/void-adapter": "^0.4.1" + }, + "autoload": { + "psr-4": { "Geocoder\\Plugin\\": "" }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "scripts": { + "test": "vendor/bin/phpunit", + "test-ci": "vendor/bin/phpunit --coverage-text --coverage-clover=build/coverage.xml" + }, + "minimum-stability": "dev", + "prefer": "dist", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + } +} diff --git a/src/Plugin/phpunit.xml.dist b/src/Plugin/phpunit.xml.dist new file mode 100644 index 000000000..7581e8757 --- /dev/null +++ b/src/Plugin/phpunit.xml.dist @@ -0,0 +1,28 @@ + + + + + + + + + + ./Tests/ + + + + + + ./ + + ./Tests + ./vendor + + + + From d2c7f810eee1aececb2bf62c27249314d66dae85 Mon Sep 17 00:00:00 2001 From: Tobias Nyholm Date: Sat, 15 Jul 2017 14:32:11 +0200 Subject: [PATCH 2/5] Applied changes from StyleCI --- src/Plugin/Exception/LoopException.php | 8 ++++++ src/Plugin/Plugin.php | 12 +++++++-- src/Plugin/Plugin/BoundsPlugin.php | 8 ++++++ src/Plugin/Plugin/CachePlugin.php | 8 ++++++ src/Plugin/Plugin/LimitPlugin.php | 8 ++++++ src/Plugin/Plugin/LocalePlugin.php | 8 ++++++ src/Plugin/Plugin/LoggerPlugin.php | 9 ++++++- src/Plugin/Plugin/QueryDataPlugin.php | 8 ++++++ src/Plugin/PluginProvider.php | 19 +++++++++----- .../Promise/GeocoderFulfilledPromise.php | 9 ++++++- .../Promise/GeocoderRejectedPromise.php | 9 ++++++- src/Plugin/Tests/Plugin/BoundsPluginTest.php | 25 +++++++++++-------- src/Plugin/Tests/Plugin/CachePluginTest.php | 20 +++++++++------ src/Plugin/Tests/Plugin/LimitPluginTest.php | 12 +++++++-- src/Plugin/Tests/Plugin/LocalePluginTest.php | 14 ++++++++--- src/Plugin/Tests/Plugin/LoggerPluginTest.php | 17 +++++++------ .../Tests/Plugin/QueryDataPluginTest.php | 23 ++++++++++------- src/Plugin/Tests/PluginProviderTest.php | 19 +++++++++----- 18 files changed, 180 insertions(+), 56 deletions(-) diff --git a/src/Plugin/Exception/LoopException.php b/src/Plugin/Exception/LoopException.php index 56632479a..a0f9df02b 100644 --- a/src/Plugin/Exception/LoopException.php +++ b/src/Plugin/Exception/LoopException.php @@ -2,6 +2,14 @@ declare(strict_types=1); +/* + * This file is part of the Geocoder package. + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + * @license MIT License + */ + namespace Geocoder\Plugin\Exception; use Geocoder\Exception\Exception; diff --git a/src/Plugin/Plugin.php b/src/Plugin/Plugin.php index c8e36b62a..87fd8b52d 100644 --- a/src/Plugin/Plugin.php +++ b/src/Plugin/Plugin.php @@ -2,6 +2,14 @@ declare(strict_types=1); +/* + * This file is part of the Geocoder package. + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + * @license MIT License + */ + namespace Geocoder\Plugin; use Geocoder\Query\Query; @@ -24,8 +32,8 @@ interface Plugin * Handle the Query and return the Collection coming from the next callable. * * @param Query $query - * @param callable $next Next middleware in the chain, the query is passed as the first argument - * @param callable $first First middleware in the chain, used to to restart a request + * @param callable $next Next middleware in the chain, the query is passed as the first argument + * @param callable $first First middleware in the chain, used to to restart a request * * @return Promise Resolves a Collection or fails with an Geocoder\Exception\Exception */ diff --git a/src/Plugin/Plugin/BoundsPlugin.php b/src/Plugin/Plugin/BoundsPlugin.php index fbe00c33d..dfe273014 100644 --- a/src/Plugin/Plugin/BoundsPlugin.php +++ b/src/Plugin/Plugin/BoundsPlugin.php @@ -2,6 +2,14 @@ declare(strict_types=1); +/* + * This file is part of the Geocoder package. + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + * @license MIT License + */ + namespace Geocoder\Plugin\Plugin; use Geocoder\Model\Bounds; diff --git a/src/Plugin/Plugin/CachePlugin.php b/src/Plugin/Plugin/CachePlugin.php index f9c5423f8..e9900ba0b 100644 --- a/src/Plugin/Plugin/CachePlugin.php +++ b/src/Plugin/Plugin/CachePlugin.php @@ -2,6 +2,14 @@ declare(strict_types=1); +/* + * This file is part of the Geocoder package. + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + * @license MIT License + */ + namespace Geocoder\Plugin\Plugin; use Geocoder\Plugin\Plugin; diff --git a/src/Plugin/Plugin/LimitPlugin.php b/src/Plugin/Plugin/LimitPlugin.php index aed0cafbb..540106949 100644 --- a/src/Plugin/Plugin/LimitPlugin.php +++ b/src/Plugin/Plugin/LimitPlugin.php @@ -2,6 +2,14 @@ declare(strict_types=1); +/* + * This file is part of the Geocoder package. + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + * @license MIT License + */ + namespace Geocoder\Plugin\Plugin; use Geocoder\Plugin\Plugin; diff --git a/src/Plugin/Plugin/LocalePlugin.php b/src/Plugin/Plugin/LocalePlugin.php index a8a19822e..c87f76e25 100644 --- a/src/Plugin/Plugin/LocalePlugin.php +++ b/src/Plugin/Plugin/LocalePlugin.php @@ -2,6 +2,14 @@ declare(strict_types=1); +/* + * This file is part of the Geocoder package. + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + * @license MIT License + */ + namespace Geocoder\Plugin\Plugin; use Geocoder\Plugin\Plugin; diff --git a/src/Plugin/Plugin/LoggerPlugin.php b/src/Plugin/Plugin/LoggerPlugin.php index e90cc1121..8ab3bc5a0 100644 --- a/src/Plugin/Plugin/LoggerPlugin.php +++ b/src/Plugin/Plugin/LoggerPlugin.php @@ -2,11 +2,18 @@ declare(strict_types=1); +/* + * This file is part of the Geocoder package. + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + * @license MIT License + */ + namespace Geocoder\Plugin\Plugin; use Geocoder\Collection; use Geocoder\Exception\Exception; -use Geocoder\Plugin\Plugin; use Geocoder\Query\Query; use Psr\Log\LoggerInterface; diff --git a/src/Plugin/Plugin/QueryDataPlugin.php b/src/Plugin/Plugin/QueryDataPlugin.php index c9b849933..286eec28b 100644 --- a/src/Plugin/Plugin/QueryDataPlugin.php +++ b/src/Plugin/Plugin/QueryDataPlugin.php @@ -2,6 +2,14 @@ declare(strict_types=1); +/* + * This file is part of the Geocoder package. + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + * @license MIT License + */ + namespace Geocoder\Plugin\Plugin; use Geocoder\Plugin\Plugin; diff --git a/src/Plugin/PluginProvider.php b/src/Plugin/PluginProvider.php index 46543af59..c138cbd95 100644 --- a/src/Plugin/PluginProvider.php +++ b/src/Plugin/PluginProvider.php @@ -2,6 +2,14 @@ declare(strict_types=1); +/* + * This file is part of the Geocoder package. + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + * @license MIT License + */ + namespace Geocoder\Plugin; use Geocoder\Collection; @@ -16,7 +24,6 @@ use Geocoder\Plugin\Exception\LoopException; /** - * * @author Joel Wurtz * @author Tobias Nyholm */ @@ -41,8 +48,8 @@ class PluginProvider implements Provider /** * @param Provider $provider - * @param Plugin[] $plugins - * @param array $options { + * @param Plugin[] $plugins + * @param array $options { * * @var int $max_restarts * } @@ -55,7 +62,7 @@ public function __construct(Provider $provider, array $plugins = [], array $opti } /** - * @inheritdoc + * {@inheritdoc} */ public function geocodeQuery(GeocodeQuery $query): Collection { @@ -71,7 +78,7 @@ public function geocodeQuery(GeocodeQuery $query): Collection } /** - * @inheritdoc + * {@inheritdoc} */ public function reverseQuery(ReverseQuery $query): Collection { @@ -87,7 +94,7 @@ public function reverseQuery(ReverseQuery $query): Collection } /** - * @inheritdoc + * {@inheritdoc} */ public function getName(): string { diff --git a/src/Plugin/Promise/GeocoderFulfilledPromise.php b/src/Plugin/Promise/GeocoderFulfilledPromise.php index 86f61acb0..a68aaef48 100644 --- a/src/Plugin/Promise/GeocoderFulfilledPromise.php +++ b/src/Plugin/Promise/GeocoderFulfilledPromise.php @@ -1,5 +1,13 @@ * @author Tobias Nyholm */ diff --git a/src/Plugin/Promise/GeocoderRejectedPromise.php b/src/Plugin/Promise/GeocoderRejectedPromise.php index 5ea27d3e4..40cd4f220 100644 --- a/src/Plugin/Promise/GeocoderRejectedPromise.php +++ b/src/Plugin/Promise/GeocoderRejectedPromise.php @@ -1,12 +1,19 @@ * @author Tobias Nyholm */ diff --git a/src/Plugin/Tests/Plugin/BoundsPluginTest.php b/src/Plugin/Tests/Plugin/BoundsPluginTest.php index 305246a85..88480b5a9 100644 --- a/src/Plugin/Tests/Plugin/BoundsPluginTest.php +++ b/src/Plugin/Tests/Plugin/BoundsPluginTest.php @@ -2,28 +2,33 @@ declare(strict_types=1); +/* + * This file is part of the Geocoder package. + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + * @license MIT License + */ + namespace Geocoder\Plugin\Tests\Plugin; use Geocoder\Model\Bounds; use Geocoder\Plugin\Plugin\BoundsPlugin; -use Geocoder\Plugin\Plugin\LimitPlugin; -use Geocoder\Plugin\Plugin\LocalePlugin; use Geocoder\Query\GeocodeQuery; use Geocoder\Query\Query; use Geocoder\Query\ReverseQuery; -use League\Flysystem\Adapter\Local; use PHPUnit\Framework\TestCase; class BoundsPluginTest extends TestCase { public function testGeocode() { - $bounds = new Bounds(4,7,1,1); + $bounds = new Bounds(4, 7, 1, 1); $query = GeocodeQuery::create('foo'); - $first = function(Query $query) { + $first = function (Query $query) { $this->fail('Plugin should not restart the chain'); }; - $next = function(GeocodeQuery $query) use ($bounds) { + $next = function (GeocodeQuery $query) use ($bounds) { $this->assertEquals($bounds, $query->getBounds()); }; @@ -33,12 +38,12 @@ public function testGeocode() public function testReverse() { - $bounds = new Bounds(4,7,1,1); - $query = ReverseQuery::fromCoordinates(71,11); - $first = function(Query $query) { + $bounds = new Bounds(4, 7, 1, 1); + $query = ReverseQuery::fromCoordinates(71, 11); + $first = function (Query $query) { $this->fail('Plugin should not restart the chain'); }; - $next = function(Query $query) use ($bounds) { + $next = function (Query $query) use ($bounds) { $this->assertTrue(true, 'We should not fail on ReverseQuery'); }; diff --git a/src/Plugin/Tests/Plugin/CachePluginTest.php b/src/Plugin/Tests/Plugin/CachePluginTest.php index 31855e1c0..ebdeb700a 100644 --- a/src/Plugin/Tests/Plugin/CachePluginTest.php +++ b/src/Plugin/Tests/Plugin/CachePluginTest.php @@ -2,15 +2,20 @@ declare(strict_types=1); +/* + * This file is part of the Geocoder package. + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + * @license MIT License + */ + namespace Geocoder\Plugin\Tests\Plugin; use Cache\Adapter\Void\VoidCachePool; use Geocoder\Plugin\Plugin\CachePlugin; -use Geocoder\Plugin\Plugin\LimitPlugin; -use Geocoder\Plugin\Plugin\LocalePlugin; use Geocoder\Query\GeocodeQuery; use Geocoder\Query\Query; -use League\Flysystem\Adapter\Local; use PHPUnit\Framework\TestCase; class CachePluginTest extends TestCase @@ -34,16 +39,17 @@ public function testPluginMiss() ->with('v4'.$queryString, 'result', $ttl) ->willReturn(true); - $first = function(Query $query) { + $first = function (Query $query) { $this->fail('Plugin should not restart the chain'); }; - $next = function(Query $query) { + $next = function (Query $query) { return 'result'; }; $plugin = new CachePlugin($cache, $ttl); $this->assertEquals('result', $plugin->handleQuery($query, $next, $first)); } + public function testPluginHit() { $query = GeocodeQuery::create('foo'); @@ -59,10 +65,10 @@ public function testPluginHit() ->willReturn('result'); $cache->expects($this->never())->method('set'); - $first = function(Query $query) { + $first = function (Query $query) { $this->fail('Plugin should not restart the chain'); }; - $next = function(Query $query) { + $next = function (Query $query) { $this->fail('Plugin not call $next on cache hit'); }; diff --git a/src/Plugin/Tests/Plugin/LimitPluginTest.php b/src/Plugin/Tests/Plugin/LimitPluginTest.php index b8fc6fd9a..aac107beb 100644 --- a/src/Plugin/Tests/Plugin/LimitPluginTest.php +++ b/src/Plugin/Tests/Plugin/LimitPluginTest.php @@ -2,6 +2,14 @@ declare(strict_types=1); +/* + * This file is part of the Geocoder package. + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + * @license MIT License + */ + namespace Geocoder\Plugin\Tests\Plugin; use Geocoder\Plugin\Plugin\LimitPlugin; @@ -14,10 +22,10 @@ class LimitPluginTest extends TestCase public function testPlugin() { $query = GeocodeQuery::create('foo'); - $first = function(Query $query) { + $first = function (Query $query) { $this->fail('Plugin should not restart the chain'); }; - $next = function(Query $query) { + $next = function (Query $query) { $this->assertEquals(4711, $query->getLimit()); }; diff --git a/src/Plugin/Tests/Plugin/LocalePluginTest.php b/src/Plugin/Tests/Plugin/LocalePluginTest.php index 8db9645dc..bfb132620 100644 --- a/src/Plugin/Tests/Plugin/LocalePluginTest.php +++ b/src/Plugin/Tests/Plugin/LocalePluginTest.php @@ -2,13 +2,19 @@ declare(strict_types=1); +/* + * This file is part of the Geocoder package. + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + * @license MIT License + */ + namespace Geocoder\Plugin\Tests\Plugin; -use Geocoder\Plugin\Plugin\LimitPlugin; use Geocoder\Plugin\Plugin\LocalePlugin; use Geocoder\Query\GeocodeQuery; use Geocoder\Query\Query; -use League\Flysystem\Adapter\Local; use PHPUnit\Framework\TestCase; class LocalePluginTest extends TestCase @@ -16,10 +22,10 @@ class LocalePluginTest extends TestCase public function testPlugin() { $query = GeocodeQuery::create('foo'); - $first = function(Query $query) { + $first = function (Query $query) { $this->fail('Plugin should not restart the chain'); }; - $next = function(Query $query) { + $next = function (Query $query) { $this->assertEquals('sv', $query->getLocale()); }; diff --git a/src/Plugin/Tests/Plugin/LoggerPluginTest.php b/src/Plugin/Tests/Plugin/LoggerPluginTest.php index 7e0472573..cbc47d967 100644 --- a/src/Plugin/Tests/Plugin/LoggerPluginTest.php +++ b/src/Plugin/Tests/Plugin/LoggerPluginTest.php @@ -2,21 +2,24 @@ declare(strict_types=1); +/* + * This file is part of the Geocoder package. + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + * @license MIT License + */ + namespace Geocoder\Plugin\Tests\Plugin; use Geocoder\Exception\QuotaExceeded; use Geocoder\Model\AddressCollection; -use Geocoder\Plugin\Plugin\LimitPlugin; -use Geocoder\Plugin\Plugin\LocalePlugin; use Geocoder\Plugin\Plugin\LoggerPlugin; use Geocoder\Plugin\PluginProvider; use Geocoder\Provider\Provider; use Geocoder\Query\GeocodeQuery; -use Geocoder\Query\Query; -use League\Flysystem\Adapter\Local; use PHPUnit\Framework\TestCase; use Psr\Log\AbstractLogger; -use Psr\Log\LoggerInterface; class LoggerPluginTest extends TestCase { @@ -28,7 +31,7 @@ public function testPlugin() ->getMock(); $logger->expects($this->once()) ->method('log') - ->with('info', $this->callback(function($message) { + ->with('info', $this->callback(function ($message) { return false !== strstr($message, 'Got 0 results'); })); @@ -59,7 +62,7 @@ public function testPluginException() ->getMock(); $logger->expects($this->once()) ->method('log') - ->with('error', $this->callback(function($message) { + ->with('error', $this->callback(function ($message) { return false !== strstr($message, 'QuotaExceeded'); })); diff --git a/src/Plugin/Tests/Plugin/QueryDataPluginTest.php b/src/Plugin/Tests/Plugin/QueryDataPluginTest.php index 7e45410a7..12b288c29 100644 --- a/src/Plugin/Tests/Plugin/QueryDataPluginTest.php +++ b/src/Plugin/Tests/Plugin/QueryDataPluginTest.php @@ -2,14 +2,19 @@ declare(strict_types=1); +/* + * This file is part of the Geocoder package. + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + * @license MIT License + */ + namespace Geocoder\Plugin\Tests\Plugin; -use Geocoder\Plugin\Plugin\LimitPlugin; -use Geocoder\Plugin\Plugin\LocalePlugin; use Geocoder\Plugin\Plugin\QueryDataPlugin; use Geocoder\Query\GeocodeQuery; use Geocoder\Query\Query; -use League\Flysystem\Adapter\Local; use PHPUnit\Framework\TestCase; class QueryDataPluginTest extends TestCase @@ -18,15 +23,15 @@ public function testPlugin() { $query = GeocodeQuery::create('xxx'); $query = $query->withData('default', 'value'); - $first = function(Query $query) { + $first = function (Query $query) { $this->fail('Plugin should not restart the chain'); }; - $next = function(Query $query) { + $next = function (Query $query) { $this->assertEquals('bar', $query->getData('foo')); $this->assertEquals('value', $query->getData('default')); }; - $plugin = new QueryDataPlugin(['foo'=>'bar', 'default'=>'new value']); + $plugin = new QueryDataPlugin(['foo' => 'bar', 'default' => 'new value']); $plugin->handleQuery($query, $next, $first); } @@ -34,15 +39,15 @@ public function testPluginForce() { $query = GeocodeQuery::create('xxx'); $query = $query->withData('default', 'value'); - $first = function(Query $query) { + $first = function (Query $query) { $this->fail('Plugin should not restart the chain'); }; - $next = function(Query $query) { + $next = function (Query $query) { $this->assertEquals('bar', $query->getData('foo')); $this->assertEquals('new value', $query->getData('default')); }; - $plugin = new QueryDataPlugin(['foo'=>'bar', 'default'=>'new value'], true); + $plugin = new QueryDataPlugin(['foo' => 'bar', 'default' => 'new value'], true); $plugin->handleQuery($query, $next, $first); } } diff --git a/src/Plugin/Tests/PluginProviderTest.php b/src/Plugin/Tests/PluginProviderTest.php index edd92dfe3..f63a29148 100644 --- a/src/Plugin/Tests/PluginProviderTest.php +++ b/src/Plugin/Tests/PluginProviderTest.php @@ -2,6 +2,14 @@ declare(strict_types=1); +/* + * This file is part of the Geocoder package. + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + * @license MIT License + */ + namespace Geocoder\Plugin\Tests; use Geocoder\Model\AddressCollection; @@ -19,7 +27,7 @@ class PluginProviderTest extends TestCase public function testDispatchQueries() { $geocodeQuery = GeocodeQuery::create('foo'); - $reverseQuery = ReverseQuery::fromCoordinates(47,11); + $reverseQuery = ReverseQuery::fromCoordinates(47, 11); $collection = new AddressCollection([]); $provider = $this->getMockBuilder(Provider::class) @@ -64,7 +72,7 @@ public function testPluginsIsBeingUsedWhenGeocoding() $pluginA->expects($this->once()) ->method('handleQuery') ->with($geocodeQuery, $this->isType('callable'), $this->isType('callable')) - ->willReturnCallback(function(Query $query, callable $next, callable $first) { + ->willReturnCallback(function (Query $query, callable $next, callable $first) { return $next($query); }); @@ -72,10 +80,9 @@ public function testPluginsIsBeingUsedWhenGeocoding() $this->assertSame($collection, $pluginProvider->geocodeQuery($geocodeQuery)); } - public function testPluginsIsBeingUsedWhenReverse() { - $reverseQuery = ReverseQuery::fromCoordinates(47,11); + $reverseQuery = ReverseQuery::fromCoordinates(47, 11); $collection = new AddressCollection([]); $provider = $this->getMockBuilder(Provider::class) @@ -96,7 +103,7 @@ public function testPluginsIsBeingUsedWhenReverse() $pluginA->expects($this->once()) ->method('handleQuery') ->with($reverseQuery, $this->isType('callable'), $this->isType('callable')) - ->willReturnCallback(function(Query $query, callable $next, callable $first) { + ->willReturnCallback(function (Query $query, callable $next, callable $first) { return $next($query); }); @@ -128,7 +135,7 @@ public function testLoopException() $pluginA->expects($this->any()) ->method('handleQuery') ->with($geocodeQuery, $this->isType('callable'), $this->isType('callable')) - ->willReturnCallback(function(Query $query, callable $next, callable $first) { + ->willReturnCallback(function (Query $query, callable $next, callable $first) { return $first($query); }); From 43846895eecb6d029ebbd1922115e9a312fc13cb Mon Sep 17 00:00:00 2001 From: Tobias Nyholm Date: Sat, 15 Jul 2017 14:37:20 +0200 Subject: [PATCH 3/5] Add deps to main composer.json --- composer.json | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/composer.json b/composer.json index d242381a4..900c97f21 100644 --- a/composer.json +++ b/composer.json @@ -19,7 +19,9 @@ "php-http/client-implementation": "^1.0", "php-http/message-factory": "^1.0.2", "php-http/httplug": "^1.0", - "php-http/discovery": "^1.0" + "php-http/discovery": "^1.0", + "psr/simple-cache": "^1.0", + "php-http/promise": "^1.0" }, "require-dev": { "phpunit/phpunit": "^6.1", @@ -32,7 +34,8 @@ "nyholm/psr7": "^0.2.2", "nyholm/nsa": "^1.1", "cache/simple-cache-bridge": "^0.1.1", - "cache/array-adapter": "^0.5.0" + "cache/array-adapter": "^0.5.0", + "cache/void-adapter": "^0.4.1" }, "suggest": { "ext-geoip": "Enabling the geoip extension allows you to use the MaxMindProvider.", From 4073af8af9d89fec9586626a7a60cd1931fc206e Mon Sep 17 00:00:00 2001 From: Tobias Nyholm Date: Tue, 18 Jul 2017 10:37:20 +0200 Subject: [PATCH 4/5] Fixed the tests and use stable version of php-cache --- composer.json | 7 ++++--- src/Plugin/Tests/Plugin/CachePluginTest.php | 4 ++-- src/Plugin/Tests/PluginProviderTest.php | 18 ++++++++++++------ src/Plugin/composer.json | 2 +- 4 files changed, 19 insertions(+), 12 deletions(-) diff --git a/composer.json b/composer.json index 900c97f21..63370c9d4 100644 --- a/composer.json +++ b/composer.json @@ -33,9 +33,9 @@ "php-http/mock-client": "^1.0", "nyholm/psr7": "^0.2.2", "nyholm/nsa": "^1.1", - "cache/simple-cache-bridge": "^0.1.1", - "cache/array-adapter": "^0.5.0", - "cache/void-adapter": "^0.4.1" + "cache/simple-cache-bridge": "^1.0", + "cache/array-adapter": "^1.0", + "cache/void-adapter": "^1.0" }, "suggest": { "ext-geoip": "Enabling the geoip extension allows you to use the MaxMindProvider.", @@ -55,6 +55,7 @@ "test": "vendor/bin/phpunit" }, "minimum-stability": "dev", + "prefer-dist": true, "extra": { "branch-alias": { "dev-master": "4.0-dev" diff --git a/src/Plugin/Tests/Plugin/CachePluginTest.php b/src/Plugin/Tests/Plugin/CachePluginTest.php index ebdeb700a..a44121c95 100644 --- a/src/Plugin/Tests/Plugin/CachePluginTest.php +++ b/src/Plugin/Tests/Plugin/CachePluginTest.php @@ -24,7 +24,7 @@ public function testPluginMiss() { $ttl = 4711; $query = GeocodeQuery::create('foo'); - $queryString = $query->__toString(); + $queryString = sha1($query->__toString()); $cache = $this->getMockBuilder(VoidCachePool::class) ->disableOriginalConstructor() ->setMethods(['get', 'set']) @@ -53,7 +53,7 @@ public function testPluginMiss() public function testPluginHit() { $query = GeocodeQuery::create('foo'); - $queryString = $query->__toString(); + $queryString = sha1($query->__toString()); $cache = $this->getMockBuilder(VoidCachePool::class) ->disableOriginalConstructor() ->setMethods(['get', 'set']) diff --git a/src/Plugin/Tests/PluginProviderTest.php b/src/Plugin/Tests/PluginProviderTest.php index f63a29148..847fc69d5 100644 --- a/src/Plugin/Tests/PluginProviderTest.php +++ b/src/Plugin/Tests/PluginProviderTest.php @@ -115,16 +115,12 @@ public function testLoopException() { $this->expectException(LoopException::class); $geocodeQuery = GeocodeQuery::create('foo'); - $collection = new AddressCollection([]); $provider = $this->getMockBuilder(Provider::class) ->disableOriginalConstructor() ->setMethods(['geocodeQuery', 'reverseQuery', 'getName']) ->getMock(); - $provider->expects($this->once()) - ->method('geocodeQuery') - ->with($geocodeQuery) - ->willReturn($collection); + $provider->expects($this->never())->method('geocodeQuery'); $provider->expects($this->never())->method('reverseQuery'); $provider->expects($this->never())->method('getName'); @@ -133,13 +129,23 @@ public function testLoopException() ->setMethods(['handleQuery']) ->getMock(); $pluginA->expects($this->any()) + ->method('handleQuery') + ->with($geocodeQuery, $this->isType('callable'), $this->isType('callable')) + ->willReturnCallback(function (Query $query, callable $next, callable $first) { + return $next($query); + }); + $pluginB = $this->getMockBuilder(Plugin::class) + ->disableOriginalConstructor() + ->setMethods(['handleQuery']) + ->getMock(); + $pluginB->expects($this->any()) ->method('handleQuery') ->with($geocodeQuery, $this->isType('callable'), $this->isType('callable')) ->willReturnCallback(function (Query $query, callable $next, callable $first) { return $first($query); }); - $pluginProvider = new PluginProvider($provider, [$pluginA]); + $pluginProvider = new PluginProvider($provider, [$pluginA, $pluginB]); $pluginProvider->geocodeQuery($geocodeQuery); } } diff --git a/src/Plugin/composer.json b/src/Plugin/composer.json index a78f5c131..acb4a856d 100644 --- a/src/Plugin/composer.json +++ b/src/Plugin/composer.json @@ -21,7 +21,7 @@ }, "require-dev": { "phpunit/phpunit": "^6.1", - "cache/void-adapter": "^0.4.1" + "cache/void-adapter": "^1.0" }, "autoload": { "psr-4": { "Geocoder\\Plugin\\": "" }, From e99f9fcd26a1938e98458d3210b9e9ec00f746aa Mon Sep 17 00:00:00 2001 From: Tobias Nyholm Date: Tue, 1 Aug 2017 09:50:28 +0200 Subject: [PATCH 5/5] Minor --- src/Plugin/CHANGELOG.md | 8 +------- src/Plugin/composer.json | 1 - 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/src/Plugin/CHANGELOG.md b/src/Plugin/CHANGELOG.md index 9148ad9ef..bd787d6bf 100644 --- a/src/Plugin/CHANGELOG.md +++ b/src/Plugin/CHANGELOG.md @@ -2,12 +2,6 @@ The change log describes what is "Added", "Removed", "Changed" or "Fixed" between each release. -## 4.0.0-beta2 - -- Removed `AbstractHttpProvider::setMessageFactory`. -- Removed `AbstractHttpProvider::getHttpClient`. -- Make sure we have a `MessageFactory` in the constructor of `AbstractHttpProvider`. - -## 4.0.0-beta1 +## 1.0.0 First release of this library. diff --git a/src/Plugin/composer.json b/src/Plugin/composer.json index acb4a856d..37a40cf65 100644 --- a/src/Plugin/composer.json +++ b/src/Plugin/composer.json @@ -17,7 +17,6 @@ "psr/log": "^1.0", "psr/simple-cache": "^1.0", "php-http/promise": "^1.0" - }, "require-dev": { "phpunit/phpunit": "^6.1",