[CLEANUP] Adjust code to coding guidelines
[Packages/TYPO3.CMS.git] / typo3 / sysext / extbase / Classes / SignalSlot / Dispatcher.php
1 <?php
2 namespace TYPO3\CMS\Extbase\SignalSlot;
3
4 /***************************************************************
5 * Copyright notice
6 *
7 * (c) 2011 Felix Oertel <f@oer.tel>
8 * All rights reserved
9 *
10 * This class is a backport of the corresponding class of TYPO3 Flow.
11 * All credits go to the TYPO3 Flow team.
12 *
13 * This script is part of the TYPO3 project. The TYPO3 project is
14 * free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2 of the License, or
17 * (at your option) any later version.
18 *
19 * The GNU General Public License can be found at
20 * http://www.gnu.org/copyleft/gpl.html.
21 *
22 * This script is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU General Public License for more details.
26 *
27 * This copyright notice MUST APPEAR in all copies of the script!
28 ***************************************************************/
29 /**
30 * A dispatcher which dispatches signals by calling its registered slot methods
31 * and passing them the method arguments which were originally passed to the
32 * signal method.
33 *
34 * @api
35 */
36 class Dispatcher implements \TYPO3\CMS\Core\SingletonInterface {
37
38 /**
39 * @var boolean
40 */
41 protected $isInitialized = FALSE;
42
43 /**
44 * @var \TYPO3\CMS\Extbase\Object\ObjectManagerInterface
45 */
46 protected $objectManager;
47
48 /**
49 * Information about all slots connected a certain signal.
50 * Indexed by [$signalClassName][$signalMethodName] and then numeric with an
51 * array of information about the slot
52 *
53 * @var array
54 */
55 protected $slots = array();
56
57 /**
58 * Initializes this object.
59 *
60 * This methods needs to be used as alternative to inject aspects.
61 * Since this dispatches is used very early when the ObjectManager
62 * is not fully initialized (especially concerning caching framework),
63 * this is the only way.
64 */
65 public function initializeObject() {
66 if ($this->isInitialized) {
67 return;
68 }
69 $this->objectManager = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Extbase\\Object\\ObjectManager');
70 $this->isInitialized = TRUE;
71 }
72
73 /**
74 * Connects a signal with a slot.
75 * One slot can be connected with multiple signals by calling this method multiple times.
76 *
77 * @param string $signalClassName Name of the class containing the signal
78 * @param string $signalName Name of the signal
79 * @param mixed $slotClassNameOrObject Name of the class containing the slot or the instantiated class or a Closure object
80 * @param string $slotMethodName Name of the method to be used as a slot. If $slotClassNameOrObject is a Closure object, this parameter is ignored
81 * @param boolean $passSignalInformation If set to TRUE, the last argument passed to the slot will be information about the signal (EmitterClassName::signalName)
82 * @throws \InvalidArgumentException
83 * @return void
84 * @api
85 */
86 public function connect($signalClassName, $signalName, $slotClassNameOrObject, $slotMethodName = '', $passSignalInformation = TRUE) {
87 $class = NULL;
88 $object = NULL;
89 if (is_object($slotClassNameOrObject)) {
90 $object = $slotClassNameOrObject;
91 $method = $slotClassNameOrObject instanceof \Closure ? '__invoke' : $slotMethodName;
92 } else {
93 if ($slotMethodName === '') {
94 throw new \InvalidArgumentException('The slot method name must not be empty (except for closures).', 1229531659);
95 }
96 $class = $slotClassNameOrObject;
97 $method = $slotMethodName;
98 }
99 $slot = array(
100 'class' => $class,
101 'method' => $method,
102 'object' => $object,
103 'passSignalInformation' => $passSignalInformation === TRUE
104 );
105 if (!is_array($this->slots[$signalClassName][$signalName]) || !in_array($slot, $this->slots[$signalClassName][$signalName])) {
106 $this->slots[$signalClassName][$signalName][] = $slot;
107 }
108 }
109
110 /**
111 * Dispatches a signal by calling the registered Slot methods
112 *
113 * @param string $signalClassName Name of the class containing the signal
114 * @param string $signalName Name of the signal
115 * @param array $signalArguments arguments passed to the signal method
116 * @return void
117 * @throws \TYPO3\CMS\Extbase\SignalSlot\Exception\InvalidSlotException if the slot is not valid
118 * @api
119 */
120 public function dispatch($signalClassName, $signalName, array $signalArguments = array()) {
121 $this->initializeObject();
122 if (!isset($this->slots[$signalClassName][$signalName])) {
123 return;
124 }
125 foreach ($this->slots[$signalClassName][$signalName] as $slotInformation) {
126 if (isset($slotInformation['object'])) {
127 $object = $slotInformation['object'];
128 } else {
129 if (!isset($this->objectManager)) {
130 throw new \TYPO3\CMS\Extbase\SignalSlot\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);
131 }
132 if (!$this->objectManager->isRegistered($slotInformation['class'])) {
133 throw new \TYPO3\CMS\Extbase\SignalSlot\Exception\InvalidSlotException('The given class "' . $slotInformation['class'] . '" is not a registered object.', 1245673367);
134 }
135 $object = $this->objectManager->get($slotInformation['class']);
136 }
137 if ($slotInformation['passSignalInformation'] === TRUE) {
138 $signalArguments[] = $signalClassName . '::' . $signalName;
139 }
140 if (!method_exists($object, $slotInformation['method'])) {
141 throw new \TYPO3\CMS\Extbase\SignalSlot\Exception\InvalidSlotException('The slot method ' . get_class($object) . '->' . $slotInformation['method'] . '() does not exist.', 1245673368);
142 }
143 call_user_func_array(array($object, $slotInformation['method']), $signalArguments);
144 }
145 }
146
147 /**
148 * Returns all slots which are connected with the given signal
149 *
150 * @param string $signalClassName Name of the class containing the signal
151 * @param string $signalName Name of the signal
152 * @return array An array of arrays with slot information
153 * @api
154 */
155 public function getSlots($signalClassName, $signalName) {
156 return isset($this->slots[$signalClassName][$signalName]) ? $this->slots[$signalClassName][$signalName] : array();
157 }
158 }
159
160 ?>