Passed
Pull Request — master (#196)
by Rustam
02:36
created

AttributeRoutesProvider::getRoutes()   B

Complexity

Conditions 8
Paths 12

Size

Total Lines 35
Code Lines 25

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 8
eloc 25
c 2
b 0
f 0
nc 12
nop 0
dl 0
loc 35
rs 8.4444
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Router\Provider;
6
7
use olvlvl\ComposerAttributeCollector\Attributes;
8
use Yiisoft\Router\Group;
9
use Yiisoft\Router\Route;
10
11
/**
12
 * An attribute provider provides routes that declared via PHP Attributes.
13
 * Currently, uses `olvlvl/composer-attribute-collector`. {@link https://github.com/olvlvl/composer-attribute-collector}.
14
 *
15
 * @codeCoverageIgnore
16
 */
17
final class AttributeRoutesProvider implements RoutesProviderInterface
18
{
19
    /**
20
     * @var array<class-string, \ReflectionClass>
0 ignored issues
show
Documentation Bug introduced by
The doc comment array<class-string, \ReflectionClass> at position 2 could not be parsed: Unknown type name 'class-string' at position 2 in array<class-string, \ReflectionClass>.
Loading history...
21
     */
22
    private static array $reflectionsCache = [];
23
24
    public function getRoutes(): array
25
    {
26
        $routes = [];
27
        $groupRoutes = [];
28
        $routePredicate = Attributes::predicateForAttributeInstanceOf(Route::class);
29
        $targetMethods = Attributes::filterTargetMethods($routePredicate);
30
        foreach ($targetMethods as $targetMethod) {
31
            /** @var Route $route */
32
            $route = $targetMethod->attribute;
33
            $targetMethodReflection = self::$reflectionsCache[$targetMethod->class] ??= new \ReflectionClass(
34
                $targetMethod->class
35
            );
36
            /** @var Group[] $groupAttributes */
37
            $groupAttributes = $targetMethodReflection->getAttributes(
38
                Group::class,
39
                \ReflectionAttribute::IS_INSTANCEOF
40
            );
41
            if (!empty($groupAttributes)) {
42
                $groupRoutes[$targetMethod->class][] = $route->action([$targetMethod->class, $targetMethod->name]);
43
            } else {
44
                $routes[] = $route->action([$targetMethod->class, $targetMethod->name]);
45
            }
46
        }
47
        $groupPredicate = static fn (string $attribute): bool => is_a($attribute, Route::class, true)
48
            || is_a($attribute, Group::class, true);
49
        $targetClasses = Attributes::filterTargetClasses($groupPredicate);
50
        foreach ($targetClasses as $targetClass) {
51
            $group = $targetClass->attribute;
52
            if ($group instanceof Group && isset($groupRoutes[$targetClass->name])) {
53
                $routes[] = $group->routes(...$groupRoutes[$targetClass->name]);
54
            } elseif ($group instanceof Route) {
55
                $routes[] = $group->action($targetClass->name);
56
            }
57
        }
58
        return $routes;
0 ignored issues
show
introduced by
The expression return $routes returns an array which contains values of type Yiisoft\Router\Route which are incompatible with the return type Yiisoft\Router\Group mandated by Yiisoft\Router\Provider\...rInterface::getRoutes().
Loading history...
59
    }
60
}
61