Passed
Push — main ( a03838...173f9d )
by Fractal
02:12
created

DefinitionHelper::getServiceId()   A

Complexity

Conditions 3
Paths 1

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 4
c 0
b 0
f 0
dl 0
loc 6
rs 10
cc 3
nc 1
nop 3
1
<?php
2
3
declare(strict_types=1);
4
5
namespace FRZB\Component\DependencyInjection\Helper;
6
7
use Fp\Collections\ArrayList;
8
use Fp\Collections\Entry;
9
use Fp\Collections\HashMap;
10
use JetBrains\PhpStorm\Immutable;
11
use Symfony\Component\DependencyInjection\ContainerBuilder;
0 ignored issues
show
Bug introduced by
The type Symfony\Component\Depend...ection\ContainerBuilder was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
12
use Symfony\Component\DependencyInjection\Definition;
13
use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException;
14
use Symfony\Component\DependencyInjection\Reference;
15
16
/** @internal */
17
#[Immutable]
18
final class DefinitionHelper
19
{
20
    private const SERVICE_PREFIX = '@';
21
    private const EMPTY_STRING = '';
22
23
    private function __construct()
24
    {
25
    }
26
27
    /**
28
     * @template T
29
     *
30
     * @param class-string<T> $attributeName
0 ignored issues
show
Documentation Bug introduced by
The doc comment class-string<T> at position 0 could not be parsed: Unknown type name 'class-string' at position 0 in class-string<T>.
Loading history...
31
     *
32
     * @return T[]
33
     */
34
    public static function getAttributesFor(\ReflectionClass $reflectionClass, string $attributeName): array
35
    {
36
        return ArrayList::collect($reflectionClass->getAttributes($attributeName, \ReflectionAttribute::IS_INSTANCEOF))
37
            ->map(static fn (\ReflectionAttribute $reflectionAttribute) => $reflectionAttribute->newInstance())
38
            ->toArray()
39
        ;
40
    }
41
42
    public static function getServiceId(ContainerBuilder $container, \ReflectionClass $reflectionClass, ?string $serviceId): string
43
    {
44
        return match (true) {
45
            null !== $serviceId && $container->hasDefinition($serviceId) => $serviceId,
46
            null === $serviceId && $container->hasDefinition($reflectionClass->getName()) => $reflectionClass->getName(),
47
            default => throw new ServiceNotFoundException($attribute->id ?? $reflectionClass->getName()),
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $attribute seems to be never defined.
Loading history...
48
        };
49
    }
50
51
    public static function getClassForServiceId(ContainerBuilder $container, string $serviceId): string
52
    {
53
        return class_exists($serviceId)
54
            ? $serviceId
55
            : $container->getDefinition($serviceId)->getClass()
56
        ;
57
    }
58
59
    /** @throws \ReflectionException */
60
    public static function getReflectionClassForServiceId(ContainerBuilder $container, string $serviceId): \ReflectionClass
61
    {
62
        return $container->getReflectionClass(self::getClassForServiceId($container, $serviceId));
63
    }
64
65
    public static function getDefinitionForServiceId(ContainerBuilder $container, string $serviceId): Definition
66
    {
67
        return $container->getDefinition(self::getClassForServiceId($container, $serviceId));
68
    }
69
70
    public static function mapDefinitionMethodCalls(ContainerBuilder $container, array $methodCalls): array
71
    {
72
        return HashMap::collect($methodCalls)
73
            ->map(fn (Entry $e) => self::mapDefinitionArguments($container, $e->value))
74
            ->toArray()
75
        ;
76
    }
77
78
    public static function mapDefinitionArguments(ContainerBuilder $container, array $arguments): array
79
    {
80
        $definitionsById = HashMap::collect($arguments)
81
            ->filter(static fn (Entry $e) => \is_string($e->value))
82
            ->filter(static fn (Entry $e) => str_contains($e->value, self::SERVICE_PREFIX))
83
            ->map(static fn (Entry $e) => str_replace(self::SERVICE_PREFIX, self::EMPTY_STRING, $e->value))
84
            ->filter(static fn (Entry $e) => $container->hasDefinition($e->value))
85
            ->map(static fn (Entry $e) => new Reference((string) $e->value))
86
            ->toAssocArray()
87
            ->getOrElse([])
88
        ;
89
90
        $definitionsByClass = HashMap::collect($arguments)
91
            ->filter(static fn (Entry $e) => \is_string($e->value))
92
            ->filter(static fn (Entry $e) => class_exists($e->value))
93
            ->filter(static fn (Entry $e) => $container->hasDefinition($e->value))
94
            ->map(static fn (Entry $e) => new Reference((string) $e->value))
95
            ->toAssocArray()
96
            ->getOrElse([])
97
        ;
98
99
        $definitionsByAlias = HashMap::collect($arguments)
100
            ->filter(static fn (Entry $e) => \is_string($e->value))
101
            ->filter(static fn (Entry $e) => interface_exists($e->value) || class_exists($e->value))
102
            ->filter(static fn (Entry $e) => $container->hasAlias($e->value))
103
            ->map(static fn (Entry $e) => new Reference((string) $e->value))
104
            ->toAssocArray()
105
            ->getOrElse([])
106
        ;
107
108
        return [...$definitionsById, ...$definitionsByClass, ...$definitionsByAlias];
109
    }
110
}
111