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 diff --git a/src/AspectPecl.php b/src/AspectPecl.php index f0ce0d6c..f6e9ab6e 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; @@ -35,20 +36,24 @@ 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); - $this->apply($boundInterceptors); + $boundInterceptors = $this->getBoundInterceptors($className, $matchers); + if ($boundInterceptors === []) { + continue; + } + + $this->interceptMethods($boundInterceptors); } } /** - * Process class for interception + * Get interceptors bound to class methods based on matchers * * @param class-string $className * @param MatcherConfigList $matchers @@ -73,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']; } } @@ -81,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