From 1a5fba2b6e3aff0dba061b43c642adcc5884b812 Mon Sep 17 00:00:00 2001 From: Charles Sprayberry Date: Fri, 7 Jun 2024 19:24:05 -0400 Subject: [PATCH] Ensure decorator collections work, update changelog, deprecate cacheDir (#391) * Ensure decorator collections work, update changelog, deprecate cacheDir * Fix missing closure return type --- CHANGELOG.md | 46 +++++++++++++++++++ composer.lock | 25 +++++----- fixture_src/Fixtures.php | 4 ++ .../BarImplementation.php | 10 ++++ .../BazImplementation.php | 10 ++++ .../CompositeFooImplementation.php | 17 +++++++ .../FooImplementation.php | 10 ++++ .../FooInterface.php | 10 ++++ .../FooService.php | 14 ++++++ ...njectServiceCollectionDecoratorFixture.php | 43 +++++++++++++++++ known-issues.xml | 1 - .../XmlBootstrappingConfiguration.php | 7 +++ .../AurynContainerFactoryState.php | 2 +- .../IlluminateContainerFactory.php | 4 +- .../PhpDiContainerFactoryState.php | 2 +- test/Unit/ContainerFactoryTestCase.php | 29 ++++++++++++ 16 files changed, 218 insertions(+), 16 deletions(-) create mode 100644 fixture_src/InjectServiceCollectionDecorator/BarImplementation.php create mode 100644 fixture_src/InjectServiceCollectionDecorator/BazImplementation.php create mode 100644 fixture_src/InjectServiceCollectionDecorator/CompositeFooImplementation.php create mode 100644 fixture_src/InjectServiceCollectionDecorator/FooImplementation.php create mode 100644 fixture_src/InjectServiceCollectionDecorator/FooInterface.php create mode 100644 fixture_src/InjectServiceCollectionDecorator/FooService.php create mode 100644 fixture_src/InjectServiceCollectionDecoratorFixture.php diff --git a/CHANGELOG.md b/CHANGELOG.md index 8b2e136a..4f328ecb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,52 @@ 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). +## [v2.4.0](https://github.com/cspray/annotated-container/tree/v2.4.0) - 2024-06-08 + +### Added + +- Added the ability to inject a collection of services as an array or a custom collection by passing an implementation of `Cspray\AnnotatedContainer\ContainerFactory\ListOf` to an `#[Inject]` attribute. +- Added `Cspray\AnnotatedContainer\ContainerFactory\ListOfAsArray` implementation of to allow implementing a collection of services as an array out-of-the-box + +### Deprecated + +Several portions of the library will now trigger deprecation notices. These notices are to indicate you're using a feature that will be removed in 3.0. Each message will explain what feature is being used and what it is being replaced with. Some deprecations can be replaced now while others do not have suitable replacements until 3.0 is launched. + +#### Observer Removal Deprecations + +In v3 the bootstrapping Observer system is being replaced with a more complete Event system that encompasses the entire Annotated Container lifecycle. The deprecations in this section are related to the removal of this system. There is no suitable replacement until v3 hits for these deprecations. However, transitioning to the new Event system mostly involves implementing a new interface and adjusting a method signature. Your implementations should not require adjustments. + +- Providing a `Cspray\AnnotatedContainer\Bootstrap\ObserverFactory` during your bootstrapping process will trigger a deprecation. +- Calling `Cspray\AnnotatedContainer\Bootstrap::addObserver` during your bootstrapping process will trigger a deprecation. +- Extending and using the `Cspray\AnnotatedContainer\Bootstrap\ServiceWiringObserver` will trigger a deprecation. +- Providing any observers in your `annotated-container.xml` file will trigger a deprecation. + +#### Transition `ActiveProfiles` to `Profiles` + +In v3 the `Cspray\AnnotatedContainer\Profiles` module has been removed and drastically simplified. In v2.x this module was overly complicated and not designed properly for usability in mind. This led to funky code dealing with these complications and a subpar user experience. The entire module was replaced by a single value object and a set of static constructors. There is no suitable replacement until v3 hits for these deprecations. + +- Calling `Cspray\AnnotatedContainer\Profiles\ActiveProfiles::getProfiles` or `ActiveProfiles::isActive` will trigger a deprecation. +- Using the `Cspray\AnnotatedContainer\Profiles\ActiveProfilesBuilder` will trigger a deprecation. +- Calling `Cspray\AnnotatedContainer\Profiles\CsvActiveProfilesParser` will trigger a deprecation. + +#### Removing Logging + +In v3 Logging has been moved to a separate library that has to be explicitly opted in via the new Event system. Making this a separate, explicit opt-in that you must configure greatly simplifies the bootstrapping process and reduces the amount of code in Annotated Container. + +- Defining a `` configuration in `annoatated-container.xml` will trigger a deprecation. + +#### Removing Configuration Attribute + +The #[Configuration] Attribute has long been deprecated. It was not well-thought-out and the sole reason the ability to inject into properties existed. It has long been recommended to move to using the #[Service] Attribute directly or implementing your own custom attribute. + +- Defining an instance of `Cspray\AnnotatedContainer\Attribute\ConfigurationAttribute` will trigger a deprecation. + +#### Removing `cacheDir` configuration + +In v3 caching functionality is drastically improved and much more control is provided over how your ContainerDefinition is cached. This new caching system must be setup as part of your bootstrapping and can't be configured. + +- Defining a `` configuration in `annotated-container.xml` will trigger a deprecation. + ## [v2.3.0](https://github.com/cspray/annotated-container/tree/v2.3.0) - 2024-05-22 ### Changed diff --git a/composer.lock b/composer.lock index 18a6b008..db42bffd 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "d6d607cd1072543b99b52da6c574ea94", + "content-hash": "53633a34c26de6bd972e49bd8d1aeeb4", "packages": [ { "name": "brick/varexporter", @@ -971,12 +971,12 @@ "source": { "type": "git", "url": "https://github.com/Roave/SecurityAdvisories.git", - "reference": "a15ad8154eb2cc8f8f8ecb9def0f02bebee6309e" + "reference": "eaf1054e05e097721d376ba8779f55dd6247fcee" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Roave/SecurityAdvisories/zipball/a15ad8154eb2cc8f8f8ecb9def0f02bebee6309e", - "reference": "a15ad8154eb2cc8f8f8ecb9def0f02bebee6309e", + "url": "https://api.github.com/repos/Roave/SecurityAdvisories/zipball/eaf1054e05e097721d376ba8779f55dd6247fcee", + "reference": "eaf1054e05e097721d376ba8779f55dd6247fcee", "shasum": "" }, "conflict": { @@ -984,6 +984,7 @@ "admidio/admidio": "<4.2.13", "adodb/adodb-php": "<=5.20.20|>=5.21,<=5.21.3", "aheinze/cockpit": "<2.2", + "aimeos/ai-client-html": ">=2020.04.1,<2020.10.27|>=2021.04.1,<2021.10.21|>=2022.04.1,<2022.10.12|>=2023.04.1,<2023.10.14|>=2024.04.1,<2024.04.4", "aimeos/aimeos-core": ">=2022.04.1,<2022.10.17|>=2023.04.1,<2023.10.17|>=2024.04.1,<2024.04.7", "aimeos/aimeos-typo3": "<19.10.12|>=20,<20.10.5", "airesvsg/acf-to-rest-api": "<=3.1", @@ -1035,6 +1036,7 @@ "bmarshall511/wordpress_zero_spam": "<5.2.13", "bolt/bolt": "<3.7.2", "bolt/core": "<=4.2", + "born05/craft-twofactorauthentication": "<3.3.4", "bottelet/flarepoint": "<2.2.1", "bref/bref": "<2.1.17", "brightlocal/phpwhois": "<=4.2.5", @@ -1103,7 +1105,7 @@ "doctrine/mongodb-odm": "<1.0.2", "doctrine/mongodb-odm-bundle": "<3.0.1", "doctrine/orm": ">=1,<1.2.4|>=2,<2.4.8|>=2.5,<2.5.1|>=2.8.3,<2.8.4", - "dolibarr/dolibarr": "<=19", + "dolibarr/dolibarr": "<19.0.2", "dompdf/dompdf": "<2.0.4", "doublethreedigital/guest-entries": "<3.1.2", "drupal/core": ">=6,<6.38|>=7,<7.96|>=8,<10.1.8|>=10.2,<10.2.2", @@ -1327,7 +1329,7 @@ "mojo42/jirafeau": "<4.4", "mongodb/mongodb": ">=1,<1.9.2", "monolog/monolog": ">=1.8,<1.12", - "moodle/moodle": "<=4.3.3", + "moodle/moodle": "<4.3.4", "mos/cimage": "<0.7.19", "movim/moxl": ">=0.8,<=0.10", "movingbytes/social-network": "<=1.2.1", @@ -1422,13 +1424,13 @@ "phpxmlrpc/extras": "<0.6.1", "phpxmlrpc/phpxmlrpc": "<4.9.2", "pi/pi": "<=2.5", - "pimcore/admin-ui-classic-bundle": "<1.3.4", + "pimcore/admin-ui-classic-bundle": "<=1.4.2", "pimcore/customer-management-framework-bundle": "<4.0.6", "pimcore/data-hub": "<1.2.4", "pimcore/demo": "<10.3", "pimcore/ecommerce-framework-bundle": "<1.0.10", "pimcore/perspective-editor": "<1.5.1", - "pimcore/pimcore": "<11.1.6.5-dev|>=11.2,<11.2.3", + "pimcore/pimcore": "<11.2.4", "pixelfed/pixelfed": "<0.11.11", "plotly/plotly.js": "<2.25.2", "pocketmine/bedrock-protocol": "<8.0.2", @@ -1535,6 +1537,7 @@ "studio-42/elfinder": "<2.1.62", "subhh/libconnect": "<7.0.8|>=8,<8.1", "sukohi/surpass": "<1", + "sulu/form-bundle": ">=2,<2.5.3", "sulu/sulu": "<1.6.44|>=2,<2.4.17|>=2.5,<2.5.13", "sumocoders/framework-user-bundle": "<1.4", "superbig/craft-audit": "<3.0.2", @@ -1677,7 +1680,7 @@ "yidashi/yii2cmf": "<=2", "yii2mod/yii2-cms": "<1.9.2", "yiisoft/yii": "<1.1.29", - "yiisoft/yii2": "<=2.0.49|==2.0.49.3", + "yiisoft/yii2": "<2.0.50", "yiisoft/yii2-authclient": "<2.2.15", "yiisoft/yii2-bootstrap": "<2.0.4", "yiisoft/yii2-dev": "<2.0.43", @@ -1763,7 +1766,7 @@ "type": "tidelift" } ], - "time": "2024-06-02T23:04:59+00:00" + "time": "2024-06-06T22:04:19+00:00" } ], "aliases": [], @@ -1780,5 +1783,5 @@ "composer-runtime-api": "^2" }, "platform-dev": [], - "plugin-api-version": "2.2.0" + "plugin-api-version": "2.6.0" } diff --git a/fixture_src/Fixtures.php b/fixture_src/Fixtures.php index 5780bf29..f6a4fc48 100755 --- a/fixture_src/Fixtures.php +++ b/fixture_src/Fixtures.php @@ -202,4 +202,8 @@ public static function injectServiceDomainCollection() : InjectServiceDomainColl return new InjectServiceDomainCollectionFixture(); } + public static function injectServiceCollectionDecorator() : InjectServiceCollectionDecoratorFixture { + return new InjectServiceCollectionDecoratorFixture(); + } + } \ No newline at end of file diff --git a/fixture_src/InjectServiceCollectionDecorator/BarImplementation.php b/fixture_src/InjectServiceCollectionDecorator/BarImplementation.php new file mode 100644 index 00000000..6c0e7106 --- /dev/null +++ b/fixture_src/InjectServiceCollectionDecorator/BarImplementation.php @@ -0,0 +1,10 @@ + - $container->call([$target, $delegateInfo['delegateMethod']])]]> diff --git a/src/Bootstrap/XmlBootstrappingConfiguration.php b/src/Bootstrap/XmlBootstrappingConfiguration.php index ba671a2f..f07a2e5a 100644 --- a/src/Bootstrap/XmlBootstrappingConfiguration.php +++ b/src/Bootstrap/XmlBootstrappingConfiguration.php @@ -173,6 +173,13 @@ public function __construct( $cache = $cacheDirNodes[0]->textContent; } + if ($cache !== null) { + trigger_error( + 'A cache directory is defined in your configuration. The ability to define a cache through configuration is removed in v3 and must setup as part of your bootstrapping code.', + E_USER_DEPRECATED + ); + } + $loggingFileNodes = $xpath->query('/ac:annotatedContainer/ac:logging/ac:file/text()'); $loggingStdoutNodes = $xpath->query('/ac:annotatedContainer/ac:logging/ac:stdout'); $logger = null; diff --git a/src/ContainerFactory/AurynContainerFactoryState.php b/src/ContainerFactory/AurynContainerFactoryState.php index 09e67998..a665b0ac 100644 --- a/src/ContainerFactory/AurynContainerFactoryState.php +++ b/src/ContainerFactory/AurynContainerFactoryState.php @@ -47,7 +47,7 @@ public function addMethodInject(string $class, string $method, string $param, mi $key = '+' . $param; $values = []; foreach ($this->containerDefinition->getServiceDefinitions() as $serviceDefinition) { - if ($serviceDefinition->isAbstract()) { + if ($serviceDefinition->isAbstract() || $serviceDefinition->getType()->getName() === $class) { continue; } diff --git a/src/ContainerFactory/IlluminateContainerFactory.php b/src/ContainerFactory/IlluminateContainerFactory.php index 3dcfa5c4..c9965d48 100644 --- a/src/ContainerFactory/IlluminateContainerFactory.php +++ b/src/ContainerFactory/IlluminateContainerFactory.php @@ -178,10 +178,10 @@ protected function createAnnotatedContainer(ContainerFactoryState $state, Active $container->when($service) ->needs($paramIdentifier) - ->give(function() use($state, $container, $value) { + ->give(function() use($state, $container, $value, $service): mixed { $values = []; foreach ($state->containerDefinition->getServiceDefinitions() as $serviceDefinition) { - if ($serviceDefinition->isAbstract()) { + if ($serviceDefinition->isAbstract() || $serviceDefinition->getType()->getName() === $service) { continue; } diff --git a/src/ContainerFactory/PhpDiContainerFactoryState.php b/src/ContainerFactory/PhpDiContainerFactoryState.php index 8a912909..d8fbb55d 100644 --- a/src/ContainerFactory/PhpDiContainerFactoryState.php +++ b/src/ContainerFactory/PhpDiContainerFactoryState.php @@ -48,7 +48,7 @@ public function addMethodInject(string $class, string $method, string $param, mi if ($value instanceof ServiceCollectorReference) { $values = []; foreach ($this->containerDefinition->getServiceDefinitions() as $serviceDefinition) { - if ($serviceDefinition->isAbstract()) { + if ($serviceDefinition->isAbstract() || $serviceDefinition->getType()->getName() === $class) { continue; } diff --git a/test/Unit/ContainerFactoryTestCase.php b/test/Unit/ContainerFactoryTestCase.php index 7e51e905..6da3e11b 100644 --- a/test/Unit/ContainerFactoryTestCase.php +++ b/test/Unit/ContainerFactoryTestCase.php @@ -1000,4 +1000,33 @@ public function testCreatingServiceWithInjectServiceDomainCollection() : void { $collectionInjector->collection->services ); } + + public function testCreatingServiceWithInjectServiceCollectionDecorator() : void { + $container = $this->getContainer(Fixtures::injectServiceCollectionDecorator()->getPath()); + + $fooService = $container->get(Fixtures::injectServiceCollectionDecorator()->fooService()->getName()); + + self::assertInstanceOf( + Fixtures::injectServiceCollectionDecorator()->fooService()->getName(), + $fooService + ); + self::assertInstanceOf( + Fixtures::injectServiceCollectionDecorator()->compositeFoo()->getName(), + $fooService->foo + ); + self::assertCount(3, $fooService->foo->foos); + $fooClasses = array_map(static fn(object $foo) => $foo::class, $fooService->foo->foos); + self::assertContains( + Fixtures::injectServiceCollectionDecorator()->fooImplementation()->getName(), + $fooClasses + ); + self::assertContains( + Fixtures::injectServiceCollectionDecorator()->barImplementation()->getName(), + $fooClasses + ); + self::assertContains( + Fixtures::injectServiceCollectionDecorator()->bazImplementation()->getName(), + $fooClasses + ); + } }