Test Failed
Push — main ( cdf2b9...aa3274 )
by Thomas
13:21
created
src/Entry.php 1 patch
Indentation   +151 added lines, -151 removed lines patch added patch discarded remove patch
@@ -15,155 +15,155 @@
 block discarded – undo
15 15
  */
16 16
 class Entry
17 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
-	public function __construct(
33
-		readonly public string $id,
34
-		protected mixed $definition,
35
-	) {
36
-		$this->reify = $this->negotiateReify($definition);
37
-	}
38
-
39
-	public function reify(bool $reify = true): static
40
-	{
41
-		$this->reify = $reify;
42
-
43
-		return $this;
44
-	}
45
-
46
-	public function shouldReify(): bool
47
-	{
48
-		return $this->reify;
49
-	}
50
-
51
-	public function asIs(bool $asIs = true): static
52
-	{
53
-		// An update call is unecessary
54
-		if ($asIs) {
55
-			$this->reify = false;
56
-		}
57
-
58
-		$this->asIs = $asIs;
59
-
60
-		return $this;
61
-	}
62
-
63
-	public function shouldReturnAsIs(): bool
64
-	{
65
-		return $this->asIs;
66
-	}
67
-
68
-	public function args(mixed ...$args): static
69
-	{
70
-		$numArgs = count($args);
71
-
72
-		if ($numArgs === 1) {
73
-			if (is_string(array_key_first($args))) {
74
-				/** @psalm-var Args */
75
-				$this->args = $args;
76
-			} elseif (is_array($args[0]) || $args[0] instanceof Closure) {
77
-				/** @psalm-var Args */
78
-				$this->args = $args[0];
79
-			} else {
80
-				throw new ContainerException(
81
-					'Registry entry arguments can be passed as a single associative array, ' .
82
-					'as named arguments, or as a Closure',
83
-				);
84
-			}
85
-		} elseif ($numArgs > 1) {
86
-			if (!is_string(array_key_first($args))) {
87
-				throw new ContainerException(
88
-					'Registry entry arguments can be passed as a single associative array, ' .
89
-					'as named arguments, or as a Closure',
90
-				);
91
-			}
92
-
93
-			$this->args = $args;
94
-		}
95
-
96
-		return $this;
97
-	}
98
-
99
-	public function getArgs(): array|Closure|null
100
-	{
101
-		return $this->args;
102
-	}
103
-
104
-	public function constructor(string $methodName): static
105
-	{
106
-		$this->constructor = $methodName;
107
-
108
-		return $this;
109
-	}
110
-
111
-	public function getConstructor(): ?string
112
-	{
113
-		return $this->constructor;
114
-	}
115
-
116
-	public function call(string $method, mixed ...$args): static
117
-	{
118
-		$this->calls[] = new Call($method, ...$args);
119
-
120
-		return $this;
121
-	}
122
-
123
-	/** @psalm-return list<Call> */
124
-	public function getCalls(): array
125
-	{
126
-		return $this->calls;
127
-	}
128
-
129
-	public function definition(): mixed
130
-	{
131
-		return $this->definition;
132
-	}
133
-
134
-	public function instance(): mixed
135
-	{
136
-		return $this->instance;
137
-	}
138
-
139
-	public function get(): mixed
140
-	{
141
-		return $this->instance ?? $this->definition;
142
-	}
143
-
144
-	public function set(mixed $instance): void
145
-	{
146
-		$this->instance = $instance;
147
-	}
148
-
149
-	protected function negotiateReify(mixed $definition): bool
150
-	{
151
-		if (is_string($definition)) {
152
-			if (is_callable($definition)) {
153
-				return true;
154
-			}
155
-
156
-			if (!class_exists($definition)) {
157
-				return false;
158
-			}
159
-		} elseif ($definition instanceof Closure) {
160
-			return true;
161
-		} else {
162
-			if (is_scalar($definition) || is_array($definition) || is_object($definition)) {
163
-				return false;
164
-			}
165
-		}
166
-
167
-		return true;
168
-	}
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
+    public function __construct(
33
+        readonly public string $id,
34
+        protected mixed $definition,
35
+    ) {
36
+        $this->reify = $this->negotiateReify($definition);
37
+    }
38
+
39
+    public function reify(bool $reify = true): static
40
+    {
41
+        $this->reify = $reify;
42
+
43
+        return $this;
44
+    }
45
+
46
+    public function shouldReify(): bool
47
+    {
48
+        return $this->reify;
49
+    }
50
+
51
+    public function asIs(bool $asIs = true): static
52
+    {
53
+        // An update call is unecessary
54
+        if ($asIs) {
55
+            $this->reify = false;
56
+        }
57
+
58
+        $this->asIs = $asIs;
59
+
60
+        return $this;
61
+    }
62
+
63
+    public function shouldReturnAsIs(): bool
64
+    {
65
+        return $this->asIs;
66
+    }
67
+
68
+    public function args(mixed ...$args): static
69
+    {
70
+        $numArgs = count($args);
71
+
72
+        if ($numArgs === 1) {
73
+            if (is_string(array_key_first($args))) {
74
+                /** @psalm-var Args */
75
+                $this->args = $args;
76
+            } elseif (is_array($args[0]) || $args[0] instanceof Closure) {
77
+                /** @psalm-var Args */
78
+                $this->args = $args[0];
79
+            } else {
80
+                throw new ContainerException(
81
+                    'Registry entry arguments can be passed as a single associative array, ' .
82
+                    'as named arguments, or as a Closure',
83
+                );
84
+            }
85
+        } elseif ($numArgs > 1) {
86
+            if (!is_string(array_key_first($args))) {
87
+                throw new ContainerException(
88
+                    'Registry entry arguments can be passed as a single associative array, ' .
89
+                    'as named arguments, or as a Closure',
90
+                );
91
+            }
92
+
93
+            $this->args = $args;
94
+        }
95
+
96
+        return $this;
97
+    }
98
+
99
+    public function getArgs(): array|Closure|null
100
+    {
101
+        return $this->args;
102
+    }
103
+
104
+    public function constructor(string $methodName): static
105
+    {
106
+        $this->constructor = $methodName;
107
+
108
+        return $this;
109
+    }
110
+
111
+    public function getConstructor(): ?string
112
+    {
113
+        return $this->constructor;
114
+    }
115
+
116
+    public function call(string $method, mixed ...$args): static
117
+    {
118
+        $this->calls[] = new Call($method, ...$args);
119
+
120
+        return $this;
121
+    }
122
+
123
+    /** @psalm-return list<Call> */
124
+    public function getCalls(): array
125
+    {
126
+        return $this->calls;
127
+    }
128
+
129
+    public function definition(): mixed
130
+    {
131
+        return $this->definition;
132
+    }
133
+
134
+    public function instance(): mixed
135
+    {
136
+        return $this->instance;
137
+    }
138
+
139
+    public function get(): mixed
140
+    {
141
+        return $this->instance ?? $this->definition;
142
+    }
143
+
144
+    public function set(mixed $instance): void
145
+    {
146
+        $this->instance = $instance;
147
+    }
148
+
149
+    protected function negotiateReify(mixed $definition): bool
150
+    {
151
+        if (is_string($definition)) {
152
+            if (is_callable($definition)) {
153
+                return true;
154
+            }
155
+
156
+            if (!class_exists($definition)) {
157
+                return false;
158
+            }
159
+        } elseif ($definition instanceof Closure) {
160
+            return true;
161
+        } else {
162
+            if (is_scalar($definition) || is_array($definition) || is_object($definition)) {
163
+                return false;
164
+            }
165
+        }
166
+
167
+        return true;
168
+    }
169 169
 }
