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