Issue #2546176 by alexpott: Use SafeStrings to communicate safeness in drupal_set_message and remove SafeMarkup::set()

8.0.x
Nathaniel Catchpole 2015-08-05 19:45:36 +01:00
parent f802277731
commit bd1dbf55cb
3 changed files with 45 additions and 29 deletions

View File

@ -514,7 +514,7 @@ 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|\Drupal\Component\Utility\SafeStringInterface $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.
@ -561,12 +561,15 @@ function drupal_set_message($message = NULL, $type = 'status', $repeat = FALSE)
$_SESSION['messages'][$type] = array();
}
$new = array(
'safe' => SafeMarkup::isSafe($message),
'message' => (string) $message,
);
if ($repeat || !in_array($new, $_SESSION['messages'][$type])) {
$_SESSION['messages'][$type][] = $new;
// Convert strings which are in the safe markup list to SafeString objects.
if (is_string($message) && SafeMarkup::isSafe($message)) {
$message = \Drupal\Core\Render\SafeString::create($message);
}
// Do not use strict type checking so that equivalent string and
// SafeStringInterface objects are detected.
if ($repeat || !in_array($message, $_SESSION['messages'][$type])) {
$_SESSION['messages'][$type][] = $message;
}
// Mark this page as being uncacheable.
@ -604,18 +607,6 @@ function drupal_set_message($message = NULL, $type = 'status', $repeat = FALSE)
*/
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) {
// Because the messages are stored in the session, the safe status of
// 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().
if ($message['safe']) {
$message['message'] = SafeMarkup::set($message['message']);
}
$messages[$message_type][$key] = $message['message'];
}
}
if ($type) {
if ($clear_queue) {
unset($_SESSION['messages'][$type]);

View File

@ -24,23 +24,30 @@ class DrupalSetMessageTest extends WebTestBase {
public static $modules = array('system_test');
/**
* Tests setting messages and removing one before it is displayed.
* Tests drupal_set_message().
*/
function testSetRemoveMessages() {
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->assertText('Second message (not removed).');
}
$this->assertRaw(t('Second message with <em>markup!</em> (not removed).'));
/**
* Tests setting duplicated messages.
*/
function testDuplicatedMessages() {
$this->drupalGet('system-test/drupal-set-message');
// Ensure duplicate messages are handled as expected.
$this->assertUniqueText('Non Duplicated message');
$this->assertNoUniqueText('Duplicated message');
// Ensure SafeString objects are rendered as expected.
$this->assertRaw('SafeString with <em>markup!</em>');
$this->assertUniqueText('SafeString with markup!');
$this->assertRaw('SafeString2 with <em>markup!</em>');
// Ensure when the same message is of different types it is not duplicated.
$this->assertUniqueText('Non duplicate SafeString / string.');
$this->assertNoUniqueText('Duplicate SafeString / string.');
// Ensure that strings that are not marked as safe are escaped.
$this->assertEscaped('<em>This<span>markup will be</span> escaped</em>.');
}
}

View File

@ -10,6 +10,7 @@ namespace Drupal\system_test\Controller;
use Drupal\Core\Access\AccessResult;
use Drupal\Core\Controller\ControllerBase;
use Drupal\Core\Render\RendererInterface;
use Drupal\Core\Render\SafeString;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\Url;
use Symfony\Component\HttpFoundation\RedirectResponse;
@ -101,7 +102,7 @@ class SystemTestController extends ControllerBase {
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 <em>markup!</em> (not removed).'));
// Remove the first.
unset($_SESSION['messages']['status'][0]);
@ -112,6 +113,23 @@ class SystemTestController extends ControllerBase {
drupal_set_message('Duplicated message', 'status', TRUE);
drupal_set_message('Duplicated message', 'status', TRUE);
// Add a SafeString message.
drupal_set_message(SafeString::create('SafeString with <em>markup!</em>'));
// Test duplicate SafeString messages.
drupal_set_message(SafeString::create('SafeString with <em>markup!</em>'));
// Ensure that multiple SafeString messages work.
drupal_set_message(SafeString::create('SafeString2 with <em>markup!</em>'));
// Test mixing of types.
drupal_set_message(SafeString::create('Non duplicate SafeString / string.'));
drupal_set_message('Non duplicate SafeString / string.');
drupal_set_message(SafeString::create('Duplicate SafeString / string.'), 'status', TRUE);
drupal_set_message('Duplicate SafeString / string.', 'status', TRUE);
// Test auto-escape of non safe strings.
drupal_set_message('<em>This<span>markup will be</span> escaped</em>.');
return [];
}