diff --git a/composer.json b/composer.json index bedf3f9a..2ed59701 100644 --- a/composer.json +++ b/composer.json @@ -75,7 +75,8 @@ "Shlinkio\\Shlink\\Core\\": "module/Core/src", "Shlinkio\\Shlink\\Common\\": "module/Common/src", "Shlinkio\\Shlink\\EventDispatcher\\": "module/EventDispatcher/src", - "Shlinkio\\Shlink\\IpGeolocation\\": "module/IpGeolocation/src/" + "Shlinkio\\Shlink\\IpGeolocation\\": "module/IpGeolocation/src/", + "Shlinkio\\Shlink\\Integrations\\": "module/Integrations/src/" }, "files": [ "module/Common/functions/functions.php", @@ -96,7 +97,8 @@ "module/Common/test-db" ], "ShlinkioTest\\Shlink\\EventDispatcher\\": "module/EventDispatcher/test", - "ShlinkioTest\\Shlink\\IpGeolocation\\": "module/IpGeolocation/test" + "ShlinkioTest\\Shlink\\IpGeolocation\\": "module/IpGeolocation/test", + "ShlinkioTest\\Shlink\\Integrations\\": "module/Integrations/test" } }, "scripts": { diff --git a/config/autoload/dependencies.global.php b/config/autoload/dependencies.global.php index 2dc0de9b..3577f3d4 100644 --- a/config/autoload/dependencies.global.php +++ b/config/autoload/dependencies.global.php @@ -1,18 +1,12 @@ [ - 'factories' => [ - ImplicitOptionsMiddleware::class => EmptyResponseImplicitOptionsMiddlewareFactory::class, - ], - 'delegators' => [ Expressive\Application::class => [ Container\ApplicationConfigInjectionDelegator::class, diff --git a/config/config.php b/config/config.php index d5776eef..f6297fd8 100644 --- a/config/config.php +++ b/config/config.php @@ -18,6 +18,7 @@ return (new ConfigAggregator\ConfigAggregator([ ExpressiveErrorHandler\ConfigProvider::class, Common\ConfigProvider::class, IpGeolocation\ConfigProvider::class, + Integrations\ConfigProvider::class, Core\ConfigProvider::class, CLI\ConfigProvider::class, Rest\ConfigProvider::class, diff --git a/module/Common/config/dependencies.config.php b/module/Common/config/dependencies.config.php index 34e37d6e..fec932e1 100644 --- a/module/Common/config/dependencies.config.php +++ b/module/Common/config/dependencies.config.php @@ -3,7 +3,6 @@ declare(strict_types=1); namespace Shlinkio\Shlink\Common; -use GeoIp2\Database\Reader; use GuzzleHttp\Client as GuzzleClient; use Monolog\Logger; use Psr\Log\LoggerInterface; @@ -12,7 +11,6 @@ use Symfony\Component\Filesystem\Filesystem; use Zend\I18n\Translator\Translator; use Zend\ServiceManager\AbstractFactory\ConfigAbstractFactory; use Zend\ServiceManager\Factory\InvokableFactory; -use Zend\ServiceManager\Proxy\LazyServiceFactory; return [ @@ -20,9 +18,8 @@ return [ 'factories' => [ GuzzleClient::class => InvokableFactory::class, Filesystem::class => InvokableFactory::class, - Reader::class => ConfigAbstractFactory::class, - Translator::class => Factory\TranslatorFactory::class, + Translator::class => I18n\TranslatorFactory::class, Template\Extension\TranslatorExtension::class => ConfigAbstractFactory::class, Middleware\LocaleMiddleware::class => ConfigAbstractFactory::class, @@ -44,24 +41,9 @@ return [ 'abstract_factories' => [ Factory\DottedAccessConfigAbstractFactory::class, ], - 'delegators' => [ - // The GeoLite2 db reader has to be lazy so that it does not try to load the DB file at app bootstrapping. - // By doing so, it would fail the first time shlink tries to download it. - Reader::class => [ - LazyServiceFactory::class, - ], - ], - - 'lazy_services' => [ - 'class_map' => [ - Reader::class => Reader::class, - ], - ], ], ConfigAbstractFactory::class => [ - Reader::class => ['config.geolite2.db_location'], - Template\Extension\TranslatorExtension::class => ['translator'], Middleware\LocaleMiddleware::class => ['translator'], Middleware\CloseDbConnectionMiddleware::class => ['em'], diff --git a/module/Common/src/Factory/DottedAccessConfigAbstractFactory.php b/module/Common/src/Factory/DottedAccessConfigAbstractFactory.php index cfe01eef..64c4d2f8 100644 --- a/module/Common/src/Factory/DottedAccessConfigAbstractFactory.php +++ b/module/Common/src/Factory/DottedAccessConfigAbstractFactory.php @@ -22,11 +22,9 @@ class DottedAccessConfigAbstractFactory implements AbstractFactoryInterface /** * Can the factory create an instance for the service? * - * @param ContainerInterface $container * @param string $requestedName - * @return bool */ - public function canCreate(ContainerInterface $container, $requestedName) + public function canCreate(ContainerInterface $container, $requestedName): bool { return substr_count($requestedName, '.') > 0; } diff --git a/module/Common/src/Factory/EmptyResponseImplicitOptionsMiddlewareFactory.php b/module/Common/src/Factory/EmptyResponseImplicitOptionsMiddlewareFactory.php deleted file mode 100644 index 793a2699..00000000 --- a/module/Common/src/Factory/EmptyResponseImplicitOptionsMiddlewareFactory.php +++ /dev/null @@ -1,34 +0,0 @@ -get('config'); - return Translator::factory($config['translator'] ?? []); - } -} diff --git a/module/Common/src/I18n/TranslatorFactory.php b/module/Common/src/I18n/TranslatorFactory.php new file mode 100644 index 00000000..942dad07 --- /dev/null +++ b/module/Common/src/I18n/TranslatorFactory.php @@ -0,0 +1,16 @@ +get('config'); + return Translator::factory($config['translator'] ?? []); + } +} diff --git a/module/Common/test/Factory/TranslatorFactoryTest.php b/module/Common/test/I18n/TranslatorFactoryTest.php similarity index 66% rename from module/Common/test/Factory/TranslatorFactoryTest.php rename to module/Common/test/I18n/TranslatorFactoryTest.php index 07cbfd5b..756a3991 100644 --- a/module/Common/test/Factory/TranslatorFactoryTest.php +++ b/module/Common/test/I18n/TranslatorFactoryTest.php @@ -1,10 +1,10 @@ factory->__invoke(new ServiceManager(['services' => [ + $instance = ($this->factory)(new ServiceManager(['services' => [ 'config' => [], - ]]), ''); + ]])); $this->assertInstanceOf(Translator::class, $instance); } } diff --git a/module/EventDispatcher/config/event_dispatcher.config.php b/module/EventDispatcher/config/event_dispatcher.config.php index ed932155..8941443f 100644 --- a/module/EventDispatcher/config/event_dispatcher.config.php +++ b/module/EventDispatcher/config/event_dispatcher.config.php @@ -23,6 +23,8 @@ return [ Psr\EventDispatcherInterface::class => Phly\EventDispatcher::class, ], 'delegators' => [ + // The listener provider has to be lazy, because it uses the Swoole server to generate AsyncEventListeners + // Without making this lazy, CLI commands which depend on the EventDispatcher fail Psr\ListenerProviderInterface::class => [ LazyServiceFactory::class, ], diff --git a/module/Integrations/config/dependencies.config.php b/module/Integrations/config/dependencies.config.php new file mode 100644 index 00000000..d2944e54 --- /dev/null +++ b/module/Integrations/config/dependencies.config.php @@ -0,0 +1,16 @@ + [ + 'factories' => [ + ImplicitOptionsMiddleware::class => Middleware\EmptyResponseImplicitOptionsMiddlewareFactory::class, + ], + ], + +]; diff --git a/module/Integrations/src/ConfigProvider.php b/module/Integrations/src/ConfigProvider.php new file mode 100644 index 00000000..bcbab248 --- /dev/null +++ b/module/Integrations/src/ConfigProvider.php @@ -0,0 +1,14 @@ +factory->__invoke(new ServiceManager(), ''); + $instance = ($this->factory)(); $this->assertInstanceOf(ImplicitOptionsMiddleware::class, $instance); } /** @test */ - public function responsePrototypeIsEmptyResponse() + public function responsePrototypeIsEmptyResponse(): void { - $instance = $this->factory->__invoke(new ServiceManager(), ''); + $instance = ($this->factory)(); $ref = new ReflectionObject($instance); $prop = $ref->getProperty('responseFactory'); diff --git a/module/IpGeolocation/README.md b/module/IpGeolocation/README.md new file mode 100644 index 00000000..feed5025 --- /dev/null +++ b/module/IpGeolocation/README.md @@ -0,0 +1,18 @@ +# IP Address Geolocation module + +Shlink module with tools to locate an IP address suing different strategies. + +```php + [ + 'db_location' => __DIR__ . '/../../data/GeoLite2-City.mmdb', + 'temp_dir' => sys_get_temp_dir(), + // 'download_from' => 'http://geolite.maxmind.com/download/geoip/database/GeoLite2-City.tar.gz', + ], + +]; +``` diff --git a/module/IpGeolocation/config/geolite2.config.php b/module/IpGeolocation/config/geolite2.config.php new file mode 100644 index 00000000..aa910a50 --- /dev/null +++ b/module/IpGeolocation/config/geolite2.config.php @@ -0,0 +1,35 @@ + [ + 'factories' => [ + Reader::class => ConfigAbstractFactory::class, + ], + 'delegators' => [ + // The GeoLite2 db reader has to be lazy so that it does not try to load the DB file at app bootstrapping. + // By doing so, it would fail the first time shlink tries to download it. + Reader::class => [ + LazyServiceFactory::class, + ], + ], + + 'lazy_services' => [ + 'class_map' => [ + Reader::class => Reader::class, + ], + ], + ], + + ConfigAbstractFactory::class => [ + Reader::class => ['config.geolite2.db_location'], + ], + +]; diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 910cdc99..4787de5d 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -24,6 +24,9 @@ ./module/IpGeolocation/test + + ./module/Integrations/test +