diff --git a/src-php8/Php82InterceptTrait.php b/src-php8/ReadOnlyInterceptTrait.php similarity index 88% rename from src-php8/Php82InterceptTrait.php rename to src-php8/ReadOnlyInterceptTrait.php index 44433319..de354810 100644 --- a/src-php8/Php82InterceptTrait.php +++ b/src-php8/ReadOnlyInterceptTrait.php @@ -12,16 +12,16 @@ * @psalm-import-type MethodBindings from Types * @psalm-import-type Arguments from Types */ -trait Php82InterceptTrait +trait ReadOnlyInterceptTrait { private readonly InterceptTraitState $_state; /** * @param MethodBindings $bindings * - * @see WeavedInterface::_initState() + * @see WeavedInterface::_setBindings() */ - public function _initState(array $bindings): void + public function _setBindings(array $bindings): void { $this->_state = new InterceptTraitState($bindings); } diff --git a/src/AopCode.php b/src/AopCode.php index f461f4af..0b04d46d 100644 --- a/src/AopCode.php +++ b/src/AopCode.php @@ -139,7 +139,7 @@ private function parseClass(ReflectionClass $sourceClass, string $postfix): void $isClassSignatureEnds = $inClass && $text === '{'; if ($isClassSignatureEnds) { - $this->addIntercepterTrait(); + $this->resolveInterceptTrait($sourceClass); return; } @@ -201,11 +201,15 @@ private function addMethods(ReflectionClass $class, BindInterface $bind): void } /** @psalm-external-mutation-free */ - private function addIntercepterTrait(): void + private function addInterceporTrait(): void { - PHP_VERSION_ID >= 80200 - ? $this->add(sprintf("{\n use \%s;\n}\n", Php82InterceptTrait::class)) - : $this->add(sprintf("{\n use \%s;\n}\n", InterceptTrait::class)); + $this->add(sprintf("{\n use \%s;\n}\n", InterceptTrait::class)); + } + + /** @psalm-external-mutation-free */ + private function addReadOnlyInterceptorTrait(): void + { + $this->add(sprintf("{\n use \%s;\n}\n", ReadOnlyInterceptTrait::class)); } /** @psalm-external-mutation-free */ @@ -219,4 +223,16 @@ private function getCodeText(): string return $this->code; } + + /** @param ReflectionClass $sourceClass */ + public function resolveInterceptTrait(ReflectionClass $sourceClass): void + { + if (PHP_VERSION_ID >= 80200 && $sourceClass->isReadOnly()) { + $this->addReadOnlyInterceptorTrait(); + + return; + } + + $this->addInterceporTrait(); + } } diff --git a/src/Compiler.php b/src/Compiler.php index ea4d395a..94246e53 100644 --- a/src/Compiler.php +++ b/src/Compiler.php @@ -65,7 +65,7 @@ public function newInstance(string $class, array $args, BindInterface $bind): ob assert(class_exists($compiledClass)); $instance = (new ReflectionClass($compiledClass))->newInstanceArgs($args); if ($instance instanceof WeavedInterface) { - $instance->_initState($bind->getBindings()); + $instance->_setBindings($bind->getBindings()); } assert($instance instanceof $class); diff --git a/src/InterceptTrait.php b/src/InterceptTrait.php index 2eaa9dfe..0276f522 100644 --- a/src/InterceptTrait.php +++ b/src/InterceptTrait.php @@ -12,21 +12,24 @@ trait InterceptTrait { /** - * @var InterceptTraitState + * @var MethodBindings * @readonly - * @psalm-suppress MissingConstructor + * @deprecated Do not use this property directly. Use the `_setBindings` setter method instead for initialization. */ - private $_state; + public $bindings = []; + + /** @var bool Flag controlling whether aspect interception is active */ + private $_isAspect = true; /** * @param MethodBindings $bindings * - * @see WeavedInterface::_initState() + * @see WeavedInterface::_setBindings() * @SuppressWarnings(PHPMD.CamelCaseMethodName) */ - public function _initState(array $bindings): void // phpcs:ignore + public function _setBindings(array $bindings): void // @phpcs:ignore PSR2.Methods.MethodDeclaration.Underscore { - $this->_state = new InterceptTraitState($bindings); + $this->bindings = $bindings; } /** @@ -38,15 +41,15 @@ public function _initState(array $bindings): void // phpcs:ignore */ private function _intercept(string $func, array $args) // phpcs:ignore { - if (! $this->_state->isAspect) { - $this->_state->isAspect = true; + if (! $this->_isAspect) { + $this->_isAspect = true; return call_user_func_array([parent::class, $func], $args); } - $this->_state->isAspect = false; - $result = (new Invocation($this, $func, $args, $this->_state->bindings[$func]))->proceed(); - $this->_state->isAspect = true; + $this->_isAspect = false; + $result = (new Invocation($this, $func, $args, $this->bindings[$func]))->proceed(); + $this->_isAspect = true; return $result; } diff --git a/src/InterceptTraitState.php b/src/InterceptTraitState.php index 38aa63fb..de6806be 100644 --- a/src/InterceptTraitState.php +++ b/src/InterceptTraitState.php @@ -13,7 +13,7 @@ final class InterceptTraitState */ public $bindings; - /** @var bool */ + /** @var bool Flag controlling whether aspect interception is active */ public $isAspect = true; /** @param MethodBindings $bindings */ diff --git a/src/WeavedInterface.php b/src/WeavedInterface.php index 17d73028..1f2dfe6f 100644 --- a/src/WeavedInterface.php +++ b/src/WeavedInterface.php @@ -12,5 +12,5 @@ interface WeavedInterface * * @SuppressWarnings(PHPMD.CamelCaseMethodName) */ - public function _initState(array $bindings): void; // phpcs:ignore + public function _setBindings(array $bindings): void; // phpcs:ignore } diff --git a/src/Weaver.php b/src/Weaver.php index 2ee361c9..e70e74f9 100644 --- a/src/Weaver.php +++ b/src/Weaver.php @@ -62,7 +62,7 @@ public function newInstance(string $class, array $args): object return $instance; } - $instance->_initState($this->bind->getBindings()); + $instance->_setBindings($this->bind->getBindings()); assert($instance instanceof $class); return $instance; diff --git a/tests/CompilerTest.php b/tests/CompilerTest.php index a2bc6db7..adc1ee09 100644 --- a/tests/CompilerTest.php +++ b/tests/CompilerTest.php @@ -21,7 +21,6 @@ use function class_exists; use function file_get_contents; use function passthru; -use function property_exists; use function serialize; use function unserialize; @@ -115,7 +114,6 @@ public function testParentMethodIntercept(): void { $mock = $this->compiler->newInstance(FakeMockGrandChild::class, [], $this->bind); assert($mock instanceof FakeMockGrandChild); - assert(property_exists($mock, '_state')); $result = $mock->returnSame(1); $this->assertSame(2, $result); } @@ -125,7 +123,6 @@ public function testTypedParentMethodIntercept(): void $bind = (new Bind())->bindInterceptors('passIterator', [new NullInterceptor()]); $mock = $this->compiler->newInstance(FakeTypedMockGrandChild::class, [], $bind); assert($mock instanceof FakeTypedMockGrandChild); - assert(property_exists($mock, '_state')); $result = $mock->passIterator(new ArrayIterator()); $this->assertInstanceOf(ArrayIterator::class, $result); } @@ -134,7 +131,6 @@ public function testParentOfParentMethodIntercept(): void { $mock = $this->compiler->newInstance(FakeMockChildChild::class, [], $this->bind); assert($mock instanceof FakeMockChild); - assert(property_exists($mock, '_state')); $result = $mock->returnSame(1); $this->assertSame(2, $result); } diff --git a/tests/Fake/FakeWeavedClass.php b/tests/Fake/FakeWeavedClass.php index 68356624..d829985d 100644 --- a/tests/Fake/FakeWeavedClass.php +++ b/tests/Fake/FakeWeavedClass.php @@ -9,5 +9,5 @@ class FakeWeavedClass extends FakeClass implements WeavedInterface /** * {@inheritDoc} */ - public function _initState(array $bindings): void {} + public function _setBindings(array $bindings): void {} } diff --git a/tests/tmp_unerase/Ray_Aop_FakeWeaverMock_523567342.php b/tests/tmp_unerase/Ray_Aop_FakeWeaverMock_523567342.php index 66eb64c6..2eea1009 100644 --- a/tests/tmp_unerase/Ray_Aop_FakeWeaverMock_523567342.php +++ b/tests/tmp_unerase/Ray_Aop_FakeWeaverMock_523567342.php @@ -5,9 +5,9 @@ namespace Ray\Aop; /** doc comment of FakeMock */ -class FakeWeaverMock_523567342 extends FakeWeaverMock implements \Ray\Aop\WeavedInterface +class FakeWeaverMock_523567342 extends FakeWeaverMock implements \Ray\Aop\WeavedInterface { - use \Ray\Aop\Php82InterceptTrait; + use \Ray\Aop\ReadOnlyInterceptTrait; /** * doc comment of returnSame */ @@ -33,4 +33,4 @@ public function getPrivateVal() { return $this->_intercept(__FUNCTION__, func_get_args()); } -} \ No newline at end of file +}