isInitialized) { $this->objectManager = GeneralUtility::makeInstance(ObjectManager::class); $logManager = GeneralUtility::makeInstance(LogManager::class); $this->logger = $logManager->getLogger(self::class); $this->isInitialized = true; } } /** * Connects a signal with a slot. * One slot can be connected with multiple signals by calling this method multiple times. * * @param string $signalClassName Name of the class containing the signal * @param string $signalName Name of the signal * @param mixed $slotClassNameOrObject Name of the class containing the slot or the instantiated class or a Closure object * @param string $slotMethodName Name of the method to be used as a slot. If $slotClassNameOrObject is a Closure object, this parameter is ignored * @param bool $passSignalInformation If set to TRUE, the last argument passed to the slot will be information about the signal (EmitterClassName::signalName) * @throws \InvalidArgumentException */ public function connect($signalClassName, $signalName, $slotClassNameOrObject, $slotMethodName = '', $passSignalInformation = true) { $class = null; $object = null; if (is_object($slotClassNameOrObject)) { $object = $slotClassNameOrObject; $method = $slotClassNameOrObject instanceof \Closure ? '__invoke' : $slotMethodName; } else { if ($slotMethodName === '') { throw new \InvalidArgumentException('The slot method name must not be empty (except for closures).', 1229531659); } $class = $slotClassNameOrObject; $method = $slotMethodName; } $slot = [ 'class' => $class, 'method' => $method, 'object' => $object, 'passSignalInformation' => $passSignalInformation === true, ]; // The in_array() comparision needs to be strict to avoid potential issues // with complex objects being registered as slot. if (!is_array($this->slots[$signalClassName][$signalName] ?? false) || !in_array($slot, $this->slots[$signalClassName][$signalName], true)) { $this->slots[$signalClassName][$signalName][] = $slot; } } /** * Dispatches a signal by calling the registered Slot methods * * @param string $signalClassName Name of the class containing the signal * @param string $signalName Name of the signal * @param array $signalArguments arguments passed to the signal method * @return mixed * @throws Exception\InvalidSlotException if the slot is not valid * @throws Exception\InvalidSlotReturnException if a slot returns invalid arguments (too few or return value is not an array) */ public function dispatch($signalClassName, $signalName, array $signalArguments = []) { $this->initializeObject(); $this->logger->debug( 'Triggered signal ' . $signalClassName . ' ' . $signalName, [ 'signalClassName' => $signalClassName, 'signalName' => $signalName, 'signalArguments' => $signalArguments, ] ); if (!isset($this->slots[$signalClassName][$signalName])) { return $signalArguments; } foreach ($this->slots[$signalClassName][$signalName] as $slotInformation) { if (isset($slotInformation['object'])) { $object = $slotInformation['object']; } else { if (!isset($this->objectManager)) { 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); } if (!$this->objectManager->isRegistered($slotInformation['class'])) { throw new Exception\InvalidSlotException('The given class "' . $slotInformation['class'] . '" is not a registered object.', 1245673367); } $object = $this->objectManager->get($slotInformation['class']); } if (!method_exists($object, $slotInformation['method'])) { throw new Exception\InvalidSlotException('The slot method ' . get_class($object) . '->' . $slotInformation['method'] . '() does not exist.', 1245673368); } $preparedSlotArguments = $signalArguments; if ($slotInformation['passSignalInformation'] === true) { $preparedSlotArguments[] = $signalClassName . '::' . $signalName; } $slotReturn = call_user_func_array([$object, $slotInformation['method']], $preparedSlotArguments); if ($slotReturn) { if (!is_array($slotReturn)) { throw new Exception\InvalidSlotReturnException('The slot method ' . get_class($object) . '->' . $slotInformation['method'] . '()\'s return value is of an not allowed type (' . gettype($slotReturn) . ').', 1376683067); } if (count($slotReturn) !== count($signalArguments)) { throw new Exception\InvalidSlotReturnException('The slot method ' . get_class($object) . '->' . $slotInformation['method'] . '() returned a different number (' . count($slotReturn) . ') of arguments, than it received (' . count($signalArguments) . ').', 1376683066); } $signalArguments = $slotReturn; } } return $signalArguments; } /** * Returns all slots which are connected with the given signal * * @param string $signalClassName Name of the class containing the signal * @param string $signalName Name of the signal * @return array An array of arrays with slot information */ public function getSlots($signalClassName, $signalName) { return $this->slots[$signalClassName][$signalName] ?? []; } }