diff --git a/core/includes/bootstrap.inc b/core/includes/bootstrap.inc
index 1d05b4a..b81860d 100644
--- a/core/includes/bootstrap.inc
+++ b/core/includes/bootstrap.inc
@@ -514,10 +514,10 @@ function watchdog_exception($type, Exception $exception, $message = NULL, $varia
* drupal_set_message(t('An error occurred and processing did not complete.'), 'error');
* @endcode
*
- * @param string $message
+ * @param string|array $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.
+ * end with a period. A render array may also be provided for markup.
* @param string $type
* (optional) The message's type. Defaults to 'status'. These values are
* supported:
@@ -562,8 +562,8 @@ function drupal_set_message($message = NULL, $type = 'status', $repeat = FALSE)
}
$new = array(
- 'safe' => SafeMarkup::isSafe($message),
- 'message' => (string) $message,
+ 'safe' => (!is_array($message) && SafeMarkup::isSafe($message)),
+ 'message' => $message,
);
if ($repeat || !in_array($new, $_SESSION['messages'][$type])) {
$_SESSION['messages'][$type][] = $new;
@@ -610,6 +610,8 @@ function drupal_get_messages($type = NULL, $clear_queue = TRUE) {
// the messages also needs to be stored in the session. We retrieve the
// safe status here and determine whether to mark the string as safe or
// let autoescape do its thing. See drupal_set_message().
+ // It's only nessasary to set the message as 'safe' when the message is
+ // not a renderable array.
if ($message['safe']) {
$message['message'] = SafeMarkup::set($message['message']);
}
diff --git a/core/modules/system/src/Tests/Bootstrap/DrupalSetMessageTest.php b/core/modules/system/src/Tests/Bootstrap/DrupalSetMessageTest.php
index 37a1663..79c824e 100644
--- a/core/modules/system/src/Tests/Bootstrap/DrupalSetMessageTest.php
+++ b/core/modules/system/src/Tests/Bootstrap/DrupalSetMessageTest.php
@@ -31,7 +31,7 @@ function testSetRemoveMessages() {
// removes the first before it is displayed.
$this->drupalGet('system-test/drupal-set-message');
$this->assertNoText('First message (removed).');
- $this->assertText('Second message (not removed).');
+ $this->assertRaw(t('Second message with markup! (not removed).'));
}
/**
@@ -43,4 +43,12 @@ function testDuplicatedMessages() {
$this->assertNoUniqueText('Duplicated message');
}
+ /**
+ * Tests setting render array messages.
+ */
+ function testRenderArrayMessages() {
+ $this->drupalGet('system-test/drupal-set-message');
+ $this->assertRaw('Render array with markup!');
+ }
+
}
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 5ac7ca0..3e5fe18 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
@@ -101,7 +101,10 @@ public function mainContentFallback() {
public function drupalSetMessageTest() {
// Set two messages.
drupal_set_message('First message (removed).');
- drupal_set_message('Second message (not removed).');
+ drupal_set_message(t('Second message with markup! (not removed).'));
+
+ // Add a render array message.
+ drupal_set_message(['#markup' => 'Render array with markup!']);
// Remove the first.
unset($_SESSION['messages']['status'][0]);
@@ -112,6 +115,7 @@ public function drupalSetMessageTest() {
drupal_set_message('Duplicated message', 'status', TRUE);
drupal_set_message('Duplicated message', 'status', TRUE);
+
return [];
}