Passed
Push — php82 ( f26871 )
by Akihito
02:19
created

Argument::getDefaultValue()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 1
dl 0
loc 3
c 0
b 0
f 0
rs 10
cc 1
nc 1
nop 0
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
12
use function assert;
13
use function in_array;
14
use function sprintf;
15
16
/**
17
 * @psalm-import-type DependencyIndex from Types
18
 */
19
final class Argument implements AcceptInterface
20
{
21
    public const UNBOUND_TYPE = ['bool', 'int', 'float', 'string', 'array', 'resource', 'callable', 'iterable'];
22
23
    /** @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...
24
    private $index;
25
26
    /** @var bool */
27
    private $isDefaultAvailable;
28
29
    /** @var mixed */
30
    private $default;
31
32
    /** @var string */
33
    private $meta;
34
35
    /** @var ReflectionParameter */
36
    private $reflection;
37
38
    public function __construct(ReflectionParameter $parameter, string $name)
39
    {
40
        $type = $this->getType($parameter);
41
        $isOptional = $parameter->isOptional();
42
        $this->isDefaultAvailable = $parameter->isDefaultValueAvailable() || $isOptional;
43
        if ($isOptional) {
44
            $this->default = null;
45
        }
46
47
        $this->setDefaultValue($parameter);
48
        $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...
49
        $this->reflection = $parameter;
50
        $this->meta = sprintf(
51
            "dependency '%s' with name '%s' used in %s:%d ($%s)",
52
            $type,
53
            $name,
54
            $this->reflection->getDeclaringFunction()->getFileName(),
55
            $this->reflection->getDeclaringFunction()->getStartLine(),
56
            $parameter->getName()
57
        );
58
    }
59
60
    /**
61
     * Return index
62
     *
63
     * @return DependencyIndex
64
     */
65
    public function __toString(): string
66
    {
67
        return $this->index;
68
    }
69
70
    /**
71
     * Return reflection
72
     */
73
    public function get(): ReflectionParameter
74
    {
75
        return $this->reflection;
76
    }
77
78
    public function isDefaultAvailable(): bool
79
    {
80
        return $this->isDefaultAvailable;
81
    }
82
83
    /**
84
     * @return mixed
85
     */
86
    public function getDefaultValue()
87
    {
88
        return $this->default;
89
    }
90
91
    public function getMeta(): string
92
    {
93
        return $this->meta;
94
    }
95
96
    /**
97
     * @return array<mixed>
98
     */
99
    public function __serialize(): array
100
    {
101
        $method = $this->reflection->getDeclaringFunction();
102
        assert($method instanceof ReflectionMethod);
103
        $ref = [
104
            $method->class,
105
            $method->name,
106
            $this->reflection->getName(),
107
        ];
108
109
        return [
110
            $this->index,
111
            $this->isDefaultAvailable,
112
            $this->default,
113
            $this->meta,
114
            $ref,
115
        ];
116
    }
117
118
    /**
119
     * @param array{0: DependencyIndex, 1: bool, 2: string, 3: string, 4: string, 5: array{0: string, 1: string, 2:string}} $unserialized
120
     */
121
    public function __unserialize(array $unserialized): void
122
    {
123
        [
124
            $this->index,
125
            $this->isDefaultAvailable,
126
            $this->default,
127
            $this->meta,
128
            $ref,
129
        ] = $unserialized;
130
        $this->reflection = new ReflectionParameter([$ref[0], $ref[1]], $ref[2]);
131
    }
132
133
    /** @inheritDoc */
134
    public function accept(VisitorInterface $visitor)
135
    {
136
        $visitor->visitArgument(
137
            $this->index,
138
            $this->isDefaultAvailable,
139
            $this->default,
140
            $this->reflection
141
        );
142
    }
143
144
    private function setDefaultValue(ReflectionParameter $parameter): void
145
    {
146
        if (! $this->isDefaultAvailable) {
147
            return;
148
        }
149
150
        try {
151
            $this->default = $parameter->getDefaultValue();
152
            // @codeCoverageIgnoreStart
153
        } catch (ReflectionException $e) {
154
            $this->default = null;
155
            // @codeCoverageIgnoreEnd
156
        }
157
    }
158
159
    /**
160
     * @psalm-pure
161
     */
162
    private function getType(ReflectionParameter $parameter): string
163
    {
164
        $type = $parameter->getType();
165
166
        return $type instanceof ReflectionNamedType && ! in_array($type->getName(), self::UNBOUND_TYPE, true) ? $type->getName() : '';
167
    }
168
}
169