diff --git a/core/core.services.yml b/core/core.services.yml index a7997ea66b..0319f0e200 100644 --- a/core/core.services.yml +++ b/core/core.services.yml @@ -1661,5 +1661,5 @@ services: tags: - { name: event_subscriber } messenger: - class: Drupal\Core\Messenger\LegacyMessenger - arguments: ['@page_cache_kill_switch'] + class: Drupal\Core\Messenger\Messenger + arguments: ['@session.flash_bag'] diff --git a/core/includes/bootstrap.inc b/core/includes/bootstrap.inc index 5a1cfbe7c0..12f7ad81e1 100644 --- a/core/includes/bootstrap.inc +++ b/core/includes/bootstrap.inc @@ -455,6 +455,10 @@ function watchdog_exception($type, Exception $exception, $message = NULL, $varia * * @see drupal_get_messages() * @see status-messages.html.twig + * @see https://www.drupal.org/node/2774931 + * + * @deprecated in Drupal 8.5.0, will be removed before Drupal 9.0.0. + * Use \Drupal::service('messenger')->addMessage() instead. */ function drupal_set_message($message = NULL, $type = 'status', $repeat = FALSE) { /* @var \Drupal\Core\Messenger\MessengerInterface $messenger */ @@ -487,6 +491,11 @@ function drupal_set_message($message = NULL, $type = 'status', $repeat = FALSE) * * @see drupal_set_message() * @see status-messages.html.twig + * @see https://www.drupal.org/node/2774931 + * + * @deprecated in Drupal 8.5.0, will be removed before Drupal 9.0.0. + * Use \Drupal::service('messenger')>getMessages() or + * \Drupal::service('messenger')>getMessagesByType() instead. */ function drupal_get_messages($type = NULL, $clear_queue = TRUE) { /** @var \Drupal\Core\Messenger\MessengerInterface $messenger */ diff --git a/core/lib/Drupal/Core/Messenger/LegacyMessenger.php b/core/lib/Drupal/Core/Messenger/LegacyMessenger.php deleted file mode 100644 index 8c9751f3d8..0000000000 --- a/core/lib/Drupal/Core/Messenger/LegacyMessenger.php +++ /dev/null @@ -1,212 +0,0 @@ -killSwitch = $killSwitch; - } - - /** - * {@inheritdoc} - */ - public function addMessage($message, $type = self::TYPE_STATUS, $repeat = FALSE) { - $this->setMessage($message, $type, $repeat); - } - - /** - * {@inheritdoc} - */ - public function addStatus($message, $repeat = FALSE) { - return $this->addMessage($message, static::TYPE_STATUS); - } - - /** - * {@inheritdoc} - */ - public function addError($message, $repeat = FALSE) { - return $this->addMessage($message, static::TYPE_ERROR); - } - - /** - * {@inheritdoc} - */ - public function addWarning($message, $repeat = FALSE) { - return $this->addMessage($message, static::TYPE_WARNING); - } - - /** - * {@inheritdoc} - */ - public function all() { - return $this->getMessages(NULL, FALSE); - } - - /** - * {@inheritdoc} - */ - public function messagesByType($type) { - return $this->getMessages($type, FALSE); - } - - /** - * {@inheritdoc} - */ - public function deleteAll() { - return $this->getMessages(NULL, TRUE); - } - - /** - * {@inheritdoc} - */ - public function deleteByType($type) { - return $this->getMessages($type, TRUE); - } - - /** - * Sets a message to display to the user. - * - * Messages are stored in a session variable and displayed in the page template - * via the $messages theme variable. - * - * Example usage: - * @code - * drupal_set_message(t('An error occurred and processing did not complete.'), 'error'); - * @endcode - * - * @param string|\Drupal\Component\Render\MarkupInterface $message - * (optional) The translated message to be displayed to the user. For - * consistency with other messages, it should begin with a capital letter and - * end with a period. - * @param string $type - * (optional) The message's type. Defaults to 'status'. These values are - * supported: - * - 'status' - * - 'warning' - * - 'error' - * @param bool $repeat - * (optional) If this is FALSE and the message is already set, then the - * message won't be repeated. Defaults to FALSE. - * - * @return array|null - * A multidimensional array with keys corresponding to the set message types. - * The indexed array values of each contain the set messages for that type, - * and each message is an associative array with the following format: - * - safe: Boolean indicating whether the message string has been marked as - * safe. Non-safe strings will be escaped automatically. - * - message: The message string. - * So, the following is an example of the full return array structure: - * @code - * array( - * 'status' => array( - * array( - * 'safe' => TRUE, - * 'message' => 'A safe markup string.', - * ), - * array( - * 'safe' => FALSE, - * 'message' => "$arbitrary_user_input to escape.", - * ), - * ), - * ); - * @endcode - * If there are no messages set, the function returns NULL. - * - * @internal - */ - private function setMessage($message = NULL, $type = 'status', $repeat = FALSE) { - if (isset($message)) { - if (!isset($_SESSION['messages'][$type])) { - $_SESSION['messages'][$type] = []; - } - - // Convert strings which are safe to the simplest Markup objects. - if (!($message instanceof Markup) && $message instanceof MarkupInterface) { - $message = Markup::create((string) $message); - } - - // Do not use strict type checking so that equivalent string and - // MarkupInterface objects are detected. - if ($repeat || !in_array($message, $_SESSION['messages'][$type])) { - $_SESSION['messages'][$type][] = $message; - } - - // Mark this page as being uncacheable. - $this->killSwitch->trigger(); - } - - // Messages not set when DB connection fails. - return isset($_SESSION['messages']) ? $_SESSION['messages'] : NULL; - } - - /** - * Returns all messages that have been set with drupal_set_message(). - * - * @param string $type - * (optional) Limit the messages returned by type. Defaults to NULL, meaning - * all types. These values are supported: - * - NULL - * - 'status' - * - 'warning' - * - 'error' - * @param bool $clear_queue - * (optional) If this is TRUE, the queue will be cleared of messages of the - * type specified in the $type parameter. Otherwise the queue will be left - * intact. Defaults to TRUE. - * - * @return array - * An associative, nested array of messages grouped by message type, with - * the top-level keys as the message type. The messages returned are - * limited to the type specified in the $type parameter, if any. If there - * are no messages of the specified type, an empty array is returned. See - * drupal_set_message() for the array structure of individual messages. - * - * @see drupal_set_message() - * @see status-messages.html.twig - * - * @internal - */ - private function getMessages($type = NULL, $clear_queue = TRUE) { - if ($messages = $this->setMessage()) { - if ($type) { - if ($clear_queue) { - unset($_SESSION['messages'][$type]); - } - if (isset($messages[$type])) { - return [$type => $messages[$type]]; - } - } - else { - if ($clear_queue) { - unset($_SESSION['messages']); - } - return $messages; - } - } - return []; - } - -} diff --git a/core/lib/Drupal/Core/Messenger/Messenger.php b/core/lib/Drupal/Core/Messenger/Messenger.php new file mode 100644 index 0000000000..e0707304ad --- /dev/null +++ b/core/lib/Drupal/Core/Messenger/Messenger.php @@ -0,0 +1,98 @@ +flashBag = $flash_bag; + } + + /** + * {@inheritdoc} + */ + public function addMessage($message, $type = self::TYPE_STATUS, $repeat = FALSE) { + // Convert strings which are safe to the simplest Markup objects. + if (!($message instanceof Markup) && $message instanceof MarkupInterface) { + $message = Markup::create((string) $message); + } + // Do not use strict type checking so that equivalent string and + // MarkupInterface objects are detected. + if ($repeat || !in_array($message, $this->flashBag->peek($type))) { + $this->flashBag->add($type, $message); + } + return $this; + } + + /** + * {@inheritdoc} + */ + public function addStatus($message, $repeat = FALSE) { + return $this->addMessage($message, static::TYPE_STATUS); + } + + /** + * {@inheritdoc} + */ + public function addError($message, $repeat = FALSE) { + return $this->addMessage($message, static::TYPE_ERROR); + } + + /** + * {@inheritdoc} + */ + public function addWarning($message, $repeat = FALSE) { + return $this->addMessage($message, static::TYPE_WARNING); + } + + /** + * {@inheritdoc} + */ + public function all() { + return $this->flashBag->peekAll(); + } + + /** + * {@inheritdoc} + */ + public function messagesByType($type) { + return $this->flashBag->peek($type); + } + + /** + * {@inheritdoc} + */ + public function deleteAll() { + return $this->flashBag->clear(); + } + + /** + * {@inheritdoc} + */ + public function deleteByType($type) { + return $this->flashBag->get($type); + } + +} diff --git a/core/lib/Drupal/Core/Messenger/MessengerInterface.php b/core/lib/Drupal/Core/Messenger/MessengerInterface.php index 216835bcea..217da76575 100644 --- a/core/lib/Drupal/Core/Messenger/MessengerInterface.php +++ b/core/lib/Drupal/Core/Messenger/MessengerInterface.php @@ -109,11 +109,15 @@ public function all(); * or self::TYPE_ERROR. * * @return string[]|\Drupal\Component\Render\MarkupInterface[] + * The messages of given type. */ public function messagesByType($type); /** * Deletes all messages. + * + * @return string[]|\Drupal\Component\Render\MarkupInterface[] + * The deleted messages. */ public function deleteAll(); @@ -123,6 +127,9 @@ public function deleteAll(); * @param string $type * The messages' type. Either self::TYPE_STATUS, self::TYPE_WARNING, or * self::TYPE_ERROR. + * + * @return string[]|\Drupal\Component\Render\MarkupInterface[] + * The deleted messages of given type.. */ public function deleteByType($type); diff --git a/core/modules/system/tests/modules/system_test/src/Controller/SystemTestController.php b/core/modules/system/tests/modules/system_test/src/Controller/SystemTestController.php index 5e49c2403b..6ed439e632 100644 --- a/core/modules/system/tests/modules/system_test/src/Controller/SystemTestController.php +++ b/core/modules/system/tests/modules/system_test/src/Controller/SystemTestController.php @@ -96,13 +96,6 @@ public function mainContentFallback() { * Empty string, we just test the setting of messages. */ public function drupalSetMessageTest() { - // Set two messages. - drupal_set_message('First message (removed).'); - drupal_set_message(t('Second message with markup! (not removed).')); - - // Remove the first. - unset($_SESSION['messages']['status'][0]); - // Duplicate message check. drupal_set_message('Non Duplicated message', 'status', FALSE); drupal_set_message('Non Duplicated message', 'status', FALSE); diff --git a/core/modules/system/tests/src/Functional/Bootstrap/DrupalSetMessageTest.php b/core/modules/system/tests/src/Functional/Bootstrap/DrupalSetMessageTest.php index 976e8bebfe..ff207b5f3f 100644 --- a/core/modules/system/tests/src/Functional/Bootstrap/DrupalSetMessageTest.php +++ b/core/modules/system/tests/src/Functional/Bootstrap/DrupalSetMessageTest.php @@ -22,11 +22,7 @@ class DrupalSetMessageTest extends BrowserTestBase { * Tests drupal_set_message(). */ public function testDrupalSetMessage() { - // The page at system-test/drupal-set-message sets two messages and then - // removes the first before it is displayed. $this->drupalGet('system-test/drupal-set-message'); - $this->assertNoText('First message (removed).'); - $this->assertRaw(t('Second message with markup! (not removed).')); // Ensure duplicate messages are handled as expected. $this->assertUniqueText('Non Duplicated message'); diff --git a/core/tests/Drupal/KernelTests/Core/Common/DrupalSetMessageTest.php b/core/tests/Drupal/KernelTests/Core/Common/DrupalSetMessageTest.php index 59470e6563..7a15fc3e04 100644 --- a/core/tests/Drupal/KernelTests/Core/Common/DrupalSetMessageTest.php +++ b/core/tests/Drupal/KernelTests/Core/Common/DrupalSetMessageTest.php @@ -20,10 +20,4 @@ public function testDrupalSetMessage() { $this->assertEquals('A message: bar', (string) $messages['status'][0]); } - protected function tearDown() { - // Clear session to prevent global leakage. - unset($_SESSION['messages']); - parent::tearDown(); - } - }