Please login to merge, or discard this patch.
src/Registry.php 2 patches
Indentation   +227 added lines, -227 removed lines patch added patch discarded remove patch
@@ -19,231 +19,231 @@
 block discarded – undo
19 19
  */
20 20
 class Registry implements Container
21 21
 {
22
-	protected Creator $creator;
23
-	protected readonly ?Container $wrappedContainer;
24
-
25
-	/** @psalm-var EntryArray */
26
-	protected array $entries = [];
27
-
28
-	/** @psalm-var array<never, never>|array<non-empty-string, self> */
29
-	protected array $tags = [];
30
-
31
-	public function __construct(
32
-		public readonly bool $autowire = true,
33
-		?Container $container = null,
34
-		protected readonly string $tag = '',
35
-		protected readonly ?Registry $parent = null,
36
-	) {
37
-		if ($container) {
38
-			$this->wrappedContainer = $container;
39
-			$this->add(Container::class, $container);
40
-			$this->add($container::class, $container);
41
-		} else {
42
-			$this->wrappedContainer = null;
43
-			$this->add(Container::class, $this);
44
-		}
45
-		$this->add(Registry::class, $this);
46
-		$this->creator = new Creator($this);
47
-	}
48
-
49
-	public function has(string $id): bool
50
-	{
51
-		return isset($this->entries[$id]) || $this->parent?->has($id) || $this->wrappedContainer?->has($id);
52
-	}
53
-
54
-	/** @psalm-return list<string> */
55
-	public function entries(bool $includeRegistry = false): array
56
-	{
57
-		$keys = array_keys($this->entries);
58
-
59
-		if ($includeRegistry) {
60
-			return $keys;
61
-		}
62
-
63
-		return array_values(array_filter($keys, function ($item) {
64
-			return $item !== Container::class && !is_subclass_of($item, Container::class);
65
-		}));
66
-	}
67
-
68
-	public function entry(string $id): Entry
69
-	{
70
-		return $this->entries[$id];
71
-	}
72
-
73
-	public function get(string $id): mixed
74
-	{
75
-		$entry = $this->entries[$id] ?? null;
76
-
77
-		try {
78
-			if ($entry) {
79
-				return $this->resolveEntry($entry);
80
-			}
81
-
82
-			if ($this->wrappedContainer?->has($id)) {
83
-				return $this->wrappedContainer->get($id);
84
-			}
85
-
86
-			// We are in a tag. See if the $id can be resolved by the parent
87
-			// be registered on the root.
88
-			if ($this->parent) {
89
-				return $this->parent->get($id);
90
-			}
91
-
92
-			// Autowiring: $id does not exists as an entry in the registry
93
-			if ($this->autowire && class_exists($id)) {
94
-				return $this->creator->create($id);
95
-			}
96
-		} catch (WireException $e) {
97
-			throw new NotFoundException('Unresolvable id: ' . $id . ' - Details: ' . $e->getMessage());
98
-		}
99
-
100
-		throw new NotFoundException('Unresolvable id: ' . $id);
101
-	}
102
-
103
-	/**
104
-	 * @psalm-param non-empty-string $id
105
-	 */
106
-	public function add(
107
-		string $id,
108
-		mixed $value = null,
109
-	): Entry {
110
-		$entry = new Entry($id, $value ?? $id);
111
-		$this->entries[$id] = $entry;
112
-
113
-		return $entry;
114
-	}
115
-
116
-	public function addEntry(
117
-		Entry $entry,
118
-	): Entry {
119
-		$this->entries[$entry->id] = $entry;
120
-
121
-		return $entry;
122
-	}
123
-
124
-	/** @psalm-param non-empty-string $tag */
125
-	public function tag(string $tag): Registry
126
-	{
127
-		if (!isset($this->tags[$tag])) {
128
-			$this->tags[$tag] = new self(tag: $tag, parent: $this);
129
-		}
130
-
131
-		return $this->tags[$tag];
132
-	}
133
-
134
-	public function new(string $id, mixed ...$args): object
135
-	{
136
-		$entry = $this->entries[$id] ?? null;
137
-
138
-		if ($entry) {
139
-			/** @var mixed */
140
-			$value = $entry->definition();
141
-
142
-			if (is_string($value)) {
143
-				if (interface_exists($value)) {
144
-					return $this->new($value, ...$args);
145
-				}
146
-
147
-				if (class_exists($value)) {
148
-					/** @psalm-suppress MixedMethodCall */
149
-					return new $value(...$args);
150
-				}
151
-			}
152
-		}
153
-
154
-		if (class_exists($id)) {
155
-			/** @psalm-suppress MixedMethodCall */
156
-			return new $id(...$args);
157
-		}
158
-
159
-		throw new NotFoundException('Cannot instantiate ' . $id);
160
-	}
161
-
162
-	protected function callAndReify(Entry $entry, mixed $value): mixed
163
-	{
164
-		foreach ($entry->getCalls() as $call) {
165
-			$methodToResolve = $call->method;
166
-
167
-			/** @psalm-var callable */
168
-			$callable = [$value, $methodToResolve];
169
-			$args = (new CallableResolver($this->creator))->resolve($callable, $call->args);
170
-			$callable(...$args);
171
-		}
172
-
173
-		if ($entry->shouldReify()) {
174
-			$entry->set($value);
175
-		}
176
-
177
-		return $value;
178
-	}
179
-
180
-	protected function resolveEntry(Entry $entry): mixed
181
-	{
182
-		if ($entry->shouldReturnAsIs()) {
183
-			return $entry->definition();
184
-		}
185
-
186
-		/** @var mixed - the current value, instantiated or definition */
187
-		$value = $entry->get();
188
-
189
-		if (is_string($value)) {
190
-			if (class_exists($value)) {
191
-				$constructor = $entry->getConstructor();
192
-				$args = $entry->getArgs();
193
-
194
-				if (isset($args)) {
195
-					// Don't autowire if $args are given
196
-					if ($args instanceof Closure) {
197
-						/** @psalm-var array<string, mixed> */
198
-						$args = $args(...(new CallableResolver($this->creator))->resolve($args));
199
-
200
-						return $this->callAndReify(
201
-							$entry,
202
-							$this->creator->create($value, $args),
203
-						);
204
-					}
205
-
206
-					return $this->callAndReify(
207
-						$entry,
208
-						$this->creator->create(
209
-							$value,
210
-							predefinedArgs: $args,
211
-							constructor: $constructor,
212
-						),
213
-					);
214
-				}
215
-
216
-				return $this->callAndReify(
217
-					$entry,
218
-					$this->creator->create($value, constructor: $constructor),
219
-				);
220
-			}
221
-
222
-			if ($this->has($value)) {
223
-				return $this->get($value);
224
-			}
225
-		}
226
-
227
-		if ($value instanceof Closure) {
228
-			$args = $entry->getArgs();
229
-
230
-			if (is_null($args)) {
231
-				$args = (new CallableResolver($this->creator))->resolve($value);
232
-			} elseif ($args instanceof Closure) {
233
-				/** @var array<string, mixed> */
234
-				$args = $args();
235
-			}
236
-
237
-			/** @var mixed */
238
-			$result = $value(...$args);
239
-
240
-			return $this->callAndReify($entry, $result);
241
-		}
242
-
243
-		if (is_object($value)) {
244
-			return $value;
245
-		}
246
-
247
-		throw new NotFoundException('Unresolvable id: ' . (string) $value);
248
-	}
22
+    protected Creator $creator;
23
+    protected readonly ?Container $wrappedContainer;
24
+
25
+    /** @psalm-var EntryArray */
26
+    protected array $entries = [];
27
+
28
+    /** @psalm-var array<never, never>|array<non-empty-string, self> */
29
+    protected array $tags = [];
30
+
31
+    public function __construct(
32
+        public readonly bool $autowire = true,
33
+        ?Container $container = null,
34
+        protected readonly string $tag = '',
35
+        protected readonly ?Registry $parent = null,
36
+    ) {
37
+        if ($container) {
38
+            $this->wrappedContainer = $container;
39
+            $this->add(Container::class, $container);
40
+            $this->add($container::class, $container);
41
+        } else {
42
+            $this->wrappedContainer = null;
43
+            $this->add(Container::class, $this);
44
+        }
45
+        $this->add(Registry::class, $this);
46
+        $this->creator = new Creator($this);
47
+    }
48
+
49
+    public function has(string $id): bool
50
+    {
51
+        return isset($this->entries[$id]) || $this->parent?->has($id) || $this->wrappedContainer?->has($id);
52
+    }
53
+
54
+    /** @psalm-return list<string> */
55
+    public function entries(bool $includeRegistry = false): array
56
+    {
57
+        $keys = array_keys($this->entries);
58
+
59
+        if ($includeRegistry) {
60
+            return $keys;
61
+        }
62
+
63
+        return array_values(array_filter($keys, function ($item) {
64
+            return $item !== Container::class && !is_subclass_of($item, Container::class);
65
+        }));
66
+    }
67
+
68
+    public function entry(string $id): Entry
69
+    {
70
+        return $this->entries[$id];
71
+    }
72
+
73
+    public function get(string $id): mixed
74
+    {
75
+        $entry = $this->entries[$id] ?? null;
76
+
77
+        try {
78
+            if ($entry) {
79
+                return $this->resolveEntry($entry);
80
+            }
81
+
82
+            if ($this->wrappedContainer?->has($id)) {
83
+                return $this->wrappedContainer->get($id);
84
+            }
85
+
86
+            // We are in a tag. See if the $id can be resolved by the parent
87
+            // be registered on the root.
88
+            if ($this->parent) {
89
+                return $this->parent->get($id);
90
+            }
91
+
92
+            // Autowiring: $id does not exists as an entry in the registry
93
+            if ($this->autowire && class_exists($id)) {
94
+                return $this->creator->create($id);
95
+            }
96
+        } catch (WireException $e) {
97
+            throw new NotFoundException('Unresolvable id: ' . $id . ' - Details: ' . $e->getMessage());
98
+        }
99
+
100
+        throw new NotFoundException('Unresolvable id: ' . $id);
101
+    }
102
+
103
+    /**
104
+     * @psalm-param non-empty-string $id
105
+     */
106
+    public function add(
107
+        string $id,
108
+        mixed $value = null,
109
+    ): Entry {
110
+        $entry = new Entry($id, $value ?? $id);
111
+        $this->entries[$id] = $entry;
112
+
113
+        return $entry;
114
+    }
115
+
116
+    public function addEntry(
117
+        Entry $entry,
118
+    ): Entry {
119
+        $this->entries[$entry->id] = $entry;
120
+
121
+        return $entry;
122
+    }
123
+
124
+    /** @psalm-param non-empty-string $tag */
125
+    public function tag(string $tag): Registry
126
+    {
127
+        if (!isset($this->tags[$tag])) {
128
+            $this->tags[$tag] = new self(tag: $tag, parent: $this);
129
+        }
130
+
131
+        return $this->tags[$tag];
132
+    }
133
+
134
+    public function new(string $id, mixed ...$args): object
135
+    {
136
+        $entry = $this->entries[$id] ?? null;
137
+
138
+        if ($entry) {
139
+            /** @var mixed */
140
+            $value = $entry->definition();
141
+
142
+            if (is_string($value)) {
143
+                if (interface_exists($value)) {
144
+                    return $this->new($value, ...$args);
145
+                }
146
+
147
+                if (class_exists($value)) {
148
+                    /** @psalm-suppress MixedMethodCall */
149
+                    return new $value(...$args);
150
+                }
151
+            }
152
+        }
153
+
154
+        if (class_exists($id)) {
155
+            /** @psalm-suppress MixedMethodCall */
156
+            return new $id(...$args);
157
+        }
158
+
159
+        throw new NotFoundException('Cannot instantiate ' . $id);
160
+    }
161
+
162
+    protected function callAndReify(Entry $entry, mixed $value): mixed
163
+    {
164
+        foreach ($entry->getCalls() as $call) {
165
+            $methodToResolve = $call->method;
166
+
167
+            /** @psalm-var callable */
168
+            $callable = [$value, $methodToResolve];
169
+            $args = (new CallableResolver($this->creator))->resolve($callable, $call->args);
170
+            $callable(...$args);
171
+        }
172
+
173
+        if ($entry->shouldReify()) {
174
+            $entry->set($value);
175
+        }
176
+
177
+        return $value;
178
+    }
179
+
180
+    protected function resolveEntry(Entry $entry): mixed
181
+    {
182
+        if ($entry->shouldReturnAsIs()) {
183
+            return $entry->definition();
184
+        }
185
+
186
+        /** @var mixed - the current value, instantiated or definition */
187
+        $value = $entry->get();
188
+
189
+        if (is_string($value)) {
190
+            if (class_exists($value)) {
191
+                $constructor = $entry->getConstructor();
192
+                $args = $entry->getArgs();
193
+
194
+                if (isset($args)) {
195
+                    // Don't autowire if $args are given
196
+                    if ($args instanceof Closure) {
197
+                        /** @psalm-var array<string, mixed> */
198
+                        $args = $args(...(new CallableResolver($this->creator))->resolve($args));
199
+
200
+                        return $this->callAndReify(
201
+                            $entry,
202
+                            $this->creator->create($value, $args),
203
+                        );
204
+                    }
205
+
206
+                    return $this->callAndReify(
207
+                        $entry,
208
+                        $this->creator->create(
209
+                            $value,
210
+                            predefinedArgs: $args,
211
+                            constructor: $constructor,
212
+                        ),
213
+                    );
214
+                }
215
+
216
+                return $this->callAndReify(
217
+                    $entry,
218
+                    $this->creator->create($value, constructor: $constructor),
219
+                );
220
+            }
221
+
222
+            if ($this->has($value)) {
223
+                return $this->get($value);
224
+            }
225
+        }
226
+
227
+        if ($value instanceof Closure) {
228
+            $args = $entry->getArgs();
229
+
230
+            if (is_null($args)) {
231
+                $args = (new CallableResolver($this->creator))->resolve($value);
232
+            } elseif ($args instanceof Closure) {
233
+                /** @var array<string, mixed> */
234
+                $args = $args();
235
+            }
236
+
237
+            /** @var mixed */
238
+            $result = $value(...$args);
239
+
240
+            return $this->callAndReify($entry, $result);
241
+        }
242
+
243
+        if (is_object($value)) {
244
+            return $value;
245
+        }
246
+
247
+        throw new NotFoundException('Unresolvable id: ' . (string) $value);
248
+    }
249 249
 }
Please login to merge, or discard this patch.
Spacing   +2 added lines, -2 removed lines patch added patch discarded remove patch
@@ -60,7 +60,7 @@  discard block
 block discarded – undo
60 60
 			return $keys;
61 61
 		}
62 62
 
63
-		return array_values(array_filter($keys, function ($item) {
63
+		return array_values(array_filter($keys, function($item) {
64 64
 			return $item !== Container::class && !is_subclass_of($item, Container::class);
65 65
 		}));
66 66
 	}
@@ -244,6 +244,6 @@  discard block
 block discarded – undo
244 244
 			return $value;
245 245
 		}
246 246
 
247
-		throw new NotFoundException('Unresolvable id: ' . (string) $value);
247
+		throw new NotFoundException('Unresolvable id: ' . (string)$value);
248 248
 	}
249 249
 }
Please login to merge, or discard this patch.