diff --git a/.gitattributes b/.gitattributes index 6c4cc13..57365ce 100644 --- a/.gitattributes +++ b/.gitattributes @@ -5,7 +5,6 @@ /.gitignore export-ignore /.scrutinizer.yml export-ignore /.travis.yml export-ignore -/bootstrap.php export-ignore /CHANGELOG.md export-ignore /LICENSE export-ignore /phpunit.xml.dist export-ignore diff --git a/.scrutinizer.yml b/.scrutinizer.yml index 3eb678a..1a2678d 100644 --- a/.scrutinizer.yml +++ b/.scrutinizer.yml @@ -1,35 +1,34 @@ filter: - excluded_paths: [Tests/*] + excluded_paths: [tests/*] + +build: + nodes: + analysis: + environment: + php: + version: 7.2 + cache: + disabled: false + directories: + - ~/.composer/cache + project_setup: + override: true + tests: + override: + - php-scrutinizer-run + - phpcs-run + dependencies: + override: + - composer install --no-interaction --prefer-dist + checks: php: code_rating: true - remove_extra_empty_lines: true - remove_php_closing_tag: true - remove_trailing_whitespace: true - fix_use_statements: - remove_unused: true - preserve_multiple: false - preserve_blanklines: true - order_alphabetically: true - fix_php_opening_tag: true - fix_linefeed: true - fix_line_ending: true - fix_identation_4spaces: true - fix_doc_comments: true + tools: external_code_coverage: - timeout: 600 - runs: 3 - php_analyzer: true - php_code_coverage: false - php_code_sniffer: - config: - standard: PSR2 - filter: - paths: ['./'] - php_loc: - enabled: true - excluded_dirs: [vendor, Tests] - php_cpd: - enabled: true - excluded_dirs: [vendor, Tests] + timeout: 900 + +build_failure_conditions: + - 'elements.rating(<= C).new.exists' # No new classes/methods with a rating of C or worse allowed + - 'project.metric_change("scrutinizer.test_coverage", < 0)' # Code Coverage decreased from previous inspection diff --git a/.travis.yml b/.travis.yml index f898488..87d93bb 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,52 +1,47 @@ language: php -sudo: false - -cache: - directories: - - "$HOME/.composer/cache" - php: - - 7.0 - - 7.1 - 7.2 - 7.3 + - 7.4snapshot - nightly +cache: + directories: + - "$HOME/.composer/cache" + env: - matrix: - - DOCTRINE="true" - - DOCTRINE="false" - - SYMFONY_VERSION="2.8.*" - - SYMFONY_VERSION="3.3.*" - - SYMFONY_VERSION="3.4.*" - - SYMFONY_VERSION="4.0.*" - - SYMFONY_VERSION="4.1.*" - - SYMFONY_VERSION="4.2.*" - -matrix: + - DEPENDENCIES= + - DEPENDENCIES=--prefer-lowest + +install: + composer update --no-interaction --prefer-stable --prefer-dist $DEPENDENCIES + +script: vendor/bin/phpunit + +stages: + - Validate composer.json + - Code Quality + - Test + +jobs: + allow_failures: + - php: nightly + include: - - php: 7.0 - env: COMPOSER_FLAGS="--prefer-stable --prefer-lowest" - - php: 7.0 - env: COMPOSER_FLAGS="--prefer-stable --prefer-lowest" DOCTRINE="false" - exclude: - - php: 7.0 - env: SYMFONY_VERSION="4.0.*" - - php: 7.0 - env: SYMFONY_VERSION="4.1.*" - - php: 7.0 - env: SYMFONY_VERSION="4.2.*" - -before_install: - - composer self-update || true - - if [ "$DOCTRINE" == "false" ]; then composer remove league/tactician-doctrine --dev --no-update; fi - - if [ "$SYMFONY_VERSION" != "" ]; then composer require symfony/symfony:${SYMFONY_VERSION} --no-update; fi - -install: composer update $COMPOSER_FLAGS --prefer-dist --no-interaction - -script: ./vendor/bin/phpunit --coverage-text --coverage-clover=coverage.clover - -after_script: - - wget https://scrutinizer-ci.com/ocular.phar - - php ocular.phar code-coverage:upload --format=php-clover coverage.clover + - stage: Code Quality + - name: PHPStan + php: 7.2 + script: vendor/bin/phpstan analyse + - stage: Test + - name: Coverage + php: 7.2 + before_script: + - mv ~/.phpenv/versions/$(phpenv version-name)/etc/conf.d/xdebug.ini{.disabled,} + - if [[ ! $(php -m | grep -si xdebug) ]]; then echo "xdebug required for coverage"; exit 1; fi + script: + - ./vendor/bin/phpunit --coverage-clover ./build/logs/clover.xml + after_script: + - wget https://github.com/scrutinizer-ci/ocular/releases/download/1.5.2/ocular.phar + - php ocular.phar code-coverage:upload --format=php-clover build/logs/clover.xml + diff --git a/README.md b/README.md index 9d130f9..cf3fb78 100644 --- a/README.md +++ b/README.md @@ -11,8 +11,8 @@ Symfony2 Bundle for the Tactician library Open a command console, enter your project directory and execute the following command to download the latest stable release for this bundle: -```bash -$ composer require league/tactician-bundle +```sh +composer require league/tactician-bundle ``` This command requires you to have Composer installed globally, as explained diff --git a/bootstrap.php b/bootstrap.php deleted file mode 100644 index 0046e15..0000000 --- a/bootstrap.php +++ /dev/null @@ -1,10 +0,0 @@ -=7.0", - "league/tactician": "^1.0", - "league/tactician-logger": "^0.10.0", - "league/tactician-container": "^2.0", - "symfony/config": "^2.8|^3.3|^4.0", - "symfony/dependency-injection": "^2.8|^3.3|^4.0", - "symfony/http-kernel": "^2.8|^3.3|^4.0", - "symfony/yaml": "^2.8|^3.3|^4.0" + "php": "^7.2", + "league/tactician": "dev-master as 1.1.16", + "symfony/config": "^4.4", + "symfony/dependency-injection": "^4.4", + "symfony/http-kernel": "^4.4", + "symfony/yaml": "^4.4" + }, + "require-dev": { + "matthiasnoback/symfony-config-test": "^4.0", + "matthiasnoback/symfony-dependency-injection-test": "^4.0", + "mockery/mockery": "^1.2", + "phpstan/phpstan": "^0.11.19", + "phpstan/phpstan-phpunit": "^0.11.2", + "phpstan/phpstan-strict-rules": "^0.11.1", + "phpunit/phpunit": "^8", + "symfony/console": "^4.4", + "symfony/framework-bundle": "^4.4" }, - "minimum-stability": "beta", "suggest": { - "symfony/console": "For debugging command-to-handler routing using the tactician:debug console command", - "symfony/validator": "For command validator middleware", - "symfony/security": "For command security middleware", - "league/tactician-doctrine": "For doctrine transaction middleware" + "symfony/console": "For debugging command-to-handler routing using the tactician:debug console command" }, "autoload" : { "psr-4" : { @@ -60,16 +51,7 @@ "dev-master": "1.0-dev" } }, - "require-dev": { - "phpunit/phpunit": "~6.1", - "mockery/mockery": "~1.0", - "symfony/console": "^2.8|^3.3|^4.0", - "symfony/security": "^2.8|^3.3|^4.0", - "symfony/validator": "^2.8|^3.3|^4.0", - "league/tactician-doctrine": "^1.1.1", - "symfony/framework-bundle": "^2.8.15|^3.3|^4.0", - "symfony/security-bundle": "^2.8|^3.3|^4.0", - "matthiasnoback/symfony-config-test": "^3.0", - "matthiasnoback/symfony-dependency-injection-test": "^2.1" + "config": { + "sort-packages": true } } diff --git a/phpstan.neon.dist b/phpstan.neon.dist new file mode 100644 index 0000000..35299be --- /dev/null +++ b/phpstan.neon.dist @@ -0,0 +1,10 @@ +parameters: + level: max + paths: + - %currentWorkingDirectory%/src + - %currentWorkingDirectory%/tests + +includes: + - vendor/phpstan/phpstan-phpunit/extension.neon + - vendor/phpstan/phpstan-phpunit/rules.neon + - vendor/phpstan/phpstan-strict-rules/rules.neon diff --git a/phpunit.xml.dist b/phpunit.xml.dist index e759330..025b9cd 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -1,37 +1,22 @@ - + + bootstrap="tests/bootstrap.php" + executionOrder="random" +> - - tests/ - tests/Integration - - - - tests/Integration + + tests - - - src/ - - - - - - - diff --git a/src/Command/DebugCommand.php b/src/Console/DebugCommand.php similarity index 84% rename from src/Command/DebugCommand.php rename to src/Console/DebugCommand.php index 81c3792..25c1c46 100644 --- a/src/Command/DebugCommand.php +++ b/src/Console/DebugCommand.php @@ -1,14 +1,14 @@ mappings = $mappings; } - protected function configure() + protected function configure() : void { $this->setName('debug:tactician'); } - public function execute(InputInterface $input, OutputInterface $output) + public function execute(InputInterface $input, OutputInterface $output) : int { $io = new SymfonyStyle($input, $output); @@ -44,9 +44,11 @@ public function execute(InputInterface $input, OutputInterface $output) $io->warning("No registered commands for bus $busId"); } } + + return 0; } - private function mappingToRows(array $map) + private function mappingToRows(array $map) : array { $rows = []; foreach ($map as $commandName => $handlerService) { diff --git a/src/DependencyInjection/Compiler/BusBuilder/BusBuilder.php b/src/DependencyInjection/Compiler/BusBuilder/BusBuilder.php index 986d5e5..9980926 100644 --- a/src/DependencyInjection/Compiler/BusBuilder/BusBuilder.php +++ b/src/DependencyInjection/Compiler/BusBuilder/BusBuilder.php @@ -3,15 +3,11 @@ namespace League\Tactician\Bundle\DependencyInjection\Compiler\BusBuilder; -use League\Tactician\Bundle\Handler\ContainerBasedHandlerLocator; use League\Tactician\CommandBus; -use League\Tactician\Container\ContainerLocator; use League\Tactician\Handler\CommandHandlerMiddleware; -use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\Reference; -use Symfony\Component\DependencyInjection\ServiceLocator; final class BusBuilder { @@ -23,52 +19,42 @@ final class BusBuilder /** * @var string[] */ - private $middlewareIds = []; + private $middlewareIds; - /** - * @var string - */ - private $methodInflectorId; + /** @var string */ + private $commandToHandlerMapping; - public function __construct(string $busId, string $methodInflector, array $middlewareIds) + public function __construct(string $busId, string $commandToHandlerMapping, array $middlewareIds) { - $this->busId = $busId; - $this->methodInflectorId = $methodInflector; - $this->middlewareIds = $middlewareIds; + $this->busId = $busId; + $this->commandToHandlerMapping = $commandToHandlerMapping; + $this->middlewareIds = $middlewareIds; } - public function id(): string + public function id() : string { return $this->busId; } - public function serviceId(): string + public function serviceId() : string { return "tactician.commandbus.$this->busId"; } - public function locatorServiceId() - { - return "tactician.commandbus.{$this->busId}.handler.locator"; - } - - public function commandHandlerMiddlewareId(): string + public function commandHandlerMiddlewareId() : string { return "tactician.commandbus.{$this->busId}.middleware.command_handler"; } - public function registerInContainer(ContainerBuilder $container, array $commandsToAccept) + public function registerInContainer(ContainerBuilder $container) : void { - $this->registerLocatorService($container, $commandsToAccept); - $container->setDefinition( $this->commandHandlerMiddlewareId(), new Definition( CommandHandlerMiddleware::class, [ - new Reference('tactician.handler.command_name_extractor.class_name'), - new Reference($this->locatorServiceId()), - new Reference($this->methodInflectorId), + new Reference('service_container'), + new Reference($this->commandToHandlerMapping), ] ) ); @@ -77,50 +63,13 @@ public function registerInContainer(ContainerBuilder $container, array $commands $this->serviceId(), new Definition( CommandBus::class, - [ - array_map( - function (string $id) { return new Reference($id); }, - $this->middlewareIds - ) - ] + array_map( + static function (string $id) { + return new Reference($id); + }, + $this->middlewareIds + ) ) )->setPublic(true); } - - private function registerLocatorService(ContainerBuilder $container, $commandsToAccept) - { - // Leverage symfony/dependency-injection:^3.3 service locators - if (class_exists(ServiceLocator::class)) { - $definition = new Definition( - ContainerLocator::class, - [new Reference($this->registerHandlerServiceLocator($container, $commandsToAccept)), $commandsToAccept] - ); - } else { - $definition = new Definition( - ContainerBasedHandlerLocator::class, - [new Reference('service_container'), $commandsToAccept] - ); - } - - $container->setDefinition($this->locatorServiceId(), $definition); - } - - private function registerHandlerServiceLocator(ContainerBuilder $container, array $commandsToAccept): string - { - $handlers = []; - foreach ($commandsToAccept as $commandName => $handlerId) { - $handlers[$handlerId] = new ServiceClosureArgument(new Reference($handlerId)); - } - - $handlerServiceLocator = (new Definition(ServiceLocator::class, [$handlers])) - ->setPublic(false) - ->addTag('container.service_locator'); - - $container->setDefinition( - $handlerId = "tactician.commandbus.{$this->busId}.handler.service_locator", - $handlerServiceLocator - ); - - return $handlerId; - } } diff --git a/src/DependencyInjection/Compiler/BusBuilder/BusBuilders.php b/src/DependencyInjection/Compiler/BusBuilder/BusBuilders.php index de4cfea..21dc0b4 100644 --- a/src/DependencyInjection/Compiler/BusBuilder/BusBuilders.php +++ b/src/DependencyInjection/Compiler/BusBuilder/BusBuilders.php @@ -3,12 +3,12 @@ namespace League\Tactician\Bundle\DependencyInjection\Compiler\BusBuilder; +use ArrayIterator; +use IteratorAggregate; use League\Tactician\Bundle\DependencyInjection\DuplicatedCommandBusId; -use League\Tactician\Bundle\DependencyInjection\HandlerMapping\Routing; use League\Tactician\Bundle\DependencyInjection\InvalidCommandBusId; -use ArrayIterator; -final class BusBuilders implements \IteratorAggregate +final class BusBuilders implements IteratorAggregate { /** * @var BusBuilder[] @@ -30,17 +30,12 @@ public function __construct(array $busBuilders, string $defaultBusId) $this->defaultBusId = $defaultBusId; } - public function createBlankRouting(): Routing - { - return new Routing(array_keys($this->busBuilders)); - } - - public function defaultBus(): BusBuilder + public function defaultBus() : BusBuilder { return $this->get($this->defaultBusId); } - private function get(string $busId): BusBuilder + private function get(string $busId) : BusBuilder { $this->assertValidBusId($busId); @@ -55,14 +50,14 @@ public function getIterator() return new ArrayIterator($this->busBuilders); } - private function assertValidBusId($busId) + private function assertValidBusId(string $busId) : void { - if (!isset($this->busBuilders[$busId])) { + if (! isset($this->busBuilders[$busId])) { throw InvalidCommandBusId::ofName($busId, array_keys($this->busBuilders)); } } - private function add(BusBuilder $builder) + private function add(BusBuilder $builder) : void { $id = $builder->id(); diff --git a/src/DependencyInjection/Compiler/BusBuilder/BusBuildersFromConfig.php b/src/DependencyInjection/Compiler/BusBuilder/BusBuildersFromConfig.php index 9b7231b..64759ba 100644 --- a/src/DependencyInjection/Compiler/BusBuilder/BusBuildersFromConfig.php +++ b/src/DependencyInjection/Compiler/BusBuilder/BusBuildersFromConfig.php @@ -5,19 +5,18 @@ final class BusBuildersFromConfig { - const DEFAULT_METHOD_INFLECTOR = 'tactician.handler.method_name_inflector.handle'; + public const DEFAULT_BUS_ID = 'default'; + public const DEFAULT_COMMAND_HANDLER_MAPPING = 'tactician.handler.command_handler_mapping.map_by_naming_convention'; - const DEFAULT_BUS_ID = 'default'; - - public static function convert(array $config): BusBuilders + public static function convert(array $config) : BusBuilders { - $defaultInflector = $config['method_inflector'] ?? self::DEFAULT_METHOD_INFLECTOR; + $defaultCommandHandlerMapping = $config['command_handler_mapping'] ?? self::DEFAULT_COMMAND_HANDLER_MAPPING; $builders = []; foreach ($config['commandbus'] ?? [] as $busId => $busConfig) { $builders[] = new BusBuilder( $busId, - $busConfig['method_inflector'] ?? $defaultInflector, + $busConfig['command_handler_mapping'] ?? $defaultCommandHandlerMapping, $busConfig['middleware'] ); } diff --git a/src/DependencyInjection/Compiler/CommandHandlerPass.php b/src/DependencyInjection/Compiler/CommandHandlerPass.php index cfd2172..64d1c13 100644 --- a/src/DependencyInjection/Compiler/CommandHandlerPass.php +++ b/src/DependencyInjection/Compiler/CommandHandlerPass.php @@ -3,56 +3,48 @@ namespace League\Tactician\Bundle\DependencyInjection\Compiler; use League\Tactician\Bundle\DependencyInjection\Compiler\BusBuilder\BusBuildersFromConfig; -use League\Tactician\Bundle\DependencyInjection\HandlerMapping\HandlerMapping; +use League\Tactician\CommandBus; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; use Symfony\Component\DependencyInjection\ContainerBuilder; -use League\Tactician\CommandBus; +use function array_keys; /** * This compiler pass maps Handler DI tags to specific commands. */ -class CommandHandlerPass implements CompilerPassInterface +final class CommandHandlerPass implements CompilerPassInterface { - /** - * @var HandlerMapping - */ - private $handlerMapping; + public const TACTICIAN_HANDLER_TAG = 'tactician.handler'; - public function __construct(HandlerMapping $mappingStrategy) + public function process(ContainerBuilder $container) : void { - $this->handlerMapping = $mappingStrategy; - } + $handlers = $container->findTaggedServiceIds(self::TACTICIAN_HANDLER_TAG); + foreach ($handlers as $handler => $_) { + $definition = $container->findDefinition($handler); + $definition->setPublic(true); + } - public function process(ContainerBuilder $container) - { $builders = BusBuildersFromConfig::convert( $this->readAndForgetParameter($container, 'tactician.merged_config') ); - $routing = $this->handlerMapping->build($container, $builders->createBlankRouting()); - - $mappings = []; - // Register the completed builders in our container foreach ($builders as $builder) { - $commandToServiceMapping = $routing->commandToServiceMapping($builder->id()); - $mappings[$builder->id()] = $commandToServiceMapping; - $builder->registerInContainer($container, $commandToServiceMapping); + $builder->registerInContainer($container); } // Setup default aliases $container->setAlias('tactician.commandbus', $builders->defaultBus()->serviceId()); $container->setAlias(CommandBus::class, 'tactician.commandbus'); - $container->setAlias('tactician.handler.locator.symfony', $builders->defaultBus()->locatorServiceId()); $container->setAlias('tactician.middleware.command_handler', $builders->defaultBus()->commandHandlerMiddlewareId()); // Wire debug command if ($container->hasDefinition('tactician.command.debug')) { - $container->getDefinition('tactician.command.debug')->addArgument($mappings); + $container->getDefinition('tactician.command.debug')->addArgument(array_keys($handlers)); } } - private function readAndForgetParameter(ContainerBuilder $container, $parameter) + /** @return mixed */ + private function readAndForgetParameter(ContainerBuilder $container, string $parameter) { $value = $container->getParameter($parameter); $container->getParameterBag()->remove($parameter); diff --git a/src/DependencyInjection/Compiler/DoctrineMiddlewarePass.php b/src/DependencyInjection/Compiler/DoctrineMiddlewarePass.php deleted file mode 100644 index ff50f44..0000000 --- a/src/DependencyInjection/Compiler/DoctrineMiddlewarePass.php +++ /dev/null @@ -1,47 +0,0 @@ -hasParameter('doctrine.entity_managers')) { - return; - } - - $entityManagers = $container->getParameter('doctrine.entity_managers'); - if (empty($entityManagers)) { - return; - } - - foreach ($entityManagers as $name => $serviceId) { - $container->setDefinition( - sprintf('tactician.middleware.doctrine.%s', $name), - new Definition(TransactionMiddleware::class, [ new Reference($serviceId) ]) - ); - - $container->setDefinition( - sprintf('tactician.middleware.doctrine_rollback_only.%s', $name), - new Definition(RollbackOnlyTransactionMiddleware::class, [ new Reference($serviceId) ]) - ); - } - - $defaultEntityManager = $container->getParameter('doctrine.default_entity_manager'); - $container->setAlias('tactician.middleware.doctrine', sprintf('tactician.middleware.doctrine.%s', $defaultEntityManager)); - $container->setAlias('tactician.middleware.doctrine_rollback_only', sprintf('tactician.middleware.doctrine_rollback_only.%s', $defaultEntityManager)); - } -} - diff --git a/src/DependencyInjection/Compiler/SecurityMiddlewarePass.php b/src/DependencyInjection/Compiler/SecurityMiddlewarePass.php deleted file mode 100644 index e9439df..0000000 --- a/src/DependencyInjection/Compiler/SecurityMiddlewarePass.php +++ /dev/null @@ -1,32 +0,0 @@ -hasDefinition('security.authorization_checker')) { - return; - } - - $container->setDefinition( - static::SERVICE_ID, - new Definition(SecurityMiddleware::class, [ new Reference('security.authorization_checker') ]) - ); - } -} - diff --git a/src/DependencyInjection/Compiler/ValidatorMiddlewarePass.php b/src/DependencyInjection/Compiler/ValidatorMiddlewarePass.php deleted file mode 100644 index 8d8ffcd..0000000 --- a/src/DependencyInjection/Compiler/ValidatorMiddlewarePass.php +++ /dev/null @@ -1,32 +0,0 @@ -hasDefinition('validator')) { - return; - } - - $container->setDefinition( - static::SERVICE_ID, - new Definition(ValidatorMiddleware::class, [ new Reference('validator') ]) - ); - } -} - diff --git a/src/DependencyInjection/Configuration.php b/src/DependencyInjection/Configuration.php index ad1ad3d..64f562e 100644 --- a/src/DependencyInjection/Configuration.php +++ b/src/DependencyInjection/Configuration.php @@ -6,29 +6,26 @@ use Symfony\Component\Config\Definition\Builder\TreeBuilder; use Symfony\Component\Config\Definition\ConfigurationInterface; use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException; +use function array_key_exists; +use function end; +use function in_array; +use function is_array; /** * This is the class that validates and merges configuration from your app/config files. * * To learn more see {@link http://symfony.com/doc/current/cookbook/bundles/extension.html#cookbook-bundles-extension-config-class} */ -class Configuration implements ConfigurationInterface +final class Configuration implements ConfigurationInterface { /** * Create a rootnode tree for configuration that can be injected into the DI container. - * - * @return TreeBuilder */ - public function getConfigTreeBuilder() + public function getConfigTreeBuilder() : TreeBuilder { - $treeBuilder = new TreeBuilder('tactician'); + $treeBuilder = new TreeBuilder(TacticianExtension::ALIAS); - if (\method_exists($treeBuilder, 'getRootNode')) { - $rootNode = $treeBuilder->getRootNode(); - } else { - // BC layer for symfony/config 4.1 and older - $rootNode = $treeBuilder->root('tactician'); - } + $rootNode = $treeBuilder->getRootNode(); $rootNode ->children() @@ -43,9 +40,10 @@ public function getConfigTreeBuilder() ->useAttributeAsKey('name') ->prototype('scalar')->end() ->validate() - ->ifTrue(function ($config) { - $isPresent = in_array('tactician.middleware.command_handler', $config); - $isLast = end($config) == 'tactician.middleware.command_handler'; + ->ifTrue( + static function (array $config) : bool { + $isPresent = in_array('tactician.middleware.command_handler', $config, true); + $isLast = end($config) === 'tactician.middleware.command_handler'; return $isPresent && !$isLast; }) @@ -63,36 +61,25 @@ public function getConfigTreeBuilder() ->defaultValue(BusBuildersFromConfig::DEFAULT_BUS_ID) ->cannotBeEmpty() ->end() - ->scalarNode('method_inflector') - ->defaultValue(BusBuildersFromConfig::DEFAULT_METHOD_INFLECTOR) - ->cannotBeEmpty() - ->end() - ->arrayNode('security') - ->defaultValue([]) - ->useAttributeAsKey('name') - ->prototype('array') - ->prototype('scalar')->end() - ->end() - ->end() - ->scalarNode('logger_formatter') - ->defaultValue('tactician.logger.class_properties_formatter') + ->scalarNode('command_handler_mapping') + ->defaultValue(BusBuildersFromConfig::DEFAULT_COMMAND_HANDLER_MAPPING) ->cannotBeEmpty() ->end() ->end() ->validate() - ->ifTrue(function ($config) { + ->ifTrue(static function ($config) : bool { return is_array($config) && array_key_exists('default_bus', $config) && array_key_exists('commandbus', $config) ; }) - ->then(function ($config) { + ->then(static function (array $config) : array { $busNames = []; foreach ($config['commandbus'] as $busName => $busConfig) { $busNames[] = $busName; } - if (!in_array($config['default_bus'], $busNames)) { + if (! in_array($config['default_bus'], $busNames, true)) { throw new InvalidConfigurationException( sprintf( 'The default_bus "%s" was not defined as a command bus. Valid option(s): %s', diff --git a/src/DependencyInjection/DuplicatedCommandBusId.php b/src/DependencyInjection/DuplicatedCommandBusId.php index 677d2bb..0a6c801 100644 --- a/src/DependencyInjection/DuplicatedCommandBusId.php +++ b/src/DependencyInjection/DuplicatedCommandBusId.php @@ -3,10 +3,15 @@ namespace League\Tactician\Bundle\DependencyInjection; -final class DuplicatedCommandBusId extends \Exception +use Exception; +use function sprintf; + +final class DuplicatedCommandBusId extends Exception { - public static function withId(string $id) + public static function withId(string $id) : self { - return new static("There are multiple command buses with the id '$id'. All bus ids must be unique."); + return new static( + sprintf("There are multiple command buses with the id '%s'. All bus ids must be unique.", $id) + ); } } diff --git a/src/DependencyInjection/HandlerMapping/ClassNameMapping.php b/src/DependencyInjection/HandlerMapping/ClassNameMapping.php deleted file mode 100644 index e16ca13..0000000 --- a/src/DependencyInjection/HandlerMapping/ClassNameMapping.php +++ /dev/null @@ -1,22 +0,0 @@ -getParameterBag()->resolveValue($tagAttributes['command'])); - } - - protected function findCommandsForService(ContainerBuilder $container, Definition $definition, array $tagAttributes): array - { - return [ - $container->getParameterBag()->resolveValue($tagAttributes['command']) - ]; - } -} diff --git a/src/DependencyInjection/HandlerMapping/CompositeMapping.php b/src/DependencyInjection/HandlerMapping/CompositeMapping.php deleted file mode 100644 index 48783ba..0000000 --- a/src/DependencyInjection/HandlerMapping/CompositeMapping.php +++ /dev/null @@ -1,28 +0,0 @@ -strategies = $strategies; - } - - public function build(ContainerBuilder $container, Routing $routing): Routing - { - foreach ($this->strategies as $strategy) { - $routing = $strategy->build($container, $routing); - } - - return $routing; - } -} \ No newline at end of file diff --git a/src/DependencyInjection/HandlerMapping/HandlerMapping.php b/src/DependencyInjection/HandlerMapping/HandlerMapping.php deleted file mode 100644 index 2a5f440..0000000 --- a/src/DependencyInjection/HandlerMapping/HandlerMapping.php +++ /dev/null @@ -1,11 +0,0 @@ - [ - * 'My\Command\Name1' => 'some.service.id', - * 'My\Other\Command' => 'some.service.id.or.same.one' - * ], - * 'busId_2' => [ - * 'Legacy\App\Command1' => 'some.old.handler', - * ... - * ], - * ] - * - * @var array - */ - private $mapping = []; - - public function __construct(array $validBusIds) - { - foreach ($validBusIds as $validBusId) { - $this->mapping[$validBusId] = []; - } - } - - public function routeToBus($busId, $commandClassName, $serviceId) - { - $this->assertValidBusId($busId); - $this->assertValidCommandFQCN($commandClassName, $serviceId); - - $this->mapping[$busId][$commandClassName] = $serviceId; - } - - public function routeToAllBuses($commandClassName, $serviceId) - { - $this->assertValidCommandFQCN($commandClassName, $serviceId); - - foreach($this->mapping as $busId => $mapping) { - $this->mapping[$busId][$commandClassName] = $serviceId; - } - } - - public function commandToServiceMapping(string $busId): array - { - $this->assertValidBusId($busId); - return $this->mapping[$busId]; - } - - private function assertValidBusId(string $busId) - { - if (!isset($this->mapping[$busId])) { - throw InvalidCommandBusId::ofName($busId, array_keys($this->mapping)); - } - } - - /** - * @param $commandClassName - * @param $serviceId - */ - protected function assertValidCommandFQCN($commandClassName, $serviceId) - { - if (!class_exists($commandClassName)) { - throw new InvalidArgumentException("Can not route $commandClassName to $serviceId, class $commandClassName does not exist!"); - } - } -} \ No newline at end of file diff --git a/src/DependencyInjection/HandlerMapping/TagBasedMapping.php b/src/DependencyInjection/HandlerMapping/TagBasedMapping.php deleted file mode 100644 index abcd652..0000000 --- a/src/DependencyInjection/HandlerMapping/TagBasedMapping.php +++ /dev/null @@ -1,50 +0,0 @@ -findTaggedServiceIds(self::TAG_NAME) as $serviceId => $tags) { - foreach ($tags as $attributes) { - $this->mapServiceByTag($container, $routing, $serviceId, $attributes); - } - } - - return $routing; - } - - /** - * @param ContainerBuilder $container - * @param Routing $routing - * @param $serviceId - * @param $attributes - */ - private function mapServiceByTag(ContainerBuilder $container, Routing $routing, $serviceId, $attributes) - { - $definition = $container->getDefinition($serviceId); - - if (!$this->isSupported($container, $definition, $attributes)) { - return; - } - - foreach ($this->findCommandsForService($container, $definition, $attributes) as $commandClassName) { - if (isset($attributes['bus'])) { - $routing->routeToBus($attributes['bus'], $commandClassName, $serviceId); - } else { - $routing->routeToAllBuses($commandClassName, $serviceId); - } - } - } - - abstract protected function isSupported(ContainerBuilder $container, Definition $definition, array $tagAttributes): bool; - - abstract protected function findCommandsForService(ContainerBuilder $container, Definition $definition, array $tagAttributes): array; -} diff --git a/src/DependencyInjection/HandlerMapping/TypeHintMapping.php b/src/DependencyInjection/HandlerMapping/TypeHintMapping.php deleted file mode 100644 index 2109626..0000000 --- a/src/DependencyInjection/HandlerMapping/TypeHintMapping.php +++ /dev/null @@ -1,70 +0,0 @@ -getParameterBag()->resolveValue($definition->getClass())); - - foreach ($reflClass->getMethods() as $method) { - - if (!$method->isPublic() - || $method->isConstructor() - || $method->isStatic() - || $method->isAbstract() - || $method->isVariadic() - || $method->getNumberOfParameters() !== 1 - ) { - continue; - } - - $parameter = $method->getParameters()[0]; - if (!$parameter->hasType() - || $parameter->getType()->isBuiltin() - || $parameter->getClass()->isInterface() - ) { - continue; - } - - $results[] = (string)$parameter->getType(); - } - - return $results; - } -} diff --git a/src/DependencyInjection/InvalidCommandBusId.php b/src/DependencyInjection/InvalidCommandBusId.php index 1dd53fc..73c340f 100644 --- a/src/DependencyInjection/InvalidCommandBusId.php +++ b/src/DependencyInjection/InvalidCommandBusId.php @@ -3,12 +3,19 @@ namespace League\Tactician\Bundle\DependencyInjection; -final class InvalidCommandBusId extends \Exception +use Exception; +use function implode; +use function sprintf; + +final class InvalidCommandBusId extends Exception { - public static function ofName(string $expectedId, array $validIds) + /** + * @param string[] $validIds + */ + public static function ofName(string $expectedId, array $validIds) : self { return new static( - "Could not find a command bus with id '$expectedId'. Valid buses are: " . implode(', ', $validIds) + sprintf("Could not find a command bus with id '%s'. Valid buses are: %s", $expectedId, implode(', ', $validIds)) ); } -} \ No newline at end of file +} diff --git a/src/DependencyInjection/TacticianExtension.php b/src/DependencyInjection/TacticianExtension.php index 931b916..62eafed 100644 --- a/src/DependencyInjection/TacticianExtension.php +++ b/src/DependencyInjection/TacticianExtension.php @@ -2,106 +2,29 @@ namespace League\Tactician\Bundle\DependencyInjection; -use League\Tactician\Bundle\Security\Voter\HandleCommandVoter; -use League\Tactician\Logger\Formatter\ClassNameFormatter; -use League\Tactician\Logger\Formatter\ClassPropertiesFormatter; -use League\Tactician\Logger\LoggerMiddleware; use Symfony\Component\Config\FileLocator; use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\Loader; -use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\HttpKernel\DependencyInjection\ConfigurableExtension; -class TacticianExtension extends ConfigurableExtension +final class TacticianExtension extends ConfigurableExtension { - /** - * Configures the passed container according to the merged configuration. - * - * @param array $mergedConfig - * @param ContainerBuilder $container - */ - protected function loadInternal(array $mergedConfig, ContainerBuilder $container) - { - $loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__ . '/../Resources/config/services')); - $loader->load('services.yml'); - $container->setParameter('tactician.merged_config', $mergedConfig); - $this->configureSecurity($mergedConfig, $container); - $this->configureLogger($mergedConfig, $container); - } + public const ALIAS = 'tactician'; - public function getAlias() + public function getAlias() : string { - return 'tactician'; + return self::ALIAS; } /** - * Configure the security voter if the security middleware is loaded. - * - * @param array $mergedConfig - * @param ContainerBuilder $container - */ - private function configureSecurity(array $mergedConfig, ContainerBuilder $container) - { - foreach ($mergedConfig['commandbus'] as $commandBusConfig) { - if (in_array('tactician.middleware.security', $commandBusConfig['middleware'])) { - return $this->configureCommandSecurityVoter($mergedConfig, $container); - } - } - } - - /** - * Configure the security voter. - * - * @param array $mergedConfig - * @param ContainerBuilder $container - */ - private function configureCommandSecurityVoter(array $mergedConfig, ContainerBuilder $container) - { - if (!$container->has('tactician.middleware.security_voter')) { - $definition = new Definition( - HandleCommandVoter::class, - [ - new Reference('security.access.decision_manager'), - $mergedConfig['security'] - ] - ); - $definition->addTag('security.voter'); - $container->setDefinition('tactician.middleware.security_voter', $definition); - } - } - - /** - * Configure the logger middleware. + * Configures the passed container according to the merged configuration. * * @param array $mergedConfig - * @param ContainerBuilder $container */ - private function configureLogger(array $mergedConfig, ContainerBuilder $container) + protected function loadInternal(array $mergedConfig, ContainerBuilder $container) : void { - $this->configureLoggerFormatters($container); - - $loggerMiddleware = new Definition(LoggerMiddleware::class, [ - new Reference($mergedConfig['logger_formatter']), - new Reference('logger') - ]); - $loggerMiddleware->setPublic(false); - $loggerMiddleware->addTag('monolog.logger', ['channel' => 'command_bus']); - - $container->setDefinition('tactician.middleware.logger', $loggerMiddleware); - } - - - private function configureLoggerFormatters(ContainerBuilder $container) - { - $container->setDefinition( - 'tactician.logger.class_properties_formatter', - new Definition(ClassPropertiesFormatter::class) - )->setPublic(false); - - $container->setDefinition( - 'tactician.logger.class_name_formatter', - new Definition(ClassNameFormatter::class) - )->setPublic(false); + $loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__ . '/../Resources/config/services')); + $loader->load('services.yml'); + $container->setParameter('tactician.merged_config', $mergedConfig); } } diff --git a/src/Handler/ContainerBasedHandlerLocator.php b/src/Handler/ContainerBasedHandlerLocator.php deleted file mode 100644 index 1fbf958..0000000 --- a/src/Handler/ContainerBasedHandlerLocator.php +++ /dev/null @@ -1,50 +0,0 @@ -container = $container; - $this->commandToServiceId = $commandToServiceIdMapping; - } - - /** - * Retrieves the handler for a specified command - * - * @param string $commandName - * @return object - * - * @throws MissingHandlerException - */ - public function getHandlerForCommand($commandName) - { - if (!isset($this->commandToServiceId[$commandName])) { - throw MissingHandlerException::forCommand($commandName); - } - - return $this->container->get($this->commandToServiceId[$commandName]); - } -} diff --git a/src/Middleware/InvalidCommandException.php b/src/Middleware/InvalidCommandException.php deleted file mode 100644 index f1027f3..0000000 --- a/src/Middleware/InvalidCommandException.php +++ /dev/null @@ -1,54 +0,0 @@ -count() . ' violation(s).' - ); - - $exception->command = $command; - $exception->violations = $violations; - - return $exception; - } - - /** - * @return object - */ - public function getCommand() - { - return $this->command; - } - - /** - * @return ConstraintViolationListInterface - */ - public function getViolations() - { - return $this->violations; - } -} diff --git a/src/Middleware/SecurityMiddleware.php b/src/Middleware/SecurityMiddleware.php deleted file mode 100644 index 3682814..0000000 --- a/src/Middleware/SecurityMiddleware.php +++ /dev/null @@ -1,41 +0,0 @@ -authorizationChecker = $authorizationChecker; - } - - /** - * @param object $command - * @param callable $next - * - * @return mixed - */ - public function execute($command, callable $next) - { - if ($this->authorizationChecker->isGranted('handle', $command)) { - return $next($command); - } - - throw new AccessDeniedException( - sprintf('The current user is not allowed to handle command of type \'%s\'', get_class($command)) - ); - } -} - diff --git a/src/Middleware/ValidatorMiddleware.php b/src/Middleware/ValidatorMiddleware.php deleted file mode 100644 index e8eb1c1..0000000 --- a/src/Middleware/ValidatorMiddleware.php +++ /dev/null @@ -1,42 +0,0 @@ -validator = $validator; - } - - /** - * @param object $command - * @param callable $next - * - * @return mixed - * - * @throws InvalidCommandException - */ - public function execute($command, callable $next) - { - $constraintViolations = $this->validator->validate($command); - - if (count($constraintViolations) > 0) { - throw InvalidCommandException::onCommand($command, $constraintViolations); - } - - return $next($command); - } -} - diff --git a/src/Resources/config/services/services.yml b/src/Resources/config/services/services.yml index fb4ea5c..7f438b2 100644 --- a/src/Resources/config/services/services.yml +++ b/src/Resources/config/services/services.yml @@ -1,31 +1,34 @@ services: - tactician.middleware.locking: - class: League\Tactician\Plugins\LockingMiddleware + + # The standard Handler class name inflectors + tactician.handler.class_name_inflector.suffix.handler: + class: League\Tactician\Handler\Mapping\ClassName\Suffix + arguments: + $suffix: 'Handler' # The standard Handler method name inflectors tactician.handler.method_name_inflector.handle: - class: League\Tactician\Handler\MethodNameInflector\HandleInflector - - tactician.handler.method_name_inflector.class_name: - class: League\Tactician\Handler\MethodNameInflector\ClassNameInflector - - tactician.handler.method_name_inflector.handle_class_name: - class: League\Tactician\Handler\MethodNameInflector\HandleClassNameInflector + class: League\Tactician\Handler\Mapping\MethodName\Handle tactician.handler.method_name_inflector.handle_class_name_without_suffix: - class: League\Tactician\Handler\MethodNameInflector\HandleClassNameWithoutSuffixInflector + class: League\Tactician\Handler\Mapping\MethodName\HandleClassNameWithoutSuffix + + tactician.handler.method_name_inflector.handle_last_part_of_class_name: + class: League\Tactician\Handler\Mapping\MethodName\HandleLastPartOfClassName tactician.handler.method_name_inflector.invoke: - class: League\Tactician\Handler\MethodNameInflector\InvokeInflector + class: League\Tactician\Handler\Mapping\MethodName\Invoke - # The CommandNameExtractors in Tactician core - tactician.handler.command_name_extractor.class_name: - class: League\Tactician\Handler\CommandNameExtractor\ClassNameExtractor + tactician.handler.method_name_inflector.last_part_of_class_name: + class: League\Tactician\Handler\Mapping\MethodName\LastPartOfClassName - tactician.plugins.named_command.extractor: - class: League\Tactician\Plugins\NamedCommand\NamedCommandExtractor + tactician.handler.command_handler_mapping.map_by_naming_convention: + class: League\Tactician\Handler\Mapping\MapByNamingConvention + arguments: + $classNameInflector: '@tactician.handler.class_name_inflector.suffix.handler' + $methodNameInflector: '@tactician.handler.method_name_inflector.handle' tactician.command.debug: - class: League\Tactician\Bundle\Command\DebugCommand + class: League\Tactician\Bundle\Console\DebugCommand tags: - { name: console.command } diff --git a/src/Security/Voter/HandleCommandVoter.php b/src/Security/Voter/HandleCommandVoter.php deleted file mode 100644 index a608d05..0000000 --- a/src/Security/Voter/HandleCommandVoter.php +++ /dev/null @@ -1,91 +0,0 @@ -decisionManager = $decisionManager; - $this->commandRoleMapping = $commandRoleMapping; - } - - /** - * The voter supports checking handle commands - * - * @param string $attribute - * @param object $subject - * - * @return bool - */ - protected function supports($attribute, $subject): bool - { - return $attribute === 'handle' && is_object($subject); - } - - /** - * Checks if the currently logged on user may handle $subject. - * - * @param string $attribute - * @param mixed $subject - * @param TokenInterface $token - * - * @return bool - */ - protected function voteOnAttribute($attribute, $subject, TokenInterface $token) - { - $allowedRoles = $this->getAllowedRoles(get_class($subject)); - - if (count($allowedRoles) > 0) { - return $this->decisionManager->decide($token, $allowedRoles); - } - - // default conclusion is access denied - return false; - } - - /** - * Gets the roles allowed to handle a command of $type - * - * @param string $type - * - * @return array - */ - private function getAllowedRoles(string $type) - { - if (array_key_exists($type, $this->commandRoleMapping)) { - return $this->commandRoleMapping[$type]; - } - - return []; - } -} diff --git a/src/TacticianBundle.php b/src/TacticianBundle.php index 446a844..aa6023d 100755 --- a/src/TacticianBundle.php +++ b/src/TacticianBundle.php @@ -2,48 +2,21 @@ namespace League\Tactician\Bundle; -use League\Tactician\Bundle\DependencyInjection\HandlerMapping\ClassNameMapping; -use League\Tactician\Bundle\DependencyInjection\HandlerMapping\CompositeMapping; -use League\Tactician\Bundle\DependencyInjection\HandlerMapping\HandlerMapping; -use League\Tactician\Bundle\DependencyInjection\HandlerMapping\TypeHintMapping; -use Symfony\Component\DependencyInjection\ContainerBuilder; use League\Tactician\Bundle\DependencyInjection\Compiler; use League\Tactician\Bundle\DependencyInjection\TacticianExtension; +use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\HttpKernel\Bundle\Bundle; -class TacticianBundle extends Bundle +final class TacticianBundle extends Bundle { - /** - * @var HandlerMapping - */ - private $handlerMapping; - - public function __construct(HandlerMapping $handlerMapping = null) - { - if ($handlerMapping === null) { - $handlerMapping = static::defaultMappingStrategy(); - } - - $this->handlerMapping = $handlerMapping; - } - - - public function build(ContainerBuilder $container) + public function build(ContainerBuilder $container) : void { parent::build($container); - $container->addCompilerPass(new Compiler\DoctrineMiddlewarePass()); - $container->addCompilerPass(new Compiler\ValidatorMiddlewarePass()); - $container->addCompilerPass(new Compiler\SecurityMiddlewarePass()); - $container->addCompilerPass(new Compiler\CommandHandlerPass($this->handlerMapping)); + $container->addCompilerPass(new Compiler\CommandHandlerPass()); } public function getContainerExtension() { return new TacticianExtension(); } - - public static function defaultMappingStrategy(): HandlerMapping - { - return new CompositeMapping(new TypeHintMapping(), new ClassNameMapping()); - } } diff --git a/tests/DependencyInjection/Compiler/BusBuilder/BusBuilderTest.php b/tests/DependencyInjection/Compiler/BusBuilder/BusBuilderTest.php index 0fa3215..03987f2 100644 --- a/tests/DependencyInjection/Compiler/BusBuilder/BusBuilderTest.php +++ b/tests/DependencyInjection/Compiler/BusBuilder/BusBuilderTest.php @@ -4,65 +4,47 @@ namespace League\Tactician\Bundle\Tests\DependencyInjection\Compiler\BusBuilder; use League\Tactician\Bundle\DependencyInjection\Compiler\BusBuilder\BusBuilder; -use League\Tactician\Bundle\Handler\ContainerBasedHandlerLocator; -use League\Tactician\Container\ContainerLocator; use PHPUnit\Framework\TestCase; use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\ServiceLocator; final class BusBuilderTest extends TestCase { - public function test_default_name_generates_expected_ids() + public function test_default_name_generates_expected_ids() : void { - $builder = new BusBuilder('default', 'some.method.inflector', ['middleware1', 'middleware2']); + $builder = new BusBuilder('default', 'some.command_handler_mapping', ['middleware1', 'middleware2']); - $this->assertEquals('default', $builder->id()); - $this->assertEquals('tactician.commandbus.default', $builder->serviceId()); - $this->assertEquals('tactician.commandbus.default.handler.locator', $builder->locatorServiceId()); - $this->assertEquals('tactician.commandbus.default.middleware.command_handler', $builder->commandHandlerMiddlewareId()); + self::assertEquals('default', $builder->id()); + self::assertEquals('tactician.commandbus.default', $builder->serviceId()); + self::assertEquals('tactician.commandbus.default.middleware.command_handler', $builder->commandHandlerMiddlewareId()); } - public function test_alternate_name_generates_expected_ids() + public function test_alternate_name_generates_expected_ids() : void { - $builder = new BusBuilder('foobar', 'some.method.inflector', ['middleware1', 'middleware2']); + $builder = new BusBuilder('foobar', 'some.command_handler_mapping', ['middleware1', 'middleware2']); - $this->assertEquals('foobar', $builder->id()); - $this->assertEquals('tactician.commandbus.foobar', $builder->serviceId()); - $this->assertEquals('tactician.commandbus.foobar.handler.locator', $builder->locatorServiceId()); - $this->assertEquals('tactician.commandbus.foobar.middleware.command_handler', $builder->commandHandlerMiddlewareId()); + self::assertEquals('foobar', $builder->id()); + self::assertEquals('tactician.commandbus.foobar', $builder->serviceId()); + self::assertEquals('tactician.commandbus.foobar.middleware.command_handler', $builder->commandHandlerMiddlewareId()); } - public function testProcess() + public function testProcess() : void { - $builder = new BusBuilder('default', 'some.method.inflector', ['middleware1', 'middleware2']); + $builder = new BusBuilder('default', 'some.command_handler_mapping', ['middleware1', 'middleware2']); - $builder->registerInContainer($container = new ContainerBuilder(), []); + $builder->registerInContainer($container = new ContainerBuilder()); - $this->busShouldBeCorrectlyRegisteredInContainer($container, 'default', 'some.method.inflector'); + $this->busShouldBeCorrectlyRegisteredInContainer($container, 'default', 'some.command_handler_mapping'); } - private function busShouldBeCorrectlyRegisteredInContainer(ContainerBuilder $container, $busId, $methodInflector) + private function busShouldBeCorrectlyRegisteredInContainer(ContainerBuilder $container, string $busId, string $commandHandlerMapping) : void { - $handlerLocatorId = "tactician.commandbus.$busId.handler.locator"; $handlerId = "tactician.commandbus.$busId.middleware.command_handler"; - if (class_exists(ServiceLocator::class)) { - $this->assertSame( - ServiceLocator::class, - $container->getDefinition("tactician.commandbus.$busId.handler.service_locator")->getClass() - ); - } - - $this->assertSame( - class_exists(ServiceLocator::class) ? ContainerLocator::class : ContainerBasedHandlerLocator::class, - $container->getDefinition($handlerLocatorId)->getClass() - ); - - $this->assertSame( - $methodInflector, - (string)$container + self::assertSame( + $commandHandlerMapping, + (string) $container ->getDefinition($handlerId) - ->getArgument(2) + ->getArgument(1) ); } } diff --git a/tests/DependencyInjection/Compiler/BusBuilder/BusBuildersFromConfigTest.php b/tests/DependencyInjection/Compiler/BusBuilder/BusBuildersFromConfigTest.php index 7f2c608..f06fbb3 100644 --- a/tests/DependencyInjection/Compiler/BusBuilder/BusBuildersFromConfigTest.php +++ b/tests/DependencyInjection/Compiler/BusBuilder/BusBuildersFromConfigTest.php @@ -3,13 +3,13 @@ namespace League\Tactician\Bundle\Tests\DependencyInjection\Compiler\BusBuilder; -use PHPUnit\Framework\TestCase; use League\Tactician\Bundle\DependencyInjection\Compiler\BusBuilder\BusBuilder; use League\Tactician\Bundle\DependencyInjection\Compiler\BusBuilder\BusBuildersFromConfig; +use PHPUnit\Framework\TestCase; final class BusBuildersFromConfigTest extends TestCase { - public function test_config_leads_to_builder_with_default_for_each_commandbus() + public function test_config_leads_to_builder_with_default_for_each_commandbus() : void { $builders = BusBuildersFromConfig::convert([ 'commandbus' => [ @@ -26,20 +26,20 @@ public function test_config_leads_to_builder_with_default_for_each_commandbus() ], ]); - $this->assertEquals( - new BusBuilder('default', BusBuildersFromConfig::DEFAULT_METHOD_INFLECTOR, ['my.middleware']), + self::assertEquals( + new BusBuilder('default', BusBuildersFromConfig::DEFAULT_COMMAND_HANDLER_MAPPING, ['my.middleware']), $builders->getIterator()['default'] ); - $this->assertEquals( - new BusBuilder('other', BusBuildersFromConfig::DEFAULT_METHOD_INFLECTOR, ['my.other.middleware']), + self::assertEquals( + new BusBuilder('other', BusBuildersFromConfig::DEFAULT_COMMAND_HANDLER_MAPPING, ['my.other.middleware']), $builders->getIterator()['other'] ); } - public function test_default_method_inflector_can_be_overrided() + public function test_default_command_handler_mapping_can_be_overrided() : void { $builders = BusBuildersFromConfig::convert([ - 'method_inflector' => 'other.inflector', + 'command_handler_mapping' => 'other.mapping', 'commandbus' => [ 'default' => [ 'middleware' => [ @@ -54,16 +54,17 @@ public function test_default_method_inflector_can_be_overrided() ], ]); - $this->assertEquals( - new BusBuilder('default', 'other.inflector', ['my.middleware']), + + self::assertEquals( + new BusBuilder('default', 'other.mapping', ['my.middleware']), $builders->getIterator()['default'] ); } - public function test_method_inflector_of_each_bus_can_be_overrided() + public function test_command_handler_mapping_of_each_bus_can_be_overrided() : void { $builders = BusBuildersFromConfig::convert([ - 'method_inflector' => 'other.inflector', + 'command_handler_mapping' => 'other.mapping', 'commandbus' => [ 'default' => [ 'middleware' => [ @@ -71,7 +72,7 @@ public function test_method_inflector_of_each_bus_can_be_overrided() ], ], 'other' => [ - 'method_inflector' => 'bus2.inflector', + 'command_handler_mapping' => 'bus2.mapping', 'middleware' => [ 'my.other.middleware', ], @@ -79,13 +80,13 @@ public function test_method_inflector_of_each_bus_can_be_overrided() ], ]); - $this->assertEquals( - new BusBuilder('other', 'bus2.inflector', ['my.other.middleware']), + self::assertEquals( + new BusBuilder('other', 'bus2.mapping', ['my.other.middleware']), $builders->getIterator()['other'] ); } - public function test_default_bus_is_set() + public function test_default_bus_is_set() : void { $builders = BusBuildersFromConfig::convert([ 'commandbus' => [ @@ -102,13 +103,13 @@ public function test_default_bus_is_set() ], ]); - $this->assertEquals( - new BusBuilder('default', BusBuildersFromConfig::DEFAULT_METHOD_INFLECTOR, ['my.middleware']), + self::assertEquals( + new BusBuilder('default', BusBuildersFromConfig::DEFAULT_COMMAND_HANDLER_MAPPING, ['my.middleware']), $builders->defaultBus() ); } - public function test_default_bus_can_be_overrided() + public function test_default_bus_can_be_overrided() : void { $builders = BusBuildersFromConfig::convert([ 'default_bus' => 'other', @@ -126,8 +127,8 @@ public function test_default_bus_can_be_overrided() ], ]); - $this->assertEquals( - new BusBuilder('other', BusBuildersFromConfig::DEFAULT_METHOD_INFLECTOR, ['my.other.middleware']), + self::assertEquals( + new BusBuilder('other', BusBuildersFromConfig::DEFAULT_COMMAND_HANDLER_MAPPING, ['my.other.middleware']), $builders->defaultBus() ); } diff --git a/tests/DependencyInjection/Compiler/BusBuilder/BusBuildersTest.php b/tests/DependencyInjection/Compiler/BusBuilder/BusBuildersTest.php index b4b0278..316b188 100644 --- a/tests/DependencyInjection/Compiler/BusBuilder/BusBuildersTest.php +++ b/tests/DependencyInjection/Compiler/BusBuilder/BusBuildersTest.php @@ -8,38 +8,39 @@ use League\Tactician\Bundle\DependencyInjection\DuplicatedCommandBusId; use League\Tactician\Bundle\DependencyInjection\HandlerMapping\Routing; use League\Tactician\Bundle\DependencyInjection\InvalidCommandBusId; +use PHPUnit\Framework\TestCase; -final class BusBuildersTest extends \PHPUnit_Framework_TestCase +final class BusBuildersTest extends TestCase { - public function test_can_iterate_over_builders() + public function test_can_iterate_over_builders() : void { $builders = new BusBuilders( - list($a, $b) = $this->buildersNamed('foo', 'bar'), + [$a, $b] = $this->buildersNamed('foo', 'bar'), 'foo' ); - $this->assertEquals(['foo' => $a, 'bar' => $b], iterator_to_array($builders)); + self::assertEquals(['foo' => $a, 'bar' => $b], iterator_to_array($builders)); } - public function test_default_builder_must_be_an_id_that_actually_exists() + public function test_default_builder_must_be_an_id_that_actually_exists() : void { $this->expectException(InvalidCommandBusId::class); $this->builders(['bus1'], 'some_bus_that_does_not_exist'); } - public function test_two_buses_can_not_have_the_same_id() + public function test_two_buses_can_not_have_the_same_id() : void { $this->expectException(DuplicatedCommandBusId::class); $this->builders(['bus1', 'bus1']); } - public function test_blank_routing_has_ids() + public function test_blank_routing_has_ids() : void { $builders = $this->builders(['bus1', 'bus2']); - $this->assertEquals(new Routing(['bus1', 'bus2']), $builders->createBlankRouting()); + self::assertEquals(new Routing(['bus1', 'bus2']), $builders->createBlankRouting()); } private function builders($ids, $default = 'bus1'): BusBuilders @@ -50,7 +51,7 @@ private function builders($ids, $default = 'bus1'): BusBuilders private function buildersNamed(string ...$ids): array { return array_map( - function (string $id) { + static function (string $id) : BusBuilder { return new BusBuilder($id, 'some.inflector', []); }, $ids diff --git a/tests/DependencyInjection/Compiler/CommandHandlerPassTest.php b/tests/DependencyInjection/Compiler/CommandHandlerPassTest.php index baa2f2e..6364e0b 100644 --- a/tests/DependencyInjection/Compiler/CommandHandlerPassTest.php +++ b/tests/DependencyInjection/Compiler/CommandHandlerPassTest.php @@ -2,7 +2,7 @@ namespace League\Tactician\Bundle\Tests\DependencyInjection\Compiler; -use League\Tactician\Bundle\Command\DebugCommand; +use League\Tactician\Bundle\Console\DebugCommand; use League\Tactician\Bundle\DependencyInjection\Compiler\CommandHandlerPass; use League\Tactician\Bundle\DependencyInjection\HandlerMapping\ClassNameMapping; use League\Tactician\Bundle\DependencyInjection\HandlerMapping\HandlerMapping; @@ -13,19 +13,19 @@ use Prophecy\Argument; use Symfony\Component\DependencyInjection\ContainerBuilder; -class CommandHandlerPassTest extends TestCase +final class CommandHandlerPassTest extends TestCase { - /** - * @var HandlerMapping - */ - private $mappingStrategy; - - protected function setUp() - { - $this->mappingStrategy = new ClassNameMapping(); - } - - public function testAddingSingleDefaultBus() +// /** +// * @var HandlerMapping +// */ +// private $mappingStrategy; +// +// protected function setUp() : void +// { +// $this->mappingStrategy = new ClassNameMapping(); +// } + + public function testAddingSingleDefaultBus() : void { $container = $this->containerWithConfig( [ @@ -36,14 +36,14 @@ public function testAddingSingleDefaultBus() ] ); - (new CommandHandlerPass($this->mappingStrategy))->process($container); + (new CommandHandlerPass())->process($container); - $this->assertTrue($container->hasDefinition('tactician.commandbus.default')); + self::assertTrue($container->hasDefinition('tactician.commandbus.default')); $this->assertDefaultAliasesAreDeclared($container, 'default'); } - public function testProcessAddsLocatorAndHandlerDefinitionForTaggedBuses() + public function testProcessAddsHandlerDefinitionForTaggedBuses() : void { $container = $this->containerWithConfig( [ @@ -57,16 +57,16 @@ public function testProcessAddsLocatorAndHandlerDefinitionForTaggedBuses() ] ); - (new CommandHandlerPass($this->mappingStrategy))->process($container); + (new CommandHandlerPass())->process($container); - $this->assertTrue($container->hasDefinition('tactician.commandbus.default')); - $this->assertTrue($container->hasDefinition('tactician.commandbus.custom_bus')); - $this->assertTrue($container->hasDefinition('tactician.commandbus.other_bus')); + self::assertTrue($container->hasDefinition('tactician.commandbus.default')); + self::assertTrue($container->hasDefinition('tactician.commandbus.custom_bus')); + self::assertTrue($container->hasDefinition('tactician.commandbus.other_bus')); $this->assertDefaultAliasesAreDeclared($container, 'custom_bus'); } - public function test_handler_mapping_is_called() + public function test_handler_mapping_is_called() : void { $container = $this->containerWithConfig( [ @@ -82,7 +82,7 @@ public function test_handler_mapping_is_called() (new CommandHandlerPass($mapping->reveal()))->process($container); - $this->assertEquals( + self::assertEquals( [FakeCommand::class => 'some.handler'], $container->getDefinition('tactician.commandbus.default.handler.locator')->getArgument(1) ); @@ -110,11 +110,11 @@ public function test_handler_mapping_is_kept_bus_specific() (new CommandHandlerPass($mapping->reveal()))->process($container); - $this->assertEquals( + self::assertEquals( [FakeCommand::class => 'some.handler.a', OtherFakeCommand::class => 'some.other.handler'], $container->getDefinition('tactician.commandbus.bus.a.handler.locator')->getArgument(1) ); - $this->assertEquals( + self::assertEquals( [FakeCommand::class => 'some.handler.b', OtherFakeCommand::class => 'some.other.handler'], $container->getDefinition('tactician.commandbus.bus.b.handler.locator')->getArgument(1) ); @@ -144,7 +144,7 @@ public function test_handler_wires_debug_command() (new CommandHandlerPass($mapping->reveal()))->process($container); - $this->assertSame( + self::assertSame( [ [ 'bus.a' => $routing->commandToServiceMapping('bus.a'), @@ -155,7 +155,7 @@ public function test_handler_wires_debug_command() ); } - private function containerWithConfig($config) + private function containerWithConfig($config) : ContainerBuilder { $container = new ContainerBuilder(); @@ -164,22 +164,14 @@ private function containerWithConfig($config) return $container; } - /** - * @param $container - */ - protected function assertDefaultAliasesAreDeclared(ContainerBuilder $container, string $defaultBusId) + protected function assertDefaultAliasesAreDeclared(ContainerBuilder $container, string $defaultBusId) : void { - $this->assertSame( + self::assertSame( $container->findDefinition('tactician.commandbus'), $container->getDefinition("tactician.commandbus.$defaultBusId") ); - $this->assertSame( - $container->findDefinition('tactician.handler.locator.symfony'), - $container->getDefinition("tactician.commandbus.$defaultBusId.handler.locator") - ); - - $this->assertSame( + self::assertSame( $container->findDefinition('tactician.middleware.command_handler'), $container->getDefinition("tactician.commandbus.$defaultBusId.middleware.command_handler") ); diff --git a/tests/DependencyInjection/Compiler/DoctrineMiddlewarePassTest.php b/tests/DependencyInjection/Compiler/DoctrineMiddlewarePassTest.php deleted file mode 100644 index 3ee4765..0000000 --- a/tests/DependencyInjection/Compiler/DoctrineMiddlewarePassTest.php +++ /dev/null @@ -1,91 +0,0 @@ -addCompilerPass(new DoctrineMiddlewarePass()); - } - - public function test_registering_middleware_for_multiple_entity_managers() - { - if (!class_exists(TransactionMiddleware::class)) { - $this->markTestSkipped('"league/tactician-doctrine" is not installed'); - } - - $this->setParameter( - 'doctrine.entity_managers', - [ - 'default' => 'doctrine.orm.default_entity_manager', - 'second' => 'doctrine.orm.second_entity_manager', - ] - ); - $this->setParameter('doctrine.default_entity_manager', 'default'); - - $this->compile(); - - $this->assertContainerBuilderHasService('tactician.middleware.doctrine.default', TransactionMiddleware::class); - $this->assertContainerBuilderHasService('tactician.middleware.doctrine.second', TransactionMiddleware::class); - $this->assertContainerBuilderHasServiceDefinitionWithArgument('tactician.middleware.doctrine.default', 0, new Reference('doctrine.orm.default_entity_manager')); - $this->assertContainerBuilderHasServiceDefinitionWithArgument('tactician.middleware.doctrine.second', 0, new Reference('doctrine.orm.second_entity_manager')); - $this->assertContainerBuilderHasAlias('tactician.middleware.doctrine', 'tactician.middleware.doctrine.default'); - } - - public function test_do_not_process_when_there_are_no_entity_managers() - { - if (!class_exists(TransactionMiddleware::class)) { - $this->markTestSkipped('"league/tactician-doctrine" is not installed'); - } - - $this->compile(); - - $this->assertContainerBuilderNotHasService('tactician.middleware.doctrine'); - } - - public function test_do_not_process_when_tactician_doctrine_is_not_installed() - { - if (class_exists(TransactionMiddleware::class)) { - $this->markTestSkipped('"league/tactician-doctrine" is installed'); - } - - $this->setParameter('doctrine.entity_managers', ['default' => 'doctrine.orm.default_entity_manager']); - $this->setParameter('doctrine.default_entity_manager', 'default'); - - $this->compile(); - - $this->assertContainerBuilderNotHasService('tactician.middleware.doctrine'); - } - - public function test_rollback_only_middleware_is_added() - { - if (!class_exists(RollbackOnlyTransactionMiddleware::class)) { - $this->markTestSkipped('"league/tactician-doctrine" is not installed'); - } - - $this->setParameter( - 'doctrine.entity_managers', - [ - 'default' => 'doctrine.orm.default_entity_manager', - 'second' => 'doctrine.orm.second_entity_manager', - ] - ); - $this->setParameter('doctrine.default_entity_manager', 'default'); - - $this->compile(); - - $this->assertContainerBuilderHasService('tactician.middleware.doctrine_rollback_only.default', RollbackOnlyTransactionMiddleware::class); - $this->assertContainerBuilderHasService('tactician.middleware.doctrine_rollback_only.second', RollbackOnlyTransactionMiddleware::class); - $this->assertContainerBuilderHasServiceDefinitionWithArgument('tactician.middleware.doctrine_rollback_only.default', 0, new Reference('doctrine.orm.default_entity_manager')); - $this->assertContainerBuilderHasServiceDefinitionWithArgument('tactician.middleware.doctrine_rollback_only.second', 0, new Reference('doctrine.orm.second_entity_manager')); - $this->assertContainerBuilderHasAlias('tactician.middleware.doctrine_rollback_only', 'tactician.middleware.doctrine_rollback_only.default'); - } -} diff --git a/tests/DependencyInjection/Compiler/SecurityMiddlewarePassTest.php b/tests/DependencyInjection/Compiler/SecurityMiddlewarePassTest.php deleted file mode 100644 index 2e66ab3..0000000 --- a/tests/DependencyInjection/Compiler/SecurityMiddlewarePassTest.php +++ /dev/null @@ -1,33 +0,0 @@ -register('security.authorization_checker'); - - (new SecurityMiddlewarePass())->process($container); - - $definition = $container->getDefinition(SecurityMiddlewarePass::SERVICE_ID); - $this->assertSame(SecurityMiddleware::class, $definition->getClass()); - $this->assertEquals([new Reference('security.authorization_checker')], $definition->getArguments()); - } - - public function testProcessReturnsIfValidatorDoesNotExist() - { - $container = new ContainerBuilder(); - - (new SecurityMiddlewarePass())->process($container); - - $this->assertFalse($container->hasDefinition(SecurityMiddlewarePass::SERVICE_ID)); - } -} diff --git a/tests/DependencyInjection/Compiler/ValidatorMiddlewarePassTest.php b/tests/DependencyInjection/Compiler/ValidatorMiddlewarePassTest.php deleted file mode 100644 index 2f31367..0000000 --- a/tests/DependencyInjection/Compiler/ValidatorMiddlewarePassTest.php +++ /dev/null @@ -1,33 +0,0 @@ -register('validator'); - - (new ValidatorMiddlewarePass())->process($container); - - $definition = $container->getDefinition(ValidatorMiddlewarePass::SERVICE_ID); - $this->assertSame(ValidatorMiddleware::class, $definition->getClass()); - $this->assertEquals([new Reference('validator')], $definition->getArguments()); - } - - public function testProcessReturnsIfAuthorizationCheckerDoesNotExist() - { - $container = new ContainerBuilder(); - - (new ValidatorMiddlewarePass())->process($container); - - $this->assertFalse($container->hasDefinition(ValidatorMiddlewarePass::SERVICE_ID)); - } -} diff --git a/tests/DependencyInjection/ConfigurationTest.php b/tests/DependencyInjection/ConfigurationTest.php index e2fd71a..fef0885 100644 --- a/tests/DependencyInjection/ConfigurationTest.php +++ b/tests/DependencyInjection/ConfigurationTest.php @@ -1,63 +1,58 @@ assertConfigurationIsValid([]); } - public function testDefaultConfiguration() + public function testDefaultConfiguration() : void { $this->assertProcessedConfigurationEquals( [], [ - 'commandbus' => ['default' => ['middleware' => ['tactician.middleware.command_handler']]], - 'default_bus' => 'default', - 'method_inflector' => 'tactician.handler.method_name_inflector.handle', - 'security' => [], - 'logger_formatter' => 'tactician.logger.class_properties_formatter' + 'commandbus' => ['default' => ['middleware' => ['tactician.middleware.command_handler']]], + 'default_bus' => 'default', + 'command_handler_mapping' => 'tactician.handler.command_handler_mapping.map_by_naming_convention', ] ); } - public function testSimpleMiddleware() + public function testSimpleMiddleware() : void { - $this->assertConfigurationIsValid([ - 'tactician' => [ - 'commandbus' => [ - 'default' => [ - 'middleware' => [ - 'my_middleware' => 'some_middleware', - 'my_middleware2' => 'some_middleware', - ] - ] - ] + $this->assertConfigurationIsValid( + [ + 'tactician' => [ + 'commandbus' => [ + 'default' => [ + 'middleware' => [ + 'my_middleware' => 'some_middleware', + 'my_middleware2' => 'some_middleware', + ], + ], + ], + ], ] - ]); + ); } - public function testMiddlewareMustBeScalar() + public function testMiddlewareMustBeScalar() : void { $this->assertConfigurationIsInvalid( [ @@ -67,29 +62,29 @@ public function testMiddlewareMustBeScalar() 'middleware' => [ 'my_middleware' => [], 'my_middleware2' => 'some_middleware', - ] - ] - ] - ] + ], + ], + ], + ], ], 'Invalid type for path "tactician.commandbus.default.middleware.my_middleware". Expected scalar, but got array.' ); } - public function testDefaultMiddlewareMustExist() + public function testDefaultMiddlewareMustExist() : void { $this->assertConfigurationIsInvalid( [ 'tactician' => [ 'default_bus' => 'foo', - 'commandbus' => [ + 'commandbus' => [ 'bar' => [ 'middleware' => [ - 'my_middleware' => 'some_middleware', - ] - ] - ] - ] + 'my_middleware' => 'some_middleware', + ], + ], + ], + ], ], 'The default_bus "foo" was not defined as a command bus.' ); @@ -100,17 +95,17 @@ public function testDefaultMiddlewareMustExist() 'commandbus' => [ 'bar' => [ 'middleware' => [ - 'my_middleware' => 'some_middleware', - ] - ] - ] - ] + 'my_middleware' => 'some_middleware', + ], + ], + ], + ], ], 'The default_bus "default" was not defined as a command bus.' ); } - public function testMiddlewareDefinitionCannotBeEmpty() + public function testMiddlewareDefinitionCannotBeEmpty() : void { $this->assertConfigurationIsInvalid( [ @@ -118,10 +113,10 @@ public function testMiddlewareDefinitionCannotBeEmpty() 'commandbus' => [ 'default' => [ 'middleware' => [ - ] - ] - ] - ] + ], + ], + ], + ], ], 'The path "tactician.commandbus.default.middleware" should have at least 1 element(s) defined.' ); @@ -132,16 +127,16 @@ public function testMiddlewareDefinitionCannotBeEmpty() 'commandbus' => [ 'foo' => [ 'middleware' => [ - ] - ] - ] - ] + ], + ], + ], + ], ], 'The path "tactician.commandbus.foo.middleware" should have at least 1 element(s) defined.' ); } - public function testCommandHandlerMiddlewareIfPresentAndNotLastIsInvalid() + public function testCommandHandlerMiddlewareIfPresentAndNotLastIsInvalid() : void { $this->assertConfigurationIsInvalid( [ @@ -152,16 +147,16 @@ public function testCommandHandlerMiddlewareIfPresentAndNotLastIsInvalid() 'tactician.middleware.command_handler', 'my_middleware.custom.stuff', - ] - ] - ] - ] + ], + ], + ], + ], ], '"tactician.middleware.command_handler" should be the last middleware loaded when it is used.' ); } - public function testCommandHandlerMiddlewarePresentAndLastIsValid() + public function testCommandHandlerMiddlewarePresentAndLastIsValid() : void { $this->assertConfigurationIsValid( [ @@ -171,37 +166,19 @@ public function testCommandHandlerMiddlewarePresentAndLastIsValid() 'middleware' => [ 'my_middleware.custom.stuff', 'tactician.middleware.command_handler', - ] - ] - ] - ] - ] - ); - } - public function testCommandHandlerMiddlewareNotPresentDoesNotAffectValidation() - { - $this->assertConfigurationIsValid( - [ - 'tactician' => [ - 'commandbus' => [ - 'default' => [ - 'middleware' => [ - 'my_middleware.custom.stuff', - 'my_middleware.custom.other_stuff', - ] - ] - ] - ] + ], + ], + ], + ], ] ); } - public function testCustomMethodInflectorCanBeSet() + public function testCommandHandlerMiddlewareNotPresentDoesNotAffectValidation() : void { $this->assertConfigurationIsValid( [ 'tactician' => [ - 'method_inflector' => 'some.inflector.service', 'commandbus' => [ 'default' => [ 'middleware' => [ @@ -209,59 +186,33 @@ public function testCustomMethodInflectorCanBeSet() 'my_middleware.custom.other_stuff', ], ], - 'second' => [ - 'middleware' => [ - 'my_middleware.custom.stuff', - 'my_middleware.custom.other_stuff', - ] - ] - ] - ] - ] - ); - } - - public function testSecurityConfiguration() - { - $this->assertConfigurationIsValid([ - 'tactician' => [ - 'commandbus' => [ - 'default' => [ - 'middleware' => [ - 'my_middleware' => 'some_middleware', - 'my_middleware2' => 'some_middleware', - ] - ] + ], ], - 'security' => [ - 'Some\Command' => ['ROLE_USER'], - 'Some\Other\Command' => ['ROLE_ADMIN'], - ] ] - ]); + ); } - public function testCustomLoggerFormatterCanBeSet() + public function testCustomCommandHandlerMappingCanBeSet() : void { $this->assertConfigurationIsValid( [ 'tactician' => [ - 'logger_formatter' => 'some.formatter.service', - 'commandbus' => [ + 'command_handler_mapping' => 'some.command_handler_mapping.service', + 'commandbus' => [ 'default' => [ 'middleware' => [ 'my_middleware.custom.stuff', 'my_middleware.custom.other_stuff', ], ], - 'second' => [ + 'second' => [ 'middleware' => [ 'my_middleware.custom.stuff', 'my_middleware.custom.other_stuff', - ] - ] - ] - ] + ], + ], + ], + ], ] ); } diff --git a/tests/DependencyInjection/HandlerMapping/ClassNameMappingTest.php b/tests/DependencyInjection/HandlerMapping/ClassNameMappingTest.php deleted file mode 100644 index 55893fc..0000000 --- a/tests/DependencyInjection/HandlerMapping/ClassNameMappingTest.php +++ /dev/null @@ -1,105 +0,0 @@ -setDefinition('some.handler', new Definition(SomeHandler::class)) - ->addTag('tactician.handler', ['foo' => 'bar']); - - $routing = (new ClassNameMapping())->build($builder, new Routing(['default'])); - - $this->assertEquals([], $routing->commandToServiceMapping('default')); - } - - public function test_will_resolve_parameters_in_command_attribute() - { - $builder = new ContainerBuilder(); - $builder->setParameter('fake_command_class', FakeCommand::class); - $builder - ->setDefinition('some.handler', new Definition(SomeHandler::class)) - ->addTag('tactician.handler', ['command' => '%fake_command_class%']); - - $routing = (new ClassNameMapping())->build($builder, new Routing(['default'])); - - $this->assertEquals([FakeCommand::class => 'some.handler'], $routing->commandToServiceMapping('default')); - } - - public function test_will_find_handler_for_defined_command() - { - $builder = new ContainerBuilder(); - $builder - ->setDefinition('some.handler', new Definition(SomeHandler::class)) - ->addTag('tactician.handler', ['command' => FakeCommand::class]); - - $routing = (new ClassNameMapping())->build($builder, new Routing(['default'])); - - $this->assertEquals([FakeCommand::class => 'some.handler'], $routing->commandToServiceMapping('default')); - } - - public function test_can_bind_to_specific_bus() - { - $builder = new ContainerBuilder(); - $builder - ->setDefinition('first.handler', new Definition(SomeHandler::class)) - ->addTag('tactician.handler', ['command' => FakeCommand::class, 'bus' => 'bus.a']); - - $builder - ->setDefinition('second.handler', new Definition(SomeHandler::class)) - ->addTag('tactician.handler', ['command' => OtherFakeCommand::class, 'bus' => 'bus.b']); - - $routing = (new ClassNameMapping())->build($builder, new Routing(['bus.a', 'bus.b'])); - - $this->assertEquals( - [ - FakeCommand::class => 'first.handler', - ], - $routing->commandToServiceMapping('bus.a') - ); - $this->assertEquals( - [OtherFakeCommand::class => 'second.handler'], - $routing->commandToServiceMapping('bus.b') - ); - } - - public function test_can_bind_to_multiple_buses() - { - $builder = new ContainerBuilder(); - $builder - ->setDefinition('first.handler', new Definition(SomeHandler::class)) - ->addTag('tactician.handler', ['command' => FakeCommand::class, 'bus' => 'bus.a']) - ->addTag('tactician.handler', ['command' => FakeCommand::class, 'bus' => 'bus.b']); - - $routing = (new ClassNameMapping())->build($builder, new Routing(['bus.a', 'bus.b'])); - - $this->assertEquals([FakeCommand::class => 'first.handler'], $routing->commandToServiceMapping('bus.a')); - $this->assertEquals([FakeCommand::class => 'first.handler'], $routing->commandToServiceMapping('bus.b')); - } - - public function test_will_error_when_given_invalid_bus() - { - $this->expectException(InvalidCommandBusId::class); - - $builder = new ContainerBuilder(); - $builder - ->setDefinition('first.handler', new Definition(SomeHandler::class)) - ->addTag('tactician.handler', ['command' => FakeCommand::class, 'bus' => 'bus.does.not.exist.mwhahahaha']); - - (new ClassNameMapping())->build($builder, new Routing(['bus.a', 'bus.b'])); - } -} diff --git a/tests/DependencyInjection/HandlerMapping/CompositeMappingTest.php b/tests/DependencyInjection/HandlerMapping/CompositeMappingTest.php deleted file mode 100644 index a63dc8c..0000000 --- a/tests/DependencyInjection/HandlerMapping/CompositeMappingTest.php +++ /dev/null @@ -1,51 +0,0 @@ -build( - new ContainerBuilder(), - new Routing(['default_bus_id']) - ); - - $this->assertEquals( - [ - FakeCommand::class => 'fake.command.handler', - OtherFakeCommand::class => 'other.fake.command.handler' - ], - $finalRouting->commandToServiceMapping('default_bus_id') - ); - } -} - -class MockMapping implements HandlerMapping -{ - private $fqcn; - private $serviceId; - - public function __construct($fqcn, $serviceId) - { - $this->fqcn = $fqcn; - $this->serviceId = $serviceId; - } - - public function build(ContainerBuilder $container, Routing $routing): Routing - { - $routing->routeToAllBuses($this->fqcn, $this->serviceId); - return $routing; - } -} diff --git a/tests/DependencyInjection/HandlerMapping/RoutingTest.php b/tests/DependencyInjection/HandlerMapping/RoutingTest.php deleted file mode 100644 index 4e2dea3..0000000 --- a/tests/DependencyInjection/HandlerMapping/RoutingTest.php +++ /dev/null @@ -1,74 +0,0 @@ -routeToBus('bus1', FakeCommand::class, 'some.handler.1'); - $routing->routeToBus('bus2', OtherFakeCommand::class, 'some.handler.2'); - - $this->assertEquals([FakeCommand::class => 'some.handler.1'], $routing->commandToServiceMapping('bus1')); - $this->assertEquals([OtherFakeCommand::class => 'some.handler.2'], $routing->commandToServiceMapping('bus2')); - } - - public function test_routing_to_all_buses() - { - $routing = new Routing(['bus1', 'bus2']); - $routing->routeToAllBuses(FakeCommand::class, 'some.handler'); - - $this->assertEquals([FakeCommand::class => 'some.handler'], $routing->commandToServiceMapping('bus1')); - $this->assertEquals([FakeCommand::class => 'some.handler'], $routing->commandToServiceMapping('bus2')); - } - - public function test_mixture_of_broadcast_and_specific_routing_commands() - { - $routing = new Routing(['bus1', 'bus2']); - $routing->routeToAllBuses(FakeCommand::class, 'very.broad.handler'); - $routing->routeToBus('bus1', OtherFakeCommand::class, 'some.specific.handler'); - - $this->assertEquals( - [FakeCommand::class => 'very.broad.handler', OtherFakeCommand::class => 'some.specific.handler'], - $routing->commandToServiceMapping('bus1') - ); - $this->assertEquals([FakeCommand::class => 'very.broad.handler'], $routing->commandToServiceMapping('bus2')); - } - - /** - * @expectedException \League\Tactician\Bundle\DependencyInjection\InvalidCommandBusId - * @expectedExceptionMessage Could not find a command bus with id 'fake_bus'. Valid buses are: default - */ - public function test_can_not_get_mapping_for_unknown_bus() - { - $routing = new Routing(['default']); - $routing->commandToServiceMapping('fake_bus'); - } - - /** - * @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException - * @expectedExceptionMessage Can not route Legit\Class to some.handler.service, class Legit\Class does not exist! - */ - public function test_will_not_route_unknown_class_name() - { - $routing = new Routing(['default']); - $routing->routeToBus('default', 'Legit\Class', 'some.handler.service'); - } - - /** - * @expectedException \League\Tactician\Bundle\DependencyInjection\InvalidCommandBusId - * @expectedExceptionMessage Could not find a command bus with id 'bus3'. Valid buses are: bus1, bus2 - */ - public function test_will_not_accept_command_on_invalid_bus_id() - { - $routing = new Routing(['bus1', 'bus2']); - $routing->routeToBus('bus3', FakeCommand::class, 'some.handler.service'); - } -} diff --git a/tests/DependencyInjection/HandlerMapping/TypeHintMappingTest.php b/tests/DependencyInjection/HandlerMapping/TypeHintMappingTest.php deleted file mode 100644 index 1f78e01..0000000 --- a/tests/DependencyInjection/HandlerMapping/TypeHintMappingTest.php +++ /dev/null @@ -1,244 +0,0 @@ -setDefinition('some.handler', new Definition(InvokeHandler::class)) - ->addTag('tactician.handler', ['foo' => 'bar']); - - $routing = (new TypeHintMapping())->build($builder, new Routing(['default'])); - - $this->assertEquals([], $routing->commandToServiceMapping('default')); - } - - public function test_will_resolve_parameters_in_handler_class() - { - $builder = new ContainerBuilder(); - $builder->setParameter('handler_class', InvokeHandler::class); - $builder - ->setDefinition('some.handler', new Definition('%handler_class%')) - ->addTag('tactician.handler', ['typehints' => true]); - - $routing = (new TypeHintMapping())->build($builder, new Routing(['default'])); - - $this->assertEquals([FakeCommand::class => 'some.handler'], $routing->commandToServiceMapping('default')); - } - - /** - * @dataProvider simpleTestCases - */ - public function test_standard(string $handlerFQCN, array $expectedMapping) - { - $builder = new ContainerBuilder(); - $builder - ->setDefinition('some.handler', new Definition($handlerFQCN)) - ->addTag('tactician.handler', ['typehints' => true]); - - $routing = (new TypeHintMapping())->build($builder, new Routing(['default'])); - - $this->assertEquals($expectedMapping, $routing->commandToServiceMapping('default')); - } - - public function simpleTestCases() - { - return [ - 'can read __invoke magic method type hint' => [ - InvokeHandler::class, - [FakeCommand::class => 'some.handler'] - ], - 'takes unary methods but not those with multiple parameters' => [ - BasicHandler::class, - [FakeCommand::class => 'some.handler', OtherFakeCommand::class => 'some.handler'] - ], - 'can not exclude built-in objects unfortunately' => [ - DateTimeHandler::class, - [DateTime::class => 'some.handler'] - ], - 'will skip methods with no typehint' => [NoTypehintHandler::class, []], - 'will skip methods with an interface typehint' => [InterfaceTypehintHandler::class, []], - 'will not try to map scalar typehints' => [ScalarHandler::class, []], - 'will not use protected or private methods' => [ProtectedMethodHandler::class, []], - 'will not use constructor method' => [ConstructorHandler::class, []], - 'will not use static methods' => [StaticHandler::class, []], - 'will not use abstract methods' => [AbstractHandler::class, []], - 'will not use variadic methods' => [VariadicHandler::class, []] - ]; - } - - public function test_can_bind_to_specific_bus() - { - $builder = new ContainerBuilder(); - $builder - ->setDefinition('first.handler', new Definition(BasicHandler::class)) - ->addTag('tactician.handler', ['typehints' => true, 'bus' => 'bus.a']); - - $builder - ->setDefinition('second.handler', new Definition(DateTimeHandler::class)) - ->addTag('tactician.handler', ['typehints' => true, 'bus' => 'bus.b']); - - $routing = (new TypeHintMapping())->build($builder, new Routing(['bus.a', 'bus.b'])); - - $this->assertEquals( - [ - FakeCommand::class => 'first.handler', - OtherFakeCommand::class => 'first.handler' - ], - $routing->commandToServiceMapping('bus.a') - ); - $this->assertEquals( - [DateTime::class => 'second.handler'], - $routing->commandToServiceMapping('bus.b') - ); - } - - public function test_can_bind_to_multiple_buses() - { - $builder = new ContainerBuilder(); - $builder - ->setDefinition('first.handler', new Definition(BasicHandler::class)) - ->addTag('tactician.handler', ['typehints' => true, 'bus' => 'bus.a']) - ->addTag('tactician.handler', ['typehints' => true, 'bus' => 'bus.b']); - - $routing = (new TypeHintMapping())->build($builder, new Routing(['bus.a', 'bus.b'])); - - $expected = [ - FakeCommand::class => 'first.handler', - OtherFakeCommand::class => 'first.handler', - ]; - - $this->assertEquals($expected, $routing->commandToServiceMapping('bus.a')); - $this->assertEquals($expected, $routing->commandToServiceMapping('bus.b')); - } - - public function test_will_error_when_given_invalid_bus() - { - $this->expectException(InvalidCommandBusId::class); - - $builder = new ContainerBuilder(); - $builder - ->setDefinition('first.handler', new Definition(BasicHandler::class)) - ->addTag('tactician.handler', ['typehints' => true, 'bus' => 'bus.does.not.exist.mwhahahaha']); - - (new TypeHintMapping())->build($builder, new Routing(['bus.a', 'bus.b'])); - } -} - -class BasicHandler -{ - public function handle(FakeCommand $command) - { - } - - public function run(OtherFakeCommand $command) - { - } - - public function notACommand(FakeCommand $cmdA, OtherFakeCommand $cmdB) - { - } -} - -class VariadicHandler -{ - public function handle(FakeCommand ...$commands) - { - } -} - -class DateTimeHandler -{ - public function handle(DateTime $command) - { - } -} - -class StaticHandler -{ - public static function handle(FakeCommand $command) - { - } -} - -abstract class AbstractHandler -{ - abstract public function handle(FakeCommand $command); -} - -class ScalarHandler -{ - public function handle(string $someString) - { - } - - public function execute(int $foobar) - { - } - - public function that(callable $thing) - { - } -} - -interface ServiceInterface { - -} - -class InterfaceTypehintHandler -{ - public function interfaced(ServiceInterface $foo) - { - } -} - -class NoTypehintHandler -{ - public function handle($foo) - { - } -} - -class InvokeHandler -{ - public function __invoke(FakeCommand $command) - { - } -} - - -class ProtectedMethodHandler -{ - protected function handle(FakeCommand $command) - { - } - - private function execute(OtherFakeCommand $command) - { - } -} - -class ConstructorHandler -{ - public function __construct(SomeDependency $dependency) - { - } -} - -class SomeDependency -{ -} diff --git a/tests/DependencyInjection/TacticianExtensionTest.php b/tests/DependencyInjection/TacticianExtensionTest.php deleted file mode 100644 index 269a9fd..0000000 --- a/tests/DependencyInjection/TacticianExtensionTest.php +++ /dev/null @@ -1,77 +0,0 @@ - ['ROLE_USER'], 'Some\Other\Command' => ['ROLE_ADMIN']]; - - $this->load([ - 'commandbus' => [ - 'default' => [ - 'middleware' => [ - 'tactician.middleware.security', - 'tactician.middleware.command_handler', - ] - ] - ], - 'security' => $securitySettings - ]); - - $this->assertContainerBuilderHasServiceDefinitionWithArgument('tactician.middleware.security_voter', 1, $securitySettings); - $this->assertContainerBuilderHasServiceDefinitionWithTag('tactician.middleware.security_voter', 'security.voter'); - } - - public function testDefaultSecurityConfigurationIsAllowNothing() - { - $this->load([ - 'commandbus' => [ - 'default' => [ - 'middleware' => [ - 'tactician.middleware.security', - 'tactician.middleware.command_handler', - ] - ] - ] - ]); - - $this->assertContainerBuilderHasServiceDefinitionWithArgument('tactician.middleware.security_voter', 1, []); - $this->assertContainerBuilderHasServiceDefinitionWithTag('tactician.middleware.security_voter', 'security.voter'); - } - - public function testVoterIsNotLoadedWithoutSecurityMiddleware() - { - $this->load(); - - $this->assertContainerBuilderNotHasService('tactician.middleware.security_voter'); - } - - public function testLoggerMiddlewareIsCreated() - { - $this->load(); - - $this->assertContainerBuilderHasService('tactician.middleware.logger'); - $this->assertContainerBuilderHasService('tactician.logger.class_properties_formatter'); - $this->assertContainerBuilderHasService('tactician.logger.class_name_formatter'); - } -} diff --git a/tests/Handler/ContainerBasedHandlerLocatorTest.php b/tests/Handler/ContainerBasedHandlerLocatorTest.php deleted file mode 100644 index 70236b8..0000000 --- a/tests/Handler/ContainerBasedHandlerLocatorTest.php +++ /dev/null @@ -1,37 +0,0 @@ -register('fake_command_handler', 'stdClass')->setPublic(true); - $container->compile(); - - $locator = new ContainerBasedHandlerLocator($container, [ - 'FakeCommand' => 'fake_command_handler', - 'OtherCommand' => 'other_command_handler' - ]); - - $this->assertInstanceOf('stdClass', $locator->getHandlerForCommand('FakeCommand')); - } - - /** - * @expectedException \League\Tactician\Exception\MissingHandlerException - */ - public function testGetHandlerThrowsExceptionForNotFound() - { - $locator = new ContainerBasedHandlerLocator(new ContainerBuilder(), [ - 'OtherCommand' => 'my_bundle.order.id' - ]); - - $locator->getHandlerForCommand('MyFakeCommand'); - } - -} diff --git a/tests/Integration/BasicCommandAndBusMappingTest.php b/tests/Integration/BasicCommandAndBusMappingTest.php deleted file mode 100644 index 548f2c1..0000000 --- a/tests/Integration/BasicCommandAndBusMappingTest.php +++ /dev/null @@ -1,135 +0,0 @@ -registerService('tactician.test.handler', \League\Tactician\Bundle\Tests\EchoTextHandler::class, [ - ['name' => 'tactician.handler', 'command' => 'League\Tactician\Bundle\Tests\EchoText'], - ]); - - $this->expectOutputString('Hello world'); - $this->handleCommand('default', \League\Tactician\Bundle\Tests\EchoText::class, ['Hello world']); - } - - /** - * @expectedException \Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException - */ - public function testHandleCommandWithInvalidMiddleware() - { - $this->givenConfig('tactician', <<<'EOF' -commandbus: - default: - middleware: - - tactician.middleware.whatever - - tactician.middleware.command_handler -EOF - ); - static::$kernel->boot(); - } - - public function testHandleCommandOnMiddlewareWithDependencies() - { - $this->givenConfig('framework', <<<'EOF' -validation: - enabled: true -EOF - ); - $this->givenConfig('tactician', <<<'EOF' -commandbus: - default: - middleware: - - tactician.middleware.validator - - tactician.middleware.command_handler -EOF - ); - $this->registerService('tactician.test.handler', \League\Tactician\Bundle\Tests\EchoTextHandler::class, [ - ['name' => 'tactician.handler', 'command' => 'League\Tactician\Bundle\Tests\EchoText'], - ]); - - $this->expectOutputString('Hello world'); - $this->handleCommand('default', \League\Tactician\Bundle\Tests\EchoText::class, ['Hello world']); - } - - public function testHandleCommandOnSpecificBus() - { - $this->givenConfig('tactician', <<<'EOF' -commandbus: - default: - middleware: - - tactician.middleware.command_handler - other: - middleware: - - tactician.commandbus.other.middleware.command_handler -EOF - ); - $this->registerService('tactician.test.handler', \League\Tactician\Bundle\Tests\EchoTextHandler::class, [ - ['name' => 'tactician.handler', 'command' => 'League\Tactician\Bundle\Tests\EchoText', 'bus' => 'other'], - ]); - $this->expectOutputString('Welcome'); - $this->handleCommand('other', \League\Tactician\Bundle\Tests\EchoText::class, ['Welcome']); - } - - /** - * @expectedException \League\Tactician\Bundle\DependencyInjection\InvalidCommandBusId - * @expectedExceptionMessage Could not find a command bus with id 'other'. Valid buses are: default - */ - public function testHandlerOnUnknownBus() - { - $this->givenConfig('tactician', <<<'EOF' -commandbus: - default: - middleware: - - tactician.middleware.command_handler -EOF - ); - $this->registerService('tactician.test.handler', \League\Tactician\Bundle\Tests\EchoTextHandler::class, [ - ['name' => 'tactician.handler', 'command' => 'League\Tactician\Bundle\Tests\EchoText', 'bus' => 'other'], - ]); - static::$kernel->boot(); - } - - public function testInvalidDefaultBus() - { - $this->expectException(InvalidConfigurationException::class); - - $this->givenConfig('tactician', <<<'EOF' -default_bus: some_bus_that_does_not_exist -commandbus: - default: - middleware: - - tactician.middleware.command_handler -EOF - ); - - static::$kernel->boot(); - } - - /** - * @expectedException \League\Tactician\Exception\MissingHandlerException - */ - public function testHandleCommandSpecifiedOnAnotherBus() - { - $this->givenConfig('tactician', <<<'EOF' -commandbus: - default: - middleware: - - tactician.middleware.command_handler - other: - middleware: - - tactician.commandbus.other.middleware.command_handler -EOF - ); - $this->registerService('tactician.test.handler', \League\Tactician\Bundle\Tests\EchoTextHandler::class, [ - ['name' => 'tactician.handler', 'command' => 'League\Tactician\Bundle\Tests\EchoText', 'bus' => 'other'], - ]); - $this->handleCommand('default', \League\Tactician\Bundle\Tests\EchoText::class, ['Welcome']); - } -} diff --git a/tests/Integration/DebugCommandTest.php b/tests/Integration/DebugCommandTest.php deleted file mode 100644 index ccece16..0000000 --- a/tests/Integration/DebugCommandTest.php +++ /dev/null @@ -1,73 +0,0 @@ -givenConfig('tactician', <<<'EOF' -commandbus: - default: - middleware: - - tactician.middleware.command_handler -EOF - ); - - $this->registerService('a.handler', SomeHandler::class, [['name' => 'tactician.handler', 'command' => FakeCommand::class]]); - $this->registerService('b.handler', SomeHandler::class, [['name' => 'tactician.handler', 'command' => OtherFakeCommand::class]]); - - // WHEN - $result = $this->runCommand()->getDisplay(); - - // THEN - $expectation = <<<'EOF' - -Tactician routing -================= - -Bus: default ------------- - - ----------------------------------------------------- ----------------- - Command Handler Service - ----------------------------------------------------- ----------------- - League\Tactician\Bundle\Tests\Fake\FakeCommand a.handler - League\Tactician\Bundle\Tests\Fake\OtherFakeCommand b.handler - ----------------------------------------------------- ----------------- - - -EOF; - - $this->assertEquals( - $expectation, - $result - ); - } - - /** - * @return CommandTester - */ - private function runCommand(): CommandTester - { - $application = new Application(static::$kernel); - - $command = $application->find('debug:tactician'); - $commandTester = new CommandTester($command); - $commandTester->execute(array( - 'command' => $command->getName() - )); - return $commandTester; - } -} diff --git a/tests/Integration/IntegrationTest.php b/tests/Integration/IntegrationTest.php deleted file mode 100644 index 361539f..0000000 --- a/tests/Integration/IntegrationTest.php +++ /dev/null @@ -1,67 +0,0 @@ -filesystem = new Filesystem(); - - $cacheDir = sys_get_temp_dir().DIRECTORY_SEPARATOR.'tactician-bundle'.DIRECTORY_SEPARATOR.uniqid("tactician-bundle", true); - - $this->filesystem->mkdir($cacheDir); - static::$kernel->defineCacheDir($cacheDir); - } - - protected function tearDown() - { - $this->filesystem->remove( - static::$kernel->getCacheDir() - ); - } - - protected function givenConfig($namespace, $config) - { - static::$kernel->loadConfig($namespace, Yaml::parse((string) $config)); - } - - protected function registerService($serviceId, $className, array $tags) - { - static::$kernel->addServiceToRegister($serviceId, $className, $tags); - } - - protected function handleCommand($busId, $commandClass, array $args = []) - { - $class = new \ReflectionClass($commandClass); - $command = $class->newInstanceArgs($args); - - static::$kernel->boot(); - static::$kernel->getContainer()->get('tactician.commandbus.'.$busId)->handle($command); - } -} diff --git a/tests/Integration/MappingPrecedenceTest.php b/tests/Integration/MappingPrecedenceTest.php deleted file mode 100644 index b34be28..0000000 --- a/tests/Integration/MappingPrecedenceTest.php +++ /dev/null @@ -1,83 +0,0 @@ -givenConfig('tactician', <<<'EOF' -commandbus: - default: - middleware: - - tactician.middleware.command_handler -EOF - ); - } - - public function test_typehint_mapping_works_standalone() - { - $this->registerService( - 'tactician.test.handler', - TypehintedHandler::class, - [['name' => 'tactician.handler', 'typehints' => true]] - ); - - $this->expectOutputString("typehint wins"); - $this->handleCommand('default', FakeCommand::class); - } - - public function test_FQCN_mapping_works_standalone() - { - $this->registerService( - 'tactician.test.handler', - PlainHandler::class, - [['name' => 'tactician.handler', 'command' => FakeCommand::class]] - ); - - $this->expectOutputString("plain wins"); - $this->handleCommand('default', FakeCommand::class); - } - - public function test_FQCN_mapping_has_precedence_over_typehint_mapping() - { - $this->registerService( - 'tactician.test.typehinted_handler', - TypehintedHandler::class, - [['name' => 'tactician.handler', 'typehints' => true]] - ); - - $this->registerService( - 'tactician.test.plain_handler', - PlainHandler::class, - [['name' => 'tactician.handler', 'command' => FakeCommand::class]] - ); - - $this->expectOutputString("plain wins"); - $this->handleCommand('default', FakeCommand::class); - } -} - -class TypehintedHandler -{ - public function handle(FakeCommand $command) - { - echo 'typehint wins'; - } -} - -class PlainHandler -{ - public function handle($someCommand) - { - echo 'plain wins'; - } -} diff --git a/tests/Integration/SecurityTest.php b/tests/Integration/SecurityTest.php deleted file mode 100644 index 9170f21..0000000 --- a/tests/Integration/SecurityTest.php +++ /dev/null @@ -1,139 +0,0 @@ -loadSecurityConfiguration(); - - $this->givenConfig('tactician', <<<'EOF' -commandbus: - default: - middleware: - - tactician.middleware.security -EOF - ); - static::$kernel->boot(); - $this->assertTrue(true); - } - - public function testCanNotBootKernelIfLoadingSecurityMiddlewareWithoutSecurityBeingTurnedOn() - { - $this->expectException(ServiceNotFoundException::class); - $this->givenConfig('tactician', <<<'EOF' -commandbus: - default: - middleware: - - tactician.middleware.security -EOF - ); - static::$kernel->boot(); - } - - public function testCanBootKernelWithoutSecurityOrSecurityMiddleware() - { - $this->givenConfig('tactician', <<<'EOF' -commandbus: - default: - middleware: - - tactician.middleware.command_handler -EOF - ); - static::$kernel->boot(); - $this->assertTrue(true); - } - - /** - * @dataProvider provideTestData - */ - public function testSecurityMiddleware($command, string $role, string $expectedExceptionClassName = null) - { - if ($expectedExceptionClassName) { - $this->expectException($expectedExceptionClassName); - } - - $this->loadSecurityConfiguration(); - $this->givenConfig('tactician', <<<'EOF' -commandbus: - default: - middleware: - - tactician.middleware.security -security: - League\Tactician\Bundle\Tests\Fake\FakeCommand: - - 'ROLE_ADMIN' -EOF - ); - - static::$kernel->boot(); - $this->setUserRole($role); - - static::$kernel->getContainer()->get('tactician.commandbus.default')->handle($command); - } - - /** - * Gets test data for security middleware integration test. - * - * @return array - */ - public function provideTestData(): array - { - return [ - 'Role may handle the command' => [new FakeCommand(), 'ROLE_ADMIN'], - 'Test role hierarchy' => [new FakeCommand(), 'ROLE_SUPER_ADMIN'], - 'Role may not handle the command' => [new FakeCommand(), 'ROLE_USER', AccessDeniedException::class], - 'Deny access if command is not in the mapping' => [new stdClass(), 'ROLE_SUPER_ADMIN', AccessDeniedException::class], - ]; - } - - /** - * Security configuration. - */ - private function loadSecurityConfiguration() - { - $this->givenConfig('security', <<< 'EOF' -access_denied_url: / - -role_hierarchy: - ROLE_ADMIN: ROLE_USER - ROLE_SUPER_ADMIN: ROLE_ADMIN - -providers: - my_in_memory_provider: - memory: - -firewalls: - main: - anonymous: ~ - http_basic: ~ -EOF - ); - } - - /** - * @param string $role - */ - protected function setUserRole(string $role) - { - static::$kernel->getContainer() - ->get('security.token_storage') - ->setToken( - new AnonymousToken('test', 'anon', [new Role($role)]) - ); - } -} diff --git a/tests/Integration/ValidatorTest.php b/tests/Integration/ValidatorTest.php deleted file mode 100644 index 9ad4c99..0000000 --- a/tests/Integration/ValidatorTest.php +++ /dev/null @@ -1,74 +0,0 @@ -givenConfig('framework', <<<'EOF' -validation: - enabled: true -EOF - ); - - $this->givenConfig('tactician', <<<'EOF' -commandbus: - default: - middleware: - - tactician.middleware.validator -EOF - ); - static::$kernel->boot(); - } - - public function testCanNotBootKernelWhenOptionalComponentMiddlewareIsDisabled() - { - $this->expectException(ServiceNotFoundException::class); - - $this->givenConfig('framework', <<<'EOF' -validation: - enabled: false -EOF - ); - - $this->givenConfig('tactician', <<<'EOF' -commandbus: - default: - middleware: - - tactician.middleware.validator -EOF - ); - static::$kernel->boot(); - } - - public function testHandleCommandOnMiddlewareWithDependencies() - { - $this->givenConfig('framework', <<<'EOF' -validation: - enabled: true -EOF - ); - $this->givenConfig('tactician', <<<'EOF' -commandbus: - default: - middleware: - - tactician.middleware.validator - - tactician.middleware.command_handler -EOF - ); - $this->registerService('tactician.test.handler', \League\Tactician\Bundle\Tests\EchoTextHandler::class, [ - ['name' => 'tactician.handler', 'command' => 'League\Tactician\Bundle\Tests\EchoText'], - ]); - - $this->expectOutputString('Hello world'); - $this->handleCommand('default', \League\Tactician\Bundle\Tests\EchoText::class, ['Hello world']); - } -} diff --git a/tests/Middleware/SecurityMiddlewareTest.php b/tests/Middleware/SecurityMiddlewareTest.php deleted file mode 100644 index 5eb87d4..0000000 --- a/tests/Middleware/SecurityMiddlewareTest.php +++ /dev/null @@ -1,62 +0,0 @@ -authorizationChecker = Mockery::mock(AuthorizationCheckerInterface::class); - } - - /** - * Tests the command is handled if access is granted. - */ - public function testAccessIsGranted() - { - $this->authorizationChecker->shouldReceive('isGranted')->andReturn(true); - $middleware = new SecurityMiddleware($this->authorizationChecker); - $handled = false; - $middleware->execute(new FakeCommand(), function () use(&$handled) { - $handled = true; - }); - - $this->assertTrue($handled); - } - - /** - * Tests the command is not handled if access is denied and an AccessDenied exception is thrown. - */ - public function testAccessIsNotGranted() - { - $this->expectException(AccessDeniedException::class); - $this->authorizationChecker->shouldReceive('isGranted')->andReturn(false); - $middleware = new SecurityMiddleware($this->authorizationChecker); - $handled = false; - $middleware->execute(new FakeCommand(), function () use(&$handled) { - $handled = true; - }); - - $this->assertFalse($handled); - } -} diff --git a/tests/Middleware/ValidatorMiddlewareTest.php b/tests/Middleware/ValidatorMiddlewareTest.php deleted file mode 100644 index 3a6ac72..0000000 --- a/tests/Middleware/ValidatorMiddlewareTest.php +++ /dev/null @@ -1,60 +0,0 @@ -validator = \Mockery::mock('Symfony\Component\Validator\Validator\ValidatorInterface'); - - $this->middleware = new ValidatorMiddleware($this->validator); - } - - public function testExecute() - { - $list = new ConstraintViolationList([\Mockery::mock('Symfony\Component\Validator\ConstraintViolation')]); - - $this->validator->shouldReceive('validate')->once()->andReturn($list); - - try { - - $this->middleware->execute(new FakeCommand(), function () { - }); - - } catch (InvalidCommandException $e) { - $this->assertEquals($list, $e->getViolations()); - $this->assertEquals(new FakeCommand(), $e->getCommand()); - } - } - - public function testExecuteWithoutViolations() - { - $list = new ConstraintViolationList([]); - - $this->validator->shouldReceive('validate')->once()->andReturn($list); - - $this->middleware->execute(new FakeCommand(), function () { - }); - } -} diff --git a/tests/Security/Voter/HandleCommandVoterTest.php b/tests/Security/Voter/HandleCommandVoterTest.php deleted file mode 100644 index c4daf0e..0000000 --- a/tests/Security/Voter/HandleCommandVoterTest.php +++ /dev/null @@ -1,92 +0,0 @@ -decisionManager = Mockery::mock(AccessDecisionManager::class); - } - - public function testAKnownCommandWillBeDelegatedToTheDecisionManager() - { - $tokenMock = Mockery::mock(TokenInterface::class); - - $voter = new HandleCommandVoter($this->decisionManager, [FakeCommand::class => ['ROLE_USER']]); - - $this->decisionManager - ->shouldReceive('decide') - ->with($tokenMock, ['ROLE_USER']) - ->andReturn(true) - ->once(); - - $this->assertEquals(VoterInterface::ACCESS_GRANTED, $voter->vote($tokenMock, new FakeCommand(), ['handle'])); - } - - /** - * @dataProvider provideTestVoteData - */ - public function testAbstainOrDenyScenarios($attribute, $subject, $expected) - { - // In the test cases provided, we either abstain from voting or refuse - // to do it since there's no declared mapping. Therefore, it would be - // an error to ever call the decision manager. - $this->decisionManager->shouldReceive('decide')->never(); - - $voter = new HandleCommandVoter($this->decisionManager, []); - $tokenMock = Mockery::mock(TokenInterface::class); - - $this->assertEquals($expected, $voter->vote($tokenMock, $subject, [$attribute])); - } - - /** - * Gets the testdata for the vote test. - * - * @return array - */ - public function provideTestVoteData() - { - return [ - 'abstain when not handling a command, but using the handle attribute' => [ - 'handle', - null, - VoterInterface::ACCESS_ABSTAIN - ], - 'abstain when not handling a command and not using the handle attribute' => [ - 'create', - null, - VoterInterface::ACCESS_ABSTAIN - ], - 'abstain when handling a command and not using the handle attribute' => [ - 'create', - new FakeCommand, - VoterInterface::ACCESS_ABSTAIN - ], - 'default access is false' => [ - 'handle', - new FakeCommand, - VoterInterface::ACCESS_DENIED - ], - ]; - } -} diff --git a/tests/Fake/FakeCommand.php b/tests/Stub/FakeCommand.php similarity index 65% rename from tests/Fake/FakeCommand.php rename to tests/Stub/FakeCommand.php index 800eb72..3900f14 100644 --- a/tests/Fake/FakeCommand.php +++ b/tests/Stub/FakeCommand.php @@ -1,5 +1,5 @@ cacheDir = $dir; - } - - public function loadConfig($namespace, array $tacticianConfig) - { - $this->config[$namespace] = $tacticianConfig; - } - - public function addServiceToRegister($serviceId, $className, array $tags) - { - $this->services[$serviceId] = [ - 'className' => $className, - 'tags' => $tags, - ]; - } - - public function getCacheDir() - { - return $this->cacheDir; - } - - protected function configureContainer(ContainerBuilder $c, LoaderInterface $loader) - { - $frameworkConfig = ['secret' => 'S0ME_SECRET']; - if (array_key_exists('framework', $this->config)) { - $this->config['framework'] = array_merge($frameworkConfig, $this->config['framework']); - } else { - $this->config['framework'] = $frameworkConfig; - } - - foreach ($this->config as $namespace => $config) { - $c->loadFromExtension($namespace, $config); - } - - foreach ($this->services as $serviceId => $definition) { - $service = $c->register($serviceId, $definition['className']); - foreach ($definition['tags'] as $tag) { - $tagName = $tag['name']; - unset($tag['name']); - $service->addTag($tagName, $tag); - } - } - } - - protected function configureRoutes(RouteCollectionBuilder $routes) - { - } -} diff --git a/tests/testapp/src/EchoText.php b/tests/testapp/src/EchoText.php deleted file mode 100644 index af1d9fe..0000000 --- a/tests/testapp/src/EchoText.php +++ /dev/null @@ -1,18 +0,0 @@ -text = $text; - } - - public function getText() - { - return $this->text; - } -} diff --git a/tests/testapp/src/EchoTextHandler.php b/tests/testapp/src/EchoTextHandler.php deleted file mode 100644 index f8b78ee..0000000 --- a/tests/testapp/src/EchoTextHandler.php +++ /dev/null @@ -1,11 +0,0 @@ -getText(); - } -}