Code Coverage |
||||||||||||||||
Lines |
Branches |
Paths |
Functions and Methods |
Classes and Traits |
||||||||||||
| Total | |
100.00% |
23 / 23 |
|
40.00% |
4 / 10 |
|
42.86% |
3 / 7 |
|
100.00% |
3 / 3 |
CRAP | |
0.00% |
0 / 1 |
| AttributesResolver | |
100.00% |
23 / 23 |
|
40.00% |
4 / 10 |
|
42.86% |
3 / 7 |
|
100.00% |
3 / 3 |
12.72 | |
100.00% |
1 / 1 |
| __construct | |
100.00% |
7 / 7 |
|
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
| get | |
100.00% |
5 / 5 |
|
100.00% |
3 / 3 |
|
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
2 | |||
| newAttributeInstance | |
100.00% |
11 / 11 |
|
0.00% |
0 / 6 |
|
0.00% |
0 / 4 |
|
100.00% |
1 / 1 |
3 | |||
| 1 | <?php |
| 2 | |
| 3 | declare(strict_types=1); |
| 4 | |
| 5 | namespace Celemas\Router; |
| 6 | |
| 7 | use Celemas\Wire\Call; |
| 8 | use Celemas\Wire\CallableResolver; |
| 9 | use Celemas\Wire\Creator; |
| 10 | use Psr\Container\ContainerInterface as Container; |
| 11 | use ReflectionAttribute; |
| 12 | use ReflectionClass; |
| 13 | use ReflectionFunctionAbstract; |
| 14 | use ReflectionObject; |
| 15 | |
| 16 | /** @internal */ |
| 17 | final 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 | } |
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.
| 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 | } |
| 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 | } |
| 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 | } |
| 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 | } |
| 27 | ...array_map(static fn($reflector) => $reflector->getAttributes(), $reflectors), |
| 41 | array_filter($this->attributes, static fn($attribute) => $attribute instanceof $filter), |