ScalarParam::__construct()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 2
nc 1
nop 1
dl 0
loc 6
rs 10
c 1
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace BEAR\Resource;
6
7
use Ray\Di\Di\Named;
8
use Ray\Di\Di\Qualifier;
9
use Ray\Di\InjectorInterface;
10
use ReflectionClass;
11
use ReflectionMethod;
12
use ReflectionNamedType;
13
14
use function array_shift;
15
use function array_unshift;
16
use function assert;
17
use function class_exists;
18
19
/**
20
 * @psalm-type DependencyMeta = array{0:class-string|'', 1:string}
21
 * @psalm-type DependencyMetas = list<DependencyMeta>
22
 */
23
final class ScalarParam implements ParamInterface
24
{
25
    /** @var DependencyMetas */
0 ignored issues
show
Bug introduced by
The type BEAR\Resource\DependencyMetas 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...
26
    private array $dependenciesMetas;
27
    private QueryProp $queryProp;
28
29
    /** @param class-string $typeName */
0 ignored issues
show
Documentation Bug introduced by
The doc comment class-string at position 0 could not be parsed: Unknown type name 'class-string' at position 0 in class-string.
Loading history...
30
    public function __construct(
31
        private string $typeName,
32
    ) {
33
        // Retrieve the dependency metadata to construct the object later
34
        $this->dependenciesMetas = $this->getDependenciesMetas();
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->getDependenciesMetas() of type array is incompatible with the declared type BEAR\Resource\DependencyMetas of property $dependenciesMetas.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
35
        $this->queryProp = new QueryProp();
36
    }
37
38
    /**
39
     * {@inheritDoc}
40
     *
41
     * @param array<string, mixed> $query
42
     *
43
     * @return object
44
     */
45
    public function __invoke(string $varName, array $query, InjectorInterface $injector): object
46
    {
47
        /** @psalm-suppress MixedAssignment */
48
        $arg1 = $this->queryProp->getProp($varName, $query, $injector);
49
        $args = [];
50
        foreach ($this->dependenciesMetas as $meta) {
51
            /** @psalm-suppress MixedAssignment */
52
            [$className, $qualifier] = $meta;
53
            /** @psalm-suppress MixedAssignment, ArgumentTypeCoercion, MixedArgument */
54
            $args[] = $injector->getInstance($className, $qualifier);
55
        }
56
57
        array_unshift($args, $arg1);
58
59
        /** @psalm-suppress InvalidStringClass, MixedMethodCall */
60
        return new $this->typeName(...$args);
61
    }
62
63
    /**
64
     * @return DependencyMetas
65
     *
66
     * @psalm-suppress MoreSpecificReturnType, LessSpecificReturnStatement
67
     */
68
    public function getDependenciesMetas(): array
69
    {
70
        $class = new ReflectionClass($this->typeName);
71
        $const = $class->getConstructor();
72
        assert($const instanceof ReflectionMethod, 'Expected class has a constructor');
73
74
        $args = $const->getParameters();
75
        $params = [];
76
77
        // Skip the first parameter (scalar value)
78
        array_shift($args);
79
80
        foreach ($args as $arg) {
81
            $type = $arg->getType();
82
            assert($type instanceof ReflectionNamedType || $type === null, 'Expected a named type or null');
83
            $typeName = $type ? $type->getName() : '';
84
            $attributes = $arg->getAttributes();
85
            foreach ($attributes as $attribute) {
86
                if ($attribute->getName() === Named::class) {
87
                    $named = $attribute->newInstance();
88
                    /** @var DependencyMeta $dependencyMeta */
89
                    $dependencyMeta = [$typeName, $named->value];
90
                    $params[] = $dependencyMeta;
91
                    continue;
92
                }
93
94
                $class = $attribute->getName();
95
                assert(class_exists($class));
96
                $attributeReflection = new ReflectionClass($class);
97
                // Check if this attribute has the Qualifier attribute
98
                $qualifierAttributes = $attributeReflection->getAttributes(Qualifier::class);
99
                if (! $qualifierAttributes) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $qualifierAttributes of type ReflectionAttribute[] is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
100
                    continue;
101
                }
102
103
                /** @var DependencyMeta $dependencyMeta */
104
                $dependencyMeta = [$typeName, $attribute->getName()];
105
106
                $params[] = $dependencyMeta;
107
            }
108
109
            $params[] = [$typeName, ''];
110
        }
111
112
        /** @var DependencyMetas $params */
113
        return $params;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $params returns the type BEAR\Resource\DependencyMetas which is incompatible with the type-hinted return array.
Loading history...
114
    }
115
}
116