Passed
Push — visitor ( 2d5566 )
by Akihito
11:02
created

Argument   A

Complexity

Total Complexity 19

Size/Duplication

Total Lines 154
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 19
eloc 57
c 1
b 0
f 0
dl 0
loc 154
rs 10

13 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 __construct() 0 19 3
A __unserialize() 0 10 1
A serialize() 0 3 1
A unserialize() 0 5 1
A __serialize() 0 16 1
A accept() 0 3 1
A setDefaultValue() 0 11 3
A getType() 0 5 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 Serializable;
12
13
use function assert;
14
use function in_array;
15
use function serialize;
16
use function sprintf;
17
use function unserialize;
18
19
final class Argument implements Serializable
20
{
21
    public const UNBOUND_TYPE = ['bool', 'int', 'float', 'string', 'array', 'resource', 'callable', 'iterable'];
22
23
    /** @var string */
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;
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
    public function __toString(): string
61
    {
62
        return $this->index;
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
     * {@inheritDoc}
93
     */
94
    public function serialize(): ?string
95
    {
96
        return serialize($this->__serialize());
97
    }
98
99
    /**
100
     * {@inheritDoc}
101
     *
102
     * @psalm-param string $data
103
     */
104
    public function unserialize($data): void
105
    {
106
        /** @var array{0: string, 1: bool, 2: string, 3: string, 4: string, 5: array{0: string, 1: string, 2:string}} $array */
107
        $array = unserialize($data, ['allowed_classes' => false]);
108
        $this->__unserialize($array);
109
    }
110
111
    /**
112
     * @return array<mixed>
113
     */
114
    public function __serialize(): array
115
    {
116
        $method = $this->reflection->getDeclaringFunction();
117
        assert($method instanceof ReflectionMethod);
118
        $ref = [
119
            $method->class,
120
            $method->name,
121
            $this->reflection->getName(),
122
        ];
123
124
        return [
125
            $this->index,
126
            $this->isDefaultAvailable,
127
            $this->default,
128
            $this->meta,
129
            $ref,
130
        ];
131
    }
132
133
    /**
134
     * @param array{0: string, 1: bool, 2: string, 3: string, 4: string, 5: array{0: string, 1: string, 2:string}} $unserialized
135
     */
136
    public function __unserialize(array $unserialized): void
137
    {
138
        [
139
            $this->index,
140
            $this->isDefaultAvailable,
141
            $this->default,
142
            $this->meta,
143
            $ref,
144
        ] = $unserialized;
145
        $this->reflection = new ReflectionParameter([$ref[0], $ref[1]], $ref[2]);
146
    }
147
148
    public function accept(VisitorInterface $visitor)
149
    {
150
        $visitor->visitArgument($this->index, $this->isDefaultAvailable, $this->default, $this->reflection);
0 ignored issues
show
Bug introduced by
The method visitArgument() does not exist on Ray\Di\VisitorInterface. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

150
        $visitor->/** @scrutinizer ignore-call */ 
151
                  visitArgument($this->index, $this->isDefaultAvailable, $this->default, $this->reflection);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
151
    }
152
153
    private function setDefaultValue(ReflectionParameter $parameter): void
154
    {
155
        if (! $this->isDefaultAvailable) {
156
            return;
157
        }
158
159
        try {
160
            $this->default = $parameter->getDefaultValue();
161
            // @codeCoverageIgnoreStart
162
        } catch (ReflectionException $e) {
163
            $this->default = null;
164
            // @codeCoverageIgnoreEnd
165
        }
166
    }
167
168
    private function getType(ReflectionParameter $parameter): string
169
    {
170
        $type = $parameter->getType();
171
172
        return $type instanceof ReflectionNamedType && ! in_array($type->getName(), self::UNBOUND_TYPE, true) ? $type->getName() : '';
173
    }
174
}
175