[!!!][FEATURE] Refactoring of FlashMessage rendering
[Packages/TYPO3.CMS.git] / typo3 / sysext / core / Classes / Messaging / FlashMessageQueue.php
1 <?php
2 namespace TYPO3\CMS\Core\Messaging;
3
4 /*
5 * This file is part of the TYPO3 CMS project.
6 *
7 * It is free software; you can redistribute it and/or modify it under
8 * the terms of the GNU General Public License, either version 2
9 * of the License, or any later version.
10 *
11 * For the full copyright and license information, please read the
12 * LICENSE.txt file that was distributed with this source code.
13 *
14 * The TYPO3 project - inspiring people to share!
15 */
16
17 use TYPO3\CMS\Core\Authentication\AbstractUserAuthentication;
18 use TYPO3\CMS\Core\Messaging\Renderer\FlashMessageRendererInterface;
19 use TYPO3\CMS\Core\Utility\GeneralUtility;
20
21 /**
22 * A class which collects and renders flash messages.
23 */
24 class FlashMessageQueue extends \SplQueue
25 {
26 /**
27 * A unique identifier for this queue
28 *
29 * @var string
30 */
31 protected $identifier;
32
33 /**
34 * @param string $identifier The unique identifier for this queue
35 */
36 public function __construct($identifier)
37 {
38 $this->identifier = $identifier;
39 }
40
41 /**
42 * @return string
43 */
44 public function getIdentifier()
45 {
46 return $this->identifier;
47 }
48
49 /**
50 * Adds a message either to the BE_USER session (if the $message has the storeInSession flag set)
51 * or it enqueues the message.
52 *
53 * @param FlashMessage $message Instance of \TYPO3\CMS\Core\Messaging\FlashMessage, representing a message
54 * @throws \TYPO3\CMS\Core\Exception
55 * @return void
56 */
57 public function enqueue($message)
58 {
59 if (!($message instanceof FlashMessage)) {
60 throw new \TYPO3\CMS\Core\Exception(
61 'FlashMessageQueue::enqueue() expects an object of type \TYPO3\CMS\Core\Messaging\FlashMessage but got type "' . (is_object($message) ? get_class($message) : gettype($message)) . '"',
62 1376833554
63 );
64 }
65 if ($message->isSessionMessage()) {
66 $this->addFlashMessageToSession($message);
67 } else {
68 parent::enqueue($message);
69 }
70 }
71
72 /**
73 * @param FlashMessage $message
74 * @return void
75 */
76 public function addMessage(FlashMessage $message)
77 {
78 $this->enqueue($message);
79 }
80
81 /**
82 * @return void
83 */
84 public function dequeue()
85 {
86 // deliberately empty
87 }
88
89 /**
90 * Adds the given flash message to the array of
91 * flash messages that will be stored in the session.
92 *
93 * @param FlashMessage $message
94 * @return void
95 */
96 protected function addFlashMessageToSession(FlashMessage $message)
97 {
98 $queuedFlashMessages = $this->getFlashMessagesFromSession();
99 $queuedFlashMessages[] = $message;
100 $this->storeFlashMessagesInSession($queuedFlashMessages);
101 }
102
103 /**
104 * Returns all messages from the current PHP session and from the current request.
105 *
106 * @param int $severity Optional severity, must be one of \TYPO3\CMS\Core\Messaging\AbstractMessage constants
107 * @return FlashMessage[]
108 */
109 public function getAllMessages($severity = null)
110 {
111 // Get messages from user session
112 $queuedFlashMessagesFromSession = $this->getFlashMessagesFromSession();
113 $queuedFlashMessages = array_merge($queuedFlashMessagesFromSession, $this->toArray());
114 if ($severity !== null) {
115 $filteredFlashMessages = [];
116 foreach ($queuedFlashMessages as $message) {
117 if ($message->getSeverity() === $severity) {
118 $filteredFlashMessages[] = $message;
119 }
120 }
121 return $filteredFlashMessages;
122 }
123
124 return $queuedFlashMessages;
125 }
126
127 /**
128 * Returns all messages from the current PHP session and from the current request.
129 * After fetching the messages the internal queue and the message queue in the session
130 * will be emptied.
131 *
132 * @param int $severity Optional severity, must be one of \TYPO3\CMS\Core\Messaging\AbstractMessage constants
133 * @return FlashMessage[]
134 */
135 public function getAllMessagesAndFlush($severity = null)
136 {
137 $queuedFlashMessages = $this->getAllMessages($severity);
138 // Reset messages in user session
139 $this->removeAllFlashMessagesFromSession($severity);
140 // Reset internal messages
141 $this->clear($severity);
142 return $queuedFlashMessages;
143 }
144
145 /**
146 * Stores given flash messages in the session
147 *
148 * @param FlashMessage[] $flashMessages
149 * @return void
150 */
151 protected function storeFlashMessagesInSession(array $flashMessages = null)
152 {
153 $this->getUserByContext()->setAndSaveSessionData($this->identifier, $flashMessages);
154 }
155
156 /**
157 * Removes all flash messages from the session
158 *
159 * @param int $severity Optional severity, must be one of \TYPO3\CMS\Core\Messaging\AbstractMessage constants
160 * @return void
161 */
162 protected function removeAllFlashMessagesFromSession($severity = null)
163 {
164 if ($severity === null) {
165 $this->storeFlashMessagesInSession(null);
166 } else {
167 $messages = $this->getFlashMessagesFromSession();
168 foreach ($messages as $index => $message) {
169 if ($message->getSeverity() === $severity) {
170 unset($messages[$index]);
171 }
172 }
173 $this->storeFlashMessagesInSession($messages);
174 }
175 }
176
177 /**
178 * Returns current flash messages from the session, making sure to always
179 * return an array.
180 *
181 * @return FlashMessage[]
182 */
183 protected function getFlashMessagesFromSession()
184 {
185 $flashMessages = $this->getUserByContext()->getSessionData($this->identifier);
186 return is_array($flashMessages) ? $flashMessages : [];
187 }
188
189 /**
190 * Gets user object by context
191 *
192 * @return AbstractUserAuthentication
193 */
194 protected function getUserByContext()
195 {
196 return TYPO3_MODE === 'BE' ? $GLOBALS['BE_USER'] : $GLOBALS['TSFE']->fe_user;
197 }
198
199 /**
200 * Fetches and renders all available flash messages from the queue.
201 *
202 * @param FlashMessageRendererInterface|null $flashMessageRenderer
203 * @return string All flash messages in the queue rendered by context based FlashMessageRendererResolver.
204 */
205 public function renderFlashMessages(FlashMessageRendererInterface $flashMessageRenderer = null)
206 {
207 $content = '';
208 $flashMessages = $this->getAllMessagesAndFlush();
209
210 if (!empty($flashMessages)) {
211 if ($flashMessageRenderer === null) {
212 $flashMessageRenderer = GeneralUtility::makeInstance(FlashMessageRendererResolver::class)->resolve();
213 }
214 $content = $flashMessageRenderer->render($flashMessages);
215 }
216
217 return $content;
218 }
219
220 /**
221 * Returns all items of the queue as array
222 *
223 * @return FlashMessage[]
224 */
225 public function toArray()
226 {
227 $array = [];
228 $this->rewind();
229 while ($this->valid()) {
230 $array[] = $this->current();
231 $this->next();
232 }
233 return $array;
234 }
235
236 /**
237 * Removes all items from the queue
238 *
239 * @param int $severity Optional severity, must be one of \TYPO3\CMS\Core\Messaging\AbstractMessage constants
240 * @return void
241 */
242 public function clear($severity = null)
243 {
244 $this->rewind();
245 if ($severity === null) {
246 while (!$this->isEmpty()) {
247 parent::dequeue();
248 }
249 } else {
250 $keysToRemove = [];
251 while ($cur = $this->current()) {
252 if ($cur->getSeverity() === $severity) {
253 $keysToRemove[] = $this->key();
254 }
255 $this->next();
256 }
257 // keys are renumbered when unsetting elements
258 // so unset them from last to first
259 $keysToRemove = array_reverse($keysToRemove);
260 foreach ($keysToRemove as $key) {
261 $this->offsetUnset($key);
262 }
263 }
264 }
265 }