Argument   A
last analyzed

Complexity

Total Complexity 17

Size/Duplication

Total Lines 142
Duplicated Lines 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
wmc 17
eloc 58
c 2
b 0
f 0
dl 0
loc 142
rs 10

11 Methods

Rating   Name   Duplication   Size   Complexity  
A __toString() 0 3 1
A get() 0 3 1
A getMeta() 0 3 1
A isDefaultAvailable() 0 3 1
A getDefaultValue() 0 3 1
A __unserialize() 0 10 1
A accept() 0 7 1
A setDefaultValue() 0 11 3
A getType() 0 5 3
A __serialize() 0 16 1
A __construct() 0 19 3
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Ray\Di;
6
7
use ReflectionException;
8
use ReflectionMethod;
9
use ReflectionNamedType;
10
use ReflectionParameter;
11
use Stringable;
12
13
use function assert;
14
use function in_array;
15
use function sprintf;
16
17
/**
18
 * @psalm-import-type DependencyIndex from Types
19
 */
20
final class Argument implements AcceptInterface, Stringable
21
{
22
    public const UNBOUND_TYPE = ['bool', 'int', 'float', 'string', 'array', 'resource', 'callable', 'iterable'];
23
24
    /** @var DependencyIndex */
0 ignored issues
show
Bug introduced by
The type Ray\Di\DependencyIndex 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...
25
    private string $index;
26
    private bool $isDefaultAvailable;
27
28
    /** @var mixed */
29
    private $default;
30
    private string $meta;
31
    private ReflectionParameter $reflection;
32
33
    public function __construct(ReflectionParameter $parameter, string $name)
34
    {
35
        $type = $this->getType($parameter);
36
        $isOptional = $parameter->isOptional();
37
        $this->isDefaultAvailable = $parameter->isDefaultValueAvailable() || $isOptional;
38
        if ($isOptional) {
39
            $this->default = null;
40
        }
41
42
        $this->setDefaultValue($parameter);
43
        $this->index = $type . '-' . $name;
0 ignored issues
show
Documentation Bug introduced by
It seems like $type . '-' . $name of type string is incompatible with the declared type Ray\Di\DependencyIndex of property $index.

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...
44
        $this->reflection = $parameter;
45
        $this->meta = sprintf(
46
            "dependency '%s' with name '%s' used in %s:%d ($%s)",
47
            $type,
48
            $name,
49
            $this->reflection->getDeclaringFunction()->getFileName(),
50
            $this->reflection->getDeclaringFunction()->getStartLine(),
51
            $parameter->getName()
52
        );
53
    }
54
55
    /**
56
     * Return index
57
     *
58
     * @return DependencyIndex
59
     */
60
    public function __toString(): string
61
    {
62
        return $this->index;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->index returns the type string which is incompatible with the documented return type Ray\Di\DependencyIndex.
Loading history...
63
    }
64
65
    /**
66
     * Return reflection
67
     */
68
    public function get(): ReflectionParameter
69
    {
70
        return $this->reflection;
71
    }
72
73
    public function isDefaultAvailable(): bool
74
    {
75
        return $this->isDefaultAvailable;
76
    }
77
78
    /**
79
     * @return mixed
80
     */
81
    public function getDefaultValue()
82
    {
83
        return $this->default;
84
    }
85
86
    public function getMeta(): string
87
    {
88
        return $this->meta;
89
    }
90
91
    /**
92
     * @return array<mixed>
93
     */
94
    public function __serialize(): array
95
    {
96
        $method = $this->reflection->getDeclaringFunction();
97
        assert($method instanceof ReflectionMethod);
98
        $ref = [
99
            $method->class,
100
            $method->name,
101
            $this->reflection->getName(),
102
        ];
103
104
        return [
105
            $this->index,
106
            $this->isDefaultAvailable,
107
            $this->default,
108
            $this->meta,
109
            $ref,
110
        ];
111
    }
112
113
    /**
114
     * @param array{0: DependencyIndex, 1: bool, 2: string, 3: string, 4: string, 5: array{0: string, 1: string, 2:string}} $unserialized
115
     */
116
    public function __unserialize(array $unserialized): void
117
    {
118
        [
119
            $this->index,
120
            $this->isDefaultAvailable,
121
            $this->default,
122
            $this->meta,
123
            $ref,
124
        ] = $unserialized;
125
        $this->reflection = new ReflectionParameter([$ref[0], $ref[1]], $ref[2]);
126
    }
127
128
    /** @inheritDoc */
129
    public function accept(VisitorInterface $visitor): void
130
    {
131
        $visitor->visitArgument(
132
            $this->index,
133
            $this->isDefaultAvailable,
134
            $this->default,
135
            $this->reflection
136
        );
137
    }
138
139
    private function setDefaultValue(ReflectionParameter $parameter): void
140
    {
141
        if (! $this->isDefaultAvailable) {
142
            return;
143
        }
144
145
        try {
146
            $this->default = $parameter->getDefaultValue();
147
            // @codeCoverageIgnoreStart
148
        } catch (ReflectionException) {
149
            $this->default = null;
150
            // @codeCoverageIgnoreEnd
151
        }
152
    }
153
154
    /**
155
     * @psalm-pure
156
     */
157
    private function getType(ReflectionParameter $parameter): string
158
    {
159
        $type = $parameter->getType();
160
161
        return $type instanceof ReflectionNamedType && ! in_array($type->getName(), self::UNBOUND_TYPE, true) ? $type->getName() : '';
162
    }
163
}
164