Skip to content

Commit

Permalink
Refactor Aspect class and update dependencies
Browse files Browse the repository at this point in the history
The Aspect class has been refactored for simplification and efficiency: the scanning and compilation process is now using a more performant approach by employing the package "wyrihaximus/list-classes-in-directory". Furthermore, usage of RecursiveDirectoryIterator and RecursiveIteratorIterator has been removed. The composer dependencies have been updated to reflect these changes.
  • Loading branch information
koriym committed Jul 11, 2024
1 parent 166768c commit 972771e
Show file tree
Hide file tree
Showing 2 changed files with 13 additions and 37 deletions.
3 changes: 2 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@
"ext-hash": "*",
"ext-tokenizer": "*",
"doctrine/annotations": "^1.12 || ^2.0",
"koriym/attributes": "^1.0.3"
"koriym/attributes": "^1.0.3",
"wyrihaximus/list-classes-in-directory": "^1.6"
},
"require-dev": {
"bamarni/composer-bin-plugin": "^1.4.1",
Expand Down
47 changes: 11 additions & 36 deletions src/Aspect.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@

namespace Ray\Aop;

use RecursiveDirectoryIterator;
use RecursiveIteratorIterator;
use Ray\Aop\ReflectionMethod as RayAopReflectionMethod;
use ReflectionClass;
use ReflectionMethod;
use RuntimeException;
Expand All @@ -20,9 +19,11 @@
use function end;

Check failure on line 19 in src/Aspect.php

View workflow job for this annotation

GitHub Actions / cs / Coding Standards

Type end is not used in this file.
use function extension_loaded;
use function get_declared_classes;

Check failure on line 21 in src/Aspect.php

View workflow job for this annotation

GitHub Actions / cs / Coding Standards

Type get_declared_classes is not used in this file.
use function ksort;
use function method_intercept; // @phpstan-ignore-line
use function strcasecmp;

Check failure on line 24 in src/Aspect.php

View workflow job for this annotation

GitHub Actions / cs / Coding Standards

Type strcasecmp is not used in this file.
use function sys_get_temp_dir;
use function WyriHaximus\listClassesInDirectories;

final class Aspect
{
Expand Down Expand Up @@ -50,7 +51,7 @@ public function bind(AbstractMatcher $classMatcher, AbstractMatcher $methodMatch
];
}

public function weave(string $classDir): void
public function weave(string $classDir, ?callable $dispatcherFactory = null): void
{
if (! extension_loaded('rayaop')) {
throw new RuntimeException('Ray.Aop extension is not loaded. Cannot use weave() method.');
Expand All @@ -62,47 +63,19 @@ public function weave(string $classDir): void

private function scanAndCompile(string $classDir): void
{
$files = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($classDir)
);

/** @var SplFileInfo[] $files */
foreach ($files as $file) {
if ($file->isDir() || $file->getExtension() !== 'php') {
continue;
}

$className = $this->getClassNameFromFile($file->getPathname());
if ($className === null) {
$classList = listClassesInDirectories($classDir);
foreach ($classList as $className) {
if (! class_exists($className)) {
continue;
}

$this->processClass($className);
}
}

private function getClassNameFromFile(string $file): ?string
{
$declaredClasses = get_declared_classes();
$previousCount = count($declaredClasses);

/** @psalm-suppress UnresolvableInclude */
require_once $file;

$newClasses = array_slice(get_declared_classes(), $previousCount);

foreach ($newClasses as $class) {
if (strcasecmp(basename($file, '.php'), $class) === 0) {
return $class;
}
}

return $newClasses ? end($newClasses) : null;
}

private function processClass(string $className): void
{
assert(class_exists($className));
assert(class_exists($className), 'Class does not exist:' . $className);
$reflection = new ReflectionClass($className);

foreach ($this->matchers as $matcher) {
Expand All @@ -111,7 +84,8 @@ private function processClass(string $className): void
}

foreach ($reflection->getMethods(ReflectionMethod::IS_PUBLIC) as $method) {
if (! $matcher['methodMatcher']->matchesMethod($method, $matcher['methodMatcher']->getArguments())) {
$aopMethod = new RayAopReflectionMethod($className, $method->getName());
if (! $matcher['methodMatcher']->matchesMethod($aopMethod, $matcher['methodMatcher']->getArguments())) {
continue;
}

Expand All @@ -127,6 +101,7 @@ private function applyInterceptors(): void
}

$dispatcher = new PeclDispatcher($this->bound);
ksort($this->bound);
foreach ($this->bound as $className => $methods) {
$methodNames = array_keys($methods);
foreach ($methodNames as $methodName) {
Expand Down

0 comments on commit 972771e

Please sign in to comment.