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

AttributeRoutesProvider::getRoutes()   B

Complexity

Conditions 6
Paths 9

Size

Total Lines 38
Code Lines 26

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 6
eloc 26
c 1
b 0
f 0
nc 9
nop 0
dl 0
loc 38
rs 8.8817
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
 * @codeCoverageIgnore
15
 */
16
final class AttributeRoutesProvider implements RoutesProviderInterface
17
{
18
    /**
19
     * @var array<class-string, \ReflectionMethod>
0 ignored issues
show
Documentation Bug introduced by
The doc comment array<class-string, \ReflectionMethod> at position 2 could not be parsed: Unknown type name 'class-string' at position 2 in array<class-string, \ReflectionMethod>.
Loading history...
20
     */
21
    private static array $reflectionsCache = [];
22
23
    public function getRoutes(): array
24
    {
25
        $routes = [];
26
        $groupRoutes = [];
27
        $routePredicate = Attributes::predicateForAttributeInstanceOf(Route::class);
28
        $targetMethods = Attributes::filterTargetMethods($routePredicate);
29
        foreach ($targetMethods as $targetMethod) {
30
            /** @var Route $route */
31
            $route = $targetMethod->attribute;
32
            $targetMethodReflection = self::$reflectionsCache[$targetMethod->class] ??= new \ReflectionMethod(
33
                $targetMethod->class,
34
                $targetMethod->name
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
            if (isset($groupRoutes[$targetClass->name])) {
52
                /** @var Group $group */
53
                $group = $targetClass->attribute;
54
                $routes[] = $group->routes(...$groupRoutes[$targetClass->name]);
55
            } else {
56
                /** @var Route $group */
57
                $routes[] = $group->action($targetClass->name);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $group seems to be defined later in this foreach loop on line 53. Are you sure it is defined here?
Loading history...
58
            }
59
        }
60
        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...
61
    }
62
}
63