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 path as identified by Xdebug. Please note a path is not
necessarily coterminous with a line, a line may contain multiple paths and therefore show up more than once.
Please also be aware that some paths may include implicit rather than explicit branches, 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), |
| 37 | public function get(?string $filter = null): array |
| 38 | { |
| 39 | if ($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) { |
| 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(); |
| 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) { |
| 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) { |
| 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) { |
| 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(); |
| 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) { |
| 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) { |
| 69 | return $instance; |
| 70 | } |
| 27 | ...array_map(static fn($reflector) => $reflector->getAttributes(), $reflectors), |
| 41 | array_filter($this->attributes, static fn($attribute) => $attribute instanceof $filter), |