2424 */
2525class 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
0 commit comments