From 86796883e71da9f68eeddf88e6bfd89234007359 Mon Sep 17 00:00:00 2001 From: Dmitrii Derepko Date: Sun, 20 Nov 2022 11:26:47 +0300 Subject: [PATCH 01/25] Add lazy definition --- src/LazyDefinitionDecorator.php | 30 ++++++++++ tests/Unit/LazyDefinitionDecoratorTest.php | 69 ++++++++++++++++++++++ 2 files changed, 99 insertions(+) create mode 100644 src/LazyDefinitionDecorator.php create mode 100644 tests/Unit/LazyDefinitionDecoratorTest.php diff --git a/src/LazyDefinitionDecorator.php b/src/LazyDefinitionDecorator.php new file mode 100644 index 0000000..82e4dc1 --- /dev/null +++ b/src/LazyDefinitionDecorator.php @@ -0,0 +1,30 @@ +factory->createProxy( + $this->objectClass, + function (&$wrappedObject) use ($container) { + $wrappedObject = $this->definition->resolve($container); + } + ); + } +} diff --git a/tests/Unit/LazyDefinitionDecoratorTest.php b/tests/Unit/LazyDefinitionDecoratorTest.php new file mode 100644 index 0000000..39e8b43 --- /dev/null +++ b/tests/Unit/LazyDefinitionDecoratorTest.php @@ -0,0 +1,69 @@ + $class, + ]); + $definition = new LazyDefinitionDecorator($factory, $definition, $class); + + $this->expectException(InvalidProxiedClassException::class); + $definition->resolve($container); + } + + public function testDecorateNotFinalClass(): void + { + $container = new SimpleContainer(); + $factory = new LazyLoadingValueHolderFactory(); + + $class = NotFinalClass::class; + + $definition = ArrayDefinition::fromConfig([ + ArrayDefinition::CLASS_NAME => $class, + ]); + $definition = new LazyDefinitionDecorator($factory, $definition, $class); + + $phone = $definition->resolve($container); + + self::assertInstanceOf(LazyLoadingInterface::class, $phone); + } + + public function testDecorateInterface(): void + { + $container = new SimpleContainer(); + $factory = new LazyLoadingValueHolderFactory(); + + $class = EngineInterface::class; + + $definition = ArrayDefinition::fromConfig([ + ArrayDefinition::CLASS_NAME => $class, + ]); + $definition = new LazyDefinitionDecorator($factory, $definition, $class); + + $phone = $definition->resolve($container); + + self::assertInstanceOf(LazyLoadingInterface::class, $phone); + } +} From a783c5d300cfd07006555b4c1f76e5b99ae282c3 Mon Sep 17 00:00:00 2001 From: StyleCI Bot Date: Sun, 20 Nov 2022 08:27:05 +0000 Subject: [PATCH 02/25] Apply fixes from StyleCI --- src/LazyDefinitionDecorator.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/LazyDefinitionDecorator.php b/src/LazyDefinitionDecorator.php index 82e4dc1..56f2f7d 100644 --- a/src/LazyDefinitionDecorator.php +++ b/src/LazyDefinitionDecorator.php @@ -14,8 +14,7 @@ public function __construct( private LazyLoadingValueHolderFactory $factory, private DefinitionInterface $definition, private string $objectClass, - ) - { + ) { } public function resolve(ContainerInterface $container): mixed From 5ccf19c4ee5c7e9edc65570631c8e9863bf831f6 Mon Sep 17 00:00:00 2001 From: Dmitrii Derepko Date: Sun, 20 Nov 2022 11:35:38 +0300 Subject: [PATCH 03/25] Add missed files --- composer.json | 1 + src/LazyDefinitionDecorator.php | 5 +++-- tests/Support/NotFinalClass.php | 20 ++++++++++++++++++++ tests/Unit/LazyDefinitionDecoratorTest.php | 6 +++--- 4 files changed, 27 insertions(+), 5 deletions(-) create mode 100644 tests/Support/NotFinalClass.php diff --git a/composer.json b/composer.json index fc29b58..be0a916 100644 --- a/composer.json +++ b/composer.json @@ -31,6 +31,7 @@ }, "require-dev": { "maglnet/composer-require-checker": "^4.2", + "ocramius/proxy-manager": "^2.14.1", "phpunit/phpunit": "^9.5", "rector/rector": "^0.14.3", "roave/infection-static-analysis-plugin": "^1.18", diff --git a/src/LazyDefinitionDecorator.php b/src/LazyDefinitionDecorator.php index 82e4dc1..7e7db16 100644 --- a/src/LazyDefinitionDecorator.php +++ b/src/LazyDefinitionDecorator.php @@ -7,12 +7,13 @@ use ProxyManager\Factory\LazyLoadingValueHolderFactory; use Psr\Container\ContainerInterface; use Yiisoft\Definitions\Contract\DefinitionInterface; +use Yiisoft\Definitions\Helpers\DefinitionResolver; final class LazyDefinitionDecorator implements DefinitionInterface { public function __construct( private LazyLoadingValueHolderFactory $factory, - private DefinitionInterface $definition, + private mixed $definition, private string $objectClass, ) { @@ -23,7 +24,7 @@ public function resolve(ContainerInterface $container): mixed return $this->factory->createProxy( $this->objectClass, function (&$wrappedObject) use ($container) { - $wrappedObject = $this->definition->resolve($container); + $wrappedObject = DefinitionResolver::resolve($container, null, $this->definition); } ); } diff --git a/tests/Support/NotFinalClass.php b/tests/Support/NotFinalClass.php new file mode 100644 index 0000000..636d486 --- /dev/null +++ b/tests/Support/NotFinalClass.php @@ -0,0 +1,20 @@ +arguments = $arguments; + } + + public function getArguments(): array + { + return $this->arguments; + } +} diff --git a/tests/Unit/LazyDefinitionDecoratorTest.php b/tests/Unit/LazyDefinitionDecoratorTest.php index 39e8b43..5a87e45 100644 --- a/tests/Unit/LazyDefinitionDecoratorTest.php +++ b/tests/Unit/LazyDefinitionDecoratorTest.php @@ -10,9 +10,9 @@ use ProxyManager\Proxy\LazyLoadingInterface; use Yiisoft\Definitions\ArrayDefinition; use Yiisoft\Definitions\LazyDefinitionDecorator; -use Yiisoft\Factory\Tests\Support\EngineInterface; -use Yiisoft\Factory\Tests\Support\NotFinalClass; -use Yiisoft\Factory\Tests\Support\Phone; +use Yiisoft\Definitions\Tests\Support\EngineInterface; +use Yiisoft\Definitions\Tests\Support\NotFinalClass; +use Yiisoft\Definitions\Tests\Support\Phone; use Yiisoft\Test\Support\Container\SimpleContainer; final class LazyDefinitionDecoratorTest extends TestCase From 5d6b89fb2827843a846b6a5a10e79a39c0a9e6e2 Mon Sep 17 00:00:00 2001 From: Dmitrii Derepko Date: Sun, 20 Nov 2022 11:49:57 +0300 Subject: [PATCH 04/25] Fix decorator --- src/Helpers/Normalizer.php | 6 +++++- src/LazyDefinitionDecorator.php | 6 ++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/Helpers/Normalizer.php b/src/Helpers/Normalizer.php index 6747deb..5d4171f 100644 --- a/src/Helpers/Normalizer.php +++ b/src/Helpers/Normalizer.php @@ -87,8 +87,12 @@ public static function normalize(mixed $definition, ?string $class = null): Defi return ArrayDefinition::fromConfig($config); } + if ($definition instanceof DefinitionInterface) { + return $definition; + } + // Ready object - if (is_object($definition) && !($definition instanceof DefinitionInterface)) { + if (is_object($definition)) { return new ValueDefinition($definition); } diff --git a/src/LazyDefinitionDecorator.php b/src/LazyDefinitionDecorator.php index ec4ee20..0e6e36f 100644 --- a/src/LazyDefinitionDecorator.php +++ b/src/LazyDefinitionDecorator.php @@ -7,7 +7,7 @@ use ProxyManager\Factory\LazyLoadingValueHolderFactory; use Psr\Container\ContainerInterface; use Yiisoft\Definitions\Contract\DefinitionInterface; -use Yiisoft\Definitions\Helpers\DefinitionResolver; +use Yiisoft\Di\Helpers\DefinitionNormalizer; final class LazyDefinitionDecorator implements DefinitionInterface { @@ -23,7 +23,9 @@ public function resolve(ContainerInterface $container): mixed return $this->factory->createProxy( $this->objectClass, function (&$wrappedObject) use ($container) { - $wrappedObject = DefinitionResolver::resolve($container, null, $this->definition); + $definition = DefinitionNormalizer::normalize($this->definition, $this->objectClass); + + $wrappedObject = $definition->resolve($container); } ); } From f5225c2be1cbf4ebe100f048b679fcef547b8775 Mon Sep 17 00:00:00 2001 From: rector-bot Date: Sun, 20 Nov 2022 08:52:10 +0000 Subject: [PATCH 05/25] [ci-review] Apply changes from Rector action. --- src/Reference.php | 6 +----- tests/Unit/DefinitionStorageTest.php | 1 + tests/Unit/Helpers/DefinitionResolverTest.php | 1 + 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/Reference.php b/src/Reference.php index 4650ac4..fd58541 100644 --- a/src/Reference.php +++ b/src/Reference.php @@ -29,21 +29,17 @@ final class Reference implements ReferenceInterface { private string $id; - private bool $optional; /** - * @param mixed $id - * * @throws InvalidConfigException */ - private function __construct(mixed $id, bool $optional) + private function __construct(mixed $id, private bool $optional) { if (!is_string($id)) { throw new InvalidConfigException('Reference ID must be string.'); } $this->id = $id; - $this->optional = $optional; } /** diff --git a/tests/Unit/DefinitionStorageTest.php b/tests/Unit/DefinitionStorageTest.php index ef754bd..54f2a1d 100644 --- a/tests/Unit/DefinitionStorageTest.php +++ b/tests/Unit/DefinitionStorageTest.php @@ -229,6 +229,7 @@ public function testSelfCircular(): void public function testBuildStackOnThrowException(): void { + $stack = null; $storage = new DefinitionStorage(); try { diff --git a/tests/Unit/Helpers/DefinitionResolverTest.php b/tests/Unit/Helpers/DefinitionResolverTest.php index 3ca5f26..3b07274 100644 --- a/tests/Unit/Helpers/DefinitionResolverTest.php +++ b/tests/Unit/Helpers/DefinitionResolverTest.php @@ -52,6 +52,7 @@ public function testEnsureResolvableDefinition(): void public function testCustomArrayOfDefinitions(): void { + $definitions = []; $container = new SimpleContainer([ 'int' => 42, ]); From 8dbcf888c29f91116496763b1bb98cbcaa5a4a77 Mon Sep 17 00:00:00 2001 From: Dmitrii Derepko Date: Sun, 20 Nov 2022 11:53:49 +0300 Subject: [PATCH 06/25] Add suggest section --- composer.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/composer.json b/composer.json index be0a916..c097cce 100644 --- a/composer.json +++ b/composer.json @@ -39,6 +39,9 @@ "vimeo/psalm": "^4.22", "yiisoft/test-support": "^1.4" }, + "suggest": { + "ocramius/proxy-manager": "Allows create proxy classes" + }, "autoload": { "psr-4": { "Yiisoft\\Definitions\\": "src" From f034ae088603e51aaa78943dde5b3caa3f2718b0 Mon Sep 17 00:00:00 2001 From: Dmitrii Derepko Date: Sat, 3 Dec 2022 17:56:56 +0300 Subject: [PATCH 07/25] Use `friendsofphp/proxy-manager-lts` package --- composer.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/composer.json b/composer.json index c097cce..f1a6f65 100644 --- a/composer.json +++ b/composer.json @@ -31,7 +31,7 @@ }, "require-dev": { "maglnet/composer-require-checker": "^4.2", - "ocramius/proxy-manager": "^2.14.1", + "friendsofphp/proxy-manager-lts": "^1.0", "phpunit/phpunit": "^9.5", "rector/rector": "^0.14.3", "roave/infection-static-analysis-plugin": "^1.18", @@ -40,7 +40,7 @@ "yiisoft/test-support": "^1.4" }, "suggest": { - "ocramius/proxy-manager": "Allows create proxy classes" + "friendsofphp/proxy-manager-lts": "Allows create proxy classes" }, "autoload": { "psr-4": { From e03e225d9a8d645d7fe68269c77e20835a679c30 Mon Sep 17 00:00:00 2001 From: Dmitrii Derepko Date: Sat, 3 Dec 2022 19:33:52 +0300 Subject: [PATCH 08/25] Rework lazy definition --- ...nitionDecorator.php => LazyDefinition.php} | 14 ++++++----- tests/Unit/ArrayDefinitionTest.php | 16 +++++++++++++ tests/Unit/LazyDefinitionDecoratorTest.php | 23 +++++++++++-------- 3 files changed, 37 insertions(+), 16 deletions(-) rename src/{LazyDefinitionDecorator.php => LazyDefinition.php} (54%) diff --git a/src/LazyDefinitionDecorator.php b/src/LazyDefinition.php similarity index 54% rename from src/LazyDefinitionDecorator.php rename to src/LazyDefinition.php index 0e6e36f..912b64a 100644 --- a/src/LazyDefinitionDecorator.php +++ b/src/LazyDefinition.php @@ -9,10 +9,9 @@ use Yiisoft\Definitions\Contract\DefinitionInterface; use Yiisoft\Di\Helpers\DefinitionNormalizer; -final class LazyDefinitionDecorator implements DefinitionInterface +final class LazyDefinition implements DefinitionInterface { public function __construct( - private LazyLoadingValueHolderFactory $factory, private mixed $definition, private string $objectClass, ) { @@ -20,11 +19,14 @@ public function __construct( public function resolve(ContainerInterface $container): mixed { - return $this->factory->createProxy( - $this->objectClass, - function (&$wrappedObject) use ($container) { - $definition = DefinitionNormalizer::normalize($this->definition, $this->objectClass); + $factory = $container->get(LazyLoadingValueHolderFactory::class); + $definition = $this->definition; + $objectClass = $this->objectClass; + return $factory->createProxy( + $objectClass, + function (&$wrappedObject) use ($container, $objectClass, $definition) { + $definition = DefinitionNormalizer::normalize($definition, $objectClass); $wrappedObject = $definition->resolve($container); } ); diff --git a/tests/Unit/ArrayDefinitionTest.php b/tests/Unit/ArrayDefinitionTest.php index 796b057..1445e56 100644 --- a/tests/Unit/ArrayDefinitionTest.php +++ b/tests/Unit/ArrayDefinitionTest.php @@ -6,6 +6,7 @@ use InvalidArgumentException; use PHPUnit\Framework\TestCase; +use TypeError; use Yiisoft\Definitions\ArrayDefinition; use Yiisoft\Definitions\Exception\InvalidConfigException; use Yiisoft\Definitions\Reference; @@ -523,4 +524,19 @@ public function testMagicMethods(): void $object->getEvents() ); } + + public function testNonArrayArguments(): void + { + $definition = ArrayDefinition::fromConfig([ + ArrayDefinition::CLASS_NAME => Mouse::class, + 'setNameAndEngine()' => 'kitty', + ]); + $container = new SimpleContainer(); + + $this->expectException(TypeError::class); + $this->expectExceptionMessage( + 'Yiisoft\Definitions\ArrayDefinition::resolveFunctionArguments(): Argument #3 ($arguments) must be of type array, string given' + ); + $definition->resolve($container); + } } diff --git a/tests/Unit/LazyDefinitionDecoratorTest.php b/tests/Unit/LazyDefinitionDecoratorTest.php index 5a87e45..daad1b1 100644 --- a/tests/Unit/LazyDefinitionDecoratorTest.php +++ b/tests/Unit/LazyDefinitionDecoratorTest.php @@ -9,7 +9,7 @@ use ProxyManager\Factory\LazyLoadingValueHolderFactory; use ProxyManager\Proxy\LazyLoadingInterface; use Yiisoft\Definitions\ArrayDefinition; -use Yiisoft\Definitions\LazyDefinitionDecorator; +use Yiisoft\Definitions\LazyDefinition; use Yiisoft\Definitions\Tests\Support\EngineInterface; use Yiisoft\Definitions\Tests\Support\NotFinalClass; use Yiisoft\Definitions\Tests\Support\Phone; @@ -19,15 +19,16 @@ final class LazyDefinitionDecoratorTest extends TestCase { public function testDecorateFinalClass(): void { - $container = new SimpleContainer(); - $factory = new LazyLoadingValueHolderFactory(); + $container = new SimpleContainer([ + LazyLoadingValueHolderFactory::class => new LazyLoadingValueHolderFactory(), + ]); $class = Phone::class; $definition = ArrayDefinition::fromConfig([ ArrayDefinition::CLASS_NAME => $class, ]); - $definition = new LazyDefinitionDecorator($factory, $definition, $class); + $definition = new LazyDefinition($definition, $class); $this->expectException(InvalidProxiedClassException::class); $definition->resolve($container); @@ -35,15 +36,16 @@ public function testDecorateFinalClass(): void public function testDecorateNotFinalClass(): void { - $container = new SimpleContainer(); - $factory = new LazyLoadingValueHolderFactory(); + $container = new SimpleContainer([ + LazyLoadingValueHolderFactory::class => new LazyLoadingValueHolderFactory(), + ]); $class = NotFinalClass::class; $definition = ArrayDefinition::fromConfig([ ArrayDefinition::CLASS_NAME => $class, ]); - $definition = new LazyDefinitionDecorator($factory, $definition, $class); + $definition = new LazyDefinition($definition, $class); $phone = $definition->resolve($container); @@ -52,15 +54,16 @@ public function testDecorateNotFinalClass(): void public function testDecorateInterface(): void { - $container = new SimpleContainer(); - $factory = new LazyLoadingValueHolderFactory(); + $container = new SimpleContainer([ + LazyLoadingValueHolderFactory::class => new LazyLoadingValueHolderFactory(), + ]); $class = EngineInterface::class; $definition = ArrayDefinition::fromConfig([ ArrayDefinition::CLASS_NAME => $class, ]); - $definition = new LazyDefinitionDecorator($factory, $definition, $class); + $definition = new LazyDefinition($definition, $class); $phone = $definition->resolve($container); From 6a8f40e4309c94d43d3150c77657a6f3894fb9cf Mon Sep 17 00:00:00 2001 From: StyleCI Bot Date: Sat, 1 Jul 2023 13:55:06 +0000 Subject: [PATCH 09/25] Apply fixes from StyleCI --- src/CallableDefinition.php | 1 + src/DynamicReferencesArray.php | 1 + src/Helpers/DefinitionExtractor.php | 2 ++ src/ReferencesArray.php | 1 + 4 files changed, 5 insertions(+) diff --git a/src/CallableDefinition.php b/src/CallableDefinition.php index 3d9edce..e3542eb 100644 --- a/src/CallableDefinition.php +++ b/src/CallableDefinition.php @@ -25,6 +25,7 @@ final class CallableDefinition implements DefinitionInterface { /** * @var array|callable + * * @psalm-var callable|array{0:class-string,1:string} */ private $callable; diff --git a/src/DynamicReferencesArray.php b/src/DynamicReferencesArray.php index 056601f..0b183af 100644 --- a/src/DynamicReferencesArray.php +++ b/src/DynamicReferencesArray.php @@ -68,6 +68,7 @@ final class DynamicReferencesArray * @throws InvalidConfigException * * @return DynamicReference[] + * * @psalm-suppress DocblockTypeContradiction */ public static function from(array $ids): array diff --git a/src/Helpers/DefinitionExtractor.php b/src/Helpers/DefinitionExtractor.php index c0f68fd..052ae6f 100644 --- a/src/Helpers/DefinitionExtractor.php +++ b/src/Helpers/DefinitionExtractor.php @@ -32,6 +32,7 @@ final class DefinitionExtractor * @throws NotInstantiableException * * @return ParameterDefinition[] + * * @psalm-return array */ public static function fromClassName(string $class): array @@ -61,6 +62,7 @@ public static function fromClassName(string $class): array * Extract dependency definitions from type hints of a function. * * @return ParameterDefinition[] + * * @psalm-return array */ public static function fromFunction(ReflectionFunctionAbstract $reflectionFunction): array diff --git a/src/ReferencesArray.php b/src/ReferencesArray.php index ccf873e..d098dfa 100644 --- a/src/ReferencesArray.php +++ b/src/ReferencesArray.php @@ -67,6 +67,7 @@ final class ReferencesArray * @throws InvalidConfigException * * @return Reference[] + * * @psalm-suppress DocblockTypeContradiction */ public static function from(array $ids): array From de1c7e8470aaeeddfd40f6e12318c8cc9d62bd40 Mon Sep 17 00:00:00 2001 From: xepozz Date: Sat, 29 Jul 2023 14:06:26 +0000 Subject: [PATCH 10/25] Apply Rector changes (CI) --- tests/Support/NotFinalClass.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Support/NotFinalClass.php b/tests/Support/NotFinalClass.php index 636d486..25f7512 100644 --- a/tests/Support/NotFinalClass.php +++ b/tests/Support/NotFinalClass.php @@ -6,7 +6,7 @@ class NotFinalClass { - private $arguments; + private array $arguments; public function __construct(...$arguments) { From bd65bf9b95111d1f69243a34f77453b6081d5f6c Mon Sep 17 00:00:00 2001 From: Dmitrii Derepko Date: Sat, 29 Jul 2023 17:06:31 +0300 Subject: [PATCH 11/25] Add php 8.2 in CI --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 8506ea1..ed9a60b 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -28,4 +28,4 @@ jobs: os: >- ['ubuntu-latest', 'windows-latest'] php: >- - ['8.0', '8.1'] + ['8.0', '8.1', '8.2'] From fba80b0aa9a90fb8221e561c931b49288f24620b Mon Sep 17 00:00:00 2001 From: Dmitrii Derepko Date: Sat, 29 Jul 2023 17:06:56 +0300 Subject: [PATCH 12/25] Add php 8.2 in CI --- .github/workflows/mutation.yml | 2 +- .github/workflows/static.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/mutation.yml b/.github/workflows/mutation.yml index c1aca98..f9fd931 100644 --- a/.github/workflows/mutation.yml +++ b/.github/workflows/mutation.yml @@ -26,6 +26,6 @@ jobs: os: >- ['ubuntu-latest'] php: >- - ['8.1'] + ['8.1', '8.2'] secrets: STRYKER_DASHBOARD_API_KEY: ${{ secrets.STRYKER_DASHBOARD_API_KEY }} diff --git a/.github/workflows/static.yml b/.github/workflows/static.yml index 96b2679..fb7fc77 100644 --- a/.github/workflows/static.yml +++ b/.github/workflows/static.yml @@ -28,4 +28,4 @@ jobs: os: >- ['ubuntu-latest'] php: >- - ['8.0', '8.1'] + ['8.0', '8.1', '8.2'] From 4ced43c489dc278f805fd41ef8c3f36c395c0988 Mon Sep 17 00:00:00 2001 From: Dmitrii Derepko Date: Sat, 29 Jul 2023 17:38:34 +0300 Subject: [PATCH 13/25] Fix tests and psalm errors --- src/LazyDefinition.php | 20 ++++++++++++++++--- tests/Unit/Helpers/DefinitionResolverTest.php | 2 +- .../Unit/Helpers/DefinitionValidatorTest.php | 2 +- 3 files changed, 19 insertions(+), 5 deletions(-) diff --git a/src/LazyDefinition.php b/src/LazyDefinition.php index 912b64a..de82f04 100644 --- a/src/LazyDefinition.php +++ b/src/LazyDefinition.php @@ -7,26 +7,40 @@ use ProxyManager\Factory\LazyLoadingValueHolderFactory; use Psr\Container\ContainerInterface; use Yiisoft\Definitions\Contract\DefinitionInterface; -use Yiisoft\Di\Helpers\DefinitionNormalizer; +use Yiisoft\Definitions\Helpers\Normalizer; final class LazyDefinition implements DefinitionInterface { public function __construct( private mixed $definition, + /** + * @var class-string + */ private string $objectClass, ) { } + /** + * @psalm-suppress MixedArgumentTypeCoercion + */ public function resolve(ContainerInterface $container): mixed { + /** @var LazyLoadingValueHolderFactory $factory */ $factory = $container->get(LazyLoadingValueHolderFactory::class); + /** + * @var mixed $definition + */ $definition = $this->definition; $objectClass = $this->objectClass; + /** @psalm-suppress InvalidArgument */ return $factory->createProxy( $objectClass, - function (&$wrappedObject) use ($container, $objectClass, $definition) { - $definition = DefinitionNormalizer::normalize($definition, $objectClass); + function (mixed &$wrappedObject) use ($container, $objectClass, $definition) { + $definition = Normalizer::normalize($definition, $objectClass); + /** + * @var mixed $wrappedObject + */ $wrappedObject = $definition->resolve($container); } ); diff --git a/tests/Unit/Helpers/DefinitionResolverTest.php b/tests/Unit/Helpers/DefinitionResolverTest.php index 3b07274..6a611eb 100644 --- a/tests/Unit/Helpers/DefinitionResolverTest.php +++ b/tests/Unit/Helpers/DefinitionResolverTest.php @@ -45,7 +45,7 @@ public function testEnsureResolvableDefinition(): void $this->expectException(InvalidConfigException::class); $this->expectExceptionMessage( 'Only references are allowed in constructor arguments, a definition object was provided: ' . - ValueDefinition::class + var_export(new ValueDefinition(7), true) ); DefinitionResolver::ensureResolvable(new ValueDefinition(7)); } diff --git a/tests/Unit/Helpers/DefinitionValidatorTest.php b/tests/Unit/Helpers/DefinitionValidatorTest.php index 72c665f..7b4dc60 100644 --- a/tests/Unit/Helpers/DefinitionValidatorTest.php +++ b/tests/Unit/Helpers/DefinitionValidatorTest.php @@ -311,7 +311,7 @@ public function testDefinitionInArguments(): void $this->expectException(InvalidConfigException::class); $this->expectExceptionMessage( 'Only references are allowed in constructor arguments, a definition object was provided: ' . - ValueDefinition::class + var_export(new ValueDefinition(56), true) ); DefinitionValidator::validate([ 'class' => GearBox::class, From 2ca1b5e18a3813f22134305b02c0b2ffb1ec3db6 Mon Sep 17 00:00:00 2001 From: Dmitriy Derepko Date: Tue, 1 Aug 2023 22:16:11 +0300 Subject: [PATCH 14/25] Apply suggestions from code review Co-authored-by: Sergei Predvoditelev --- composer.json | 2 +- tests/Unit/LazyDefinitionDecoratorTest.php | 15 +++------------ 2 files changed, 4 insertions(+), 13 deletions(-) diff --git a/composer.json b/composer.json index f8ffac7..e6301fd 100644 --- a/composer.json +++ b/composer.json @@ -40,7 +40,7 @@ "yiisoft/test-support": "^1.4" }, "suggest": { - "friendsofphp/proxy-manager-lts": "Allows create proxy classes" + "friendsofphp/proxy-manager-lts": "Allows use lazy definitions" }, "autoload": { "psr-4": { diff --git a/tests/Unit/LazyDefinitionDecoratorTest.php b/tests/Unit/LazyDefinitionDecoratorTest.php index daad1b1..6824a2e 100644 --- a/tests/Unit/LazyDefinitionDecoratorTest.php +++ b/tests/Unit/LazyDefinitionDecoratorTest.php @@ -25,10 +25,7 @@ public function testDecorateFinalClass(): void $class = Phone::class; - $definition = ArrayDefinition::fromConfig([ - ArrayDefinition::CLASS_NAME => $class, - ]); - $definition = new LazyDefinition($definition, $class); + $definition = new LazyDefinition([ArrayDefinition::CLASS_NAME => $class], $class); $this->expectException(InvalidProxiedClassException::class); $definition->resolve($container); @@ -42,10 +39,7 @@ public function testDecorateNotFinalClass(): void $class = NotFinalClass::class; - $definition = ArrayDefinition::fromConfig([ - ArrayDefinition::CLASS_NAME => $class, - ]); - $definition = new LazyDefinition($definition, $class); + $definition = new LazyDefinition([ArrayDefinition::CLASS_NAME => $class], $class); $phone = $definition->resolve($container); @@ -60,10 +54,7 @@ public function testDecorateInterface(): void $class = EngineInterface::class; - $definition = ArrayDefinition::fromConfig([ - ArrayDefinition::CLASS_NAME => $class, - ]); - $definition = new LazyDefinition($definition, $class); + $definition = new LazyDefinition([ArrayDefinition::CLASS_NAME => $class], $class); $phone = $definition->resolve($container); From e1d409314a89a290f893de1dc2bacc3d8de2eddf Mon Sep 17 00:00:00 2001 From: Dmitrii Derepko Date: Tue, 1 Aug 2023 22:27:42 +0300 Subject: [PATCH 15/25] Apply PR suggestions --- .github/workflows/mutation.yml | 2 +- src/Helpers/Normalizer.php | 6 +----- src/LazyDefinition.php | 18 ++++++++---------- tests/Unit/ArrayDefinitionTest.php | 2 +- ...ecoratorTest.php => LazyDefinitionTest.php} | 18 ++++++++++-------- 5 files changed, 21 insertions(+), 25 deletions(-) rename tests/Unit/{LazyDefinitionDecoratorTest.php => LazyDefinitionTest.php} (74%) diff --git a/.github/workflows/mutation.yml b/.github/workflows/mutation.yml index f9fd931..03b72c0 100644 --- a/.github/workflows/mutation.yml +++ b/.github/workflows/mutation.yml @@ -26,6 +26,6 @@ jobs: os: >- ['ubuntu-latest'] php: >- - ['8.1', '8.2'] + ['8.2'] secrets: STRYKER_DASHBOARD_API_KEY: ${{ secrets.STRYKER_DASHBOARD_API_KEY }} diff --git a/src/Helpers/Normalizer.php b/src/Helpers/Normalizer.php index 5d4171f..9860772 100644 --- a/src/Helpers/Normalizer.php +++ b/src/Helpers/Normalizer.php @@ -49,7 +49,7 @@ final class Normalizer public static function normalize(mixed $definition, ?string $class = null): DefinitionInterface { // Reference - if ($definition instanceof ReferenceInterface) { + if ($definition instanceof DefinitionInterface) { return $definition; } @@ -87,10 +87,6 @@ public static function normalize(mixed $definition, ?string $class = null): Defi return ArrayDefinition::fromConfig($config); } - if ($definition instanceof DefinitionInterface) { - return $definition; - } - // Ready object if (is_object($definition)) { return new ValueDefinition($definition); diff --git a/src/LazyDefinition.php b/src/LazyDefinition.php index de82f04..1e39c6d 100644 --- a/src/LazyDefinition.php +++ b/src/LazyDefinition.php @@ -5,6 +5,7 @@ namespace Yiisoft\Definitions; use ProxyManager\Factory\LazyLoadingValueHolderFactory; +use ProxyManager\Proxy\VirtualProxyInterface; use Psr\Container\ContainerInterface; use Yiisoft\Definitions\Contract\DefinitionInterface; use Yiisoft\Definitions\Helpers\Normalizer; @@ -16,14 +17,11 @@ public function __construct( /** * @var class-string */ - private string $objectClass, + private string $class, ) { } - /** - * @psalm-suppress MixedArgumentTypeCoercion - */ - public function resolve(ContainerInterface $container): mixed + public function resolve(ContainerInterface $container): VirtualProxyInterface { /** @var LazyLoadingValueHolderFactory $factory */ $factory = $container->get(LazyLoadingValueHolderFactory::class); @@ -31,17 +29,17 @@ public function resolve(ContainerInterface $container): mixed * @var mixed $definition */ $definition = $this->definition; - $objectClass = $this->objectClass; + $class = $this->class; - /** @psalm-suppress InvalidArgument */ return $factory->createProxy( - $objectClass, - function (mixed &$wrappedObject) use ($container, $objectClass, $definition) { - $definition = Normalizer::normalize($definition, $objectClass); + $class, + static function (mixed &$wrappedObject) use ($container, $class, $definition) { + $definition = Normalizer::normalize($definition, $class); /** * @var mixed $wrappedObject */ $wrappedObject = $definition->resolve($container); + return true; } ); } diff --git a/tests/Unit/ArrayDefinitionTest.php b/tests/Unit/ArrayDefinitionTest.php index 1445e56..0377174 100644 --- a/tests/Unit/ArrayDefinitionTest.php +++ b/tests/Unit/ArrayDefinitionTest.php @@ -525,7 +525,7 @@ public function testMagicMethods(): void ); } - public function testNonArrayArguments(): void + public function testNonArrayMethodArguments(): void { $definition = ArrayDefinition::fromConfig([ ArrayDefinition::CLASS_NAME => Mouse::class, diff --git a/tests/Unit/LazyDefinitionDecoratorTest.php b/tests/Unit/LazyDefinitionTest.php similarity index 74% rename from tests/Unit/LazyDefinitionDecoratorTest.php rename to tests/Unit/LazyDefinitionTest.php index 6824a2e..cfd85f6 100644 --- a/tests/Unit/LazyDefinitionDecoratorTest.php +++ b/tests/Unit/LazyDefinitionTest.php @@ -15,9 +15,9 @@ use Yiisoft\Definitions\Tests\Support\Phone; use Yiisoft\Test\Support\Container\SimpleContainer; -final class LazyDefinitionDecoratorTest extends TestCase +final class LazyDefinitionTest extends TestCase { - public function testDecorateFinalClass(): void + public function testFinalClass(): void { $container = new SimpleContainer([ LazyLoadingValueHolderFactory::class => new LazyLoadingValueHolderFactory(), @@ -31,7 +31,7 @@ public function testDecorateFinalClass(): void $definition->resolve($container); } - public function testDecorateNotFinalClass(): void + public function testNotFinalClass(): void { $container = new SimpleContainer([ LazyLoadingValueHolderFactory::class => new LazyLoadingValueHolderFactory(), @@ -41,12 +41,13 @@ public function testDecorateNotFinalClass(): void $definition = new LazyDefinition([ArrayDefinition::CLASS_NAME => $class], $class); - $phone = $definition->resolve($container); + $object = $definition->resolve($container); - self::assertInstanceOf(LazyLoadingInterface::class, $phone); + self::assertInstanceOf($class, $object); + self::assertInstanceOf(LazyLoadingInterface::class, $object); } - public function testDecorateInterface(): void + public function testInterface(): void { $container = new SimpleContainer([ LazyLoadingValueHolderFactory::class => new LazyLoadingValueHolderFactory(), @@ -56,8 +57,9 @@ public function testDecorateInterface(): void $definition = new LazyDefinition([ArrayDefinition::CLASS_NAME => $class], $class); - $phone = $definition->resolve($container); + $engine = $definition->resolve($container); - self::assertInstanceOf(LazyLoadingInterface::class, $phone); + self::assertInstanceOf($class, $engine); + self::assertInstanceOf(LazyLoadingInterface::class, $engine); } } From baee30028e40d1b5a20a4ff4bc099bb8ac784c0b Mon Sep 17 00:00:00 2001 From: Dmitrii Derepko Date: Tue, 1 Aug 2023 22:34:03 +0300 Subject: [PATCH 16/25] Add composer-require-checker.json --- composer-require-checker.json | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 composer-require-checker.json diff --git a/composer-require-checker.json b/composer-require-checker.json new file mode 100644 index 0000000..eb439d1 --- /dev/null +++ b/composer-require-checker.json @@ -0,0 +1,17 @@ +{ + "symbol-whitelist": [ + "ProxyManager\\Factory\\LazyLoadingValueHolderFactory", + "ProxyManager\\Proxy\\VirtualProxyInterface" + ], + "php-core-extensions": [ + "Core", + "date", + "json", + "pcre", + "Phar", + "Reflection", + "SPL", + "standard" + ], + "scan-files": [] +} From 3f99488b1df8a9352bcae4ccfb080f85518a0b97 Mon Sep 17 00:00:00 2001 From: Dmitrii Derepko Date: Tue, 1 Aug 2023 22:57:44 +0300 Subject: [PATCH 17/25] Fix null class property --- src/Helpers/Normalizer.php | 2 +- tests/Unit/Helpers/NormalizerTest.php | 17 +++++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/Helpers/Normalizer.php b/src/Helpers/Normalizer.php index 9860772..ef0977c 100644 --- a/src/Helpers/Normalizer.php +++ b/src/Helpers/Normalizer.php @@ -75,7 +75,7 @@ public static function normalize(mixed $definition, ?string $class = null): Defi // Array definition if (is_array($definition)) { $config = $definition; - if (!array_key_exists(ArrayDefinition::CLASS_NAME, $config)) { + if (!isset($config[ArrayDefinition::CLASS_NAME])) { if ($class === null) { throw new InvalidConfigException( 'Array definition should contain the key "class": ' . var_export($definition, true) diff --git a/tests/Unit/Helpers/NormalizerTest.php b/tests/Unit/Helpers/NormalizerTest.php index 8bd31ce..ccda5ac 100644 --- a/tests/Unit/Helpers/NormalizerTest.php +++ b/tests/Unit/Helpers/NormalizerTest.php @@ -51,6 +51,23 @@ public function testArray(): void $this->assertSame([], $definition->getMethodsAndProperties()); } + public function testNullClass(): void + { + /** @var ArrayDefinition $definition */ + $definition = Normalizer::normalize( + [ + 'class' => null, + '__construct()' => [42], + ], + GearBox::class + ); + + $this->assertInstanceOf(ArrayDefinition::class, $definition); + $this->assertSame(GearBox::class, $definition->getClass()); + $this->assertSame([42], $definition->getConstructorArguments()); + $this->assertSame([], $definition->getMethodsAndProperties()); + } + public function testReadyObject(): void { $container = new SimpleContainer(); From bc09d5303c787f66e46ee0cba181a967201c692c Mon Sep 17 00:00:00 2001 From: StyleCI Bot Date: Tue, 1 Aug 2023 20:01:18 +0000 Subject: [PATCH 18/25] Apply fixes from StyleCI --- src/Helpers/Normalizer.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Helpers/Normalizer.php b/src/Helpers/Normalizer.php index ef0977c..7d452a2 100644 --- a/src/Helpers/Normalizer.php +++ b/src/Helpers/Normalizer.php @@ -12,7 +12,6 @@ use Yiisoft\Definitions\Reference; use Yiisoft\Definitions\ValueDefinition; -use function array_key_exists; use function is_array; use function is_callable; use function is_object; From cbc4373e10659d84aa432ae82e35d837b95a8277 Mon Sep 17 00:00:00 2001 From: Dmitrii Derepko Date: Tue, 1 Aug 2023 23:42:13 +0300 Subject: [PATCH 19/25] Add a hack for already normalized configs --- src/ArrayDefinition.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/ArrayDefinition.php b/src/ArrayDefinition.php index b482d24..52d2182 100644 --- a/src/ArrayDefinition.php +++ b/src/ArrayDefinition.php @@ -69,7 +69,8 @@ public static function fromConfig(array $config): self return new self( $config[self::CLASS_NAME], $config[self::CONSTRUCTOR] ?? [], - self::getMethodsAndPropertiesFromConfig($config) + // Already normalized config. Ignore all the rest parameters + $config['methodsAndProperties'] ?? self::getMethodsAndPropertiesFromConfig($config), ); } From 6060238370d5637076be0a9c44b2e5a624c8c4f3 Mon Sep 17 00:00:00 2001 From: StyleCI Bot Date: Tue, 1 Aug 2023 20:44:01 +0000 Subject: [PATCH 20/25] Apply fixes from StyleCI --- src/Helpers/Normalizer.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Helpers/Normalizer.php b/src/Helpers/Normalizer.php index ef0977c..7d452a2 100644 --- a/src/Helpers/Normalizer.php +++ b/src/Helpers/Normalizer.php @@ -12,7 +12,6 @@ use Yiisoft\Definitions\Reference; use Yiisoft\Definitions\ValueDefinition; -use function array_key_exists; use function is_array; use function is_callable; use function is_object; From 6d4696e57bf848fe91edd27b44d4881b5f42dabc Mon Sep 17 00:00:00 2001 From: Dmitrii Derepko Date: Wed, 2 Aug 2023 08:53:45 +0300 Subject: [PATCH 21/25] Fix psalm --- src/ArrayDefinition.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/ArrayDefinition.php b/src/ArrayDefinition.php index 52d2182..c1f6372 100644 --- a/src/ArrayDefinition.php +++ b/src/ArrayDefinition.php @@ -66,6 +66,9 @@ public function withReferenceContainer(?ContainerInterface $referenceContainer): */ public static function fromConfig(array $config): self { + /** + * @psalm-suppress MixedArgument + */ return new self( $config[self::CLASS_NAME], $config[self::CONSTRUCTOR] ?? [], From 41eef65db05d33a464442a246c727bd4452dcc59 Mon Sep 17 00:00:00 2001 From: Dmitrii Derepko Date: Wed, 2 Aug 2023 09:19:07 +0300 Subject: [PATCH 22/25] Remove PHP 8.2 from psalm CI --- .github/workflows/static.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/static.yml b/.github/workflows/static.yml index fb7fc77..96b2679 100644 --- a/.github/workflows/static.yml +++ b/.github/workflows/static.yml @@ -28,4 +28,4 @@ jobs: os: >- ['ubuntu-latest'] php: >- - ['8.0', '8.1', '8.2'] + ['8.0', '8.1'] From 29f4c54f62f0f2504f20c04e06c1bcd7c2e4999f Mon Sep 17 00:00:00 2001 From: Dmitrii Derepko Date: Sat, 19 Aug 2023 12:24:33 +0300 Subject: [PATCH 23/25] Fix psalm error --- src/LazyDefinition.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/LazyDefinition.php b/src/LazyDefinition.php index 1e39c6d..aa9142d 100644 --- a/src/LazyDefinition.php +++ b/src/LazyDefinition.php @@ -15,7 +15,7 @@ final class LazyDefinition implements DefinitionInterface public function __construct( private mixed $definition, /** - * @var class-string + * @psalm-var class-string */ private string $class, ) { From 23e3ff7c281906e49c719eea98cab50d4442d9ac Mon Sep 17 00:00:00 2001 From: Sergei Predvoditelev Date: Sun, 3 Mar 2024 08:25:22 +0000 Subject: [PATCH 24/25] improve --- src/ArrayDefinition.php | 8 ++------ src/LazyDefinition.php | 13 +++---------- 2 files changed, 5 insertions(+), 16 deletions(-) diff --git a/src/ArrayDefinition.php b/src/ArrayDefinition.php index 0aa2f74..c4b7903 100644 --- a/src/ArrayDefinition.php +++ b/src/ArrayDefinition.php @@ -60,20 +60,16 @@ public function withReferenceContainer(?ContainerInterface $referenceContainer): } /** - * Create ArrayDefinition from array config. + * Create `ArrayDefinition` from array config. * * @psalm-param ArrayDefinitionConfig $config */ public static function fromConfig(array $config): self { - /** - * @psalm-suppress MixedArgument - */ return new self( $config[self::CLASS_NAME], $config[self::CONSTRUCTOR] ?? [], - // Already normalized config. Ignore all the rest parameters - $config['methodsAndProperties'] ?? self::getMethodsAndPropertiesFromConfig($config), + self::getMethodsAndPropertiesFromConfig($config), ); } diff --git a/src/LazyDefinition.php b/src/LazyDefinition.php index aa9142d..4830728 100644 --- a/src/LazyDefinition.php +++ b/src/LazyDefinition.php @@ -25,19 +25,12 @@ public function resolve(ContainerInterface $container): VirtualProxyInterface { /** @var LazyLoadingValueHolderFactory $factory */ $factory = $container->get(LazyLoadingValueHolderFactory::class); - /** - * @var mixed $definition - */ $definition = $this->definition; - $class = $this->class; return $factory->createProxy( - $class, - static function (mixed &$wrappedObject) use ($container, $class, $definition) { - $definition = Normalizer::normalize($definition, $class); - /** - * @var mixed $wrappedObject - */ + $this->class, + static function (mixed &$wrappedObject) use ($container, $definition) { + $definition = Normalizer::normalize($definition); $wrappedObject = $definition->resolve($container); return true; } From cf7935f4c03c3e1d111137af9d75425c4ae03cc6 Mon Sep 17 00:00:00 2001 From: StyleCI Bot Date: Tue, 16 Apr 2024 15:58:38 +0000 Subject: [PATCH 25/25] Apply fixes from StyleCI --- tests/Unit/ArrayDefinitionTest.php | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/Unit/ArrayDefinitionTest.php b/tests/Unit/ArrayDefinitionTest.php index e35fcb3..030e2a4 100644 --- a/tests/Unit/ArrayDefinitionTest.php +++ b/tests/Unit/ArrayDefinitionTest.php @@ -525,7 +525,6 @@ public function testMagicMethods(): void ); } - public function testNonArrayMethodArguments(): void { $definition = ArrayDefinition::fromConfig([