From d767c415d1fa03ea849df83656c06e1118649db6 Mon Sep 17 00:00:00 2001 From: Alejandro Celaya <alejandro@alejandrocelaya.com> Date: Mon, 12 Aug 2019 18:34:52 +0200 Subject: [PATCH] Deleted local Common module and used external one --- composer.json | 6 +- module/Common/LICENSE | 21 ----- module/Common/README.md | 89 ------------------- module/Common/config/cache.config.php | 17 ---- module/Common/config/dependencies.config.php | 48 ---------- module/Common/config/doctrine.config.php | 35 -------- module/Common/config/templates.config.php | 14 --- module/Common/functions/functions.php | 72 --------------- module/Common/src/Cache/CacheFactory.php | 51 ----------- module/Common/src/Cache/RedisFactory.php | 28 ------ module/Common/src/ConfigProvider.php | 12 --- .../Common/src/Doctrine/ConnectionFactory.php | 17 ---- .../src/Doctrine/EntityManagerFactory.php | 52 ----------- .../Doctrine/NoDbNameConnectionFactory.php | 21 ----- .../src/Doctrine/ReopeningEntityManager.php | 57 ------------ .../ReopeningEntityManagerDelegator.php | 15 ---- .../src/Doctrine/Type/ChronosDateTimeType.php | 53 ----------- module/Common/src/Entity/AbstractEntity.php | 24 ----- .../src/Exception/ExceptionInterface.php | 10 --- .../Exception/InvalidArgumentException.php | 10 --- .../DottedAccessConfigAbstractFactory.php | 86 ------------------ module/Common/src/I18n/TranslatorFactory.php | 16 ---- .../Lock/RetryLockStoreDelegatorFactory.php | 18 ---- .../Logger/LoggerAwareDelegatorFactory.php | 20 ----- module/Common/src/Logger/LoggerFactory.php | 29 ------ .../ExceptionWithNewLineProcessor.php | 30 ------- .../CloseDbConnectionMiddleware.php | 31 ------- .../Middleware/IpAddressMiddlewareFactory.php | 19 ---- .../src/Middleware/LocaleMiddleware.php | 61 ------------- .../Paginator/Util/PaginatorUtilsTrait.php | 43 --------- module/Common/src/Response/PixelResponse.php | 36 -------- module/Common/src/Response/QrCodeResponse.php | 32 ------- .../src/Response/ResponseUtilsTrait.php | 30 ------- .../src/Rest/DataTransformerInterface.php | 9 -- .../Extension/TranslatorExtension.php | 25 ------ module/Common/src/Util/DateRange.php | 35 -------- module/Common/src/Util/IpAddress.php | 72 --------------- module/Common/src/Util/StringUtilsTrait.php | 46 ---------- .../src/Validation/InputFactoryTrait.php | 35 -------- .../Common/src/Validation/SluggerFilter.php | 31 ------- module/Common/test/Cache/CacheFactoryTest.php | 62 ------------- module/Common/test/Cache/RedisFactoryTest.php | 79 ---------------- module/Common/test/ConfigProviderTest.php | 27 ------ .../test/Doctrine/ConnectionFactoryTest.php | 44 --------- .../Doctrine/EntityManagerFactoryTest.php | 44 --------- .../NoDbNameConnectionFactoryTest.php | 56 ------------ .../ReopeningEntityManagerDelegatorTest.php | 28 ------ .../Doctrine/ReopeningEntityManagerTest.php | 80 ----------------- .../Doctrine/Type/ChronosDateTimeTypeTest.php | 88 ------------------ .../DottedAccessConfigAbstractFactoryTest.php | 78 ---------------- .../test/I18n/TranslatorFactoryTest.php | 29 ------ .../RetryLockStoreDelegatorFactoryTest.php | 41 --------- .../LoggerAwareDelegatorFactoryTest.php | 55 ------------ .../Common/test/Logger/LoggerFactoryTest.php | 48 ---------- .../ExceptionWithNewLineProcessorTest.php | 67 -------------- .../CloseDbConnectionMiddlewareTest.php | 72 --------------- .../IpAddressMiddlewareFactoryTest.php | 85 ------------------ .../test/Middleware/LocaleMiddlewareTest.php | 63 ------------- .../test/Response/PixelResponseTest.php | 25 ------ .../test/Response/QrCodeResponseTest.php | 21 ----- .../Extension/TranslatorExtensionTest.php | 36 -------- module/Common/test/Util/DateRangeTest.php | 52 ----------- .../Common/test/Util/StringUtilsTraitTest.php | 44 --------- module/Common/test/Util/TestUtils.php | 37 -------- .../test/Validation/SluggerFilterTest.php | 44 --------- module/Core/test/Action/PixelActionTest.php | 6 +- module/Core/test/Action/PreviewActionTest.php | 9 +- .../Core/test/Action/RedirectActionTest.php | 13 ++- phpstan.neon | 1 - phpunit.xml.dist | 3 - 70 files changed, 15 insertions(+), 2678 deletions(-) delete mode 100644 module/Common/LICENSE delete mode 100644 module/Common/README.md delete mode 100644 module/Common/config/cache.config.php delete mode 100644 module/Common/config/dependencies.config.php delete mode 100644 module/Common/config/doctrine.config.php delete mode 100644 module/Common/config/templates.config.php delete mode 100644 module/Common/functions/functions.php delete mode 100644 module/Common/src/Cache/CacheFactory.php delete mode 100644 module/Common/src/Cache/RedisFactory.php delete mode 100644 module/Common/src/ConfigProvider.php delete mode 100644 module/Common/src/Doctrine/ConnectionFactory.php delete mode 100644 module/Common/src/Doctrine/EntityManagerFactory.php delete mode 100644 module/Common/src/Doctrine/NoDbNameConnectionFactory.php delete mode 100644 module/Common/src/Doctrine/ReopeningEntityManager.php delete mode 100644 module/Common/src/Doctrine/ReopeningEntityManagerDelegator.php delete mode 100644 module/Common/src/Doctrine/Type/ChronosDateTimeType.php delete mode 100644 module/Common/src/Entity/AbstractEntity.php delete mode 100644 module/Common/src/Exception/ExceptionInterface.php delete mode 100644 module/Common/src/Exception/InvalidArgumentException.php delete mode 100644 module/Common/src/Factory/DottedAccessConfigAbstractFactory.php delete mode 100644 module/Common/src/I18n/TranslatorFactory.php delete mode 100644 module/Common/src/Lock/RetryLockStoreDelegatorFactory.php delete mode 100644 module/Common/src/Logger/LoggerAwareDelegatorFactory.php delete mode 100644 module/Common/src/Logger/LoggerFactory.php delete mode 100644 module/Common/src/Logger/Processor/ExceptionWithNewLineProcessor.php delete mode 100644 module/Common/src/Middleware/CloseDbConnectionMiddleware.php delete mode 100644 module/Common/src/Middleware/IpAddressMiddlewareFactory.php delete mode 100644 module/Common/src/Middleware/LocaleMiddleware.php delete mode 100644 module/Common/src/Paginator/Util/PaginatorUtilsTrait.php delete mode 100644 module/Common/src/Response/PixelResponse.php delete mode 100644 module/Common/src/Response/QrCodeResponse.php delete mode 100644 module/Common/src/Response/ResponseUtilsTrait.php delete mode 100644 module/Common/src/Rest/DataTransformerInterface.php delete mode 100644 module/Common/src/Template/Extension/TranslatorExtension.php delete mode 100644 module/Common/src/Util/DateRange.php delete mode 100644 module/Common/src/Util/IpAddress.php delete mode 100644 module/Common/src/Util/StringUtilsTrait.php delete mode 100644 module/Common/src/Validation/InputFactoryTrait.php delete mode 100644 module/Common/src/Validation/SluggerFilter.php delete mode 100644 module/Common/test/Cache/CacheFactoryTest.php delete mode 100644 module/Common/test/Cache/RedisFactoryTest.php delete mode 100644 module/Common/test/ConfigProviderTest.php delete mode 100644 module/Common/test/Doctrine/ConnectionFactoryTest.php delete mode 100644 module/Common/test/Doctrine/EntityManagerFactoryTest.php delete mode 100644 module/Common/test/Doctrine/NoDbNameConnectionFactoryTest.php delete mode 100644 module/Common/test/Doctrine/ReopeningEntityManagerDelegatorTest.php delete mode 100644 module/Common/test/Doctrine/ReopeningEntityManagerTest.php delete mode 100644 module/Common/test/Doctrine/Type/ChronosDateTimeTypeTest.php delete mode 100644 module/Common/test/Factory/DottedAccessConfigAbstractFactoryTest.php delete mode 100644 module/Common/test/I18n/TranslatorFactoryTest.php delete mode 100644 module/Common/test/Lock/RetryLockStoreDelegatorFactoryTest.php delete mode 100644 module/Common/test/Logger/LoggerAwareDelegatorFactoryTest.php delete mode 100644 module/Common/test/Logger/LoggerFactoryTest.php delete mode 100644 module/Common/test/Logger/Processor/ExceptionWithNewLineProcessorTest.php delete mode 100644 module/Common/test/Middleware/CloseDbConnectionMiddlewareTest.php delete mode 100644 module/Common/test/Middleware/IpAddressMiddlewareFactoryTest.php delete mode 100644 module/Common/test/Middleware/LocaleMiddlewareTest.php delete mode 100644 module/Common/test/Response/PixelResponseTest.php delete mode 100644 module/Common/test/Response/QrCodeResponseTest.php delete mode 100644 module/Common/test/Template/Extension/TranslatorExtensionTest.php delete mode 100644 module/Common/test/Util/DateRangeTest.php delete mode 100644 module/Common/test/Util/StringUtilsTraitTest.php delete mode 100644 module/Common/test/Util/TestUtils.php delete mode 100644 module/Common/test/Validation/SluggerFilterTest.php diff --git a/composer.json b/composer.json index bfdaa59b..7f2677c2 100644 --- a/composer.json +++ b/composer.json @@ -32,6 +32,7 @@ "ocramius/proxy-manager": "~2.2.2", "phly/phly-event-dispatcher": "^1.0", "predis/predis": "^1.1", + "shlinkio/shlink-common": "^1.0", "shlinkio/shlink-installer": "^1.2.1", "symfony/console": "^4.3", "symfony/filesystem": "^4.3", @@ -56,7 +57,7 @@ "devster/ubench": "^2.0", "eaglewu/swoole-ide-helper": "dev-master", "filp/whoops": "^2.4", - "infection/infection": "^0.12.2", + "infection/infection": "^0.13.4", "phpstan/phpstan": "^0.11.2", "phpunit/phpcov": "^6.0", "phpunit/phpunit": "^8.3", @@ -73,13 +74,11 @@ "Shlinkio\\Shlink\\CLI\\": "module/CLI/src", "Shlinkio\\Shlink\\Rest\\": "module/Rest/src", "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\\PreviewGenerator\\": "module/PreviewGenerator/src/" }, "files": [ - "module/Common/functions/functions.php", "module/EventDispatcher/functions/functions.php" ] }, @@ -92,7 +91,6 @@ "module/Core/test", "module/Core/test-db" ], - "ShlinkioTest\\Shlink\\Common\\": "module/Common/test", "ShlinkioTest\\Shlink\\EventDispatcher\\": "module/EventDispatcher/test", "ShlinkioTest\\Shlink\\IpGeolocation\\": "module/IpGeolocation/test", "ShlinkioTest\\Shlink\\PreviewGenerator\\": "module/PreviewGenerator/test" diff --git a/module/Common/LICENSE b/module/Common/LICENSE deleted file mode 100644 index 31778387..00000000 --- a/module/Common/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2019 Alejandro Celaya - -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/module/Common/README.md b/module/Common/README.md deleted file mode 100644 index d4dc4815..00000000 --- a/module/Common/README.md +++ /dev/null @@ -1,89 +0,0 @@ -# Shlink Common - -This library provides some utils and conventions for web apps. It's main purpose is to be used on [Shlink](https://github.com/shlinkio/shlink) project, but any PHP project can take advantage. - -Most of the elements it provides require a [PSR-11] container, and it's easy to integrate on [expressive] applications thanks to the `ConfigProvider` it includes. - -## Install - -Install this library using composer: - - composer require shlinkio/shlink-common - -> This library is also an expressive module which provides its own `ConfigProvider`. Add it to your configuration to get everything automatically set up. - -## Cache - -A [doctrine cache] adapter is registered, which returns different instances depending on your configuration: - - * An `ArrayCache` instance when the `debug` config is set to true or when the APUc extension is not installed and the `cache.redis` config is not defined. - * An `ApcuCache`instance when no `cache.redis` is defined and the APCu extension is installed. - * A `PredisCache` instance when the `cache.redis` config is defined. - - Any of the adapters will use the namespace defined in `cache.namespace` config entry. - - ```php -<?php -declare(strict_types=1); - -return [ - - 'debug' => false, - - 'cache' => [ - 'namespace' => 'my_namespace', - 'redis' => [ - 'servers' => [ - 'tcp://1.1.1.1:6379', - 'tcp://2.2.2.2:6379', - 'tcp://3.3.3.3:6379', - ], - ], - ], - -]; -``` - -When the `cache.redis` config is provided, a set of servers is expected. If only one server is provided, this library will treat it as a regular server, but if several servers are defined, it will treat them as a redis cluster and expect the servers to be configured as such. - -## Middlewares - -This module provides a set of useful middlewares, all registered as services in the container: - -* **CloseDatabaseConnectionMiddleware**: - - Should be an early middleware in the pipeline. It makes use of the EntityManager that ensure the database connection is closed at the end of the request. - - It should be used when serving an app with a non-blocking IO server (like Swoole or ReactPHP), which persist services between requests. - -* **LocaleMiddleware**: - - Sets the locale in the translator, based on the `Accapt-Language` header. - -* **IpAddress** (from [akrabat/ip-address-middleware] package): - - Improves detection of the remote IP address. - - The set of headers which are inspected in order to search for the address can be customized using this configuration: - - ```php - <?php - declare(strict_types=1); - - return [ - - 'ip_address_resolution' => [ - 'headers_to_inspect' => [ - 'CF-Connecting-IP', - 'True-Client-IP', - 'X-Real-IP', - 'Forwarded', - 'X-Forwarded-For', - 'X-Forwarded', - 'X-Cluster-Client-Ip', - 'Client-Ip', - ], - ], - - ]; - ``` diff --git a/module/Common/config/cache.config.php b/module/Common/config/cache.config.php deleted file mode 100644 index 26f547d6..00000000 --- a/module/Common/config/cache.config.php +++ /dev/null @@ -1,17 +0,0 @@ -<?php -declare(strict_types=1); - -namespace Shlinkio\Shlink\Common; - -use Doctrine\Common\Cache as DoctrineCache; - -return [ - - 'dependencies' => [ - 'factories' => [ - DoctrineCache\Cache::class => Cache\CacheFactory::class, - Cache\RedisFactory::SERVICE_NAME => Cache\RedisFactory::class, - ], - ], - -]; diff --git a/module/Common/config/dependencies.config.php b/module/Common/config/dependencies.config.php deleted file mode 100644 index d4d3110d..00000000 --- a/module/Common/config/dependencies.config.php +++ /dev/null @@ -1,48 +0,0 @@ -<?php -declare(strict_types=1); - -namespace Shlinkio\Shlink\Common; - -use GuzzleHttp\Client as GuzzleClient; -use Monolog\Logger; -use Psr\Log\LoggerInterface; -use RKA\Middleware\IpAddress; -use Symfony\Component\Filesystem\Filesystem; -use Zend\I18n\Translator\Translator; -use Zend\ServiceManager\AbstractFactory\ConfigAbstractFactory; -use Zend\ServiceManager\Factory\InvokableFactory; - -return [ - - 'dependencies' => [ - 'factories' => [ - GuzzleClient::class => InvokableFactory::class, - Filesystem::class => InvokableFactory::class, - - Translator::class => I18n\TranslatorFactory::class, - Template\Extension\TranslatorExtension::class => ConfigAbstractFactory::class, - - Middleware\LocaleMiddleware::class => ConfigAbstractFactory::class, - Middleware\CloseDbConnectionMiddleware::class => ConfigAbstractFactory::class, - IpAddress::class => Middleware\IpAddressMiddlewareFactory::class, - ], - 'aliases' => [ - 'httpClient' => GuzzleClient::class, - 'translator' => Translator::class, - - 'logger' => LoggerInterface::class, - Logger::class => 'Logger_Shlink', - LoggerInterface::class => 'Logger_Shlink', - ], - 'abstract_factories' => [ - Factory\DottedAccessConfigAbstractFactory::class, - ], - ], - - ConfigAbstractFactory::class => [ - Template\Extension\TranslatorExtension::class => ['translator'], - Middleware\LocaleMiddleware::class => ['translator'], - Middleware\CloseDbConnectionMiddleware::class => ['em'], - ], - -]; diff --git a/module/Common/config/doctrine.config.php b/module/Common/config/doctrine.config.php deleted file mode 100644 index d85ef8e8..00000000 --- a/module/Common/config/doctrine.config.php +++ /dev/null @@ -1,35 +0,0 @@ -<?php -declare(strict_types=1); - -namespace Shlinkio\Shlink\Common; - -use Doctrine\DBAL\Connection; -use Doctrine\ORM\EntityManager; - -return [ - - 'entity_manager' => [ - 'orm' => [ - 'types' => [ - Doctrine\Type\ChronosDateTimeType::CHRONOS_DATETIME => Doctrine\Type\ChronosDateTimeType::class, - ], - ], - ], - - 'dependencies' => [ - 'factories' => [ - EntityManager::class => Doctrine\EntityManagerFactory::class, - Connection::class => Doctrine\ConnectionFactory::class, - Doctrine\NoDbNameConnectionFactory::SERVICE_NAME => Doctrine\NoDbNameConnectionFactory::class, - ], - 'aliases' => [ - 'em' => EntityManager::class, - ], - 'delegators' => [ - EntityManager::class => [ - Doctrine\ReopeningEntityManagerDelegator::class, - ], - ], - ], - -]; diff --git a/module/Common/config/templates.config.php b/module/Common/config/templates.config.php deleted file mode 100644 index eb25ef78..00000000 --- a/module/Common/config/templates.config.php +++ /dev/null @@ -1,14 +0,0 @@ -<?php -declare(strict_types=1); - -use Shlinkio\Shlink\Common\Template\Extension\TranslatorExtension; - -return [ - - 'plates' => [ - 'extensions' => [ - TranslatorExtension::class, - ], - ], - -]; diff --git a/module/Common/functions/functions.php b/module/Common/functions/functions.php deleted file mode 100644 index aab0ef26..00000000 --- a/module/Common/functions/functions.php +++ /dev/null @@ -1,72 +0,0 @@ -<?php -declare(strict_types=1); - -namespace Shlinkio\Shlink\Common; - -use Zend\Config\Factory; -use Zend\Stdlib\Glob; - -use function getenv; -use function json_decode as spl_json_decode; -use function json_last_error; -use function json_last_error_msg; -use function sprintf; -use function strtolower; -use function trim; - -use const JSON_ERROR_NONE; - -/** - * Gets the value of an environment variable. Supports boolean, empty and null. - * This is basically Laravel's env helper - * - * @param string $key - * @param mixed $default - * @return mixed - * @link https://github.com/laravel/framework/blob/5.2/src/Illuminate/Foundation/helpers.php#L369 - */ -function env($key, $default = null) -{ - $value = getenv($key); - if ($value === false) { - return $default; - } - - switch (strtolower($value)) { - case 'true': - case '(true)': - return true; - case 'false': - case '(false)': - return false; - case 'empty': - case '(empty)': - return ''; - case 'null': - case '(null)': - return null; - } - - return trim($value); -} - -/** - * @throws Exception\InvalidArgumentException - */ -function json_decode(string $json, int $depth = 512, int $options = 0): array -{ - $data = spl_json_decode($json, true, $depth, $options); - if (JSON_ERROR_NONE !== json_last_error()) { - throw new Exception\InvalidArgumentException(sprintf('Error decoding JSON: %s', json_last_error_msg())); - } - - return $data; -} - -/** - * Loads configuration files which match provided glob pattern, and returns the merged result as array - */ -function loadConfigFromGlob(string $globPattern): array -{ - return Factory::fromFiles(Glob::glob($globPattern, Glob::GLOB_BRACE)); -} diff --git a/module/Common/src/Cache/CacheFactory.php b/module/Common/src/Cache/CacheFactory.php deleted file mode 100644 index 12676dd8..00000000 --- a/module/Common/src/Cache/CacheFactory.php +++ /dev/null @@ -1,51 +0,0 @@ -<?php -declare(strict_types=1); - -namespace Shlinkio\Shlink\Common\Cache; - -use Doctrine\Common\Cache; -use Predis\Client as PredisClient; -use Psr\Container\ContainerInterface; - -use function extension_loaded; - -class CacheFactory -{ - /** @var callable|null */ - private $apcuEnabled; - - public function __construct(?callable $apcuEnabled = null) - { - $this->apcuEnabled = $apcuEnabled ?? function () { - return extension_loaded('apcu'); - }; - } - - public function __invoke(ContainerInterface $container): Cache\CacheProvider - { - $config = $container->get('config'); - $adapter = $this->buildAdapter($config, $container); - $adapter->setNamespace($config['cache']['namespace'] ?? ''); - - return $adapter; - } - - private function buildAdapter(array $config, ContainerInterface $container): Cache\CacheProvider - { - $isDebug = (bool) ($config['debug'] ?? false); - $redisConfig = $config['cache']['redis'] ?? null; - $apcuEnabled = ($this->apcuEnabled)(); - - if ($isDebug || (! $apcuEnabled && $redisConfig === null)) { - return new Cache\ArrayCache(); - } - - if ($redisConfig === null) { - return new Cache\ApcuCache(); - } - - /** @var PredisClient $predis */ - $predis = $container->get(RedisFactory::SERVICE_NAME); - return new Cache\PredisCache($predis); - } -} diff --git a/module/Common/src/Cache/RedisFactory.php b/module/Common/src/Cache/RedisFactory.php deleted file mode 100644 index f1a2d693..00000000 --- a/module/Common/src/Cache/RedisFactory.php +++ /dev/null @@ -1,28 +0,0 @@ -<?php -declare(strict_types=1); - -namespace Shlinkio\Shlink\Common\Cache; - -use Predis\Client as PredisClient; -use Psr\Container\ContainerInterface; - -use function count; -use function explode; -use function is_string; - -class RedisFactory -{ - public const SERVICE_NAME = 'Shlinkio\Shlink\Common\Cache\Redis'; - - public function __invoke(ContainerInterface $container): PredisClient - { - $config = $container->get('config'); - $redisConfig = $config['cache']['redis'] ?? $config['redis'] ?? []; - - $servers = $redisConfig['servers'] ?? []; - $servers = is_string($servers) ? explode(',', $servers) : $servers; - $options = count($servers) <= 1 ? null : ['cluster' => 'redis']; - - return new PredisClient($servers, $options); - } -} diff --git a/module/Common/src/ConfigProvider.php b/module/Common/src/ConfigProvider.php deleted file mode 100644 index 7d900823..00000000 --- a/module/Common/src/ConfigProvider.php +++ /dev/null @@ -1,12 +0,0 @@ -<?php -declare(strict_types=1); - -namespace Shlinkio\Shlink\Common; - -class ConfigProvider -{ - public function __invoke(): array - { - return loadConfigFromGlob(__DIR__ . '/../config/{,*.}config.php'); - } -} diff --git a/module/Common/src/Doctrine/ConnectionFactory.php b/module/Common/src/Doctrine/ConnectionFactory.php deleted file mode 100644 index f0c1a561..00000000 --- a/module/Common/src/Doctrine/ConnectionFactory.php +++ /dev/null @@ -1,17 +0,0 @@ -<?php -declare(strict_types=1); - -namespace Shlinkio\Shlink\Common\Doctrine; - -use Doctrine\DBAL\Connection; -use Doctrine\ORM\EntityManager; -use Psr\Container\ContainerInterface; - -class ConnectionFactory -{ - public function __invoke(ContainerInterface $container): Connection - { - $em = $container->get(EntityManager::class); - return $em->getConnection(); - } -} diff --git a/module/Common/src/Doctrine/EntityManagerFactory.php b/module/Common/src/Doctrine/EntityManagerFactory.php deleted file mode 100644 index 43847645..00000000 --- a/module/Common/src/Doctrine/EntityManagerFactory.php +++ /dev/null @@ -1,52 +0,0 @@ -<?php -declare(strict_types=1); - -namespace Shlinkio\Shlink\Common\Doctrine; - -use Doctrine\Common\Cache\ArrayCache; -use Doctrine\Common\Cache\Cache; -use Doctrine\Common\Persistence\Mapping\Driver\PHPDriver; -use Doctrine\DBAL\DBALException; -use Doctrine\DBAL\Types\Type; -use Doctrine\ORM\EntityManager; -use Doctrine\ORM\ORMException; -use Doctrine\ORM\Tools\Setup; -use Psr\Container\ContainerInterface; - -class EntityManagerFactory -{ - /** - * @throws ORMException - * @throws DBALException - */ - public function __invoke(ContainerInterface $container): EntityManager - { - $globalConfig = $container->get('config'); - $isDevMode = (bool) ($globalConfig['debug'] ?? false); - $cache = $container->has(Cache::class) ? $container->get(Cache::class) : new ArrayCache(); - $emConfig = $globalConfig['entity_manager'] ?? []; - $connectionConfig = $emConfig['connection'] ?? []; - $ormConfig = $emConfig['orm'] ?? []; - - $this->registerTypes($ormConfig); - - $config = Setup::createConfiguration($isDevMode, $ormConfig['proxies_dir'] ?? null, $cache); - $config->setMetadataDriverImpl(new PHPDriver($ormConfig['entities_mappings'] ?? [])); - - return EntityManager::create($connectionConfig, $config); - } - - /** - * @throws DBALException - */ - private function registerTypes(array $ormConfig): void - { - $types = $ormConfig['types'] ?? []; - - foreach ($types as $name => $className) { - if (! Type::hasType($name)) { - Type::addType($name, $className); - } - } - } -} diff --git a/module/Common/src/Doctrine/NoDbNameConnectionFactory.php b/module/Common/src/Doctrine/NoDbNameConnectionFactory.php deleted file mode 100644 index fdf470e0..00000000 --- a/module/Common/src/Doctrine/NoDbNameConnectionFactory.php +++ /dev/null @@ -1,21 +0,0 @@ -<?php -declare(strict_types=1); - -namespace Shlinkio\Shlink\Common\Doctrine; - -use Doctrine\DBAL\Connection; -use Psr\Container\ContainerInterface; - -class NoDbNameConnectionFactory -{ - public const SERVICE_NAME = 'Shlinkio\Shlink\Common\Doctrine\NoDbNameConnection'; - - public function __invoke(ContainerInterface $container): Connection - { - $conn = $container->get(Connection::class); - $params = $conn->getParams(); - unset($params['dbname']); - - return new Connection($params, $conn->getDriver(), $conn->getConfiguration(), $conn->getEventManager()); - } -} diff --git a/module/Common/src/Doctrine/ReopeningEntityManager.php b/module/Common/src/Doctrine/ReopeningEntityManager.php deleted file mode 100644 index d9a80e2e..00000000 --- a/module/Common/src/Doctrine/ReopeningEntityManager.php +++ /dev/null @@ -1,57 +0,0 @@ -<?php -declare(strict_types=1); - -namespace Shlinkio\Shlink\Common\Doctrine; - -use Doctrine\ORM\Decorator\EntityManagerDecorator; -use Doctrine\ORM\EntityManagerInterface; - -class ReopeningEntityManager extends EntityManagerDecorator -{ - /** @var callable */ - private $emFactory; - - public function __construct(EntityManagerInterface $wrapped, callable $emFactory) - { - parent::__construct($wrapped); - $this->emFactory = $emFactory; - } - - protected function getWrappedEntityManager(): EntityManagerInterface - { - if (! $this->wrapped->isOpen()) { - $this->wrapped = ($this->emFactory)( - $this->wrapped->getConnection(), - $this->wrapped->getConfiguration(), - $this->wrapped->getEventManager() - ); - } - - return $this->wrapped; - } - - public function flush($entity = null): void - { - $this->getWrappedEntityManager()->flush($entity); - } - - public function persist($object): void - { - $this->getWrappedEntityManager()->persist($object); - } - - public function remove($object): void - { - $this->getWrappedEntityManager()->remove($object); - } - - public function refresh($object): void - { - $this->getWrappedEntityManager()->refresh($object); - } - - public function merge($object) - { - return $this->getWrappedEntityManager()->merge($object); - } -} diff --git a/module/Common/src/Doctrine/ReopeningEntityManagerDelegator.php b/module/Common/src/Doctrine/ReopeningEntityManagerDelegator.php deleted file mode 100644 index 3ea6a2f1..00000000 --- a/module/Common/src/Doctrine/ReopeningEntityManagerDelegator.php +++ /dev/null @@ -1,15 +0,0 @@ -<?php -declare(strict_types=1); - -namespace Shlinkio\Shlink\Common\Doctrine; - -use Doctrine\ORM\EntityManager; -use Psr\Container\ContainerInterface; - -class ReopeningEntityManagerDelegator -{ - public function __invoke(ContainerInterface $container, string $name, callable $callback): ReopeningEntityManager - { - return new ReopeningEntityManager($callback(), [EntityManager::class, 'create']); - } -} diff --git a/module/Common/src/Doctrine/Type/ChronosDateTimeType.php b/module/Common/src/Doctrine/Type/ChronosDateTimeType.php deleted file mode 100644 index 210eb03a..00000000 --- a/module/Common/src/Doctrine/Type/ChronosDateTimeType.php +++ /dev/null @@ -1,53 +0,0 @@ -<?php -declare(strict_types=1); - -namespace Shlinkio\Shlink\Common\Doctrine\Type; - -use Cake\Chronos\Chronos; -use DateTimeInterface; -use Doctrine\DBAL\Platforms\AbstractPlatform; -use Doctrine\DBAL\Types\ConversionException; -use Doctrine\DBAL\Types\DateTimeImmutableType; - -class ChronosDateTimeType extends DateTimeImmutableType -{ - public const CHRONOS_DATETIME = 'chronos_datetime'; - - public function getName(): string - { - return self::CHRONOS_DATETIME; - } - - /** - * @throws ConversionException - */ - public function convertToPHPValue($value, AbstractPlatform $platform): ?Chronos - { - if ($value === null) { - return null; - } - - $dateTime = parent::convertToPHPValue($value, $platform); - return Chronos::instance($dateTime); - } - - /** - * @throws ConversionException - */ - public function convertToDatabaseValue($value, AbstractPlatform $platform): ?string - { - if (null === $value) { - return $value; - } - - if ($value instanceof DateTimeInterface) { - return $value->format($platform->getDateTimeFormatString()); - } - - throw ConversionException::conversionFailedInvalidType( - $value, - $this->getName(), - ['null', DateTimeInterface::class] - ); - } -} diff --git a/module/Common/src/Entity/AbstractEntity.php b/module/Common/src/Entity/AbstractEntity.php deleted file mode 100644 index dc3b84bc..00000000 --- a/module/Common/src/Entity/AbstractEntity.php +++ /dev/null @@ -1,24 +0,0 @@ -<?php -declare(strict_types=1); - -namespace Shlinkio\Shlink\Common\Entity; - -abstract class AbstractEntity -{ - /** @var string */ - protected $id; - - public function getId(): string - { - return $this->id; - } - - /** - * @internal - */ - public function setId(string $id): self - { - $this->id = $id; - return $this; - } -} diff --git a/module/Common/src/Exception/ExceptionInterface.php b/module/Common/src/Exception/ExceptionInterface.php deleted file mode 100644 index 9f2eca48..00000000 --- a/module/Common/src/Exception/ExceptionInterface.php +++ /dev/null @@ -1,10 +0,0 @@ -<?php -declare(strict_types=1); - -namespace Shlinkio\Shlink\Common\Exception; - -use Throwable; - -interface ExceptionInterface extends Throwable -{ -} diff --git a/module/Common/src/Exception/InvalidArgumentException.php b/module/Common/src/Exception/InvalidArgumentException.php deleted file mode 100644 index 52e6b365..00000000 --- a/module/Common/src/Exception/InvalidArgumentException.php +++ /dev/null @@ -1,10 +0,0 @@ -<?php -declare(strict_types=1); - -namespace Shlinkio\Shlink\Common\Exception; - -use InvalidArgumentException as SplInvalidArgumentException; - -class InvalidArgumentException extends SplInvalidArgumentException implements ExceptionInterface -{ -} diff --git a/module/Common/src/Factory/DottedAccessConfigAbstractFactory.php b/module/Common/src/Factory/DottedAccessConfigAbstractFactory.php deleted file mode 100644 index 64c4d2f8..00000000 --- a/module/Common/src/Factory/DottedAccessConfigAbstractFactory.php +++ /dev/null @@ -1,86 +0,0 @@ -<?php -declare(strict_types=1); - -namespace Shlinkio\Shlink\Common\Factory; - -use ArrayAccess; -use Interop\Container\ContainerInterface; -use Interop\Container\Exception\ContainerException; -use Shlinkio\Shlink\Common\Exception\InvalidArgumentException; -use Zend\ServiceManager\Exception\ServiceNotCreatedException; -use Zend\ServiceManager\Exception\ServiceNotFoundException; -use Zend\ServiceManager\Factory\AbstractFactoryInterface; - -use function array_shift; -use function explode; -use function is_array; -use function sprintf; -use function substr_count; - -class DottedAccessConfigAbstractFactory implements AbstractFactoryInterface -{ - /** - * Can the factory create an instance for the service? - * - * @param string $requestedName - */ - public function canCreate(ContainerInterface $container, $requestedName): bool - { - return substr_count($requestedName, '.') > 0; - } - - /** - * Create an object - * - * @param ContainerInterface $container - * @param string $requestedName - * @param null|array $options - * @return object - * @throws InvalidArgumentException - * @throws ServiceNotFoundException if unable to resolve the service. - * @throws ServiceNotCreatedException if an exception is raised when - * creating a service. - * @throws ContainerException if any other error occurs - */ - public function __invoke(ContainerInterface $container, $requestedName, ?array $options = null) - { - $parts = explode('.', $requestedName); - $serviceName = array_shift($parts); - if (! $container->has($serviceName)) { - throw new ServiceNotCreatedException(sprintf( - 'Defined service "%s" could not be found in container after resolving dotted expression "%s".', - $serviceName, - $requestedName - )); - } - - $array = $container->get($serviceName); - return $this->readKeysFromArray($parts, $array); - } - - /** - * @param array $keys - * @param array|\ArrayAccess $array - * @return mixed|null - * @throws InvalidArgumentException - */ - private function readKeysFromArray(array $keys, $array) - { - $key = array_shift($keys); - - // When one of the provided keys is not found, throw an exception - if (! isset($array[$key])) { - throw new InvalidArgumentException(sprintf( - 'The key "%s" provided in the dotted notation could not be found in the array service', - $key - )); - } - - $value = $array[$key]; - if (! empty($keys) && (is_array($value) || $value instanceof ArrayAccess)) { - $value = $this->readKeysFromArray($keys, $value); - } - - return $value; - } -} diff --git a/module/Common/src/I18n/TranslatorFactory.php b/module/Common/src/I18n/TranslatorFactory.php deleted file mode 100644 index 942dad07..00000000 --- a/module/Common/src/I18n/TranslatorFactory.php +++ /dev/null @@ -1,16 +0,0 @@ -<?php -declare(strict_types=1); - -namespace Shlinkio\Shlink\Common\I18n; - -use Interop\Container\ContainerInterface; -use Zend\I18n\Translator\Translator; - -class TranslatorFactory -{ - public function __invoke(ContainerInterface $container): Translator - { - $config = $container->get('config'); - return Translator::factory($config['translator'] ?? []); - } -} diff --git a/module/Common/src/Lock/RetryLockStoreDelegatorFactory.php b/module/Common/src/Lock/RetryLockStoreDelegatorFactory.php deleted file mode 100644 index 7828e24f..00000000 --- a/module/Common/src/Lock/RetryLockStoreDelegatorFactory.php +++ /dev/null @@ -1,18 +0,0 @@ -<?php -declare(strict_types=1); - -namespace Shlinkio\Shlink\Common\Lock; - -use Interop\Container\ContainerInterface; -use Symfony\Component\Lock\Store\RetryTillSaveStore; -use Symfony\Component\Lock\StoreInterface; - -class RetryLockStoreDelegatorFactory -{ - public function __invoke(ContainerInterface $container, $name, callable $callback): RetryTillSaveStore - { - /** @var StoreInterface $originalStore */ - $originalStore = $callback(); - return new RetryTillSaveStore($originalStore); - } -} diff --git a/module/Common/src/Logger/LoggerAwareDelegatorFactory.php b/module/Common/src/Logger/LoggerAwareDelegatorFactory.php deleted file mode 100644 index 8cb04499..00000000 --- a/module/Common/src/Logger/LoggerAwareDelegatorFactory.php +++ /dev/null @@ -1,20 +0,0 @@ -<?php -declare(strict_types=1); - -namespace Shlinkio\Shlink\Common\Logger; - -use Psr\Container\ContainerInterface; -use Psr\Log; - -class LoggerAwareDelegatorFactory -{ - public function __invoke(ContainerInterface $container, $name, callable $callback) - { - $instance = $callback(); - if ($instance instanceof Log\LoggerAwareInterface) { - $instance->setLogger($container->get(Log\LoggerInterface::class)); - } - - return $instance; - } -} diff --git a/module/Common/src/Logger/LoggerFactory.php b/module/Common/src/Logger/LoggerFactory.php deleted file mode 100644 index 7e896108..00000000 --- a/module/Common/src/Logger/LoggerFactory.php +++ /dev/null @@ -1,29 +0,0 @@ -<?php -declare(strict_types=1); - -namespace Shlinkio\Shlink\Common\Logger; - -use Cascade\Cascade; -use Interop\Container\ContainerInterface; -use Monolog\Logger; - -use function count; -use function explode; - -class LoggerFactory -{ - public function __invoke(ContainerInterface $container, string $requestedName, ?array $options = null): Logger - { - $config = $container->has('config') ? $container->get('config') : []; - Cascade::fileConfig($config['logger'] ?? ['loggers' => []]); - - // Compose requested logger name - $loggerName = $options['logger_name'] ?? 'Logger'; - $nameParts = explode('_', $requestedName); - if (count($nameParts) > 1) { - $loggerName = $nameParts[1]; - } - - return Cascade::getLogger($loggerName); - } -} diff --git a/module/Common/src/Logger/Processor/ExceptionWithNewLineProcessor.php b/module/Common/src/Logger/Processor/ExceptionWithNewLineProcessor.php deleted file mode 100644 index 91c0a657..00000000 --- a/module/Common/src/Logger/Processor/ExceptionWithNewLineProcessor.php +++ /dev/null @@ -1,30 +0,0 @@ -<?php -declare(strict_types=1); - -namespace Shlinkio\Shlink\Common\Logger\Processor; - -use function str_replace; -use function strpos; - -use const PHP_EOL; - -final class ExceptionWithNewLineProcessor -{ - private const EXCEPTION_PLACEHOLDER = '{e}'; - - public function __invoke(array $record) - { - $message = $record['message']; - $messageHasExceptionPlaceholder = strpos($message, self::EXCEPTION_PLACEHOLDER) !== false; - - if ($messageHasExceptionPlaceholder) { - $record['message'] = str_replace( - self::EXCEPTION_PLACEHOLDER, - PHP_EOL . self::EXCEPTION_PLACEHOLDER, - $message - ); - } - - return $record; - } -} diff --git a/module/Common/src/Middleware/CloseDbConnectionMiddleware.php b/module/Common/src/Middleware/CloseDbConnectionMiddleware.php deleted file mode 100644 index 1294848d..00000000 --- a/module/Common/src/Middleware/CloseDbConnectionMiddleware.php +++ /dev/null @@ -1,31 +0,0 @@ -<?php -declare(strict_types=1); - -namespace Shlinkio\Shlink\Common\Middleware; - -use Doctrine\ORM\EntityManagerInterface; -use Psr\Http\Message\ResponseInterface; -use Psr\Http\Message\ServerRequestInterface; -use Psr\Http\Server\MiddlewareInterface; -use Psr\Http\Server\RequestHandlerInterface; - -class CloseDbConnectionMiddleware implements MiddlewareInterface -{ - /** @var EntityManagerInterface */ - private $em; - - public function __construct(EntityManagerInterface $em) - { - $this->em = $em; - } - - public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface - { - try { - return $handler->handle($request); - } finally { - $this->em->getConnection()->close(); - $this->em->clear(); - } - } -} diff --git a/module/Common/src/Middleware/IpAddressMiddlewareFactory.php b/module/Common/src/Middleware/IpAddressMiddlewareFactory.php deleted file mode 100644 index 73d643b4..00000000 --- a/module/Common/src/Middleware/IpAddressMiddlewareFactory.php +++ /dev/null @@ -1,19 +0,0 @@ -<?php -declare(strict_types=1); - -namespace Shlinkio\Shlink\Common\Middleware; - -use Psr\Container\ContainerInterface; -use RKA\Middleware\IpAddress; - -class IpAddressMiddlewareFactory -{ - public const REQUEST_ATTR = 'remote_address'; - - public function __invoke(ContainerInterface $container): IpAddress - { - $config = $container->get('config'); - $headersToInspect = $config['ip_address_resolution']['headers_to_inspect'] ?? []; - return new IpAddress(true, [], self::REQUEST_ATTR, $headersToInspect); - } -} diff --git a/module/Common/src/Middleware/LocaleMiddleware.php b/module/Common/src/Middleware/LocaleMiddleware.php deleted file mode 100644 index 12ba084b..00000000 --- a/module/Common/src/Middleware/LocaleMiddleware.php +++ /dev/null @@ -1,61 +0,0 @@ -<?php -declare(strict_types=1); - -namespace Shlinkio\Shlink\Common\Middleware; - -use Psr\Http\Message\ResponseInterface as Response; -use Psr\Http\Message\ServerRequestInterface as Request; -use Psr\Http\Server\MiddlewareInterface; -use Psr\Http\Server\RequestHandlerInterface as DelegateInterface; -use Zend\I18n\Translator\Translator; - -use function count; -use function explode; - -class LocaleMiddleware implements MiddlewareInterface -{ - private const ACCEPT_LANGUAGE = 'Accept-Language'; - - /** @var Translator */ - private $translator; - - public function __construct(Translator $translator) - { - $this->translator = $translator; - } - - /** - * Process an incoming server request and return a response, optionally delegating - * to the next middleware component to create the response. - * - * @param Request $request - * @param DelegateInterface $delegate - * - * @return Response - */ - public function process(Request $request, DelegateInterface $delegate): Response - { - if (! $request->hasHeader(self::ACCEPT_LANGUAGE)) { - return $delegate->handle($request); - } - - $locale = $request->getHeaderLine(self::ACCEPT_LANGUAGE); - $this->translator->setLocale($this->normalizeLocale($locale)); - return $delegate->handle($request); - } - - private function normalizeLocale(string $locale): string - { - $parts = explode('_', $locale); - if (count($parts) > 1) { - return $parts[0]; - } - - $parts = explode('-', $locale); - if (count($parts) > 1) { - return $parts[0]; - } - - return $locale; - } -} diff --git a/module/Common/src/Paginator/Util/PaginatorUtilsTrait.php b/module/Common/src/Paginator/Util/PaginatorUtilsTrait.php deleted file mode 100644 index 2009164d..00000000 --- a/module/Common/src/Paginator/Util/PaginatorUtilsTrait.php +++ /dev/null @@ -1,43 +0,0 @@ -<?php -declare(strict_types=1); - -namespace Shlinkio\Shlink\Common\Paginator\Util; - -use Shlinkio\Shlink\Common\Rest\DataTransformerInterface; -use Zend\Paginator\Paginator; -use Zend\Stdlib\ArrayUtils; - -use function array_map; -use function sprintf; - -trait PaginatorUtilsTrait -{ - private function serializePaginator(Paginator $paginator, ?DataTransformerInterface $transformer = null): array - { - return [ - 'data' => $this->serializeItems(ArrayUtils::iteratorToArray($paginator->getCurrentItems()), $transformer), - 'pagination' => [ - 'currentPage' => $paginator->getCurrentPageNumber(), - 'pagesCount' => $paginator->count(), - 'itemsPerPage' => $paginator->getItemCountPerPage(), - 'itemsInCurrentPage' => $paginator->getCurrentItemCount(), - 'totalItems' => $paginator->getTotalItemCount(), - ], - ]; - } - - private function serializeItems(array $items, ?DataTransformerInterface $transformer = null): array - { - return $transformer === null ? $items : array_map([$transformer, 'transform'], $items); - } - - private function isLastPage(Paginator $paginator): bool - { - return $paginator->getCurrentPageNumber() >= $paginator->count(); - } - - private function formatCurrentPageMessage(Paginator $paginator, string $pattern): string - { - return sprintf($pattern, $paginator->getCurrentPageNumber(), $paginator->count()); - } -} diff --git a/module/Common/src/Response/PixelResponse.php b/module/Common/src/Response/PixelResponse.php deleted file mode 100644 index 94a81cfc..00000000 --- a/module/Common/src/Response/PixelResponse.php +++ /dev/null @@ -1,36 +0,0 @@ -<?php -declare(strict_types=1); - -namespace Shlinkio\Shlink\Common\Response; - -use Fig\Http\Message\StatusCodeInterface as StatusCode; -use Psr\Http\Message\StreamInterface; -use Zend\Diactoros\Response; -use Zend\Diactoros\Stream; - -use function base64_decode; - -class PixelResponse extends Response -{ - private const BASE_64_IMAGE = 'R0lGODlhAQABAJAAAP8AAAAAACH5BAUQAAAALAAAAAABAAEAAAICBAEAOw=='; - private const CONTENT_TYPE = 'image/gif'; - - public function __construct(int $status = StatusCode::STATUS_OK, array $headers = []) - { - $headers['content-type'] = self::CONTENT_TYPE; - parent::__construct($this->createBody(), $status, $headers); - } - - /** - * Create the message body. - * - * @return StreamInterface - */ - private function createBody(): StreamInterface - { - $body = new Stream('php://temp', 'wb+'); - $body->write(base64_decode(self::BASE_64_IMAGE)); - $body->rewind(); - return $body; - } -} diff --git a/module/Common/src/Response/QrCodeResponse.php b/module/Common/src/Response/QrCodeResponse.php deleted file mode 100644 index 230ae08f..00000000 --- a/module/Common/src/Response/QrCodeResponse.php +++ /dev/null @@ -1,32 +0,0 @@ -<?php -declare(strict_types=1); - -namespace Shlinkio\Shlink\Common\Response; - -use Endroid\QrCode\QrCode; -use Fig\Http\Message\StatusCodeInterface as StatusCode; -use Psr\Http\Message\StreamInterface; -use Zend\Diactoros\Response; -use Zend\Diactoros\Stream; - -class QrCodeResponse extends Response -{ - use Response\InjectContentTypeTrait; - - public function __construct(QrCode $qrCode, int $status = StatusCode::STATUS_OK, array $headers = []) - { - parent::__construct( - $this->createBody($qrCode), - $status, - $this->injectContentType($qrCode->getContentType(), $headers) - ); - } - - private function createBody(QrCode $qrCode): StreamInterface - { - $body = new Stream('php://temp', 'wb+'); - $body->write($qrCode->get()); - $body->rewind(); - return $body; - } -} diff --git a/module/Common/src/Response/ResponseUtilsTrait.php b/module/Common/src/Response/ResponseUtilsTrait.php deleted file mode 100644 index dee426fc..00000000 --- a/module/Common/src/Response/ResponseUtilsTrait.php +++ /dev/null @@ -1,30 +0,0 @@ -<?php -declare(strict_types=1); - -namespace Shlinkio\Shlink\Common\Response; - -use Fig\Http\Message\StatusCodeInterface as StatusCode; -use finfo; -use Psr\Http\Message\ResponseInterface; -use Zend\Diactoros\Response; -use Zend\Diactoros\Stream; -use Zend\Stdlib\ArrayUtils; - -use const FILEINFO_MIME; - -trait ResponseUtilsTrait -{ - private function generateImageResponse(string $imagePath): ResponseInterface - { - return $this->generateBinaryResponse($imagePath); - } - - private function generateBinaryResponse(string $path, array $extraHeaders = []): ResponseInterface - { - $body = new Stream($path); - return new Response($body, StatusCode::STATUS_OK, ArrayUtils::merge([ - 'Content-Type' => (new finfo(FILEINFO_MIME))->file($path), - 'Content-Length' => (string) $body->getSize(), - ], $extraHeaders)); - } -} diff --git a/module/Common/src/Rest/DataTransformerInterface.php b/module/Common/src/Rest/DataTransformerInterface.php deleted file mode 100644 index 933f6cce..00000000 --- a/module/Common/src/Rest/DataTransformerInterface.php +++ /dev/null @@ -1,9 +0,0 @@ -<?php -declare(strict_types=1); - -namespace Shlinkio\Shlink\Common\Rest; - -interface DataTransformerInterface -{ - public function transform($value): array; -} diff --git a/module/Common/src/Template/Extension/TranslatorExtension.php b/module/Common/src/Template/Extension/TranslatorExtension.php deleted file mode 100644 index 775bd909..00000000 --- a/module/Common/src/Template/Extension/TranslatorExtension.php +++ /dev/null @@ -1,25 +0,0 @@ -<?php -declare(strict_types=1); - -namespace Shlinkio\Shlink\Common\Template\Extension; - -use League\Plates\Engine; -use League\Plates\Extension\ExtensionInterface; -use Zend\I18n\Translator\TranslatorInterface; - -class TranslatorExtension implements ExtensionInterface -{ - /** @var TranslatorInterface */ - private $translator; - - public function __construct(TranslatorInterface $translator) - { - $this->translator = $translator; - } - - public function register(Engine $engine): void - { - $engine->registerFunction('translate', [$this->translator, 'translate']); - $engine->registerFunction('locale', [$this->translator, 'getLocale']); - } -} diff --git a/module/Common/src/Util/DateRange.php b/module/Common/src/Util/DateRange.php deleted file mode 100644 index 34c7b865..00000000 --- a/module/Common/src/Util/DateRange.php +++ /dev/null @@ -1,35 +0,0 @@ -<?php -declare(strict_types=1); - -namespace Shlinkio\Shlink\Common\Util; - -use Cake\Chronos\Chronos; - -final class DateRange -{ - /** @var Chronos|null */ - private $startDate; - /** @var Chronos|null */ - private $endDate; - - public function __construct(?Chronos $startDate = null, ?Chronos $endDate = null) - { - $this->startDate = $startDate; - $this->endDate = $endDate; - } - - public function getStartDate(): ?Chronos - { - return $this->startDate; - } - - public function getEndDate(): ?Chronos - { - return $this->endDate; - } - - public function isEmpty(): bool - { - return $this->startDate === null && $this->endDate === null; - } -} diff --git a/module/Common/src/Util/IpAddress.php b/module/Common/src/Util/IpAddress.php deleted file mode 100644 index a71bac14..00000000 --- a/module/Common/src/Util/IpAddress.php +++ /dev/null @@ -1,72 +0,0 @@ -<?php -declare(strict_types=1); - -namespace Shlinkio\Shlink\Common\Util; - -use Shlinkio\Shlink\Common\Exception\InvalidArgumentException; - -use function count; -use function explode; -use function implode; -use function sprintf; -use function trim; - -final class IpAddress -{ - private const IPV4_PARTS_COUNT = 4; - private const OBFUSCATED_OCTET = '0'; - public const LOCALHOST = '127.0.0.1'; - - /** @var string */ - private $firstOctet; - /** @var string */ - private $secondOctet; - /** @var string */ - private $thirdOctet; - /** @var string */ - private $fourthOctet; - - private function __construct(string $firstOctet, string $secondOctet, string $thirdOctet, string $fourthOctet) - { - $this->firstOctet = $firstOctet; - $this->secondOctet = $secondOctet; - $this->thirdOctet = $thirdOctet; - $this->fourthOctet = $fourthOctet; - } - - /** - * @param string $address - * @return IpAddress - * @throws InvalidArgumentException - */ - public static function fromString(string $address): self - { - $address = trim($address); - $parts = explode('.', $address); - if (count($parts) !== self::IPV4_PARTS_COUNT) { - throw new InvalidArgumentException(sprintf('Provided IP "%s" is invalid', $address)); - } - - return new self(...$parts); - } - - public function getObfuscatedCopy(): self - { - return new self( - $this->firstOctet, - $this->secondOctet, - $this->thirdOctet, - self::OBFUSCATED_OCTET - ); - } - - public function __toString(): string - { - return implode('.', [ - $this->firstOctet, - $this->secondOctet, - $this->thirdOctet, - $this->fourthOctet, - ]); - } -} diff --git a/module/Common/src/Util/StringUtilsTrait.php b/module/Common/src/Util/StringUtilsTrait.php deleted file mode 100644 index 853ba7b8..00000000 --- a/module/Common/src/Util/StringUtilsTrait.php +++ /dev/null @@ -1,46 +0,0 @@ -<?php -declare(strict_types=1); - -namespace Shlinkio\Shlink\Common\Util; - -use function random_int; -use function sprintf; -use function strlen; - -trait StringUtilsTrait -{ - private function generateRandomString(int $length = 10): string - { - $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; - $charactersLength = strlen($characters); - $randomString = ''; - for ($i = 0; $i < $length; $i++) { - $randomString .= $characters[random_int(0, $charactersLength - 1)]; - } - - return $randomString; - } - - private function generateV4Uuid(): string - { - return sprintf( - '%04x%04x-%04x-%04x-%04x-%04x%04x%04x', - // 32 bits for "time_low" - random_int(0, 0xffff), - random_int(0, 0xffff), - // 16 bits for "time_mid" - random_int(0, 0xffff), - // 16 bits for "time_hi_and_version", - // four most significant bits holds version number 4 - random_int(0, 0x0fff) | 0x4000, - // 16 bits, 8 bits for "clk_seq_hi_res", - // 8 bits for "clk_seq_low", - // two most significant bits holds zero and one for variant DCE1.1 - random_int(0, 0x3fff) | 0x8000, - // 48 bits for "node" - random_int(0, 0xffff), - random_int(0, 0xffff), - random_int(0, 0xffff) - ); - } -} diff --git a/module/Common/src/Validation/InputFactoryTrait.php b/module/Common/src/Validation/InputFactoryTrait.php deleted file mode 100644 index 71d92818..00000000 --- a/module/Common/src/Validation/InputFactoryTrait.php +++ /dev/null @@ -1,35 +0,0 @@ -<?php -declare(strict_types=1); - -namespace Shlinkio\Shlink\Common\Validation; - -use Zend\Filter; -use Zend\InputFilter\Input; -use Zend\Validator; - -trait InputFactoryTrait -{ - private function createInput($name, $required = true): Input - { - $input = new Input($name); - $input->setRequired($required) - ->getFilterChain()->attach(new Filter\StripTags()) - ->attach(new Filter\StringTrim()); - return $input; - } - - private function createBooleanInput(string $name, bool $required = true): Input - { - $input = $this->createInput($name, $required); - $input->getFilterChain()->attach(new Filter\Boolean()); - $input->getValidatorChain()->attach(new Validator\NotEmpty(['type' => [ - Validator\NotEmpty::OBJECT, - Validator\NotEmpty::SPACE, - Validator\NotEmpty::NULL, - Validator\NotEmpty::EMPTY_ARRAY, - Validator\NotEmpty::STRING, - ]])); - - return $input; - } -} diff --git a/module/Common/src/Validation/SluggerFilter.php b/module/Common/src/Validation/SluggerFilter.php deleted file mode 100644 index 9387e85a..00000000 --- a/module/Common/src/Validation/SluggerFilter.php +++ /dev/null @@ -1,31 +0,0 @@ -<?php -declare(strict_types=1); - -namespace Shlinkio\Shlink\Common\Validation; - -use Cocur\Slugify; -use Zend\Filter\Exception; -use Zend\Filter\FilterInterface; - -class SluggerFilter implements FilterInterface -{ - /** @var Slugify\SlugifyInterface */ - private $slugger; - - public function __construct(?Slugify\SlugifyInterface $slugger = null) - { - $this->slugger = $slugger ?: new Slugify\Slugify(['lowercase' => false]); - } - - /** - * Returns the result of filtering $value - * - * @param mixed $value - * @throws Exception\RuntimeException If filtering $value is impossible - * @return mixed - */ - public function filter($value) - { - return ! empty($value) ? $this->slugger->slugify($value) : null; - } -} diff --git a/module/Common/test/Cache/CacheFactoryTest.php b/module/Common/test/Cache/CacheFactoryTest.php deleted file mode 100644 index 9575befc..00000000 --- a/module/Common/test/Cache/CacheFactoryTest.php +++ /dev/null @@ -1,62 +0,0 @@ -<?php -declare(strict_types=1); - -namespace ShlinkioTest\Shlink\Common\Cache; - -use Doctrine\Common\Cache; -use PHPUnit\Framework\TestCase; -use Predis\ClientInterface; -use Prophecy\Prophecy\ObjectProphecy; -use Psr\Container\ContainerInterface; -use Shlinkio\Shlink\Common\Cache\CacheFactory; -use Shlinkio\Shlink\Common\Cache\RedisFactory; - -class CacheFactoryTest extends TestCase -{ - /** @var ObjectProphecy */ - private $container; - - public function setUp(): void - { - $this->container = $this->prophesize(ContainerInterface::class); - } - - /** - * @test - * @dataProvider provideCacheConfig - */ - public function expectedCacheAdapterIsReturned( - array $config, - string $expectedAdapterClass, - string $expectedNamespace, - ?callable $apcuEnabled = null - ): void { - $factory = new CacheFactory($apcuEnabled); - - $getConfig = $this->container->get('config')->willReturn($config); - $getRedis = $this->container->get(RedisFactory::SERVICE_NAME)->willReturn( - $this->prophesize(ClientInterface::class)->reveal() - ); - - $cache = $factory($this->container->reveal()); - - $this->assertInstanceOf($expectedAdapterClass, $cache); - $this->assertEquals($expectedNamespace, $cache->getNamespace()); - $getConfig->shouldHaveBeenCalledOnce(); - $getRedis->shouldHaveBeenCalledTimes($expectedAdapterClass === Cache\PredisCache::class ? 1 :0); - } - - public function provideCacheConfig(): iterable - { - yield 'debug true' => [['debug' => true], Cache\ArrayCache::class, '']; - yield 'debug false' => [['debug' => false], Cache\ApcuCache::class, '']; - yield 'no debug' => [[], Cache\ApcuCache::class, '']; - yield 'with redis' => [['cache' => [ - 'namespace' => $namespace = 'some_namespace', - 'redis' => [], - ]], Cache\PredisCache::class, $namespace]; - yield 'debug false and no apcu' => [['debug' => false], Cache\ArrayCache::class, '', function () { - return false; - }]; - } -} diff --git a/module/Common/test/Cache/RedisFactoryTest.php b/module/Common/test/Cache/RedisFactoryTest.php deleted file mode 100644 index 67acba2c..00000000 --- a/module/Common/test/Cache/RedisFactoryTest.php +++ /dev/null @@ -1,79 +0,0 @@ -<?php -declare(strict_types=1); - -namespace ShlinkioTest\Shlink\Common\Cache; - -use PHPUnit\Framework\TestCase; -use Predis\Connection\Aggregate\PredisCluster; -use Predis\Connection\Aggregate\RedisCluster; -use Prophecy\Prophecy\ObjectProphecy; -use Psr\Container\ContainerInterface; -use Shlinkio\Shlink\Common\Cache\RedisFactory; - -class RedisFactoryTest extends TestCase -{ - /** @var RedisFactory */ - private $factory; - /** @var ObjectProphecy */ - private $container; - - public function setUp(): void - { - $this->container = $this->prophesize(ContainerInterface::class); - $this->factory = new RedisFactory(); - } - - /** - * @test - * @dataProvider provideRedisConfig - */ - public function createsRedisClientBasedOnRedisConfig(?array $config, string $expectedCluster): void - { - $getConfig = $this->container->get('config')->willReturn([ - 'redis' => $config, - ]); - - $client = ($this->factory)($this->container->reveal()); - - $getConfig->shouldHaveBeenCalledOnce(); - $this->assertInstanceOf($expectedCluster, $client->getOptions()->cluster); - } - - /** - * @test - * @dataProvider provideRedisConfig - */ - public function createsRedisClientBasedOnCacheConfig(?array $config, string $expectedCluster): void - { - $getConfig = $this->container->get('config')->willReturn([ - 'cache' => [ - 'redis' => $config, - ], - ]); - - $client = ($this->factory)($this->container->reveal()); - - $getConfig->shouldHaveBeenCalledOnce(); - $this->assertInstanceOf($expectedCluster, $client->getOptions()->cluster); - } - - public function provideRedisConfig(): iterable - { - yield 'no config' => [null, PredisCluster::class]; - yield 'single server as string' => [[ - 'servers' => 'tcp://127.0.0.1:6379', - ], PredisCluster::class]; - yield 'single server as array' => [[ - 'servers' => ['tcp://127.0.0.1:6379'], - ], PredisCluster::class]; - yield 'cluster of servers' => [[ - 'servers' => ['tcp://1.1.1.1:6379', 'tcp://2.2.2.2:6379'], - ], RedisCluster::class]; - yield 'empty cluster of servers' => [[ - 'servers' => [], - ], PredisCluster::class]; - yield 'cluster of servers as string' => [[ - 'servers' => 'tcp://1.1.1.1:6379,tcp://2.2.2.2:6379', - ], RedisCluster::class]; - } -} diff --git a/module/Common/test/ConfigProviderTest.php b/module/Common/test/ConfigProviderTest.php deleted file mode 100644 index c253483e..00000000 --- a/module/Common/test/ConfigProviderTest.php +++ /dev/null @@ -1,27 +0,0 @@ -<?php -declare(strict_types=1); - -namespace ShlinkioTest\Shlink\Common; - -use PHPUnit\Framework\TestCase; -use Shlinkio\Shlink\Common\ConfigProvider; - -class ConfigProviderTest extends TestCase -{ - /** @var ConfigProvider */ - private $configProvider; - - public function setUp(): void - { - $this->configProvider = new ConfigProvider(); - } - - /** @test */ - public function configIsReturned() - { - $config = $this->configProvider->__invoke(); - - $this->assertArrayHasKey('dependencies', $config); - $this->assertArrayHasKey('plates', $config); - } -} diff --git a/module/Common/test/Doctrine/ConnectionFactoryTest.php b/module/Common/test/Doctrine/ConnectionFactoryTest.php deleted file mode 100644 index a89ef79c..00000000 --- a/module/Common/test/Doctrine/ConnectionFactoryTest.php +++ /dev/null @@ -1,44 +0,0 @@ -<?php -declare(strict_types=1); - -namespace ShlinkioTest\Shlink\Common\Doctrine; - -use Doctrine\DBAL\Connection; -use Doctrine\ORM\EntityManager; -use Doctrine\ORM\EntityManagerInterface; -use PHPUnit\Framework\TestCase; -use Prophecy\Prophecy\ObjectProphecy; -use Psr\Container\ContainerInterface; -use Shlinkio\Shlink\Common\Doctrine\ConnectionFactory; - -class ConnectionFactoryTest extends TestCase -{ - /** @var ConnectionFactory */ - private $factory; - /** @var ObjectProphecy */ - private $container; - /** @var ObjectProphecy */ - private $em; - - public function setUp(): void - { - $this->container = $this->prophesize(ContainerInterface::class); - $this->em = $this->prophesize(EntityManagerInterface::class); - $this->container->get(EntityManager::class)->willReturn($this->em->reveal()); - - $this->factory = new ConnectionFactory(); - } - - /** @test */ - public function properServiceFallbackOccursWhenInvoked(): void - { - $connection = $this->prophesize(Connection::class)->reveal(); - $getConnection = $this->em->getConnection()->willReturn($connection); - - $result = ($this->factory)($this->container->reveal()); - - $this->assertSame($connection, $result); - $getConnection->shouldHaveBeenCalledOnce(); - $this->container->get(EntityManager::class)->shouldHaveBeenCalledOnce(); - } -} diff --git a/module/Common/test/Doctrine/EntityManagerFactoryTest.php b/module/Common/test/Doctrine/EntityManagerFactoryTest.php deleted file mode 100644 index 419c7ffd..00000000 --- a/module/Common/test/Doctrine/EntityManagerFactoryTest.php +++ /dev/null @@ -1,44 +0,0 @@ -<?php -declare(strict_types=1); - -namespace ShlinkioTest\Shlink\Common\Doctrine; - -use Doctrine\ORM\EntityManager; -use PHPUnit\Framework\TestCase; -use Shlinkio\Shlink\Common\Doctrine\EntityManagerFactory; -use Shlinkio\Shlink\Common\Doctrine\Type\ChronosDateTimeType; -use Zend\ServiceManager\ServiceManager; - -class EntityManagerFactoryTest extends TestCase -{ - /** @var EntityManagerFactory */ - private $factory; - - public function setUp(): void - { - $this->factory = new EntityManagerFactory(); - } - - /** @test */ - public function serviceIsCreated(): void - { - $sm = new ServiceManager(['services' => [ - 'config' => [ - 'debug' => true, - 'entity_manager' => [ - 'orm' => [ - 'types' => [ - ChronosDateTimeType::CHRONOS_DATETIME => ChronosDateTimeType::class, - ], - ], - 'connection' => [ - 'driver' => 'pdo_sqlite', - ], - ], - ], - ]]); - - $em = ($this->factory)($sm, EntityManager::class); - $this->assertInstanceOf(EntityManager::class, $em); - } -} diff --git a/module/Common/test/Doctrine/NoDbNameConnectionFactoryTest.php b/module/Common/test/Doctrine/NoDbNameConnectionFactoryTest.php deleted file mode 100644 index d8f58f8e..00000000 --- a/module/Common/test/Doctrine/NoDbNameConnectionFactoryTest.php +++ /dev/null @@ -1,56 +0,0 @@ -<?php -declare(strict_types=1); - -namespace ShlinkioTest\Shlink\Common\Doctrine; - -use Doctrine\DBAL\Connection; -use Doctrine\DBAL\Driver; -use PHPUnit\Framework\TestCase; -use Prophecy\Prophecy\ObjectProphecy; -use Psr\Container\ContainerInterface; -use Shlinkio\Shlink\Common\Doctrine\NoDbNameConnectionFactory; - -class NoDbNameConnectionFactoryTest extends TestCase -{ - /** @var NoDbNameConnectionFactory */ - private $factory; - /** @var ObjectProphecy */ - private $container; - /** @var ObjectProphecy */ - private $originalConn; - - public function setUp(): void - { - $this->container = $this->prophesize(ContainerInterface::class); - $this->originalConn = $this->prophesize(Connection::class); - $this->container->get(Connection::class)->willReturn($this->originalConn->reveal()); - - $this->factory = new NoDbNameConnectionFactory(); - } - - /** @test */ - public function createsNewConnectionRemovingDbNameFromOriginalConnectionParams(): void - { - $params = [ - 'username' => 'foo', - 'password' => 'bar', - 'dbname' => 'something', - ]; - $getOriginalParams = $this->originalConn->getParams()->willReturn($params); - $getOriginalDriver = $this->originalConn->getDriver()->willReturn($this->prophesize(Driver::class)->reveal()); - $getOriginalConfig = $this->originalConn->getConfiguration()->willReturn(null); - $getOriginalEvents = $this->originalConn->getEventManager()->willReturn(null); - - $conn = ($this->factory)($this->container->reveal()); - - $this->assertEquals([ - 'username' => 'foo', - 'password' => 'bar', - ], $conn->getParams()); - $getOriginalParams->shouldHaveBeenCalledOnce(); - $getOriginalDriver->shouldHaveBeenCalledOnce(); - $getOriginalConfig->shouldHaveBeenCalledOnce(); - $getOriginalEvents->shouldHaveBeenCalledOnce(); - $this->container->get(Connection::class)->shouldHaveBeenCalledOnce(); - } -} diff --git a/module/Common/test/Doctrine/ReopeningEntityManagerDelegatorTest.php b/module/Common/test/Doctrine/ReopeningEntityManagerDelegatorTest.php deleted file mode 100644 index 1193541b..00000000 --- a/module/Common/test/Doctrine/ReopeningEntityManagerDelegatorTest.php +++ /dev/null @@ -1,28 +0,0 @@ -<?php -declare(strict_types=1); - -namespace ShlinkioTest\Shlink\Common\Doctrine; - -use Doctrine\ORM\EntityManagerInterface; -use PHPUnit\Framework\TestCase; -use ReflectionObject; -use Shlinkio\Shlink\Common\Doctrine\ReopeningEntityManagerDelegator; -use Zend\ServiceManager\ServiceManager; - -class ReopeningEntityManagerDelegatorTest extends TestCase -{ - /** @test */ - public function decoratesEntityManagerFromCallback(): void - { - $em = $this->prophesize(EntityManagerInterface::class)->reveal(); - $result = (new ReopeningEntityManagerDelegator())(new ServiceManager(), '', function () use ($em) { - return $em; - }); - - $ref = new ReflectionObject($result); - $prop = $ref->getProperty('wrapped'); - $prop->setAccessible(true); - - $this->assertSame($em, $prop->getValue($result)); - } -} diff --git a/module/Common/test/Doctrine/ReopeningEntityManagerTest.php b/module/Common/test/Doctrine/ReopeningEntityManagerTest.php deleted file mode 100644 index 74e8d260..00000000 --- a/module/Common/test/Doctrine/ReopeningEntityManagerTest.php +++ /dev/null @@ -1,80 +0,0 @@ -<?php -declare(strict_types=1); - -namespace ShlinkioTest\Shlink\Common\Doctrine; - -use Doctrine\Common\EventManager; -use Doctrine\DBAL\Connection; -use Doctrine\ORM\Configuration; -use Doctrine\ORM\EntityManagerInterface; -use PHPUnit\Framework\TestCase; -use Prophecy\Argument; -use Prophecy\Prophecy\ObjectProphecy; -use Shlinkio\Shlink\Common\Doctrine\ReopeningEntityManager; -use stdClass; - -class ReopeningEntityManagerTest extends TestCase -{ - /** @var ReopeningEntityManager */ - private $decoratorEm; - /** @var ObjectProphecy */ - private $wrapped; - - public function setUp(): void - { - $this->wrapped = $this->prophesize(EntityManagerInterface::class); - $this->wrapped->getConnection()->willReturn($this->prophesize(Connection::class)); - $this->wrapped->getConfiguration()->willReturn($this->prophesize(Configuration::class)); - $this->wrapped->getEventManager()->willReturn($this->prophesize(EventManager::class)); - - $wrappedMock = $this->wrapped->reveal(); - $this->decoratorEm = new ReopeningEntityManager($wrappedMock, function () use ($wrappedMock) { - return $wrappedMock; - }); - } - - /** - * @test - * @dataProvider provideMethodNames - */ - public function wrappedInstanceIsTransparentlyCalledWhenItIsNotClosed(string $methodName): void - { - $method = $this->wrapped->__call($methodName, [Argument::cetera()])->willReturnArgument(); - $isOpen = $this->wrapped->isOpen()->willReturn(true); - - $this->decoratorEm->{$methodName}(new stdClass()); - - $method->shouldHaveBeenCalledOnce(); - $isOpen->shouldHaveBeenCalledOnce(); - $this->wrapped->getConnection()->shouldNotHaveBeenCalled(); - $this->wrapped->getConfiguration()->shouldNotHaveBeenCalled(); - $this->wrapped->getEventManager()->shouldNotHaveBeenCalled(); - } - - /** - * @test - * @dataProvider provideMethodNames - */ - public function wrappedInstanceIsRecreatedWhenItIsClosed(string $methodName): void - { - $method = $this->wrapped->__call($methodName, [Argument::cetera()])->willReturnArgument(); - $isOpen = $this->wrapped->isOpen()->willReturn(false); - - $this->decoratorEm->{$methodName}(new stdClass()); - - $method->shouldHaveBeenCalledOnce(); - $isOpen->shouldHaveBeenCalledOnce(); - $this->wrapped->getConnection()->shouldHaveBeenCalledOnce(); - $this->wrapped->getConfiguration()->shouldHaveBeenCalledOnce(); - $this->wrapped->getEventManager()->shouldHaveBeenCalledOnce(); - } - - public function provideMethodNames(): iterable - { - yield 'flush' => ['flush']; - yield 'persist' => ['persist']; - yield 'remove' => ['remove']; - yield 'refresh' => ['refresh']; - yield 'merge' => ['merge']; - } -} diff --git a/module/Common/test/Doctrine/Type/ChronosDateTimeTypeTest.php b/module/Common/test/Doctrine/Type/ChronosDateTimeTypeTest.php deleted file mode 100644 index b86547cd..00000000 --- a/module/Common/test/Doctrine/Type/ChronosDateTimeTypeTest.php +++ /dev/null @@ -1,88 +0,0 @@ -<?php -declare(strict_types=1); - -namespace ShlinkioTest\Shlink\Common\Doctrine\Type; - -use Cake\Chronos\Chronos; -use DateTime; -use DateTimeImmutable; -use DateTimeInterface; -use Doctrine\DBAL\Platforms\AbstractPlatform; -use Doctrine\DBAL\Types\ConversionException; -use Doctrine\DBAL\Types\Type; -use PHPUnit\Framework\TestCase; -use Shlinkio\Shlink\Common\Doctrine\Type\ChronosDateTimeType; -use stdClass; - -class ChronosDateTimeTypeTest extends TestCase -{ - /** @var ChronosDateTimeType */ - private $type; - - public function setUp(): void - { - if (! Type::hasType(ChronosDateTimeType::CHRONOS_DATETIME)) { - Type::addType(ChronosDateTimeType::CHRONOS_DATETIME, ChronosDateTimeType::class); - } - - $this->type = Type::getType(ChronosDateTimeType::CHRONOS_DATETIME); - } - - /** @test */ - public function nameIsReturned(): void - { - $this->assertEquals(ChronosDateTimeType::CHRONOS_DATETIME, $this->type->getName()); - } - - /** - * @test - * @dataProvider provideValues - */ - public function valueIsConverted(?string $value, ?string $expected): void - { - $platform = $this->prophesize(AbstractPlatform::class); - $platform->getDateTimeFormatString()->willReturn('Y-m-d H:i:s'); - - $result = $this->type->convertToPHPValue($value, $platform->reveal()); - - if ($expected === null) { - $this->assertNull($result); - } else { - $this->assertInstanceOf($expected, $result); - } - } - - public function provideValues(): iterable - { - yield 'null date' => [null, null]; - yield 'human friendly date' => ['now', Chronos::class]; - yield 'numeric date' => ['2017-01-01', Chronos::class]; - } - - /** - * @test - * @dataProvider providePhpValues - */ - public function valueIsConvertedToDatabaseFormat(?DateTimeInterface $value, ?string $expected): void - { - $platform = $this->prophesize(AbstractPlatform::class); - $platform->getDateTimeFormatString()->willReturn('Y-m-d'); - - $this->assertEquals($expected, $this->type->convertToDatabaseValue($value, $platform->reveal())); - } - - public function providePhpValues(): iterable - { - yield 'null date' => [null, null]; - yield 'DateTimeImmutable date' => [new DateTimeImmutable('2017-01-01'), '2017-01-01']; - yield 'Chronos date' => [Chronos::parse('2017-02-01'), '2017-02-01']; - yield 'DateTime date' => [new DateTime('2017-03-01'), '2017-03-01']; - } - - /** @test */ - public function exceptionIsThrownIfInvalidValueIsParsedToDatabase(): void - { - $this->expectException(ConversionException::class); - $this->type->convertToDatabaseValue(new stdClass(), $this->prophesize(AbstractPlatform::class)->reveal()); - } -} diff --git a/module/Common/test/Factory/DottedAccessConfigAbstractFactoryTest.php b/module/Common/test/Factory/DottedAccessConfigAbstractFactoryTest.php deleted file mode 100644 index f9d2c80c..00000000 --- a/module/Common/test/Factory/DottedAccessConfigAbstractFactoryTest.php +++ /dev/null @@ -1,78 +0,0 @@ -<?php -declare(strict_types=1); - -namespace ShlinkioTest\Shlink\Common\Factory; - -use PHPUnit\Framework\TestCase; -use Shlinkio\Shlink\Common\Exception\InvalidArgumentException; -use Shlinkio\Shlink\Common\Factory\DottedAccessConfigAbstractFactory; -use Zend\ServiceManager\Exception\ServiceNotCreatedException; -use Zend\ServiceManager\ServiceManager; - -class DottedAccessConfigAbstractFactoryTest extends TestCase -{ - /** @var DottedAccessConfigAbstractFactory */ - private $factory; - - public function setUp(): void - { - $this->factory = new DottedAccessConfigAbstractFactory(); - } - - /** - * @test - * @dataProvider provideDotNames - */ - public function canCreateOnlyServicesWithDot(string $serviceName, bool $canCreate): void - { - $this->assertEquals($canCreate, $this->factory->canCreate(new ServiceManager(), $serviceName)); - } - - public function provideDotNames(): iterable - { - yield 'with a valid service' => ['foo.bar', true]; - yield 'with another valid service' => ['config.something', true]; - yield 'with an invalid service' => ['config_something', false]; - yield 'with another invalid service' => ['foo', false]; - } - - /** @test */ - public function throwsExceptionWhenFirstPartOfTheServiceIsNotRegistered() - { - $this->expectException(ServiceNotCreatedException::class); - $this->expectExceptionMessage( - 'Defined service "foo" could not be found in container after resolving dotted expression "foo.bar"' - ); - - $this->factory->__invoke(new ServiceManager(), 'foo.bar'); - } - - /** @test */ - public function dottedNotationIsRecursivelyResolvedUntilLastValueIsFoundAndReturned() - { - $expected = 'this is the result'; - - $result = $this->factory->__invoke(new ServiceManager(['services' => [ - 'foo' => [ - 'bar' => ['baz' => $expected], - ], - ]]), 'foo.bar.baz'); - - $this->assertEquals($expected, $result); - } - - /** @test */ - public function exceptionIsThrownIfAnyStepCannotBeResolved() - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage( - 'The key "baz" provided in the dotted notation could not be found in the array service' - ); - - $this->factory->__invoke(new ServiceManager(['services' => [ - 'foo' => [ - 'bar' => ['something' => 123], - ], - ]]), 'foo.bar.baz'); - } -} diff --git a/module/Common/test/I18n/TranslatorFactoryTest.php b/module/Common/test/I18n/TranslatorFactoryTest.php deleted file mode 100644 index 756a3991..00000000 --- a/module/Common/test/I18n/TranslatorFactoryTest.php +++ /dev/null @@ -1,29 +0,0 @@ -<?php -declare(strict_types=1); - -namespace ShlinkioTest\Shlink\Common\I18n; - -use PHPUnit\Framework\TestCase; -use Shlinkio\Shlink\Common\I18n\TranslatorFactory; -use Zend\I18n\Translator\Translator; -use Zend\ServiceManager\ServiceManager; - -class TranslatorFactoryTest extends TestCase -{ - /** @var TranslatorFactory */ - private $factory; - - public function setUp(): void - { - $this->factory = new TranslatorFactory(); - } - - /** @test */ - public function serviceIsCreated(): void - { - $instance = ($this->factory)(new ServiceManager(['services' => [ - 'config' => [], - ]])); - $this->assertInstanceOf(Translator::class, $instance); - } -} diff --git a/module/Common/test/Lock/RetryLockStoreDelegatorFactoryTest.php b/module/Common/test/Lock/RetryLockStoreDelegatorFactoryTest.php deleted file mode 100644 index 4f98c47c..00000000 --- a/module/Common/test/Lock/RetryLockStoreDelegatorFactoryTest.php +++ /dev/null @@ -1,41 +0,0 @@ -<?php -declare(strict_types=1); - -namespace ShlinkioTest\Shlink\Common\Lock; - -use PHPUnit\Framework\TestCase; -use Prophecy\Prophecy\ObjectProphecy; -use ReflectionObject; -use Shlinkio\Shlink\Common\Lock\RetryLockStoreDelegatorFactory; -use Symfony\Component\Lock\StoreInterface; -use Zend\ServiceManager\ServiceManager; - -class RetryLockStoreDelegatorFactoryTest extends TestCase -{ - /** @var RetryLockStoreDelegatorFactory */ - private $delegator; - /** @var ObjectProphecy */ - private $originalStore; - - public function setUp(): void - { - $this->originalStore = $this->prophesize(StoreInterface::class)->reveal(); - $this->delegator = new RetryLockStoreDelegatorFactory(); - } - - /** @test */ - public function originalStoreIsWrappedInRetryStore(): void - { - $callback = function () { - return $this->originalStore; - }; - - $result = ($this->delegator)(new ServiceManager(), '', $callback); - - $ref = new ReflectionObject($result); - $prop = $ref->getProperty('decorated'); - $prop->setAccessible(true); - - $this->assertSame($this->originalStore, $prop->getValue($result)); - } -} diff --git a/module/Common/test/Logger/LoggerAwareDelegatorFactoryTest.php b/module/Common/test/Logger/LoggerAwareDelegatorFactoryTest.php deleted file mode 100644 index 8723077b..00000000 --- a/module/Common/test/Logger/LoggerAwareDelegatorFactoryTest.php +++ /dev/null @@ -1,55 +0,0 @@ -<?php -declare(strict_types=1); - -namespace ShlinkioTest\Shlink\Common\Logger; - -use PHPUnit\Framework\Assert; -use PHPUnit\Framework\TestCase; -use Prophecy\Prophecy\ObjectProphecy; -use Psr\Container\ContainerInterface; -use Psr\Log; -use Psr\Log\LoggerInterface; -use Shlinkio\Shlink\Common\Logger\LoggerAwareDelegatorFactory; -use stdClass; - -class LoggerAwareDelegatorFactoryTest extends TestCase -{ - /** @var LoggerAwareDelegatorFactory */ - private $delegator; - /** @var ObjectProphecy */ - private $container; - - public function setUp(): void - { - $this->container = $this->prophesize(ContainerInterface::class); - $this->delegator = new LoggerAwareDelegatorFactory(); - } - - /** - * @test - * @dataProvider provideInstances - */ - public function injectsLoggerOnInstanceWhenImplementingLoggerAware($instance, int $expectedCalls): void - { - $callback = function () use ($instance) { - return $instance; - }; - $getLogger = $this->container->get(Log\LoggerInterface::class)->willReturn(new Log\NullLogger()); - - $result = ($this->delegator)($this->container->reveal(), '', $callback); - - $this->assertSame($instance, $result); - $getLogger->shouldHaveBeenCalledTimes($expectedCalls); - } - - public function provideInstances(): iterable - { - yield 'no logger aware' => [new stdClass(), 0]; - yield 'logger aware' => [new class implements Log\LoggerAwareInterface { - public function setLogger(LoggerInterface $logger): void - { - Assert::assertInstanceOf(Log\NullLogger::class, $logger); - } - }, 1]; - } -} diff --git a/module/Common/test/Logger/LoggerFactoryTest.php b/module/Common/test/Logger/LoggerFactoryTest.php deleted file mode 100644 index ae20e161..00000000 --- a/module/Common/test/Logger/LoggerFactoryTest.php +++ /dev/null @@ -1,48 +0,0 @@ -<?php -declare(strict_types=1); - -namespace ShlinkioTest\Shlink\Common\Logger; - -use Monolog\Logger; -use PHPUnit\Framework\TestCase; -use Psr\Log\LoggerInterface; -use Shlinkio\Shlink\Common\Logger\LoggerFactory; -use Zend\ServiceManager\ServiceManager; - -class LoggerFactoryTest extends TestCase -{ - /** @var LoggerFactory */ - private $factory; - - public function setUp(): void - { - $this->factory = new LoggerFactory(); - } - - /** @test */ - public function serviceIsCreated() - { - /** @var Logger $instance */ - $instance = $this->factory->__invoke(new ServiceManager(), ''); - $this->assertInstanceOf(LoggerInterface::class, $instance); - $this->assertEquals('Logger', $instance->getName()); - } - - /** @test */ - public function nameIsSetFromOptions() - { - /** @var Logger $instance */ - $instance = $this->factory->__invoke(new ServiceManager(), '', ['logger_name' => 'Foo']); - $this->assertInstanceOf(LoggerInterface::class, $instance); - $this->assertEquals('Foo', $instance->getName()); - } - - /** @test */ - public function serviceNameOverwritesOptionsLoggerName() - { - /** @var Logger $instance */ - $instance = $this->factory->__invoke(new ServiceManager(), 'Logger_Shlink', ['logger_name' => 'Foo']); - $this->assertInstanceOf(LoggerInterface::class, $instance); - $this->assertEquals('Shlink', $instance->getName()); - } -} diff --git a/module/Common/test/Logger/Processor/ExceptionWithNewLineProcessorTest.php b/module/Common/test/Logger/Processor/ExceptionWithNewLineProcessorTest.php deleted file mode 100644 index 60b30ce8..00000000 --- a/module/Common/test/Logger/Processor/ExceptionWithNewLineProcessorTest.php +++ /dev/null @@ -1,67 +0,0 @@ -<?php -declare(strict_types=1); - -namespace ShlinkioTest\Shlink\Common\Logger\Processor; - -use PHPUnit\Framework\TestCase; -use Shlinkio\Shlink\Common\Logger\Processor\ExceptionWithNewLineProcessor; -use Shlinkio\Shlink\Common\Util\StringUtilsTrait; - -use function Functional\map; -use function range; - -use const PHP_EOL; - -class ExceptionWithNewLineProcessorTest extends TestCase -{ - use StringUtilsTrait; - - /** @var ExceptionWithNewLineProcessor */ - private $processor; - - public function setUp(): void - { - $this->processor = new ExceptionWithNewLineProcessor(); - } - - /** - * @test - * @dataProvider provideNoPlaceholderRecords - */ - public function keepsRecordAsIsWhenNoPlaceholderExists(array $record): void - { - $this->assertSame($record, ($this->processor)($record)); - } - - public function provideNoPlaceholderRecords(): iterable - { - return map(range(1, 5), function () { - return [['message' => $this->generateRandomString()]]; - }); - } - - /** - * @test - * @dataProvider providePlaceholderRecords - */ - public function properlyReplacesExceptionPlaceholderAddingNewLine(array $record, array $expected): void - { - $this->assertEquals($expected, ($this->processor)($record)); - } - - public function providePlaceholderRecords(): iterable - { - yield [ - ['message' => 'Hello World with placeholder {e}'], - ['message' => 'Hello World with placeholder ' . PHP_EOL . '{e}'], - ]; - yield [ - ['message' => '{e} Shlink'], - ['message' => PHP_EOL . '{e} Shlink'], - ]; - yield [ - ['message' => 'Foo {e} bar'], - ['message' => 'Foo ' . PHP_EOL . '{e} bar'], - ]; - } -} diff --git a/module/Common/test/Middleware/CloseDbConnectionMiddlewareTest.php b/module/Common/test/Middleware/CloseDbConnectionMiddlewareTest.php deleted file mode 100644 index 2bf93a85..00000000 --- a/module/Common/test/Middleware/CloseDbConnectionMiddlewareTest.php +++ /dev/null @@ -1,72 +0,0 @@ -<?php -declare(strict_types=1); - -namespace ShlinkioTest\Shlink\Common\Middleware; - -use Doctrine\DBAL\Connection; -use Doctrine\ORM\EntityManagerInterface; -use PHPUnit\Framework\TestCase; -use Prophecy\Prophecy\ObjectProphecy; -use Psr\Http\Server\RequestHandlerInterface; -use RuntimeException; -use Shlinkio\Shlink\Common\Middleware\CloseDbConnectionMiddleware; -use Zend\Diactoros\Response; -use Zend\Diactoros\ServerRequest; - -class CloseDbConnectionMiddlewareTest extends TestCase -{ - /** @var CloseDbConnectionMiddleware */ - private $middleware; - /** @var ObjectProphecy */ - private $handler; - /** @var ObjectProphecy */ - private $em; - /** @var ObjectProphecy */ - private $conn; - - public function setUp(): void - { - $this->handler = $this->prophesize(RequestHandlerInterface::class); - $this->em = $this->prophesize(EntityManagerInterface::class); - $this->conn = $this->prophesize(Connection::class); - $this->conn->close()->will(function () { - }); - $this->em->getConnection()->willReturn($this->conn->reveal()); - $this->em->clear()->will(function () { - }); - - $this->middleware = new CloseDbConnectionMiddleware($this->em->reveal()); - } - - /** @test */ - public function connectionIsClosedWhenMiddlewareIsProcessed(): void - { - $req = new ServerRequest(); - $resp = new Response(); - $handle = $this->handler->handle($req)->willReturn($resp); - - $result = $this->middleware->process($req, $this->handler->reveal()); - - $this->assertSame($result, $resp); - $this->em->getConnection()->shouldHaveBeenCalledOnce(); - $this->conn->close()->shouldHaveBeenCalledOnce(); - $this->em->clear()->shouldHaveBeenCalledOnce(); - $handle->shouldHaveBeenCalledOnce(); - } - - /** @test */ - public function connectionIsClosedEvenIfExceptionIsThrownOnInnerMiddlewares(): void - { - $req = new ServerRequest(); - $expectedError = new RuntimeException(); - $this->handler->handle($req)->willThrow($expectedError) - ->shouldBeCalledOnce(); - - $this->em->getConnection()->shouldBeCalledOnce(); - $this->conn->close()->shouldBeCalledOnce(); - $this->em->clear()->shouldBeCalledOnce(); - $this->expectExceptionObject($expectedError); - - $this->middleware->process($req, $this->handler->reveal()); - } -} diff --git a/module/Common/test/Middleware/IpAddressMiddlewareFactoryTest.php b/module/Common/test/Middleware/IpAddressMiddlewareFactoryTest.php deleted file mode 100644 index fdf81a35..00000000 --- a/module/Common/test/Middleware/IpAddressMiddlewareFactoryTest.php +++ /dev/null @@ -1,85 +0,0 @@ -<?php -declare(strict_types=1); - -namespace ShlinkioTest\Shlink\Common\Middleware; - -use PHPUnit\Framework\TestCase; -use ReflectionObject; -use Shlinkio\Shlink\Common\Middleware\IpAddressMiddlewareFactory; -use Zend\ServiceManager\ServiceManager; - -class IpAddressMiddlewareFactoryTest extends TestCase -{ - private $factory; - - public function setUp(): void - { - $this->factory = new IpAddressMiddlewareFactory(); - } - - /** - * @test - * @dataProvider provideConfigs - */ - public function returnedInstanceIsProperlyConfigured(array $config, array $expectedHeadersToInspect): void - { - $instance = ($this->factory)(new ServiceManager(['services' => [ - 'config' => $config, - ]])); - - $ref = new ReflectionObject($instance); - $checkProxyHeaders = $ref->getProperty('checkProxyHeaders'); - $checkProxyHeaders->setAccessible(true); - $trustedProxies = $ref->getProperty('trustedProxies'); - $trustedProxies->setAccessible(true); - $attributeName = $ref->getProperty('attributeName'); - $attributeName->setAccessible(true); - $headersToInspect = $ref->getProperty('headersToInspect'); - $headersToInspect->setAccessible(true); - - $this->assertTrue($checkProxyHeaders->getValue($instance)); - $this->assertEquals([], $trustedProxies->getValue($instance)); - $this->assertEquals(IpAddressMiddlewareFactory::REQUEST_ATTR, $attributeName->getValue($instance)); - $this->assertEquals($expectedHeadersToInspect, $headersToInspect->getValue($instance)); - } - - public function provideConfigs(): iterable - { - $defaultHeadersToInspect = [ - 'Forwarded', - 'X-Forwarded-For', - 'X-Forwarded', - 'X-Cluster-Client-Ip', - 'Client-Ip', - ]; - - yield 'no ip_address_resolution config' => [[], $defaultHeadersToInspect]; - yield 'no headers_to_inspect config' => [['ip_address_resolution' => []], $defaultHeadersToInspect]; - yield 'null headers_to_inspect' => [['ip_address_resolution' => [ - 'headers_to_inspect' => null, - ]], $defaultHeadersToInspect]; - yield 'empty headers_to_inspect' => [['ip_address_resolution' => [ - 'headers_to_inspect' => [], - ]], $defaultHeadersToInspect]; - yield 'some headers_to_inspect' => [['ip_address_resolution' => [ - 'headers_to_inspect' => [ - 'foo', - 'bar', - 'baz', - ], - ]], [ - 'foo', - 'bar', - 'baz', - ]]; - yield 'some other headers_to_inspect' => [['ip_address_resolution' => [ - 'headers_to_inspect' => [ - 'something', - 'something_else', - ], - ]], [ - 'something', - 'something_else', - ]]; - } -} diff --git a/module/Common/test/Middleware/LocaleMiddlewareTest.php b/module/Common/test/Middleware/LocaleMiddlewareTest.php deleted file mode 100644 index e9145cba..00000000 --- a/module/Common/test/Middleware/LocaleMiddlewareTest.php +++ /dev/null @@ -1,63 +0,0 @@ -<?php -declare(strict_types=1); - -namespace ShlinkioTest\Shlink\Common\Middleware; - -use PHPUnit\Framework\TestCase; -use Shlinkio\Shlink\Common\Middleware\LocaleMiddleware; -use ShlinkioTest\Shlink\Common\Util\TestUtils; -use Zend\Diactoros\ServerRequest; -use Zend\I18n\Translator\Translator; - -class LocaleMiddlewareTest extends TestCase -{ - /** @var LocaleMiddleware */ - private $middleware; - /** @var Translator */ - private $translator; - - public function setUp(): void - { - $this->translator = Translator::factory(['locale' => 'ru']); - $this->middleware = new LocaleMiddleware($this->translator); - } - - /** @test */ - public function whenNoHeaderIsPresentLocaleIsNotChanged(): void - { - $this->assertEquals('ru', $this->translator->getLocale()); - $this->middleware->process(new ServerRequest(), TestUtils::createReqHandlerMock()->reveal()); - $this->assertEquals('ru', $this->translator->getLocale()); - } - - /** @test */ - public function whenTheHeaderIsPresentLocaleIsChanged(): void - { - $this->assertEquals('ru', $this->translator->getLocale()); - $request = (new ServerRequest())->withHeader('Accept-Language', 'es'); - $this->middleware->process($request, TestUtils::createReqHandlerMock()->reveal()); - $this->assertEquals('es', $this->translator->getLocale()); - } - - /** - * @test - * @dataProvider provideLanguages - */ - public function localeGetsNormalized(string $lang, string $expected): void - { - $handler = TestUtils::createReqHandlerMock(); - - $this->assertEquals('ru', $this->translator->getLocale()); - - $request = (new ServerRequest())->withHeader('Accept-Language', $lang); - $this->middleware->process($request, $handler->reveal()); - $this->assertEquals($expected, $this->translator->getLocale()); - } - - public function provideLanguages(): iterable - { - yield 'language only' => ['ru', 'ru']; - yield 'country and language with underscore' => ['es_ES', 'es']; - yield 'country and language with dash' => ['en-US', 'en']; - } -} diff --git a/module/Common/test/Response/PixelResponseTest.php b/module/Common/test/Response/PixelResponseTest.php deleted file mode 100644 index ae580472..00000000 --- a/module/Common/test/Response/PixelResponseTest.php +++ /dev/null @@ -1,25 +0,0 @@ -<?php -declare(strict_types=1); - -namespace ShlinkioTest\Shlink\Common\Response; - -use PHPUnit\Framework\TestCase; -use Shlinkio\Shlink\Common\Response\PixelResponse; - -class PixelResponseTest extends TestCase -{ - /** @var PixelResponse */ - private $resp; - - public function setUp(): void - { - $this->resp = new PixelResponse(); - } - - /** @test */ - public function responseHasGifTypeAndIsNotEmpty() - { - $this->assertEquals('image/gif', $this->resp->getHeaderLine('Content-Type')); - $this->assertNotEmpty((string) $this->resp->getBody()); - } -} diff --git a/module/Common/test/Response/QrCodeResponseTest.php b/module/Common/test/Response/QrCodeResponseTest.php deleted file mode 100644 index 7b413bc4..00000000 --- a/module/Common/test/Response/QrCodeResponseTest.php +++ /dev/null @@ -1,21 +0,0 @@ -<?php -declare(strict_types=1); - -namespace ShlinkioTest\Shlink\Common\Response; - -use Endroid\QrCode\QrCode; -use PHPUnit\Framework\TestCase; -use Shlinkio\Shlink\Common\Response\QrCodeResponse; - -class QrCodeResponseTest extends TestCase -{ - /** @test */ - public function providedQrCoideIsSetAsBody() - { - $qrCode = new QrCode('Hello'); - $resp = new QrCodeResponse($qrCode); - - $this->assertEquals($qrCode->getContentType(), $resp->getHeaderLine('Content-Type')); - $this->assertEquals($qrCode->get(), (string) $resp->getBody()); - } -} diff --git a/module/Common/test/Template/Extension/TranslatorExtensionTest.php b/module/Common/test/Template/Extension/TranslatorExtensionTest.php deleted file mode 100644 index 690daabf..00000000 --- a/module/Common/test/Template/Extension/TranslatorExtensionTest.php +++ /dev/null @@ -1,36 +0,0 @@ -<?php -declare(strict_types=1); - -namespace ShlinkioTest\Shlink\Common\Template\Extension; - -use League\Plates\Engine; -use PHPUnit\Framework\TestCase; -use Prophecy\Argument; -use Shlinkio\Shlink\Common\Template\Extension\TranslatorExtension; -use Zend\I18n\Translator\Translator; - -class TranslatorExtensionTest extends TestCase -{ - /** @var TranslatorExtension */ - private $extension; - - public function setUp(): void - { - $this->extension = new TranslatorExtension($this->prophesize(Translator::class)->reveal()); - } - - /** @test */ - public function properFunctionsAreReturned() - { - $engine = $this->prophesize(Engine::class); - $registerTranslate = $engine->registerFunction('translate', Argument::type('callable'))->will(function () { - }); - $registerLocale = $engine->registerFunction('locale', Argument::type('array'))->will(function () { - }); - - $this->extension->register($engine->reveal()); - - $registerTranslate->shouldHaveBeenCalledOnce(); - $registerLocale->shouldHaveBeenCalledOnce(); - } -} diff --git a/module/Common/test/Util/DateRangeTest.php b/module/Common/test/Util/DateRangeTest.php deleted file mode 100644 index d1716e8a..00000000 --- a/module/Common/test/Util/DateRangeTest.php +++ /dev/null @@ -1,52 +0,0 @@ -<?php -declare(strict_types=1); - -namespace ShlinkioTest\Shlink\Common\Util; - -use Cake\Chronos\Chronos; -use PHPUnit\Framework\TestCase; -use Shlinkio\Shlink\Common\Util\DateRange; - -class DateRangeTest extends TestCase -{ - /** @test */ - public function defaultConstructorSetDatesToNull() - { - $range = new DateRange(); - $this->assertNull($range->getStartDate()); - $this->assertNull($range->getEndDate()); - $this->assertTrue($range->isEmpty()); - } - - /** @test */ - public function providedDatesAreSet() - { - $startDate = Chronos::now(); - $endDate = Chronos::now(); - $range = new DateRange($startDate, $endDate); - $this->assertSame($startDate, $range->getStartDate()); - $this->assertSame($endDate, $range->getEndDate()); - $this->assertFalse($range->isEmpty()); - } - - /** - * @test - * @dataProvider provideDates - */ - public function isConsideredEmptyOnlyIfNoneOfTheDatesIsSet( - ?Chronos $startDate, - ?Chronos $endDate, - bool $isEmpty - ): void { - $range = new DateRange($startDate, $endDate); - $this->assertEquals($isEmpty, $range->isEmpty()); - } - - public function provideDates(): iterable - { - yield 'both are null' => [null, null, true]; - yield 'start is null' => [null, Chronos::now(), false]; - yield 'end is null' => [Chronos::now(), null, false]; - yield 'none are null' => [Chronos::now(), Chronos::now(), false]; - } -} diff --git a/module/Common/test/Util/StringUtilsTraitTest.php b/module/Common/test/Util/StringUtilsTraitTest.php deleted file mode 100644 index ad1417aa..00000000 --- a/module/Common/test/Util/StringUtilsTraitTest.php +++ /dev/null @@ -1,44 +0,0 @@ -<?php -declare(strict_types=1); - -namespace ShlinkioTest\Shlink\Common\Util; - -use PHPUnit\Framework\TestCase; -use Shlinkio\Shlink\Common\Util\StringUtilsTrait; - -use function Functional\map; -use function range; -use function strlen; - -class StringUtilsTraitTest extends TestCase -{ - use StringUtilsTrait; - - /** - * @test - * @dataProvider provideLengths - */ - public function generateRandomStringGeneratesStringOfProvidedLength(int $length): void - { - $this->assertEquals($length, strlen($this->generateRandomString($length))); - } - - public function provideLengths(): array - { - return map(range(10, 50, 5), function (int $i) { - return [$i]; - }); - } - - /** @test */ - public function generatesUuidV4() - { - $uuidPattern = '/[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{12}/'; - - $this->assertRegExp($uuidPattern, $this->generateV4Uuid()); - $this->assertRegExp($uuidPattern, $this->generateV4Uuid()); - $this->assertRegExp($uuidPattern, $this->generateV4Uuid()); - $this->assertRegExp($uuidPattern, $this->generateV4Uuid()); - $this->assertRegExp($uuidPattern, $this->generateV4Uuid()); - } -} diff --git a/module/Common/test/Util/TestUtils.php b/module/Common/test/Util/TestUtils.php deleted file mode 100644 index aa1e0450..00000000 --- a/module/Common/test/Util/TestUtils.php +++ /dev/null @@ -1,37 +0,0 @@ -<?php -declare(strict_types=1); - -namespace ShlinkioTest\Shlink\Common\Util; - -use Prophecy\Argument; -use Prophecy\Prophet; -use Psr\Http\Message\RequestInterface; -use Psr\Http\Message\ResponseInterface; -use Psr\Http\Server\RequestHandlerInterface; -use Zend\Diactoros\Response; - -class TestUtils -{ - private static $prophet; - - public static function createReqHandlerMock(?ResponseInterface $response = null, ?RequestInterface $request = null) - { - $argument = $request ?: Argument::any(); - $delegate = static::getProphet()->prophesize(RequestHandlerInterface::class); - $delegate->handle($argument)->willReturn($response ?: new Response()); - - return $delegate; - } - - /** - * @return Prophet - */ - private static function getProphet() - { - if (static::$prophet === null) { - static::$prophet = new Prophet(); - } - - return static::$prophet; - } -} diff --git a/module/Common/test/Validation/SluggerFilterTest.php b/module/Common/test/Validation/SluggerFilterTest.php deleted file mode 100644 index 0c02982f..00000000 --- a/module/Common/test/Validation/SluggerFilterTest.php +++ /dev/null @@ -1,44 +0,0 @@ -<?php -declare(strict_types=1); - -namespace ShlinkioTest\Shlink\Common\Validation; - -use Cocur\Slugify\SlugifyInterface; -use PHPUnit\Framework\TestCase; -use Prophecy\Prophecy\ObjectProphecy; -use Shlinkio\Shlink\Common\Validation\SluggerFilter; - -class SluggerFilterTest extends TestCase -{ - /** @var SluggerFilter */ - private $filter; - /** @var ObjectProphecy */ - private $slugger; - - public function setUp(): void - { - $this->slugger = $this->prophesize(SlugifyInterface::class); - $this->filter = new SluggerFilter($this->slugger->reveal()); - } - - /** - * @test - * @dataProvider provideValuesToFilter - */ - public function providedValueIsFilteredAsExpected($providedValue, $expectedValue): void - { - $slugify = $this->slugger->slugify($providedValue)->willReturn('slug'); - - $result = $this->filter->filter($providedValue); - - $this->assertEquals($expectedValue, $result); - $slugify->shouldHaveBeenCalledTimes($expectedValue !== null ? 1 : 0); - } - - public function provideValuesToFilter(): iterable - { - yield 'null' => [null, null]; - yield 'empty string' => ['', null]; - yield 'not empty string' => ['foo', 'slug']; - } -} diff --git a/module/Core/test/Action/PixelActionTest.php b/module/Core/test/Action/PixelActionTest.php index 483f8e4f..9fce8f0e 100644 --- a/module/Core/test/Action/PixelActionTest.php +++ b/module/Core/test/Action/PixelActionTest.php @@ -6,6 +6,7 @@ namespace ShlinkioTest\Shlink\Core\Action; use PHPUnit\Framework\TestCase; use Prophecy\Argument; use Prophecy\Prophecy\ObjectProphecy; +use Psr\Http\Server\RequestHandlerInterface; use Shlinkio\Shlink\Common\Response\PixelResponse; use Shlinkio\Shlink\Core\Action\PixelAction; use Shlinkio\Shlink\Core\Action\RedirectAction; @@ -13,7 +14,6 @@ use Shlinkio\Shlink\Core\Entity\ShortUrl; use Shlinkio\Shlink\Core\Options\AppOptions; use Shlinkio\Shlink\Core\Service\UrlShortener; use Shlinkio\Shlink\Core\Service\VisitsTracker; -use ShlinkioTest\Shlink\Common\Util\TestUtils; use Zend\Diactoros\ServerRequest; class PixelActionTest extends TestCase @@ -38,7 +38,7 @@ class PixelActionTest extends TestCase } /** @test */ - public function imageIsReturned() + public function imageIsReturned(): void { $shortCode = 'abc123'; $this->urlShortener->shortCodeToUrl($shortCode)->willReturn( @@ -47,7 +47,7 @@ class PixelActionTest extends TestCase $this->visitTracker->track(Argument::cetera())->shouldBeCalledOnce(); $request = (new ServerRequest())->withAttribute('shortCode', $shortCode); - $response = $this->action->process($request, TestUtils::createReqHandlerMock()->reveal()); + $response = $this->action->process($request, $this->prophesize(RequestHandlerInterface::class)->reveal()); $this->assertInstanceOf(PixelResponse::class, $response); $this->assertEquals(200, $response->getStatusCode()); diff --git a/module/Core/test/Action/PreviewActionTest.php b/module/Core/test/Action/PreviewActionTest.php index f8f74d88..bc2d833d 100644 --- a/module/Core/test/Action/PreviewActionTest.php +++ b/module/Core/test/Action/PreviewActionTest.php @@ -14,7 +14,6 @@ use Shlinkio\Shlink\Core\Exception\EntityDoesNotExistException; use Shlinkio\Shlink\Core\Exception\InvalidShortCodeException; use Shlinkio\Shlink\Core\Service\UrlShortener; use Shlinkio\Shlink\PreviewGenerator\Service\PreviewGenerator; -use ShlinkioTest\Shlink\Common\Util\TestUtils; use Zend\Diactoros\Response; use Zend\Diactoros\ServerRequest; @@ -39,7 +38,7 @@ class PreviewActionTest extends TestCase } /** @test */ - public function invalidShortCodeFallsBackToNextMiddleware() + public function invalidShortCodeFallsBackToNextMiddleware(): void { $shortCode = 'abc123'; $this->urlShortener->shortCodeToUrl($shortCode)->willThrow(EntityDoesNotExistException::class) @@ -52,7 +51,7 @@ class PreviewActionTest extends TestCase } /** @test */ - public function correctShortCodeReturnsImageResponse() + public function correctShortCodeReturnsImageResponse(): void { $shortCode = 'abc123'; $url = 'foobar.com'; @@ -63,7 +62,7 @@ class PreviewActionTest extends TestCase $resp = $this->action->process( (new ServerRequest())->withAttribute('shortCode', $shortCode), - TestUtils::createReqHandlerMock()->reveal() + $this->prophesize(RequestHandlerInterface::class)->reveal() ); $this->assertEquals(filesize($path), $resp->getHeaderLine('Content-length')); @@ -71,7 +70,7 @@ class PreviewActionTest extends TestCase } /** @test */ - public function invalidShortCodeExceptionFallsBackToNextMiddleware() + public function invalidShortCodeExceptionFallsBackToNextMiddleware(): void { $shortCode = 'abc123'; $this->urlShortener->shortCodeToUrl($shortCode)->willThrow(InvalidShortCodeException::class) diff --git a/module/Core/test/Action/RedirectActionTest.php b/module/Core/test/Action/RedirectActionTest.php index 9fc13906..da2199e4 100644 --- a/module/Core/test/Action/RedirectActionTest.php +++ b/module/Core/test/Action/RedirectActionTest.php @@ -13,7 +13,6 @@ use Shlinkio\Shlink\Core\Exception\EntityDoesNotExistException; use Shlinkio\Shlink\Core\Options; use Shlinkio\Shlink\Core\Service\UrlShortener; use Shlinkio\Shlink\Core\Service\VisitsTracker; -use ShlinkioTest\Shlink\Common\Util\TestUtils; use Zend\Diactoros\Response; use Zend\Diactoros\ServerRequest; @@ -43,7 +42,7 @@ class RedirectActionTest extends TestCase } /** @test */ - public function redirectionIsPerformedToLongUrl() + public function redirectionIsPerformedToLongUrl(): void { $shortCode = 'abc123'; $expectedUrl = 'http://domain.com/foo/bar'; @@ -53,7 +52,7 @@ class RedirectActionTest extends TestCase $this->visitTracker->track(Argument::cetera())->shouldBeCalledOnce(); $request = (new ServerRequest())->withAttribute('shortCode', $shortCode); - $response = $this->action->process($request, TestUtils::createReqHandlerMock()->reveal()); + $response = $this->action->process($request, $this->prophesize(RequestHandlerInterface::class)->reveal()); $this->assertInstanceOf(Response\RedirectResponse::class, $response); $this->assertEquals(302, $response->getStatusCode()); @@ -62,7 +61,7 @@ class RedirectActionTest extends TestCase } /** @test */ - public function nextMiddlewareIsInvokedIfLongUrlIsNotFound() + public function nextMiddlewareIsInvokedIfLongUrlIsNotFound(): void { $shortCode = 'abc123'; $this->urlShortener->shortCodeToUrl($shortCode)->willThrow(EntityDoesNotExistException::class) @@ -79,7 +78,7 @@ class RedirectActionTest extends TestCase } /** @test */ - public function redirectToCustomUrlIsReturnedIfConfiguredSoAndShortUrlIsNotFound() + public function redirectToCustomUrlIsReturnedIfConfiguredSoAndShortUrlIsNotFound(): void { $shortCode = 'abc123'; $shortCodeToUrl = $this->urlShortener->shortCodeToUrl($shortCode)->willThrow( @@ -102,7 +101,7 @@ class RedirectActionTest extends TestCase } /** @test */ - public function visitIsNotTrackedIfDisableParamIsProvided() + public function visitIsNotTrackedIfDisableParamIsProvided(): void { $shortCode = 'abc123'; $expectedUrl = 'http://domain.com/foo/bar'; @@ -113,7 +112,7 @@ class RedirectActionTest extends TestCase $request = (new ServerRequest())->withAttribute('shortCode', $shortCode) ->withQueryParams(['foobar' => true]); - $response = $this->action->process($request, TestUtils::createReqHandlerMock()->reveal()); + $response = $this->action->process($request, $this->prophesize(RequestHandlerInterface::class)->reveal()); $this->assertInstanceOf(Response\RedirectResponse::class, $response); $this->assertEquals(302, $response->getStatusCode()); diff --git a/phpstan.neon b/phpstan.neon index 85f81e8f..90c8b2ee 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -1,6 +1,5 @@ parameters: ignoreErrors: - - '#League\\Plates\\callback#' - '#is not subtype of Throwable#' - '#ObjectManager::flush()#' - '#\$metadata ClassMetadata#' diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 03e97254..516a48fc 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -6,9 +6,6 @@ colors="true" > <testsuites> - <testsuite name="Common"> - <directory>./module/Common/test</directory> - </testsuite> <testsuite name="Core"> <directory>./module/Core/test</directory> </testsuite>