Skip to content

Commit f8f35a7

Browse files
Bernhard Schmittmficzel
authored andcommitted
Adjust Neos.Flow SignalSlot subcontext
1 parent f732a66 commit f8f35a7

File tree

2 files changed

+54
-19
lines changed

2 files changed

+54
-19
lines changed

Neos.Flow/Classes/SignalSlot/Dispatcher.php

Lines changed: 47 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -24,18 +24,21 @@
2424
*/
2525
class Dispatcher
2626
{
27-
/**
28-
* @var ObjectManagerInterface
29-
*/
30-
protected $objectManager;
27+
protected ?ObjectManagerInterface $objectManager = null;
3128

3229
/**
3330
* Information about all slots connected a certain signal.
3431
* Indexed by [$signalClassName][$signalMethodName] and then numeric with an
3532
* array of information about the slot
36-
* @var array
33+
* @var array<class-string,array<string,array<int,array{
34+
* class: ?class-string,
35+
* method: string,
36+
* object: ?object,
37+
* passSignalInformation: bool,
38+
* useSignalInformationObject: bool,
39+
* }>>>
3740
*/
38-
protected $slots = [];
41+
protected array $slots = [];
3942

4043
/**
4144
* Injects the object manager
@@ -56,7 +59,7 @@ public function injectObjectManager(ObjectManagerInterface $objectManager): void
5659
* When $passSignalInformation is true, the slot will be passed a string (EmitterClassName::signalName) as the last
5760
* parameter.
5861
*
59-
* @param string $signalClassName Name of the class containing the signal
62+
* @param class-string $signalClassName Name of the class containing the signal
6063
* @param string $signalName Name of the signal
6164
* @param mixed $slotClassNameOrObject Name of the class containing the slot or the instantiated class or a Closure object
6265
* @param string $slotMethodName Name of the method to be used as a slot. If $slotClassNameOrObject is a Closure object, this parameter is ignored
@@ -78,7 +81,7 @@ public function connect(string $signalClassName, string $signalName, $slotClassN
7881
*
7982
* The slot will be passed a an instance of SignalInformation as the sole parameter.
8083
*
81-
* @param string $signalClassName Name of the class containing the signal
84+
* @param class-string $signalClassName Name of the class containing the signal
8285
* @param string $signalName Name of the signal
8386
* @param mixed $slotClassNameOrObject Name of the class containing the slot or the instantiated class or a Closure object
8487
* @param string $slotMethodName Name of the method to be used as a slot. If $slotClassNameOrObject is a Closure object, this parameter is ignored
@@ -94,7 +97,7 @@ public function wire(string $signalClassName, string $signalName, $slotClassName
9497
}
9598

9699
/**
97-
* @param string $signalClassName
100+
* @param class-string $signalClassName
98101
* @param string $signalName
99102
* @param mixed $slotClassNameOrObject
100103
* @param string $slotMethodName
@@ -116,6 +119,9 @@ private function connectSignalToSlot(string $signalClassName, string $signalName
116119
$object = $slotClassNameOrObject;
117120
$method = ($slotClassNameOrObject instanceof \Closure) ? '__invoke' : $slotMethodName;
118121
} else {
122+
if (!class_exists($slotClassNameOrObject)) {
123+
throw new \Exception('Unkown class ' . $slotClassNameOrObject, 1743926351);
124+
}
119125
if ($slotMethodName === '') {
120126
throw new \InvalidArgumentException('The slot method name must not be empty (except for closures).', 1229531659);
121127
}
@@ -137,7 +143,7 @@ private function connectSignalToSlot(string $signalClassName, string $signalName
137143
*
138144
* @param string $signalClassName Name of the class containing the signal
139145
* @param string $signalName Name of the signal
140-
* @param array $signalArguments arguments passed to the signal method
146+
* @param array<mixed> $signalArguments arguments passed to the signal method
141147
* @return void
142148
* @throws Exception\InvalidSlotException if the slot is not valid
143149
* @api
@@ -153,47 +159,64 @@ public function dispatch(string $signalClassName, string $signalName, array $sig
153159
if (isset($slotInformation['object'])) {
154160
$object = $slotInformation['object'];
155161
} elseif (strpos($slotInformation['method'], '::') === 0) {
156-
if (!isset($this->objectManager)) {
162+
if ($this->objectManager === null) {
157163
if (is_callable($slotInformation['class'] . $slotInformation['method'])) {
158164
$object = $slotInformation['class'];
159165
} else {
160166
throw new Exception\InvalidSlotException(sprintf('Cannot dispatch %s::%s to class %s. The object manager is not yet available in the Signal Slot Dispatcher and therefore it cannot dispatch classes.', $signalClassName, $signalName, $slotInformation['class']), 1298113624);
161167
}
162168
} else {
169+
if ($slotInformation['class'] === null) {
170+
throw new Exception\InvalidSlotException('Slot class is undefined.', 1743958214);
171+
}
163172
$object = $this->objectManager->getClassNameByObjectName($slotInformation['class']);
164173
}
165174
$slotInformation['method'] = substr($slotInformation['method'], 2);
166175
} else {
167-
if (!isset($this->objectManager)) {
176+
if ($this->objectManager === null) {
168177
throw new Exception\InvalidSlotException(sprintf('Cannot dispatch %s::%s to class %s. The object manager is not yet available in the Signal Slot Dispatcher and therefore it cannot dispatch classes.', $signalClassName, $signalName, $slotInformation['class']), 1298113624);
169178
}
179+
if ($slotInformation['class'] === null) {
180+
throw new Exception\InvalidSlotException('Slot class is undefined.', 1743958214);
181+
}
170182
if (!$this->objectManager->isRegistered($slotInformation['class'])) {
171183
throw new Exception\InvalidSlotException('The given class "' . $slotInformation['class'] . '" is not a registered object.', 1245673367);
172184
}
173185
$object = $this->objectManager->get($slotInformation['class']);
174186
}
175-
if (!method_exists($object, $slotInformation['method'])) {
187+
if (is_object($object) && !method_exists($object, $slotInformation['method'])) {
176188
throw new Exception\InvalidSlotException('The slot method ' . get_class($object) . '->' . $slotInformation['method'] . '() does not exist.', 1245673368);
177189
}
178190

191+
$callable = [$object, $slotInformation['method']];
192+
if (!is_callable($callable)) {
193+
throw new \Exception('Invalid slot method ' . $slotInformation['method'], 1743955562);
194+
}
195+
179196
if ($slotInformation['useSignalInformationObject'] === true) {
180-
call_user_func([$object, $slotInformation['method']], new SignalInformation($signalClassName, $signalName, $finalSignalArguments));
197+
call_user_func($callable, new SignalInformation($signalClassName, $signalName, $finalSignalArguments));
181198
} else {
182199
if ($slotInformation['passSignalInformation'] === true) {
183200
$finalSignalArguments[] = $signalClassName . '::' . $signalName;
184201
}
185202
// Need to use call_user_func_array here, because $object may be the class name when the slot is a static method
186-
call_user_func_array([$object, $slotInformation['method']], $finalSignalArguments);
203+
call_user_func_array($callable, $finalSignalArguments);
187204
}
188205
}
189206
}
190207

191208
/**
192209
* Returns all slots which are connected with the given signal
193210
*
194-
* @param string $signalClassName Name of the class containing the signal
211+
* @param class-string $signalClassName Name of the class containing the signal
195212
* @param string $signalName Name of the signal
196-
* @return array An array of arrays with slot information
213+
* @return array<int,array{
214+
* class: ?class-string,
215+
* method: string,
216+
* object: ?object,
217+
* passSignalInformation: bool,
218+
* useSignalInformationObject: bool,
219+
* }> An array of arrays with slot information
197220
* @api
198221
*/
199222
public function getSlots(string $signalClassName, string $signalName): array
@@ -204,7 +227,13 @@ public function getSlots(string $signalClassName, string $signalName): array
204227
/**
205228
* Returns all signals with its slots
206229
*
207-
* @return array An array of arrays with slot information
230+
* @return array<class-string,array<string,array<int,array{
231+
* class: ?class-string,
232+
* method: string,
233+
* object: ?object,
234+
* passSignalInformation: bool,
235+
* useSignalInformationObject: bool,
236+
* }>>> An array of arrays with slot information
208237
* @api
209238
*/
210239
public function getSignals(): array

Neos.Flow/Classes/SignalSlot/SignalInformation.php

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,13 @@ final class SignalInformation
3535
protected $signalName;
3636

3737
/**
38-
* @var array
38+
* @var array<mixed>
3939
*/
4040
protected $signalArguments;
4141

42+
/**
43+
* @param array<mixed> $signalArguments
44+
*/
4245
public function __construct(string $signalClassName, string $signalName, array $signalArguments)
4346
{
4447
$this->signalClassName = $signalClassName;
@@ -56,6 +59,9 @@ public function getSignalName(): string
5659
return $this->signalName;
5760
}
5861

62+
/**
63+
* @return array<mixed>
64+
*/
5965
public function getSignalArguments(): array
6066
{
6167
return $this->signalArguments;

0 commit comments

Comments
 (0)