From 81ed7d1a235efca4b5bdf82144a1c959e08ffdb0 Mon Sep 17 00:00:00 2001 From: Marcel Frankruijter Date: Tue, 11 May 2021 15:13:27 +0200 Subject: [PATCH] Feature: Support the new services layer --- .travis.yml | 3 +- CHANGELOG.md | 7 +- composer.json | 27 ++-- .../configuration/advices.configuration.json | 5 - .../join-points.configuration.json | 5 - .../pointcuts.configuration.json | 5 - configuration/invocations/aop-core.json | 21 --- configuration/schema/advices.schema.json | 14 ++ configuration/schema/join-points.schema.json | 34 +++++ configuration/schema/pointcuts.schema.json | 17 +++ .../advices.extension.json | 19 --- .../join-points.extension.json | 39 ----- .../pointcuts.extension.json | 22 --- .../service-factory-hooks/proxy-hook.json | 6 - configuration/services/aop-commands.json | 16 --- configuration/services/aop-core.json | 135 +++++++++++++++--- docs/usage/create-a-plugin.md | 87 +++++------ src/Command/AopClearCommand.php | 8 +- src/Command/AopGenerateCommand.php | 52 +++++-- .../Combiner/ConfigurationCombiner.php | 4 +- .../Compiler/Extension/AopCompiler.php | 16 +-- src/Component/Weaver/AspectWeaver.php | 2 +- src/Factory/Hook/ProxyHook.php | 75 ++++++---- tests/Command/AopClearCommandTest.php | 4 +- tests/Command/AopGenerateCommandTest.php | 55 +++++-- .../Combiner/ConfigurationCombinerTest.php | 2 +- .../Compiler/Extension/AopCompilerTest.php | 32 +---- tests/Component/Weaver/AspectWeaverTest.php | 2 +- tests/Factory/Hook/ProxyHookTest.php | 28 ++-- 29 files changed, 411 insertions(+), 331 deletions(-) delete mode 100644 configuration/configuration/advices.configuration.json delete mode 100644 configuration/configuration/join-points.configuration.json delete mode 100644 configuration/configuration/pointcuts.configuration.json delete mode 100644 configuration/invocations/aop-core.json create mode 100644 configuration/schema/advices.schema.json create mode 100644 configuration/schema/join-points.schema.json create mode 100644 configuration/schema/pointcuts.schema.json delete mode 100644 configuration/service-compiler-extensions/advices.extension.json delete mode 100644 configuration/service-compiler-extensions/join-points.extension.json delete mode 100644 configuration/service-compiler-extensions/pointcuts.extension.json delete mode 100644 configuration/service-factory-hooks/proxy-hook.json delete mode 100644 configuration/services/aop-commands.json diff --git a/.travis.yml b/.travis.yml index e1e0d74..07342d0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,6 @@ language: php php: - - '7.3' - - '7.4' + - '8.0' before_script: - composer install diff --git a/CHANGELOG.md b/CHANGELOG.md index d6b6e23..6f0f1af 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,9 +4,14 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## 1.1.0 - 2021-05-11 +### Added +- Support the new services layer. + ## 1.0.0 - 2020-11-09 ### Added - The initial implementation of the package. # Versions -- [1.0.0 > Unreleased](https://github.com/ulrack/aop-extension/compare/1.0.0...HEAD) +- [1.1.0 > Unreleased](https://github.com/ulrack/aop-extension/compare/1.1.0...HEAD) +- [1.0.0 > 1.1.0](https://github.com/ulrack/aop-extension/compare/1.0.0...1.1.0) diff --git a/composer.json b/composer.json index 561211c..3dbf5e1 100644 --- a/composer.json +++ b/composer.json @@ -11,18 +11,17 @@ "prefer-stable": true, "minimum-stability": "stable", "require": { - "php": "^7.3", - "grizz-it/ast": "^1.2", - "grizz-it/cache": "^1.0", - "grizz-it/configuration": "^1.2", - "grizz-it/php-ast-generator": "^1.1", - "grizz-it/storage": "^1.0", - "grizz-it/task": "^1.0", - "grizz-it/vfs": "^1.0", - "ulrack/command": "^2.0", - "ulrack/invocation-extension": "^1.1", - "ulrack/kernel": "^1.3", - "ulrack/services": "^3.3" + "php": "^8.0", + "grizz-it/ast": "^1.3", + "grizz-it/cache": "^1.1", + "grizz-it/command": "^1.0", + "grizz-it/configuration": "^1.3", + "grizz-it/php-ast-generator": "^1.2", + "grizz-it/services": "^1.0", + "grizz-it/storage": "^1.1", + "grizz-it/task": "^1.1", + "grizz-it/vfs": "^1.1", + "ulrack/kernel": "^2.0" }, "authors": [ { @@ -60,7 +59,7 @@ ] }, "require-dev": { - "phpunit/phpunit": "^9.3", - "squizlabs/php_codesniffer": "^3.5" + "phpunit/phpunit": "^9.5", + "squizlabs/php_codesniffer": "^3.6" } } diff --git a/configuration/configuration/advices.configuration.json b/configuration/configuration/advices.configuration.json deleted file mode 100644 index b772ae0..0000000 --- a/configuration/configuration/advices.configuration.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "$schema": "configuration.schema.json", - "key": "advices", - "location": "configuration/advices" -} diff --git a/configuration/configuration/join-points.configuration.json b/configuration/configuration/join-points.configuration.json deleted file mode 100644 index f6fe95a..0000000 --- a/configuration/configuration/join-points.configuration.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "$schema": "configuration.schema.json", - "key": "join-points", - "location": "configuration/join-points" -} diff --git a/configuration/configuration/pointcuts.configuration.json b/configuration/configuration/pointcuts.configuration.json deleted file mode 100644 index 15a1ded..0000000 --- a/configuration/configuration/pointcuts.configuration.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "$schema": "configuration.schema.json", - "key": "pointcuts", - "location": "configuration/pointcuts" -} diff --git a/configuration/invocations/aop-core.json b/configuration/invocations/aop-core.json deleted file mode 100644 index 60336c3..0000000 --- a/configuration/invocations/aop-core.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "aop.get.config.cache": { - "service": "services.core.cache.manager", - "method": "getCache", - "parameters": { - "key": "aop" - } - }, - "aop.service.factory": { - "service": "services.core.service.manager", - "method": "getServiceFactory" - }, - "aop.get.generated.directory": { - "service": "services.aop.proxy.generator", - "method": "getGeneratedDirectory" - }, - "aop.service.compiler": { - "service": "services.core.service.manager", - "method": "getServiceCompiler" - } -} \ No newline at end of file diff --git a/configuration/schema/advices.schema.json b/configuration/schema/advices.schema.json new file mode 100644 index 0000000..3e10417 --- /dev/null +++ b/configuration/schema/advices.schema.json @@ -0,0 +1,14 @@ +{ + "$id": "advices.schema.json", + "type": "object", + "properties": { + "service": { + "type": "string" + }, + "hook": { + "type": "string", + "enum": ["before", "around", "after"] + } + }, + "required": ["service", "hook"] +} \ No newline at end of file diff --git a/configuration/schema/join-points.schema.json b/configuration/schema/join-points.schema.json new file mode 100644 index 0000000..0bf3c6a --- /dev/null +++ b/configuration/schema/join-points.schema.json @@ -0,0 +1,34 @@ +{ + "$id": "join-points.schema.json", + "type": "object", + "oneOf": [ + { + "properties": { + "service": { + "type": "string", + "pattern": "^[\\.\\w-]+$" + }, + "method": { + "type": "string" + } + }, + "required": ["service", "method"] + }, + { + "properties": { + "class": { + "type": "string", + "pattern": "^(\\\\[A-z0-9]+)+$" + }, + "method": { + "type": "string" + }, + "explicit": { + "type": "boolean", + "default": false + } + }, + "required": ["class", "method"] + } + ] +} \ No newline at end of file diff --git a/configuration/schema/pointcuts.schema.json b/configuration/schema/pointcuts.schema.json new file mode 100644 index 0000000..9175a56 --- /dev/null +++ b/configuration/schema/pointcuts.schema.json @@ -0,0 +1,17 @@ +{ + "$id": "pointcuts.schema.json", + "type": "object", + "properties": { + "join-point": { + "type": "string" + }, + "advice": { + "type": "string" + }, + "sortOrder": { + "type": "integer", + "default": 1000 + } + }, + "required": ["join-point", "advice"] +} \ No newline at end of file diff --git a/configuration/service-compiler-extensions/advices.extension.json b/configuration/service-compiler-extensions/advices.extension.json deleted file mode 100644 index db3067b..0000000 --- a/configuration/service-compiler-extensions/advices.extension.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "$schema": "service.compiler.extension.schema.json", - "class": "\\Ulrack\\Services\\Component\\Compiler\\Extension\\PassThroughCompiler", - "sortOrder": 10, - "key": "advices", - "schema": { - "type": "object", - "properties": { - "service": { - "type": "string" - }, - "hook": { - "type": "string", - "enum": ["before", "around", "after"] - } - }, - "required": ["service", "hook"] - } -} \ No newline at end of file diff --git a/configuration/service-compiler-extensions/join-points.extension.json b/configuration/service-compiler-extensions/join-points.extension.json deleted file mode 100644 index 5b058b0..0000000 --- a/configuration/service-compiler-extensions/join-points.extension.json +++ /dev/null @@ -1,39 +0,0 @@ -{ - "$schema": "service.compiler.extension.schema.json", - "class": "\\Ulrack\\Services\\Component\\Compiler\\Extension\\PassThroughCompiler", - "sortOrder": 0, - "key": "join-points", - "schema": { - "type": "object", - "oneOf": [ - { - "properties": { - "service": { - "type": "string", - "pattern": "^[\\.\\w-]+$" - }, - "method": { - "type": "string" - } - }, - "required": ["service", "method"] - }, - { - "properties": { - "class": { - "type": "string", - "pattern": "^(\\\\[A-z0-9]+)+$" - }, - "method": { - "type": "string" - }, - "explicit": { - "type": "boolean", - "default": false - } - }, - "required": ["class", "method"] - } - ] - } -} \ No newline at end of file diff --git a/configuration/service-compiler-extensions/pointcuts.extension.json b/configuration/service-compiler-extensions/pointcuts.extension.json deleted file mode 100644 index 9556b9b..0000000 --- a/configuration/service-compiler-extensions/pointcuts.extension.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "$schema": "service.compiler.extension.schema.json", - "class": "\\Ulrack\\AopExtension\\Component\\Compiler\\Extension\\AopCompiler", - "sortOrder": 20, - "key": "pointcuts", - "schema": { - "type": "object", - "properties": { - "join-point": { - "type": "string" - }, - "advice": { - "type": "string" - }, - "sortOrder": { - "type": "integer", - "default": 1000 - } - }, - "required": ["join-point", "advice"] - } -} \ No newline at end of file diff --git a/configuration/service-factory-hooks/proxy-hook.json b/configuration/service-factory-hooks/proxy-hook.json deleted file mode 100644 index 52c70aa..0000000 --- a/configuration/service-factory-hooks/proxy-hook.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "$schema": "service.factory.hook.schema.json", - "class": "\\Ulrack\\AopExtension\\Factory\\Hook\\ProxyHook", - "sortOrder": 100, - "key": "global" -} \ No newline at end of file diff --git a/configuration/services/aop-commands.json b/configuration/services/aop-commands.json deleted file mode 100644 index edd0b5c..0000000 --- a/configuration/services/aop-commands.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "aop.command.aop.clear": { - "class": "\\Ulrack\\AopExtension\\Command\\AopClearCommand", - "parameters": { - "generatedDirectory": "@{invocations.aop.get.generated.directory}" - } - }, - "aop.command.aop.generate": { - "class": "\\Ulrack\\AopExtension\\Command\\AopGenerateCommand", - "parameters": { - "proxyGenerator": "@{services.aop.proxy.generator}", - "combiner": "@{services.aop.configuration.combiner}", - "serviceCompiler": "@{invocations.aop.service.compiler}" - } - } -} \ No newline at end of file diff --git a/configuration/services/aop-core.json b/configuration/services/aop-core.json index 62e4390..b1b1f7f 100644 --- a/configuration/services/aop-core.json +++ b/configuration/services/aop-core.json @@ -1,26 +1,125 @@ { - "aop.class.generator.factory": { - "class": "\\GrizzIt\\PhpAstGenerator\\Factory\\ClassGeneratorFactory" + "parameters": { + "service.configuration.validation.advices": { + "key": "advices", + "schema": "advices.schema.json" + }, + "service.configuration.validation.join-points": { + "key": "join-points", + "schema": "join-points.schema.json" + }, + "service.configuration.validation.pointcuts": { + "key": "pointcuts", + "schema": "pointcuts.schema.json" + } }, - "aop.proxy.generator": { - "class": "\\Ulrack\\AopExtension\\Component\\Generator\\ProxyGenerator", - "parameters": { - "resourceManager": "@{services.core.resource.manager}", - "classGeneratorFactory": "@{services.aop.class.generator.factory}" + "services": { + "aop.class.generator.factory": { + "class": "\\GrizzIt\\PhpAstGenerator\\Factory\\ClassGeneratorFactory" + }, + "aop.proxy.generator": { + "class": "\\Ulrack\\AopExtension\\Component\\Generator\\ProxyGenerator", + "parameters": { + "resourceManager": "@{internal.core.resource.manager}", + "classGeneratorFactory": "@{services.aop.class.generator.factory}" + } + }, + "aop.configuration.combiner": { + "class": "\\Ulrack\\AopExtension\\Component\\Combiner\\ConfigurationCombiner", + "parameters": { + "cache": "@{invocations.aop.get.config.cache}" + } + }, + "aop.aspect.weaver": { + "class": "\\Ulrack\\AopExtension\\Component\\Weaver\\AspectWeaver", + "parameters": { + "proxyGenerator": "@{services.aop.proxy.generator}", + "serviceFactory": "@{internal.core.service.factory}", + "combiner": "@{services.aop.configuration.combiner}" + } + }, + "aop.command.aop.clear": { + "class": "\\Ulrack\\AopExtension\\Command\\AopClearCommand", + "parameters": { + "generatedDirectory": "@{invocations.aop.get.generated.directory}" + } + }, + "aop.command.aop.generate": { + "class": "\\Ulrack\\AopExtension\\Command\\AopGenerateCommand", + "parameters": { + "proxyGenerator": "@{services.aop.proxy.generator}", + "combiner": "@{services.aop.configuration.combiner}", + "serviceCompiler": "@{invocations.aop.service.compiler}", + "configRegistry": "@{invocations.get.config.registry}" + } + }, + "service.compiler.aop": { + "class": "\\Ulrack\\AopExtension\\Component\\Compiler\\Extension\\AopCompiler" + }, + "service.factory.hook.aop": { + "class": "\\Ulrack\\AopExtension\\Factory\\Hook\\ProxyHook" } }, - "aop.configuration.combiner": { - "class": "\\Ulrack\\AopExtension\\Component\\Combiner\\ConfigurationCombiner", - "parameters": { - "cache": "@{invocations.aop.get.config.cache}" + "invocations": { + "aop.get.config.cache": { + "service": "internal.core.cache.manager", + "method": "getCache", + "parameters": { + "key": "aop" + } + }, + "aop.get.generated.directory": { + "service": "services.aop.proxy.generator", + "method": "getGeneratedDirectory" + }, + "aop.service.compiler": { + "service": "internal.core.service.manager", + "method": "getServiceCompiler" + }, + "add.aop.service.compiler": { + "service": "internal.core.service.compiler", + "method": "addExtension", + "parameters": { + "extension": "@{services.service.compiler.aop}", + "sortOrder": 100 + }, + "cache": true + }, + "add.aop.service.factory.hook": { + "service": "internal.core.service.factory", + "method": "addHook", + "parameters": { + "scope": "global", + "hook": "@{services.service.factory.hook.aop}", + "sortOrder": 100 + }, + "cache": true + }, + "get.config.registry": { + "service": "internal.core.configuration.manager", + "method": "getConfigRegistry" } }, - "aop.aspect.weaver": { - "class": "\\Ulrack\\AopExtension\\Component\\Weaver\\AspectWeaver", - "parameters": { - "proxyGenerator": "@{services.aop.proxy.generator}", - "serviceFactory": "@{invocations.aop.service.factory}", - "combiner": "@{services.aop.configuration.combiner}" + "tags": { + "add.aop.compiler": { + "trigger": "triggers.core.service.compilers", + "service": "invocations.add.aop.service.compiler" + }, + "add.service.validation.advices": { + "service": "parameters.service.configuration.validation.advices", + "trigger": "triggers.service.configuration.validation" + }, + "add.service.validation.join-points": { + "service": "parameters.service.configuration.validation.join-points", + "trigger": "triggers.service.configuration.validation" + }, + "add.service.validation.pointcuts": { + "service": "parameters.service.configuration.validation.pointcuts", + "trigger": "triggers.service.configuration.validation" + }, + "add.aop.service.factory.hook": { + "trigger": "triggers.core.service.hooks", + "service": "invocations.add.aop.service.factory.hook" } } -} +} \ No newline at end of file diff --git a/docs/usage/create-a-plugin.md b/docs/usage/create-a-plugin.md index 31423c4..6e2064a 100644 --- a/docs/usage/create-a-plugin.md +++ b/docs/usage/create-a-plugin.md @@ -15,24 +15,27 @@ configurations can be declared per file. Join-points describe the point on the class where plugins can be added. This can only be done for non `__construct` public methods. In order to register a -`join-point`, create a directory under `configuration/join-points` with the +`join-point`, create a file under `configuration/services` with the following contents: ```json { - "invoke-all-endpoints": { - "class": "\\Ulrack\\Web\\Common\\Endpoint\\EndpointInterface", - "method": "__invoke", - "explicit": false - }, - "invoke-my-endpoint": { - "class": "\\MyVendor\\MyProject\\MyEndpoint", - "method": "__invoke", - "explicit": true - }, - "invoke-home-endpoint": { - "service": "services.default-home-endpoint", - "method": "__invoke" - }, + "join-points": { + "invoke-all-endpoints": { + "class": "\\Ulrack\\Web\\Common\\Endpoint\\EndpointInterface", + "method": "__invoke", + "explicit": false + }, + "invoke-my-endpoint": { + "class": "\\MyVendor\\MyProject\\MyEndpoint", + "method": "__invoke", + "explicit": true + }, + "invoke-home-endpoint": { + "service": "services.default-home-endpoint", + "method": "__invoke" + } + } + } ``` @@ -52,22 +55,24 @@ through that specific service invocation. ## Advices Advices describe the usage of the plugins in the system. To register an advice, -create a file in the directory `configuration/advices` with the following +create a file in the directory `configuration/services` with the following contents: ```json { - "foo-after": { - "service": "services.advice.service", - "hook": "after" - }, - "foo-before": { - "service": "services.advice.service", - "hook": "before" - }, - "foo-around": { - "service": "services.advice.service", - "hook": "around" + "advices": { + "foo-after": { + "service": "services.advice.service", + "hook": "after" + }, + "foo-before": { + "service": "services.advice.service", + "hook": "before" + }, + "foo-around": { + "service": "services.advice.service", + "hook": "around" + } } } ``` @@ -167,22 +172,24 @@ class MyPlugin implements PluginInterface ## Pointcuts The `pointcut` describes the combination of an `advice` and a `join-point`. In -order to register a `join-point` create a file in `configuration/pointcuts` with +order to register a `join-point` create a file in `configuration/services` with the following content: ```json { - "invoke-foo-around-all-endpoints": { - "join-point": "invoke-all-endpoints", - "advice": "foo-around", - "sortOrder": 500 - }, - "invoke-foo-before-my-endpoint": { - "join-point": "invoke-my-endpoint", - "advice": "foo-before" - }, - "invoke-foo-after-home-endpoint": { - "join-point": "invoke-home-endpoint", - "advice": "foo-after" + "pointcuts": { + "invoke-foo-around-all-endpoints": { + "join-point": "invoke-all-endpoints", + "advice": "foo-around", + "sortOrder": 500 + }, + "invoke-foo-before-my-endpoint": { + "join-point": "invoke-my-endpoint", + "advice": "foo-before" + }, + "invoke-foo-after-home-endpoint": { + "join-point": "invoke-home-endpoint", + "advice": "foo-after" + } } } ``` diff --git a/src/Command/AopClearCommand.php b/src/Command/AopClearCommand.php index d4c4ffc..032d4cf 100644 --- a/src/Command/AopClearCommand.php +++ b/src/Command/AopClearCommand.php @@ -8,9 +8,9 @@ namespace Ulrack\AopExtension\Command; use GrizzIt\Vfs\Common\FileSystemInterface; -use Ulrack\Command\Common\Command\InputInterface; -use Ulrack\Command\Common\Command\OutputInterface; -use Ulrack\Command\Common\Command\CommandInterface; +use GrizzIt\Command\Common\Command\InputInterface; +use GrizzIt\Command\Common\Command\OutputInterface; +use GrizzIt\Command\Common\Command\CommandInterface; class AopClearCommand implements CommandInterface { @@ -19,7 +19,7 @@ class AopClearCommand implements CommandInterface * * @var FileSystemInterface */ - private $generatedDirectory; + private FileSystemInterface $generatedDirectory; /** * Constructor. diff --git a/src/Command/AopGenerateCommand.php b/src/Command/AopGenerateCommand.php index 807be5e..84b04ac 100644 --- a/src/Command/AopGenerateCommand.php +++ b/src/Command/AopGenerateCommand.php @@ -10,11 +10,12 @@ use GrizzIt\Task\Component\TaskList; use GrizzIt\Task\Component\Task\ConfigurableTask; use Ulrack\AopExtension\Common\CombinerInterface; -use Ulrack\Command\Common\Command\InputInterface; +use GrizzIt\Command\Common\Command\InputInterface; use Ulrack\AopExtension\Common\GeneratorInterface; -use Ulrack\Command\Common\Command\OutputInterface; -use Ulrack\Command\Common\Command\CommandInterface; -use Ulrack\Services\Common\ServiceCompilerInterface; +use GrizzIt\Command\Common\Command\OutputInterface; +use GrizzIt\Configuration\Common\RegistryInterface; +use GrizzIt\Command\Common\Command\CommandInterface; +use GrizzIt\Services\Common\Compiler\ServiceCompilerInterface; class AopGenerateCommand implements CommandInterface { @@ -23,21 +24,28 @@ class AopGenerateCommand implements CommandInterface * * @var GeneratorInterface */ - private $proxyGenerator; + private GeneratorInterface $proxyGenerator; /** * Contains the configuration combiner. * * @var CombinerInterface */ - private $combiner; + private CombinerInterface $combiner; /** * Contains the service compiler. * * @var ServiceCompilerInterface */ - private $serviceCompiler; + private ServiceCompilerInterface $serviceCompiler; + + /** + * Contains configuration registry. + * + * @var RegistryInterface + */ + private RegistryInterface $configRegistry; /** * Constructor. @@ -49,11 +57,13 @@ class AopGenerateCommand implements CommandInterface public function __construct( GeneratorInterface $proxyGenerator, CombinerInterface $combiner, - ServiceCompilerInterface $serviceCompiler + ServiceCompilerInterface $serviceCompiler, + RegistryInterface $configRegistry ) { $this->proxyGenerator = $proxyGenerator; $this->combiner = $combiner; $this->serviceCompiler = $serviceCompiler; + $this->configRegistry = $configRegistry; } /** @@ -68,12 +78,32 @@ public function __invoke( InputInterface $input, OutputInterface $output ): void { - $services = $this->serviceCompiler->compile(); + $registry = $this->serviceCompiler->compile(); $taskList = new TaskList(); $combiner = $this->combiner; - $combiner->setConfiguration($services['pointcuts']); + $combiner->setConfiguration( + [ + 'services' => $registry->getDefinitionByKey( + 'pointcuts.services' + ), + 'classes' => $registry->getDefinitionByKey( + 'pointcuts.classes' + ) + ] + ); + + $configKeys = array_keys( + array_merge( + ...array_column( + $this->configRegistry->toArray()['services'], + 'services' + ) + ) + ); + $proxyGenerator = $this->proxyGenerator; - foreach ($services['services'] as $service => $configuration) { + foreach ($configKeys as $service) { + $configuration = $registry->getDefinitionByKey('services.' . $service); $task = new ConfigurableTask((function () use ( $service, $configuration, diff --git a/src/Component/Combiner/ConfigurationCombiner.php b/src/Component/Combiner/ConfigurationCombiner.php index 5e063ee..0ecfcb5 100644 --- a/src/Component/Combiner/ConfigurationCombiner.php +++ b/src/Component/Combiner/ConfigurationCombiner.php @@ -121,7 +121,7 @@ private function joinServiceConfiguration( array $configuration, string $service ): array { - $serviceConfig = $configuration['services']; + $serviceConfig = $configuration['services'] ?? []; if (isset($serviceConfig[$service])) { foreach ($serviceConfig[$service] as $method => $config) { @@ -150,7 +150,7 @@ private function joinSimilarClassConfiguration( array $configuration, string $className ): array { - foreach ($configuration['classes'] as $class => $classConfig) { + foreach ($configuration['classes'] ?? [] as $class => $classConfig) { if ($class !== $className && is_a($className, $class, true)) { foreach ($classConfig as $method => $config) { if (($config['explicit'] ?? false) === false) { diff --git a/src/Component/Compiler/Extension/AopCompiler.php b/src/Component/Compiler/Extension/AopCompiler.php index 1c9af5c..2e09d15 100644 --- a/src/Component/Compiler/Extension/AopCompiler.php +++ b/src/Component/Compiler/Extension/AopCompiler.php @@ -7,9 +7,9 @@ namespace Ulrack\AopExtension\Component\Compiler\Extension; -use Ulrack\Services\Common\AbstractServiceCompilerExtension; +use GrizzIt\Services\Common\Compiler\ServiceCompilerExtensionInterface; -class AopCompiler extends AbstractServiceCompilerExtension +class AopCompiler implements ServiceCompilerExtensionInterface { /** * Compile the services. @@ -20,12 +20,6 @@ class AopCompiler extends AbstractServiceCompilerExtension */ public function compile(array $services): array { - $services = $this->preCompile( - $services, - $this->getParameters() - )['services']; - - $inputServices = $services; $services['pointcuts'] = $this->compileConfiguration( $services['advices'] ?? [], $services['join-points'] ?? [], @@ -35,11 +29,7 @@ public function compile(array $services): array unset($services['advices']); unset($services['join-points']); - return $this->postCompile( - $inputServices, - $services, - $this->getParameters() - )['return']; + return $services; } /** diff --git a/src/Component/Weaver/AspectWeaver.php b/src/Component/Weaver/AspectWeaver.php index 9bb6e6a..18cf65a 100644 --- a/src/Component/Weaver/AspectWeaver.php +++ b/src/Component/Weaver/AspectWeaver.php @@ -11,7 +11,7 @@ use Ulrack\AopExtension\Common\WeaverInterface; use Ulrack\AopExtension\Common\CombinerInterface; use Ulrack\AopExtension\Common\GeneratorInterface; -use Ulrack\Services\Common\ServiceFactoryInterface; +use GrizzIt\Services\Common\Factory\ServiceFactoryInterface; class AspectWeaver implements WeaverInterface { diff --git a/src/Factory/Hook/ProxyHook.php b/src/Factory/Hook/ProxyHook.php index b0060a7..c1691c3 100644 --- a/src/Factory/Hook/ProxyHook.php +++ b/src/Factory/Hook/ProxyHook.php @@ -8,69 +8,88 @@ namespace Ulrack\AopExtension\Factory\Hook; use Ulrack\AopExtension\Common\WeaverInterface; -use Ulrack\Services\Common\ServiceFactoryInterface; -use Ulrack\Services\Common\Hook\AbstractServiceFactoryHook; +use GrizzIt\Services\Common\Factory\ServiceFactoryHookInterface; -class ProxyHook extends AbstractServiceFactoryHook +class ProxyHook implements ServiceFactoryHookInterface { /** * Contains the aspect weaver. * * @var WeaverInterface */ - private $aspectWeaver; + private ?WeaverInterface $aspectWeaver = null; /** * Retrieves the aspect weaver. * + * @param callable $create + * * @return WeaverInterface */ - private function getAspectWeaver(): WeaverInterface + private function getAspectWeaver(callable $create): WeaverInterface { if (is_null($this->aspectWeaver)) { - /** @var ServiceFactoryInterface $serviceFactory */ - $serviceFactory = $this->getInternalService('service-factory'); - $this->aspectWeaver = $serviceFactory->create( - 'services.aop.aspect.weaver' - ); - + $this->aspectWeaver = $create('services.aop.aspect.weaver'); + $registry = $create('internal.core.service.compiler')->compile(); $this->aspectWeaver->getCombiner()->setConfiguration( - $this->getServices()['pointcuts'] + [ + 'services' => $registry->getDefinitionByKey( + 'pointcuts.services' + ), + 'classes' => $registry->getDefinitionByKey( + 'pointcuts.classes' + ) + ] ); } return $this->aspectWeaver; } + /** + * Hooks in before the creation of a service. + * + * @param string $key + * @param mixed $definition + * @param callable $create + * + * @return array + */ + public function preCreate( + string $key, + mixed $definition, + callable $create + ): array { + return [$key, $definition]; + } + /** * Hooks in after the creation of a service. * - * @param string $serviceKey + * @param string $key + * @param mixed $definition * @param mixed $return - * @param array $parameters + * @param callable $create * - * @return array + * @return mixed */ public function postCreate( - string $serviceKey, - $return, - array $parameters = [] - ): array { + string $key, + mixed $definition, + mixed $return, + callable $create + ): mixed { if ( is_object($return) && - strpos($serviceKey, '.aop.') === false && - strpos($serviceKey, '.core.') === false + strpos($key, '.aop.') === false && + strpos($key, '.core.') === false ) { - $return = $this->getAspectWeaver()->__invoke( - $serviceKey, + $return = $this->getAspectWeaver($create)->__invoke( + $key, $return ); } - return [ - 'serviceKey' => $serviceKey, - 'return' => $return, - 'parameters' => $parameters - ]; + return $return; } } diff --git a/tests/Command/AopClearCommandTest.php b/tests/Command/AopClearCommandTest.php index efbf3a9..2319428 100644 --- a/tests/Command/AopClearCommandTest.php +++ b/tests/Command/AopClearCommandTest.php @@ -10,8 +10,8 @@ use PHPUnit\Framework\TestCase; use GrizzIt\Vfs\Common\FileSystemInterface; use Ulrack\AopExtension\Command\AopClearCommand; -use Ulrack\Command\Common\Command\InputInterface; -use Ulrack\Command\Common\Command\OutputInterface; +use GrizzIt\Command\Common\Command\InputInterface; +use GrizzIt\Command\Common\Command\OutputInterface; /** * @coversDefaultClass \Ulrack\AopExtension\Command\AopClearCommand diff --git a/tests/Command/AopGenerateCommandTest.php b/tests/Command/AopGenerateCommandTest.php index 29eded1..7a1bebc 100644 --- a/tests/Command/AopGenerateCommandTest.php +++ b/tests/Command/AopGenerateCommandTest.php @@ -10,11 +10,13 @@ use PHPUnit\Framework\TestCase; use GrizzIt\Task\Common\TaskListInterface; use Ulrack\AopExtension\Common\CombinerInterface; -use Ulrack\Command\Common\Command\InputInterface; +use GrizzIt\Command\Common\Command\InputInterface; use Ulrack\AopExtension\Common\GeneratorInterface; -use Ulrack\Command\Common\Command\OutputInterface; +use GrizzIt\Command\Common\Command\OutputInterface; +use GrizzIt\Configuration\Common\RegistryInterface; use Ulrack\AopExtension\Command\AopGenerateCommand; -use Ulrack\Services\Common\ServiceCompilerInterface; +use GrizzIt\Services\Common\Compiler\ServiceCompilerInterface; +use GrizzIt\Services\Common\Registry\ServiceRegistryInterface; /** * @coversDefaultClass \Ulrack\AopExtension\Command\AopGenerateCommand @@ -32,30 +34,55 @@ public function testInvoke(): void $proxyGenerator = $this->createMock(GeneratorInterface::class); $combiner = $this->createMock(CombinerInterface::class); $serviceCompiler = $this->createMock(ServiceCompilerInterface::class); + $registry = $this->createMock(RegistryInterface::class); + $serviceRegistry = $this->createMock(ServiceRegistryInterface::class); $subject = new AopGenerateCommand( $proxyGenerator, $combiner, - $serviceCompiler + $serviceCompiler, + $registry ); $output = $this->createMock(OutputInterface::class); $serviceCompiler->expects(static::once()) ->method('compile') + ->willReturn($serviceRegistry); + + $serviceRegistry->expects(static::exactly(3)) + ->method('getDefinitionByKey') + ->withConsecutive( + ['pointcuts.services'], + ['pointcuts.classes'], + ['services.foo'] + )->willReturnOnConsecutiveCalls( + ['pointcut-service-config'], + ['pointcut-class-config'], + ['class' => 'foo'] + ); + + $combiner->expects(static::once()) + ->method('setConfiguration') + ->with([ + 'services' => ['pointcut-service-config'], + 'classes' => ['pointcut-class-config'] + ]); + + $registry->expects(static::once()) + ->method('toArray') ->willReturn( [ 'services' => [ - 'foo' => [ - 'class' => 'bar' + [ + 'services' => [ + 'foo' => [ + 'class' => 'foo' + ] + ] ] - ], - 'pointcuts' => ['pointcut-config'] + ] ] ); - $combiner->expects(static::once()) - ->method('setConfiguration') - ->with(['pointcut-config']); - $output->expects(static::once()) ->method('outputProgressBar') ->with($this->isInstanceOf(TaskListInterface::class)) @@ -65,12 +92,12 @@ public function testInvoke(): void $combiner->expects(static::once()) ->method('__invoke') - ->with('services.foo', 'bar') + ->with('services.foo', 'foo') ->willReturn(['foo']); $proxyGenerator->expects(static::once()) ->method('generate') - ->with('bar'); + ->with('foo'); $subject->__invoke( $this->createMock(InputInterface::class), diff --git a/tests/Component/Combiner/ConfigurationCombinerTest.php b/tests/Component/Combiner/ConfigurationCombinerTest.php index 4ca7171..e40780a 100644 --- a/tests/Component/Combiner/ConfigurationCombinerTest.php +++ b/tests/Component/Combiner/ConfigurationCombinerTest.php @@ -11,7 +11,7 @@ use GrizzIt\Cache\Common\CacheInterface; use GrizzIt\Storage\Component\ObjectStorage; use Ulrack\AopExtension\Command\AopClearCommand; -use Ulrack\Command\Common\Command\CommandInterface; +use GrizzIt\Command\Common\Command\CommandInterface; use Ulrack\AopExtension\Component\Combiner\ConfigurationCombiner; /** diff --git a/tests/Component/Compiler/Extension/AopCompilerTest.php b/tests/Component/Compiler/Extension/AopCompilerTest.php index 2550e59..28b4bcd 100644 --- a/tests/Component/Compiler/Extension/AopCompilerTest.php +++ b/tests/Component/Compiler/Extension/AopCompilerTest.php @@ -8,8 +8,8 @@ namespace Ulrack\AopExtension\Tests\Component\Compiler\Extension; use PHPUnit\Framework\TestCase; -use Ulrack\Services\Common\ServiceRegistryInterface; use GrizzIt\Validator\Component\Logical\AlwaysValidator; +use GrizzIt\Services\Common\Registry\ServiceRegistryInterface; use Ulrack\AopExtension\Component\Compiler\Extension\AopCompiler; /** @@ -21,25 +21,12 @@ class AopCompilerTest extends TestCase * @covers ::compile * @covers ::sortAdvices * @covers ::compileConfiguration - * @covers ::__construct * * @return void */ public function testCompileEmpty(): void { - $registry = $this->createMock(ServiceRegistryInterface::class); - $validator = new AlwaysValidator(true); - $getHooks = (function () { - return []; - }); - - $subject = new AopCompiler( - $registry, - 'pointcuts', - $validator, - [], - $getHooks - ); + $subject = new AopCompiler(); $services = ['pointcuts' => []]; $this->assertEquals(['pointcuts' => [ @@ -52,25 +39,12 @@ public function testCompileEmpty(): void * @covers ::compile * @covers ::sortAdvices * @covers ::compileConfiguration - * @covers ::__construct * * @return void */ public function testCompile(): void { - $registry = $this->createMock(ServiceRegistryInterface::class); - $validator = new AlwaysValidator(true); - $getHooks = (function () { - return []; - }); - - $subject = new AopCompiler( - $registry, - 'pointcuts', - $validator, - [], - $getHooks - ); + $subject = new AopCompiler(); $services = [ 'pointcuts' => [ diff --git a/tests/Component/Weaver/AspectWeaverTest.php b/tests/Component/Weaver/AspectWeaverTest.php index 4242275..676431d 100644 --- a/tests/Component/Weaver/AspectWeaverTest.php +++ b/tests/Component/Weaver/AspectWeaverTest.php @@ -11,8 +11,8 @@ use PHPUnit\Framework\TestCase; use Ulrack\AopExtension\Common\CombinerInterface; use Ulrack\AopExtension\Common\GeneratorInterface; -use Ulrack\Services\Common\ServiceFactoryInterface; use Ulrack\AopExtension\Component\Weaver\AspectWeaver; +use GrizzIt\Services\Common\Factory\ServiceFactoryInterface; /** * @coversDefaultClass \Ulrack\AopExtension\Component\Weaver\AspectWeaver diff --git a/tests/Factory/Hook/ProxyHookTest.php b/tests/Factory/Hook/ProxyHookTest.php index 1740ab1..6f1a67a 100644 --- a/tests/Factory/Hook/ProxyHookTest.php +++ b/tests/Factory/Hook/ProxyHookTest.php @@ -12,7 +12,8 @@ use Ulrack\AopExtension\Common\WeaverInterface; use Ulrack\AopExtension\Factory\Hook\ProxyHook; use Ulrack\AopExtension\Common\CombinerInterface; -use Ulrack\Services\Common\ServiceFactoryInterface; +use GrizzIt\Services\Common\Factory\ServiceFactoryInterface; +use GrizzIt\Services\Common\Compiler\ServiceCompilerInterface; /** * @coversDefaultClass \Ulrack\AopExtension\Factory\Hook\ProxyHook @@ -21,8 +22,8 @@ class ProxyHookTest extends TestCase { /** * @covers ::postCreate + * @covers ::preCreate * @covers ::getAspectWeaver - * @covers ::__construct * * @param string $serviceKey * @param mixed $return @@ -39,6 +40,7 @@ public function testPostCreate( ): void { $serviceFactory = $this->createMock(ServiceFactoryInterface::class); $weaver = $this->createMock(WeaverInterface::class); + $serviceCompiler = $this->createMock(ServiceCompilerInterface::class); $serviceFactory->method('create') ->with('services.aop.aspect.weaver') ->willReturn($weaver); @@ -50,19 +52,21 @@ public function testPostCreate( $weaver->method('getCombiner') ->willReturn($this->createMock(CombinerInterface::class)); - $key = 'global'; - $services = ['pointcuts' => []]; - $internalServices = ['service-factory' => $serviceFactory]; - $subject = new ProxyHook($key, [], $services, $internalServices); + $create = function (string $key) use ($weaver, $serviceCompiler) { + if ($key === 'services.aop.aspect.weaver') { + return $weaver; + } + if ($key === 'internal.core.service.compiler') { + return $serviceCompiler; + } + }; + $subject = new ProxyHook(); + $subject->preCreate('key', 'definition', $create); $this->assertEquals( - [ - 'serviceKey' => $serviceKey, - 'return' => $expectedReturn, - 'parameters' => [] - ], - $subject->postCreate($serviceKey, $return, []) + $expectedReturn, + $subject->postCreate($serviceKey, [], $return, $create) ); }