From c7825419a96b01351e88b38e091105f3b3e87576 Mon Sep 17 00:00:00 2001 From: Akihito Koriyama Date: Wed, 6 Nov 2024 12:04:20 +0900 Subject: [PATCH 1/5] Prevent empty interceptor application in AspectPecl Ensure the apply method is not called with an empty list of interceptors by adding a conditional check. This prevents unnecessary execution and potential errors when no interceptors are bound. --- src/AspectPecl.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/AspectPecl.php b/src/AspectPecl.php index f0ce0d6c..98514ef7 100644 --- a/src/AspectPecl.php +++ b/src/AspectPecl.php @@ -43,6 +43,10 @@ public function weave(string $classDir, array $mathcers): void { foreach (new ClassList($classDir) as $className) { $boundInterceptors = $this->getBoundInterceptors($className, $mathcers); + if ($boundInterceptors === []) { + continue; + } + $this->apply($boundInterceptors); } } From 621972f041257ec244dcab4d963c34ac93dfa978 Mon Sep 17 00:00:00 2001 From: Akihito Koriyama Date: Wed, 6 Nov 2024 12:17:14 +0900 Subject: [PATCH 2/5] Add array_merge to combine interceptors for existing methods Previously, method interceptors were overwritten if already set. This change ensures interceptors are merged instead, preserving existing ones and thus providing accumulated functionality when multiple matchers apply to the same method. --- src/AspectPecl.php | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/AspectPecl.php b/src/AspectPecl.php index 98514ef7..22373f10 100644 --- a/src/AspectPecl.php +++ b/src/AspectPecl.php @@ -9,6 +9,7 @@ use RuntimeException; use function array_keys; +use function array_merge; use function assert; use function class_exists; use function extension_loaded; @@ -77,7 +78,13 @@ private function getBoundInterceptors(string $className, array $matchers): array continue; } - $bound[$className][$method->getName()] = $matcher['interceptors']; + $methodName = $method->getName(); + if (isset($bound[$className][$methodName])) { + $bound[$className][$methodName] = array_merge($bound[$className][$methodName], $matcher['interceptors']); + continue; + } + + $bound[$className][$methodName] = $matcher['interceptors']; } } From 1f444bd5f3f148830d9aef738ccd275f16294c06 Mon Sep 17 00:00:00 2001 From: Akihito Koriyama Date: Wed, 6 Nov 2024 12:19:47 +0900 Subject: [PATCH 3/5] Fix spacing and variable typos in AspectPecl.php Corrected spacing inconsistencies before function calls and fixed typos in variable names from "mathcers" to "matchers". These changes enhance code readability and ensure accurate parameter usage within the weave method and related logic. --- src/AspectPecl.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/AspectPecl.php b/src/AspectPecl.php index 22373f10..5af5c4cf 100644 --- a/src/AspectPecl.php +++ b/src/AspectPecl.php @@ -27,7 +27,7 @@ final class AspectPecl { public function __construct() { - if (! extension_loaded('rayaop')) { + if (!extension_loaded('rayaop')) { throw new RuntimeException('Ray.Aop extension is not loaded. Cannot use weave() method.'); // @codeCoverageIgnore } } @@ -36,14 +36,14 @@ public function __construct() * Weave aspects into classes in the specified directory * * @param non-empty-string $classDir Target class directory - * @param MatcherConfigList $mathcers List of matchers and interceptors + * @param MatcherConfigList $matchers List of matchers and interceptors * * @throws RuntimeException When Ray.Aop extension is not loaded. */ - public function weave(string $classDir, array $mathcers): void + public function weave(string $classDir, array $matchers): void { foreach (new ClassList($classDir) as $className) { - $boundInterceptors = $this->getBoundInterceptors($className, $mathcers); + $boundInterceptors = $this->getBoundInterceptors($className, $matchers); if ($boundInterceptors === []) { continue; } @@ -67,14 +67,14 @@ private function getBoundInterceptors(string $className, array $matchers): array $bound = []; foreach ($matchers as $matcher) { - if (! $matcher['classMatcher']->matchesClass($reflection, $matcher['classMatcher']->getArguments())) { + if (!$matcher['classMatcher']->matchesClass($reflection, $matcher['classMatcher']->getArguments())) { continue; } /** @var ReflectionMethod[] $methods */ $methods = $reflection->getMethods(ReflectionMethod::IS_PUBLIC); foreach ($methods as $method) { - if (! $matcher['methodMatcher']->matchesMethod($method, $matcher['methodMatcher']->getArguments())) { + if (!$matcher['methodMatcher']->matchesMethod($method, $matcher['methodMatcher']->getArguments())) { continue; } From 0854ee17c6b81d27811b7e0337a469dec0665288 Mon Sep 17 00:00:00 2001 From: Akihito Koriyama Date: Wed, 6 Nov 2024 12:24:33 +0900 Subject: [PATCH 4/5] Refactor interception method naming Renamed method 'apply' to 'interceptMethods' for better clarity. Updated associated comments to reflect changes accurately, emphasizing the use of the PECL Ray.Aop extension for method interception. --- src/AspectPecl.php | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/AspectPecl.php b/src/AspectPecl.php index 5af5c4cf..f6e9ab6e 100644 --- a/src/AspectPecl.php +++ b/src/AspectPecl.php @@ -27,7 +27,7 @@ final class AspectPecl { public function __construct() { - if (!extension_loaded('rayaop')) { + if (! extension_loaded('rayaop')) { throw new RuntimeException('Ray.Aop extension is not loaded. Cannot use weave() method.'); // @codeCoverageIgnore } } @@ -48,12 +48,12 @@ public function weave(string $classDir, array $matchers): void continue; } - $this->apply($boundInterceptors); + $this->interceptMethods($boundInterceptors); } } /** - * Process class for interception + * Get interceptors bound to class methods based on matchers * * @param class-string $className * @param MatcherConfigList $matchers @@ -67,14 +67,14 @@ private function getBoundInterceptors(string $className, array $matchers): array $bound = []; foreach ($matchers as $matcher) { - if (!$matcher['classMatcher']->matchesClass($reflection, $matcher['classMatcher']->getArguments())) { + if (! $matcher['classMatcher']->matchesClass($reflection, $matcher['classMatcher']->getArguments())) { continue; } /** @var ReflectionMethod[] $methods */ $methods = $reflection->getMethods(ReflectionMethod::IS_PUBLIC); foreach ($methods as $method) { - if (!$matcher['methodMatcher']->matchesMethod($method, $matcher['methodMatcher']->getArguments())) { + if (! $matcher['methodMatcher']->matchesMethod($method, $matcher['methodMatcher']->getArguments())) { continue; } @@ -92,11 +92,11 @@ private function getBoundInterceptors(string $className, array $matchers): array } /** - * Apply interceptors to bound methods + * Intercept methods with bounded interceptors using PECL extension * * @param ClassBoundInterceptors $boundInterceptors */ - private function apply(array $boundInterceptors): void + private function interceptMethods(array $boundInterceptors): void { $dispatcher = new PeclDispatcher($boundInterceptors); assert(function_exists('\method_intercept')); // PECL Ray.Aop extension From 2d5f44f2494e783f21aa4e7ee8e50ba354156388 Mon Sep 17 00:00:00 2001 From: Akihito Koriyama Date: Wed, 6 Nov 2024 12:45:10 +0900 Subject: [PATCH 5/5] Update README.md to clarify aspect weaving paths Revised the documentation to differentiate between weaving aspects into the source directory and a specific target directory. This change enhances clarity by providing explicit example paths for both use cases. --- README.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index a70e2421..a4fa53ad 100644 --- a/README.md +++ b/README.md @@ -79,7 +79,7 @@ $aspect->bind( $billing = $aspect->newInstance(RealBillingService::class); try { - echo $billing->chargeOrder(); + echo $billing->chargeOrder(); // Interceptors applied } catch (\RuntimeException $e) { echo $e->getMessage() . "\n"; exit(1); @@ -103,7 +103,11 @@ $aspect->bind( (new Matcher())->annotatedWith(NotOnWeekends::class), [new WeekendBlocker()] ); -$aspect->weave(__DIR__ . '/src'); // Weave the aspects to all classes in the directory that match the matcher. +// Weave aspects into all matching classes in the source directory +$aspect->weave('/path/to/src'); + +// Or weave into specific target directory +$aspect->weave('/path/to/target'); $billing = new RealBillingService(); echo $billing->chargeOrder(); // Interceptors applied