diff --git a/core/core.services.yml b/core/core.services.yml
index 796ece3e9b..58cf9e841b 100644
--- a/core/core.services.yml
+++ b/core/core.services.yml
@@ -1151,7 +1151,7 @@ services:
arguments: ['@state', '@current_user']
maintenance_mode_subscriber:
class: Drupal\Core\EventSubscriber\MaintenanceModeSubscriber
- arguments: ['@maintenance_mode', '@config.factory', '@string_translation', '@url_generator', '@current_user', '@bare_html_page_renderer']
+ arguments: ['@maintenance_mode', '@config.factory', '@string_translation', '@url_generator', '@current_user', '@bare_html_page_renderer', '@messenger']
tags:
- { name: event_subscriber }
path_subscriber:
@@ -1659,3 +1659,6 @@ services:
class: Drupal\Core\EventSubscriber\RssResponseRelativeUrlFilter
tags:
- { name: event_subscriber }
+ messenger:
+ class: Drupal\Core\Messenger\SessionMessenger
+ arguments: ['@page_cache_kill_switch']
diff --git a/core/includes/bootstrap.inc b/core/includes/bootstrap.inc
index 52f574212a..2cf951e08e 100644
--- a/core/includes/bootstrap.inc
+++ b/core/includes/bootstrap.inc
@@ -11,8 +11,6 @@
use Drupal\Component\Utility\Unicode;
use Drupal\Core\Config\BootstrapConfigStorageFactory;
use Drupal\Core\Logger\RfcLogLevel;
-use Drupal\Core\Render\Markup;
-use Drupal\Component\Render\MarkupInterface;
use Drupal\Core\Test\TestDatabase;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\Site\Settings;
@@ -440,47 +438,36 @@ function watchdog_exception($type, Exception $exception, $message = NULL, $varia
* - message: The message string.
* So, the following is an example of the full return array structure:
* @code
- * array(
- * 'status' => array(
- * array(
+ * [
+ * 'status' => [
+ * [
* '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.
*
* @see drupal_get_messages()
* @see status-messages.html.twig
+ *
+ * @deprecated Deprecated as of Drupal 8.2.
+ * Use \Drupal::service('messenger')->addMessage() instead.
*/
function drupal_set_message($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.
- \Drupal::service('page_cache_kill_switch')->trigger();
+ // Workaround for code that can not check if the service exists.
+ if (!\Drupal::hasService('messenger')) {
+ return [];
}
-
- // Messages not set when DB connection fails.
- return isset($_SESSION['messages']) ? $_SESSION['messages'] : NULL;
+ /* @var \Drupal\Core\Messenger\MessengerInterface $messenger */
+ $messenger = \Drupal::service('messenger');
+ $messenger->addMessage($message, $type, $repeat);
+ return $messenger->getMessages();
}
/**
@@ -507,12 +494,19 @@ function drupal_set_message($message = NULL, $type = 'status', $repeat = FALSE)
*
* @see drupal_set_message()
* @see status-messages.html.twig
+ *
+ * @deprecated Deprecated as of Drupal 8.2.
+ * Use \Drupal::service('messenger')->getMessages() or
+ * \Drupal::service('messenger')->getMessagesByType() instead.
*/
function drupal_get_messages($type = NULL, $clear_queue = TRUE) {
- if ($messages = drupal_set_message()) {
+ /** @var \Drupal\Core\Messenger\MessengerInterface $messenger */
+ $messenger = \Drupal::service('messenger');
+
+ if ($messages = $messenger->getMessages()) {
if ($type) {
if ($clear_queue) {
- unset($_SESSION['messages'][$type]);
+ $messenger->deleteMessagesByType($type);
}
if (isset($messages[$type])) {
return [$type => $messages[$type]];
@@ -520,7 +514,7 @@ function drupal_get_messages($type = NULL, $clear_queue = TRUE) {
}
else {
if ($clear_queue) {
- unset($_SESSION['messages']);
+ $messenger->deleteMessages();
}
return $messages;
}
diff --git a/core/lib/Drupal/Core/EventSubscriber/MaintenanceModeSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/MaintenanceModeSubscriber.php
index ba82988a14..c2688edeae 100644
--- a/core/lib/Drupal/Core/EventSubscriber/MaintenanceModeSubscriber.php
+++ b/core/lib/Drupal/Core/EventSubscriber/MaintenanceModeSubscriber.php
@@ -5,6 +5,7 @@
use Drupal\Component\Utility\SafeMarkup;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Render\BareHtmlPageRendererInterface;
+use Drupal\Core\Messenger\MessengerInterface;
use Drupal\Core\Routing\RouteMatch;
use Drupal\Core\Routing\UrlGeneratorInterface;
use Drupal\Core\Session\AccountInterface;
@@ -59,6 +60,13 @@ class MaintenanceModeSubscriber implements EventSubscriberInterface {
protected $bareHtmlPageRenderer;
/**
+ * The messenger.
+ *
+ * @var \Drupal\Core\Messenger\MessengerInterface
+ */
+ protected $messenger;
+
+ /**
* Constructs a new MaintenanceModeSubscriber.
*
* @param \Drupal\Core\Site\MaintenanceModeInterface $maintenance_mode
@@ -73,14 +81,17 @@ class MaintenanceModeSubscriber implements EventSubscriberInterface {
* The current user.
* @param \Drupal\Core\Render\BareHtmlPageRendererInterface $bare_html_page_renderer
* The bare HTML page renderer.
+ * @param \Drupal\Core\Messenger\MessengerInterface $messenger
+ * The messenger.
*/
- public function __construct(MaintenanceModeInterface $maintenance_mode, ConfigFactoryInterface $config_factory, TranslationInterface $translation, UrlGeneratorInterface $url_generator, AccountInterface $account, BareHtmlPageRendererInterface $bare_html_page_renderer) {
+ public function __construct(MaintenanceModeInterface $maintenance_mode, ConfigFactoryInterface $config_factory, TranslationInterface $translation, UrlGeneratorInterface $url_generator, AccountInterface $account, BareHtmlPageRendererInterface $bare_html_page_renderer, MessengerInterface $messenger) {
$this->maintenanceMode = $maintenance_mode;
$this->config = $config_factory;
$this->stringTranslation = $translation;
$this->urlGenerator = $url_generator;
$this->account = $account;
$this->bareHtmlPageRenderer = $bare_html_page_renderer;
+ $this->messenger = $messenger;
}
/**
@@ -118,10 +129,10 @@ public function onKernelRequestMaintenance(GetResponseEvent $event) {
// settings page.
if ($route_match->getRouteName() != 'system.site_maintenance_mode') {
if ($this->account->hasPermission('administer site configuration')) {
- $this->drupalSetMessage($this->t('Operating in maintenance mode. Go online.', [':url' => $this->urlGenerator->generate('system.site_maintenance_mode')]), 'status', FALSE);
+ $this->messenger->addMessage($this->t('Operating in maintenance mode. Go online.', [':url' => $this->urlGenerator->generate('system.site_maintenance_mode')]), 'status', FALSE);
}
else {
- $this->drupalSetMessage($this->t('Operating in maintenance mode.'), 'status', FALSE);
+ $this->messenger->addMessage($this->t('Operating in maintenance mode.'), 'status', FALSE);
}
}
}
@@ -141,13 +152,6 @@ protected function getSiteMaintenanceMessage() {
}
/**
- * Wraps the drupal_set_message function.
- */
- protected function drupalSetMessage($message = NULL, $type = 'status', $repeat = FALSE) {
- return drupal_set_message($message, $type, $repeat);
- }
-
- /**
* {@inheritdoc}
*/
public static function getSubscribedEvents() {
diff --git a/core/lib/Drupal/Core/Installer/InstallerServiceProvider.php b/core/lib/Drupal/Core/Installer/InstallerServiceProvider.php
index 48341492bd..a6262d1560 100644
--- a/core/lib/Drupal/Core/Installer/InstallerServiceProvider.php
+++ b/core/lib/Drupal/Core/Installer/InstallerServiceProvider.php
@@ -5,6 +5,7 @@
use Drupal\Core\DependencyInjection\ContainerBuilder;
use Drupal\Core\DependencyInjection\ServiceProviderInterface;
use Drupal\Core\DependencyInjection\ServiceModifierInterface;
+use Drupal\Core\Messenger\StaticMessenger;
use Symfony\Component\DependencyInjection\Reference;
/**
@@ -34,6 +35,9 @@ public function register(ContainerBuilder $container) {
->register('keyvalue', 'Drupal\Core\KeyValueStore\KeyValueMemoryFactory');
$container
->register('keyvalue.expirable', 'Drupal\Core\KeyValueStore\KeyValueNullExpirableFactory');
+ $definition = $container->getDefinition('messenger');
+ $definition->setClass(StaticMessenger::class);
+ $definition->setArguments([new Reference('page_cache_kill_switch')]);
// Replace services with no-op implementations.
$container
diff --git a/core/lib/Drupal/Core/Messenger/MessengerInterface.php b/core/lib/Drupal/Core/Messenger/MessengerInterface.php
new file mode 100644
index 0000000000..da36f04216
--- /dev/null
+++ b/core/lib/Drupal/Core/Messenger/MessengerInterface.php
@@ -0,0 +1,84 @@
+pageCacheKillSwitch = $page_cache_kill_switch;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function addMessage($message, $type = self::TYPE_STATUS, $repeat = FALSE) {
+ 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
+ // \Drupal\Core\Render\Markup objects are detected.
+ if ($repeat || !in_array($message, $_SESSION['messages'][$type])) {
+ $_SESSION['messages'][$type][] = $message;
+ $this->pageCacheKillSwitch->trigger();
+ }
+
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getMessages() {
+ $messages = isset($_SESSION['messages']) ? $_SESSION['messages'] : [];
+ foreach ($messages as $type => $messages_by_type) {
+ $messages[$type] = $messages_by_type;
+ }
+
+ return $messages;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getMessagesByType($type) {
+ $messages = isset($_SESSION['messages']) && isset($_SESSION['messages'][$type]) ? $_SESSION['messages'][$type] : [];
+
+ return $messages;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function deleteMessages() {
+ unset($_SESSION['messages']);
+
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function deleteMessagesByType($type) {
+ unset($_SESSION['messages'][$type]);
+
+ return $this;
+ }
+
+}
diff --git a/core/lib/Drupal/Core/Messenger/StaticMessenger.php b/core/lib/Drupal/Core/Messenger/StaticMessenger.php
new file mode 100644
index 0000000000..f2e0f51101
--- /dev/null
+++ b/core/lib/Drupal/Core/Messenger/StaticMessenger.php
@@ -0,0 +1,104 @@
+pageCacheKillSwitch = $page_cache_kill_switch;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function addMessage($message, $type = self::TYPE_STATUS, $repeat = FALSE) {
+ if (!isset($this->messages[$type])) {
+ $this->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, $this->messages[$type])) {
+ $this->messages[$type][] = $message;
+ $this->pageCacheKillSwitch->trigger();
+ }
+
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getMessages() {
+ $messages = isset($this->messages) ? $this->messages : [];
+ foreach ($messages as $type => $messages_by_type) {
+ $messages[$type] = $messages_by_type;
+ }
+
+ return $messages;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getMessagesByType($type) {
+ $messages = isset($this->messages) && isset($this->messages[$type]) ? $this->messages[$type] : [];
+
+ return $messages;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function deleteMessages() {
+ unset($this->messages);
+
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function deleteMessagesByType($type) {
+ unset($this->messages[$type]);
+
+ return $this;
+ }
+
+}
diff --git a/core/tests/Drupal/Tests/Core/Messenger/SessionMessengerTest.php b/core/tests/Drupal/Tests/Core/Messenger/SessionMessengerTest.php
new file mode 100644
index 0000000000..2da979c0a2
--- /dev/null
+++ b/core/tests/Drupal/Tests/Core/Messenger/SessionMessengerTest.php
@@ -0,0 +1,100 @@
+pageCacheKillSwitch = $this->prophesize(KillSwitch::class);
+
+ $this->existingSession = isset($_SESSION) ? $_SESSION : NULL;
+ $_SESSION = [];
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function tearDown() {
+ if ($this->existingSession !== NULL) {
+ $_SESSION = $this->existingSession;
+ }
+ else {
+ unset($_SESSION);
+ }
+ }
+
+ /**
+ * @covers ::addMessage
+ * @covers ::getMessages
+ * @covers ::getMessagesByType
+ * @covers ::deleteMessages
+ * @covers ::deleteMessagesByType
+ */
+ public function testMessenger() {
+ $this->pageCacheKillSwitch->trigger()->shouldBeCalled();
+
+ $this->messenger = new SessionMessenger($this->pageCacheKillSwitch->reveal());
+
+ $message_a = $this->randomMachineName();
+ $type_a = $this->randomMachineName();
+ $message_b = $this->randomMachineName();
+ $type_b = $this->randomMachineName();
+
+ // Test that if there are no messages, the default is an empty array.
+ $this->assertEquals($this->messenger->getMessages(), []);
+
+ // Test that adding a message returns the messenger and that the message can
+ // be retrieved.
+ $this->assertEquals($this->messenger->addMessage($message_a, $type_a), $this->messenger);
+ $this->messenger->addMessage($message_a, $type_a);
+ $this->messenger->addMessage($message_a, $type_a, TRUE);
+ $this->messenger->addMessage($message_b, $type_b, TRUE);
+ $this->assertEquals($this->messenger->getMessages(), [
+ $type_a => [$message_a, $message_a],
+ $type_b => [$message_b],
+ ]);
+
+ // Test deleting messages of a certain type.
+ $this->assertEquals($this->messenger->deleteMessagesByType($type_a), $this->messenger);
+ $this->assertEquals($this->messenger->getMessages(), [
+ $type_b => [$message_b],
+ ]);
+
+ // Test deleting all messages.
+ $this->assertEquals($this->messenger->deleteMessages(), $this->messenger);
+ $this->assertEquals($this->messenger->getMessages(), []);
+ }
+
+}
diff --git a/core/tests/Drupal/Tests/Core/Messenger/StaticMessengerTest.php b/core/tests/Drupal/Tests/Core/Messenger/StaticMessengerTest.php
new file mode 100644
index 0000000000..d315895449
--- /dev/null
+++ b/core/tests/Drupal/Tests/Core/Messenger/StaticMessengerTest.php
@@ -0,0 +1,80 @@
+pageCacheKillSwitch = $this->prophesize(KillSwitch::class);
+ }
+
+ /**
+ * @covers ::addMessage
+ * @covers ::getMessages
+ * @covers ::getMessagesByType
+ * @covers ::deleteMessages
+ * @covers ::deleteMessagesByType
+ */
+ public function testMessenger() {
+ $message_a = $this->randomMachineName();
+ $type_a = $this->randomMachineName();
+ $message_b = $this->randomMachineName();
+ $type_b = $this->randomMachineName();
+
+ $this->pageCacheKillSwitch->trigger()->shouldBeCalled();
+
+ $this->messenger = new StaticMessenger($this->pageCacheKillSwitch->reveal());
+
+ // Test that if there are no messages, the default is an empty array.
+ $this->assertEquals($this->messenger->getMessages(), []);
+
+ // Test that adding a message returns the messenger and that the message can
+ // be retrieved.
+ $this->assertSame($this->messenger->addMessage($message_a, $type_a), $this->messenger);
+ $this->messenger->addMessage($message_a, $type_a);
+ $this->messenger->addMessage($message_a, $type_a, TRUE);
+ $this->messenger->addMessage($message_b, $type_b, TRUE);
+ $this->assertEquals([
+ $type_a => [$message_a, $message_a],
+ $type_b => [$message_b],
+ ], $this->messenger->getMessages());
+
+ // Test deleting messages of a certain type.
+ $this->assertEquals($this->messenger->deleteMessagesByType($type_a), $this->messenger);
+ $this->assertEquals([
+ $type_b => [$message_b],
+ ], $this->messenger->getMessages());
+
+ // Test deleting all messages.
+ $this->assertEquals($this->messenger->deleteMessages(), $this->messenger);
+ $this->assertEquals([], $this->messenger->getMessages());
+ }
+
+}