Passed
Push — master ( 7655a2...08803f )
by Alexander
07:55 queued 06:29
created

ResolvingState::disablePushTrailingArguments()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 1
c 1
b 0
f 0
nc 2
nop 1
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 2
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Injector;
6
7
use Generator;
8
use ReflectionFunctionAbstract;
9
10
/**
11
 * Intermediate arguments resolving data to pass around until resolving is finished.
12
 * @internal
13
 */
14
final class ResolvingState
15
{
16
    private ReflectionFunctionAbstract $reflection;
17
    /** @var array<int, object> */
18
    private array $numericArguments = [];
19
    /** @var array<string, mixed> */
20
    private array $namedArguments = [];
21
    private bool $shouldPushTrailingArguments;
22
    private array $resolvedValues = [];
23
24
    /**
25
     * @param ReflectionFunctionAbstract $reflection Function reflection.
26
     * @param array $arguments User arguments.
27
     */
28 45
    public function __construct(ReflectionFunctionAbstract $reflection, array $arguments)
29
    {
30 45
        $this->reflection = $reflection;
31 45
        $this->shouldPushTrailingArguments = !$reflection->isInternal();
32 45
        $this->sortArguments($arguments);
33 42
    }
34
35 3
    public function hasNamedArgument(string $name): bool
36
    {
37 3
        return array_key_exists($name, $this->namedArguments);
38
    }
39
40
    /**
41
     * @param bool $condition If true then trailing arguments will not be passed.
42
     */
43 38
    public function disablePushTrailingArguments(bool $condition): void
44
    {
45 38
        $this->shouldPushTrailingArguments = $this->shouldPushTrailingArguments && !$condition;
46 38
    }
47
48 30
    public function addResolvedValue(&$value): void
49
    {
50 30
        $this->resolvedValues[] = &$value;
51 30
    }
52 38
    public function resolveParameterByName(string $name, bool $variadic): bool
53
    {
54 38
        if (!array_key_exists($name, $this->namedArguments)) {
55 32
            return false;
56
        }
57 12
        if ($variadic && is_array($this->namedArguments[$name])) {
58 2
            array_walk($this->namedArguments[$name], [$this, 'addResolvedValue']);
59
        } else {
60 11
            $this->addResolvedValue($this->namedArguments[$name]);
61
        }
62 12
        return true;
63
    }
64 24
    public function resolveParameterByClass(?string $className, bool $variadic): bool
65
    {
66 24
        $generator = $this->pullNumericArgument($className);
67 24
        if (!$variadic) {
68 20
            if (!$generator->valid()) {
69 17
                return false;
70
            }
71 7
            $value = $generator->current();
72 7
            $this->addResolvedValue($value);
73 7
            return true;
74
        }
75 7
        foreach ($generator as &$value) {
76 5
            $this->addResolvedValue($value);
77
        }
78 7
        return true;
79
    }
80
81 35
    public function getResolvedValues(): array
82
    {
83 35
        return $this->shouldPushTrailingArguments
84 23
            ? [...$this->resolvedValues, ...$this->numericArguments]
85 35
            : $this->resolvedValues;
86
    }
87
88
    /**
89
     * @param null|string $className
90
     * @return Generator<void, object>
91
     */
92 24
    private function &pullNumericArgument(?string $className): Generator
93
    {
94 24
        foreach ($this->numericArguments as $key => &$value) {
95 11
            if ($className === null || $value instanceof $className) {
96 11
                unset($this->numericArguments[$key]);
97 11
                yield $value;
98
            }
99
        }
100 21
    }
101
    /**
102
     * @param array $arguments
103
     * @throws InvalidArgumentException
104
     */
105 45
    private function sortArguments(array $arguments): void
106
    {
107 45
        foreach ($arguments as $key => &$value) {
108 27
            if (is_int($key)) {
109 20
                if (!is_object($value)) {
110 3
                    throw new InvalidArgumentException($this->reflection, (string)$key);
111
                }
112 17
                $this->numericArguments[] = &$value;
113
            } else {
114 14
                $this->namedArguments[$key] = &$value;
115
            }
116
        }
117 42
    }
118
}
119