diff --git a/core/core.services.yml b/core/core.services.yml index 7abab67..8a3853c 100644 --- a/core/core.services.yml +++ b/core/core.services.yml @@ -735,7 +735,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'] + arguments: ['@maintenance_mode', '@config.factory', '@string_translation', '@url_generator', '@current_user', '@messenger'] tags: - { name: event_subscriber } path_subscriber: @@ -780,7 +780,7 @@ services: class: Drupal\Core\EventSubscriber\DefaultExceptionSubscriber tags: - { name: event_subscriber } - arguments: ['@html_fragment_renderer', '@html_page_renderer', '@config.factory'] + arguments: ['@html_fragment_renderer', '@html_page_renderer', '@config.factory', '@messenger'] exception.logger: class: Drupal\Core\EventSubscriber\ExceptionLoggingSubscriber tags: @@ -1059,3 +1059,6 @@ services: arguments: ['@module_handler'] tags: - { name: mime_type_guesser } + messenger: + class: Drupal\Core\Messenger\Messenger + arguments: ['@session_manager', '@page_cache_kill_switch'] diff --git a/core/includes/bootstrap.inc b/core/includes/bootstrap.inc index c9ad780..f6af837 100644 --- a/core/includes/bootstrap.inc +++ b/core/includes/bootstrap.inc @@ -892,26 +892,15 @@ function watchdog($type, $message, array $variables = array(), $severity = WATCH * * @see drupal_get_messages() * @see theme_status_messages() + * + * @deprecated Deprecated as of Drupal 8.0. + * Use \Drupal::service('messenger')->addMessage() instead. */ function drupal_set_message($message = NULL, $type = 'status', $repeat = FALSE) { - if ($message) { - if (!isset($_SESSION['messages'][$type])) { - $_SESSION['messages'][$type] = array(); - } - - if ($repeat || !in_array($message, $_SESSION['messages'][$type])) { - $_SESSION['messages'][$type][] = array( - 'safe' => SafeMarkup::isSafe($message), - 'message' => $message, - ); - } - - // Mark this page as being uncacheable. - \Drupal::service('page_cache_kill_switch')->trigger(); - } - - // 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(); } /** @@ -938,20 +927,25 @@ function drupal_set_message($message = NULL, $type = 'status', $repeat = FALSE) * * @see drupal_set_message() * @see theme_status_messages() + * + * + * @deprecated Deprecated as of Drupal 8.0. + * 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()) { - foreach ($messages as $message_type => $message_typed_messages) { - foreach ($message_typed_messages as $key => $message) { - if ($message['safe']) { - $message['message'] = SafeMarkup::set($message['message']); - } - $messages[$message_type][$key] = $message['message']; - } - } + // Workaround for code that can not check if the service exists. + if (!\Drupal::hasService('messenger')) { + return array(); + } + + /** @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 array($type => $messages[$type]); @@ -959,7 +953,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/DefaultExceptionSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/DefaultExceptionSubscriber.php index e35eff4..a5e0e7f 100644 --- a/core/lib/Drupal/Core/EventSubscriber/DefaultExceptionSubscriber.php +++ b/core/lib/Drupal/Core/EventSubscriber/DefaultExceptionSubscriber.php @@ -11,6 +11,7 @@ use Drupal\Component\Utility\String; use Drupal\Core\Config\ConfigFactoryInterface; use Drupal\Core\ContentNegotiation; +use Drupal\Core\Messenger\MessengerInterface; use Drupal\Core\Page\DefaultHtmlPageRenderer; use Drupal\Core\Page\HtmlFragment; use Drupal\Core\Page\HtmlFragmentRendererInterface; @@ -64,6 +65,13 @@ class DefaultExceptionSubscriber implements EventSubscriberInterface { protected $configFactory; /** + * The messenger. + * + * @var \Drupal\Core\Messenger\MessengerInterface + */ + protected $messenger; + + /** * Constructs a new DefaultExceptionHtmlSubscriber. * * @param \Drupal\Core\Page\HtmlFragmentRendererInterface $fragment_renderer @@ -72,11 +80,14 @@ class DefaultExceptionSubscriber implements EventSubscriberInterface { * The page renderer. * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory * The configuration factory. + * @param \Drupal\Core\Messenger\MessengerInterface $messenger + * The messenger. */ - public function __construct(HtmlFragmentRendererInterface $fragment_renderer, HtmlPageRendererInterface $page_renderer, ConfigFactoryInterface $config_factory) { + public function __construct(HtmlFragmentRendererInterface $fragment_renderer, HtmlPageRendererInterface $page_renderer, ConfigFactoryInterface $config_factory, MessengerInterface $messenger) { $this->fragmentRenderer = $fragment_renderer; $this->htmlPageRenderer = $page_renderer; $this->configFactory = $config_factory; + $this->messenger = $messenger; } /** @@ -141,7 +152,7 @@ protected function onHtml(GetResponseForExceptionEvent $event) { // Generate a backtrace containing only scalar argument values. $message .= '
' . Error::formatFlattenedBacktrace($backtrace) . '
'; } - drupal_set_message(SafeMarkup::set($message), $class, TRUE); + $this->messenger->addMessage(SafeMarkup::set($message), $class, TRUE); } $content = $this->t('The website has encountered an error. Please try again later.'); diff --git a/core/lib/Drupal/Core/EventSubscriber/MaintenanceModeSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/MaintenanceModeSubscriber.php index f09e3e3..4062879 100644 --- a/core/lib/Drupal/Core/EventSubscriber/MaintenanceModeSubscriber.php +++ b/core/lib/Drupal/Core/EventSubscriber/MaintenanceModeSubscriber.php @@ -10,6 +10,7 @@ use Drupal\Component\Utility\String; use Drupal\Component\Utility\Xss; use Drupal\Core\Config\ConfigFactoryInterface; +use Drupal\Core\Messenger\MessengerInterface; use Drupal\Core\Page\DefaultHtmlPageRenderer; use Drupal\Core\Routing\RouteMatch; use Drupal\Core\Routing\UrlGeneratorInterface; @@ -58,6 +59,13 @@ class MaintenanceModeSubscriber implements EventSubscriberInterface { protected $urlGenerator; /** + * The messenger. + * + * @var \Drupal\Core\Messenger\MessengerInterface + */ + protected $messenger; + + /** * Constructs a new MaintenanceModeSubscriber. * * @param \Drupal\Core\Site\MaintenanceModeInterface $maintenance_mode @@ -70,13 +78,16 @@ class MaintenanceModeSubscriber implements EventSubscriberInterface { * The url generator. * @param \Drupal\Core\Session\AccountInterface $account * The current user. + * @param \Drupal\Core\Messenger\MessengerInterface $messenger + * The messenger. */ - public function __construct(MaintenanceModeInterface $maintenance_mode, ConfigFactoryInterface $config_factory, TranslationInterface $translation, UrlGeneratorInterface $url_generator, AccountInterface $account) { + public function __construct(MaintenanceModeInterface $maintenance_mode, ConfigFactoryInterface $config_factory, TranslationInterface $translation, UrlGeneratorInterface $url_generator, AccountInterface $account, MessengerInterface $messenger) { $this->maintenanceMode = $maintenance_mode; $this->config = $config_factory; $this->stringTranslation = $translation; $this->urlGenerator = $url_generator; $this->account = $account; + $this->messenger = $messenger; } /** @@ -108,10 +119,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.', array('@url' => $this->urlGenerator->generate('system.site_maintenance_mode'))), 'status', FALSE); + $this->messenger->addMessage($this->t('Operating in maintenance mode. Go online.', array('@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); } } } @@ -119,13 +130,6 @@ public function onKernelRequestMaintenance(GetResponseEvent $event) { } /** - * 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/Messenger/Messenger.php b/core/lib/Drupal/Core/Messenger/Messenger.php new file mode 100644 index 0000000..c8eaebb --- /dev/null +++ b/core/lib/Drupal/Core/Messenger/Messenger.php @@ -0,0 +1,124 @@ +pageCacheKillSwitch = $page_cache_kill_switch; + $this->sessionManager = $session_manager; + } + + /** + * {@inheritdoc} + */ + public function addMessage($message, $type = self::STATUS, $repeat = FALSE) { + $this->sessionManager->start(); + if ($repeat || !array_key_exists('messages', $_SESSION) || !array_key_exists($type, $_SESSION['messages']) || !in_array($message, $_SESSION['messages'][$type])) { + $_SESSION['messages'][$type][] = array( + 'safe' => SafeMarkup::isSafe($message), + 'message' => $message, + ); + $this->pageCacheKillSwitch->trigger(); + } + + return $this; + } + + /** + * {@inheritdoc} + */ + public function getMessages() { + $this->sessionManager->start(); + $messages = isset($_SESSION['messages']) ? $_SESSION['messages'] : array(); + foreach ($messages as $type => $messages_by_type) { + $messages[$type] = $this->processMessages($messages_by_type); + } + + return $messages; + } + + /** + * {@inheritdoc} + */ + public function getMessagesByType($type) { + $this->sessionManager->start(); + $messages = isset($_SESSION['messages']) && isset($_SESSION['messages'][$type]) ? $_SESSION['messages'][$type] : array(); + + return $this->processMessages($messages); + } + + /** + * {@inheritdoc} + */ + public function deleteMessages() { + $this->sessionManager->start(); + unset($_SESSION['messages']); + + return $this; + } + + /** + * {@inheritdoc} + */ + public function deleteMessagesByType($type) { + $this->sessionManager->start(); + unset($_SESSION['messages'][$type]); + + return $this; + } + + /** + * Proccesses safe markup. + * + * @param array[] + * An array of arrays with the following keys: + * - message: the message string. + * - safe: a boolean indicating whether the message contains safe markup. + * + * @return string[] + * The messages. + */ + protected function processMessages(array $messages) { + $processed_messages = array(); + foreach ($messages as $message_data) { + $processed_messages[] = $message_data['safe'] ? SafeMarkup::set($message_data['message']) : $message_data['message']; + } + + return $processed_messages; + } + +} diff --git a/core/lib/Drupal/Core/Messenger/MessengerInterface.php b/core/lib/Drupal/Core/Messenger/MessengerInterface.php new file mode 100644 index 0000000..044b16c --- /dev/null +++ b/core/lib/Drupal/Core/Messenger/MessengerInterface.php @@ -0,0 +1,81 @@ + '', + 'name' => '\Drupal\Core\Messenger\Messenger unit test', + 'group' => 'Messenger', + ); + } + + /** + * {@inheritdoc} + * + * @covers ::__construct + */ + public function setUp() { + $this->pageCacheKillSwitch = $this->getMockBuilder('\Drupal\Core\PageCache\ResponsePolicy\KillSwitch') + ->disableOriginalConstructor() + ->getMock(); + + $this->messenger = new Messenger($this->pageCacheKillSwitch); + + $this->existingSession = isset($_SESSION) ? $_SESSION : NULL; + $_SESSION = array(); + } + + /** + * {@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() { + $message_a = $this->randomMachineName(); + $type_a = $this->randomMachineName(); + $message_b = $this->randomMachineName(); + $type_b = $this->randomMachineName(); + + $this->pageCacheKillSwitch->expects($this->atLeastOnce()) + ->method('trigger'); + + // Test that if there are no messages, the default is an empty array. + $this->assertEquals($this->messenger->getMessages(), array()); + + // 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(), array( + $type_a => array($message_a, $message_a, $message_a), + $type_b => array($message_b), + )); + + // Test deleting messages of a certain type. + $this->assertEquals($this->messenger->deleteMessagesByType($type_a), $this->messenger); + $this->assertEquals($this->messenger->getMessages(), array( + $type_b => array($message_b), + )); + + // Test deleting all messages. + $this->assertEquals($this->messenger->deleteMessages(), $this->messenger); + $this->assertEquals($this->messenger->getMessages(), array()); + } + +}