Test Failed
Push — main ( cdf2b9...aa3274 )
by Thomas
13:21
created

Entry::negotiateReify()   B

Complexity

Conditions 8
Paths 6

Size

Total Lines 19
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 11
CRAP Score 8

Importance

Changes 0
Metric Value
eloc 11
c 0
b 0
f 0
dl 0
loc 19
ccs 11
cts 11
cp 1
rs 8.4444
cc 8
nc 6
nop 1
crap 8
1
<?php
2
3
declare(strict_types=1);
4
5
namespace FiveOrbs\Registry;
6
7
use Closure;
8
use FiveOrbs\Registry\Exception\ContainerException;
9
use FiveOrbs\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