Code Coverage
 
Lines
Branches
Paths
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
23 / 23
40.00% covered (danger)
40.00%
4 / 10
42.86% covered (danger)
42.86%
3 / 7
100.00% covered (success)
100.00%
3 / 3
CRAP
0.00% covered (danger)
0.00%
0 / 1
AttributesResolver
100.00% covered (success)
100.00%
23 / 23
40.00% covered (danger)
40.00%
4 / 10
42.86% covered (danger)
42.86%
3 / 7
100.00% covered (success)
100.00%
3 / 3
12.72
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 get
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
2
 newAttributeInstance
100.00% covered (success)
100.00%
11 / 11
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 4
100.00% covered (success)
100.00%
1 / 1
3
1<?php
2
3declare(strict_types=1);
4
5namespace Celemas\Router;
6
7use Celemas\Wire\Call;
8use Celemas\Wire\CallableResolver;
9use Celemas\Wire\Creator;
10use Psr\Container\ContainerInterface as Container;
11use ReflectionAttribute;
12use ReflectionClass;
13use ReflectionFunctionAbstract;
14use ReflectionObject;
15
16/** @internal */
17final class AttributesResolver
18{
19    private readonly array $attributes;
20
21    /** @param list<ReflectionClass|ReflectionFunctionAbstract> $reflectors */
22    public function __construct(
23        array $reflectors,
24        protected readonly ?Container $container,
25    ) {
26        $reflectionAttributes = array_merge(
27            ...array_map(static fn($reflector) => $reflector->getAttributes(), $reflectors),
28        );
29
30        $this->attributes = array_map(
31            $this->newAttributeInstance(...),
32            $reflectionAttributes,
33        );
34    }
35
36    /** @param ?class-string $filter */
37    public function get(?string $filter = null): array
38    {
39        if ($filter) {
40            return array_values(
41                array_filter($this->attributes, static fn($attribute) => $attribute instanceof $filter),
42            );
43        }
44
45        return $this->attributes;
46    }
47
48    private function newAttributeInstance(ReflectionAttribute $attribute): object
49    {
50        $instance = $attribute->newInstance();
51        $callAttrs = new ReflectionObject($instance)->getAttributes(Call::class);
52
53        if (count($callAttrs) > 0) {
54            $resolver = new CallableResolver(new Creator($this->container));
55
56            // See if the attribute itself has one or more Call attributes. If so,
57            // resolve/autowire the arguments of the method it states and call it.
58            foreach ($callAttrs as $callAttr) {
59                $callAttr = $callAttr->newInstance();
60                $methodToResolve = $callAttr->method;
61
62                /** @var callable $callable */
63                $callable = [$instance, $methodToResolve];
64                $args = $resolver->resolve($callable, $callAttr->args);
65                $callable(...$args);
66            }
67        }
68
69        return $instance;
70    }
71}

Branches

Below are the source code lines that represent each code branch as identified by Xdebug. Please note a branch is not necessarily coterminous with a line, a line may contain multiple branches and therefore show up more than once. Please also be aware that some branches may be implicit rather than explicit, e.g. an if statement always has an else as part of its logical flow even if you didn't write one.

AttributesResolver->__construct
23        array $reflectors,
24        protected readonly ?Container $container,
25    ) {
26        $reflectionAttributes = array_merge(
27            ...array_map(static fn($reflector) => $reflector->getAttributes(), $reflectors),
28        );
29
30        $this->attributes = array_map(
31            $this->newAttributeInstance(...),
32            $reflectionAttributes,
33        );
34    }
AttributesResolver->get
37    public function get(?string $filter = null): array
38    {
39        if ($filter) {
40            return array_values(
41                array_filter($this->attributes, static fn($attribute) => $attribute instanceof $filter),
45        return $this->attributes;
46    }
AttributesResolver->newAttributeInstance
48    private function newAttributeInstance(ReflectionAttribute $attribute): object
49    {
50        $instance = $attribute->newInstance();
51        $callAttrs = new ReflectionObject($instance)->getAttributes(Call::class);
52
53        if (count($callAttrs) > 0) {
54            $resolver = new CallableResolver(new Creator($this->container));
55
56            // See if the attribute itself has one or more Call attributes. If so,
57            // resolve/autowire the arguments of the method it states and call it.
58            foreach ($callAttrs as $callAttr) {
58            foreach ($callAttrs as $callAttr) {
58            foreach ($callAttrs as $callAttr) {
59                $callAttr = $callAttr->newInstance();
58            foreach ($callAttrs as $callAttr) {
59                $callAttr = $callAttr->newInstance();
60                $methodToResolve = $callAttr->method;
61
62                /** @var callable $callable */
63                $callable = [$instance, $methodToResolve];
64                $args = $resolver->resolve($callable, $callAttr->args);
65                $callable(...$args);
66            }
67        }
68
69        return $instance;
69        return $instance;
70    }
newAttributeInstance
48    private function newAttributeInstance(ReflectionAttribute $attribute): object
49    {
50        $instance = $attribute->newInstance();
51        $callAttrs = new ReflectionObject($instance)->getAttributes(Call::class);
52
53        if (count($callAttrs) > 0) {
54            $resolver = new CallableResolver(new Creator($this->container));
55
56            // See if the attribute itself has one or more Call attributes. If so,
57            // resolve/autowire the arguments of the method it states and call it.
58            foreach ($callAttrs as $callAttr) {
58            foreach ($callAttrs as $callAttr) {
58            foreach ($callAttrs as $callAttr) {
59                $callAttr = $callAttr->newInstance();
58            foreach ($callAttrs as $callAttr) {
59                $callAttr = $callAttr->newInstance();
60                $methodToResolve = $callAttr->method;
61
62                /** @var callable $callable */
63                $callable = [$instance, $methodToResolve];
64                $args = $resolver->resolve($callable, $callAttr->args);
65                $callable(...$args);
66            }
67        }
68
69        return $instance;
69        return $instance;
70    }
{closure:/workspace/celemas/router/src/AttributesResolver.php:27-27}
27            ...array_map(static fn($reflector) => $reflector->getAttributes(), $reflectors),
{closure:/workspace/celemas/router/src/AttributesResolver.php:41-41}
41                array_filter($this->attributes, static fn($attribute) => $attribute instanceof $filter),