Entry::call()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 2
c 1
b 0
f 0
nc 1
nop 2
dl 0
loc 5
ccs 3
cts 3
cp 1
crap 1
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Conia\Registry;
6
7
use Closure;
8
use Conia\Registry\Exception\ContainerException;
9
use Conia\Wire\Call;
10
11
/**
12
 * @psalm-api
13
 *
14
 * @psalm-type Args array<string|mixed>|Closure(): array<string|mixed>
15
 */
16
class Entry
17
{
18
    /** @psalm-var null|Args */
19
    protected array|Closure|null $args = null;
20
21
    protected ?string $constructor = null;
22
    protected bool $asIs = false;
23
    protected bool $reify;
24
    protected mixed $instance = null;
25
26
    /** @psalm-var list<Call> */
27
    protected array $calls = [];
28
29
    /**
30
     * @psalm-param non-empty-string $id
31
     * */
32 39
    public function __construct(
33
        readonly public string $id,
34
        protected mixed $definition
35
    ) {
36 39
        $this->reify = $this->negotiateReify($definition);
37
    }
38
39 3
    public function reify(bool $reify = true): static
40
    {
41 3
        $this->reify = $reify;
42
43 3
        return $this;
44
    }
45
46 19
    public function shouldReify(): bool
47
    {
48 19
        return $this->reify;
49
    }
50
51 2
    public function asIs(bool $asIs = true): static
52
    {
53
        // An update call is unecessary
54 2
        if ($asIs) {
55 2
            $this->reify = false;
56
        }
57
58 2
        $this->asIs = $asIs;
59
60 2
        return $this;
61
    }
62
63 21
    public function shouldReturnAsIs(): bool
64
    {
65 21
        return $this->asIs;
66
    }
67
68 10
    public function args(mixed ...$args): static
69
    {
70 10
        $numArgs = count($args);
71
72 10
        if ($numArgs === 1) {
73 5
            if (is_string(array_key_first($args))) {
74
                /** @psalm-var Args */
75 1
                $this->args = $args;
76 4
            } elseif (is_array($args[0]) || $args[0] instanceof Closure) {
77
                /** @psalm-var Args */
78 3
                $this->args = $args[0];
79
            } else {
80 5
                throw new ContainerException(
81 5
                    'Registry entry arguments can be passed as a single associative array, ' .
82 5
                    'as named arguments, or as a Closure'
83 5
                );
84
            }
85 5
        } elseif ($numArgs > 1) {
86 5
            if (!is_string(array_key_first($args))) {
87 1
                throw new ContainerException(
88 1
                    'Registry entry arguments can be passed as a single associative array, ' .
89 1
                    'as named arguments, or as a Closure'
90 1
                );
91
            }
92
93 4
            $this->args = $args;
94
        }
95
96 8
        return $this;
97
    }
98
99 19
    public function getArgs(): array|Closure|null
100
    {
101 19
        return $this->args;
102
    }
103
104 3
    public function constructor(string $methodName): static
105
    {
106 3
        $this->constructor = $methodName;
107
108 3
        return $this;
109
    }
110
111 15
    public function getConstructor(): ?string
112
    {
113 15
        return $this->constructor;
114
    }
115
116 2
    public function call(string $method, mixed ...$args): static
117
    {
118 2
        $this->calls[] = new Call($method, ...$args);
119
120 2
        return $this;
121
    }
122
123
    /** @psalm-return list<Call> */
124 18
    public function getCalls(): array
125
    {
126 18
        return $this->calls;
127
    }
128
129 9
    public function definition(): mixed
130
    {
131 9
        return $this->definition;
132
    }
133
134 3
    public function instance(): mixed
135
    {
136 3
        return $this->instance;
137
    }
138
139 21
    public function get(): mixed
140
    {
141 21
        return $this->instance ?? $this->definition;
142
    }
143
144 17
    public function set(mixed $instance): void
145
    {
146 17
        $this->instance = $instance;
147
    }
148
149 39
    protected function negotiateReify(mixed $definition): bool
150
    {
151 39
        if (is_string($definition)) {
152 24
            if (is_callable($definition)) {
153 1
                return true;
154
            }
155
156 24
            if (!class_exists($definition)) {
157 24
                return false;
158
            }
159 37
        } elseif ($definition instanceof Closure) {
160 7
            return true;
161
        } else {
162 37
            if (is_scalar($definition) || is_array($definition) || is_object($definition)) {
163 37
                return false;
164
            }
165
        }
166
167 21
        return true;
168
    }
169
}
170