diff --git a/core/includes/common.inc b/core/includes/common.inc
index be31bf8..c1dd7c9 100644
--- a/core/includes/common.inc
+++ b/core/includes/common.inc
@@ -3373,13 +3373,13 @@ function drupal_render_children(&$element, $children_keys = NULL) {
if ($children_keys === NULL) {
$children_keys = Element::children($element);
}
- $markups = array();
+ $output = '';
foreach ($children_keys as $key) {
if (!empty($element[$key])) {
- $markups[] = drupal_render($element[$key]);
+ $output .= drupal_render($element[$key]);
}
}
- return SafeMarkup::implode('', $markups);
+ return SafeMarkup::set($output);
}
/**
diff --git a/core/includes/theme.inc b/core/includes/theme.inc
index 5b40372..68debb9 100644
--- a/core/includes/theme.inc
+++ b/core/includes/theme.inc
@@ -2018,7 +2018,13 @@ function template_preprocess_html(&$variables) {
}
$variables['head_title_array'] = $head_title;
- $variables['head_title'] = SafeMarkup::implode(' | ', $head_title);
+ $output = '';
+ $separator = '';
+ foreach ($head_title as $item) {
+ $output .= $separator . SafeMarkup::escape($item);
+ $separator = ' | ';
+ }
+ $variables['head_title'] = SafeMarkup::set($output);
// @todo Remove drupal_*_html_head() and refactor accordingly.
$html_heads = drupal_get_html_head(FALSE);
diff --git a/core/lib/Drupal/Component/Utility/SafeMarkup.php b/core/lib/Drupal/Component/Utility/SafeMarkup.php
index 4043da3..871cf74 100644
--- a/core/lib/Drupal/Component/Utility/SafeMarkup.php
+++ b/core/lib/Drupal/Component/Utility/SafeMarkup.php
@@ -31,13 +31,13 @@ class SafeMarkup {
* markup; instead, use the appropriate
* @link sanitization sanitization functions @endlink or the
* @link theme_render theme and render systems @endlink so that the output
- * can be themed and altered properly.
+ * can be themed, escaped, and altered properly.
*
* This marks strings as secure for the entire page render, not just the code
- * or element that set it. Therefore, only complete strings should be
+ * or element that set it. Therefore, only valid HTML should be
* marked as safe (never partial markup). For example, you should never do:
* @code
- * SafeMarkup::set("'");
+ * SafeMarkup::set("<");
* @endcode
* or:
* @code
@@ -81,33 +81,6 @@ public static function isSafe($string, $strategy = 'html') {
}
/**
- * Safely implodes strings by escaping any that are not known to be safe.
- *
- * @param string $delimiter
- * The delimiter to use when imploding.
- * @param array $array
- * An array of the strings to implode.
- * @param string $strategy
- * The escaping strategy. See SafeMarkup::set(). Defaults to 'html'.
- *
- * @return \Drupal\Component\Utility\SafeMarkup|string
- * The imploded string, which is now also marked as safe.
- */
- public static function implode($delimiter, array $array, $strategy = 'html') {
- $array[] = $delimiter;
- foreach ($array as $key => $string) {
- if (!(isset(static::$safeStrings[(string) $string][$strategy]) ||
- isset(static::$safeStrings[(string) $string]['all']))) {
- $array[$key] = String::checkPlain($string);
- }
- }
- // Recover the delimiter.
- $delimiter = array_pop($array);
- static::set($delimiter, $strategy);
- return static::set(implode($delimiter, $array), $strategy);
- }
-
- /**
* Adds previously retrieved known safe strings to the safe string list.
*
* This is useful for the batch and form APIs, where it is important to
@@ -135,6 +108,20 @@ public static function setMultiple(array $safe_strings) {
}
/**
+ * Encodes special characters in a plain-text string for display as HTML.
+ *
+ * @param $string
+ * A string.
+ *
+ * @return string
+ * The escaped string. If $string was already set as safe with
+ * SafeString::set, it won't be escaped again.
+ */
+ public static function escape($string) {
+ return static::isSafe($string) ? $string : String::checkPlain($string);
+ }
+
+ /**
* Retrieves all strings currently marked as safe.
*
* This is useful for the batch and form APIs, where it is important to
diff --git a/core/modules/field/src/Plugin/views/field/Field.php b/core/modules/field/src/Plugin/views/field/Field.php
index 6a168d2..c33a070 100644
--- a/core/modules/field/src/Plugin/views/field/Field.php
+++ b/core/modules/field/src/Plugin/views/field/Field.php
@@ -688,12 +688,22 @@ public function submitGroupByForm(&$form, &$form_state) {
*/
protected function renderItems($items) {
if (!empty($items)) {
+ $output = '';
if (!$this->options['group_rows']) {
- return SafeMarkup::implode('', $items);
+ foreach ($items as $item) {
+ $output .= SafeMarkup::escape($item);
+ }
+ return SafeMarkup::set($output);
}
-
if ($this->options['multi_type'] == 'separator') {
- return SafeMarkup::implode(Xss::filterAdmin($this->options['separator']), $items);
+ $output = '';
+ $separator = '';
+ $escaped_separator = Xss::filterAdmin($this->options['separator']);
+ foreach ($items as $item) {
+ $output .= $separator . SafeMarkup::escape($item);
+ $separator = $escaped_separator;
+ }
+ return SafeMarkup::set($output);
}
else {
$item_list = array(
diff --git a/core/modules/field_ui/src/DisplayOverviewBase.php b/core/modules/field_ui/src/DisplayOverviewBase.php
index bb2d114..f450313 100644
--- a/core/modules/field_ui/src/DisplayOverviewBase.php
+++ b/core/modules/field_ui/src/DisplayOverviewBase.php
@@ -404,8 +404,14 @@ protected function buildFieldRow(FieldDefinitionInterface $field_definition, Ent
$this->alterSettingsSummary($summary, $plugin, $field_definition);
if (!empty($summary)) {
+ $summary_escaped = '';
+ $separator = '';
+ foreach ($summary as $summary_item) {
+ $summary_escaped .= $separator . SafeMarkup::escape($summary_item);
+ $separator = '
';
+ }
$field_row['settings_summary'] = array(
- '#markup' => '
' . SafeMarkup::implode('
', $summary) . '
',
+ '#markup' => SafeMarkup::set('' . $summary_escaped . '
'),
'#cell_attributes' => array('class' => array('field-plugin-summary-cell')),
);
}
diff --git a/core/modules/field_ui/src/FieldConfigListBuilder.php b/core/modules/field_ui/src/FieldConfigListBuilder.php
index 74b2310..4a00229 100644
--- a/core/modules/field_ui/src/FieldConfigListBuilder.php
+++ b/core/modules/field_ui/src/FieldConfigListBuilder.php
@@ -8,7 +8,6 @@
namespace Drupal\field_ui;
use Drupal\Component\Utility\SafeMarkup;
-use Drupal\Component\Utility\String;
use Drupal\Core\Config\Entity\ConfigEntityListBuilder;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityManagerInterface;
@@ -119,7 +118,13 @@ public function buildRow(EntityInterface $field) {
$usage[] = $this->bundles[$field->entity_type][$bundle]['label'];
}
}
- $row['data']['usage'] = SafeMarkup::implode(', ', $usage);
+ $usage_escaped = '';
+ $separator = '';
+ foreach ($usage as $usage_item) {
+ $usage_escaped .= $separator . SafeMarkup::escape($usage_item);
+ $separator = ', ';
+ }
+ $row['data']['usage'] = SafeMarkup::set($usage_escaped);
return $row;
}
diff --git a/core/modules/file/file.module b/core/modules/file/file.module
index ce47280..e91a572 100644
--- a/core/modules/file/file.module
+++ b/core/modules/file/file.module
@@ -931,10 +931,10 @@ function file_save_upload($form_field_name, $validators = array(), $destination
'#theme' => 'item_list',
'#items' => $errors,
);
- $message = SafeMarkup::implode('', array($message, drupal_render($item_list)));
+ $message = SafeMarkup::set($message . drupal_render($item_list));
}
else {
- $message = SafeMarkup::implode('', array($message, ' ', array_pop($errors)));
+ $message = SafeMarkup::set($message . ' ' . SafeMarkup::escape(array_pop($errors)));
}
drupal_set_message($message, 'error');
$files[$i] = FALSE;
diff --git a/core/modules/node/src/Plugin/Search/NodeSearch.php b/core/modules/node/src/Plugin/Search/NodeSearch.php
index 1be527d..f8e76a8 100644
--- a/core/modules/node/src/Plugin/Search/NodeSearch.php
+++ b/core/modules/node/src/Plugin/Search/NodeSearch.php
@@ -269,10 +269,10 @@ public function execute() {
unset($build['#theme']);
// Fetch comment count for snippet.
- $node->rendered = SafeMarkup::implode(' ', array(
- drupal_render($build),
- $this->moduleHandler->invoke('comment', 'node_update_index', array($node, $item->langcode)),
- ));
+ $node->rendered = SafeMarkup::set(
+ drupal_render($build) . ' ' .
+ SafeMarkup::escape($this->moduleHandler->invoke('comment', 'node_update_index', array($node, $item->langcode)))
+ );
$extra = $this->moduleHandler->invokeAll('node_search_result', array($node, $item->langcode));
diff --git a/core/modules/rdf/rdf.module b/core/modules/rdf/rdf.module
index 4d79262..5bfcc2f 100644
--- a/core/modules/rdf/rdf.module
+++ b/core/modules/rdf/rdf.module
@@ -462,7 +462,7 @@ function rdf_preprocess_comment(&$variables) {
$created_metadata_markup = drupal_render($rdf_metadata);
// Appends the markup to the created variable and the submitted variable
// which are both available in comment.html.twig.
- $variables['created'] = SafeMarkup::implode('', array($variables['created'], $created_metadata_markup));
+ $variables['created'] = SafeMarkup::set(SafeMarkup::escape($variables['created']) . $created_metadata_markup);
$variables['submitted'] = SafeMarkup::set($variables['submitted'] . $created_metadata_markup);
}
$title_mapping = $mapping->getPreparedFieldMapping('subject');
diff --git a/core/modules/responsive_image/responsive_image.module b/core/modules/responsive_image/responsive_image.module
index bc1f77f..0c93cb9 100644
--- a/core/modules/responsive_image/responsive_image.module
+++ b/core/modules/responsive_image/responsive_image.module
@@ -259,7 +259,7 @@ function theme_responsive_image($variables) {
}
$output[] = '';
- return SafeMarkup::implode("\n", $output);
+ return SafeMarkup::set(implode("\n", $output));
}
}
diff --git a/core/modules/search/tests/modules/search_embedded_form/search_embedded_form.module b/core/modules/search/tests/modules/search_embedded_form/search_embedded_form.module
index cc2526a..75ddd3d 100644
--- a/core/modules/search/tests/modules/search_embedded_form/search_embedded_form.module
+++ b/core/modules/search/tests/modules/search_embedded_form/search_embedded_form.module
@@ -16,5 +16,5 @@
*/
function search_embedded_form_preprocess_search_result(&$variables) {
$form = \Drupal::formBuilder()->getForm('Drupal\search_embedded_form\Form\SearchEmbeddedForm');
- $variables['snippet'] = SafeMarkup::implode('', array($variables['snippet'] , drupal_render($form)));
+ $variables['snippet'] = SafeMarkup::set(SafeMarkup::escape($variables['snippet']) . drupal_render($form));
}
diff --git a/core/modules/system/tests/modules/batch_test/batch_test.callbacks.inc b/core/modules/system/tests/modules/batch_test/batch_test.callbacks.inc
index 667bdd6..6964668 100644
--- a/core/modules/system/tests/modules/batch_test/batch_test.callbacks.inc
+++ b/core/modules/system/tests/modules/batch_test/batch_test.callbacks.inc
@@ -83,7 +83,7 @@ function _batch_test_finished_helper($batch_id, $success, $results, $operations)
$messages = array("results for batch $batch_id");
if ($results) {
foreach ($results as $op => $op_results) {
- $messages[] = 'op '. $op . ': processed ' . count($op_results) . ' elements';
+ $messages[] = 'op '. SafeMarkup::escape($op) . ': processed ' . count($op_results) . ' elements';
}
}
else {
@@ -96,9 +96,7 @@ function _batch_test_finished_helper($batch_id, $success, $results, $operations)
$messages[] = t('An error occurred while processing @op with arguments:
@args', array('@op' => $error_operation[0], '@args' => print_r($error_operation[1], TRUE)));
}
- // The BR tag is safe as a delimiter.
- SafeMarkup::set('
');
- drupal_set_message(SafeMarkup::implode('
', $messages));
+ drupal_set_message(SafeMarkup::set(implode('
', $messages)));
}
/**
diff --git a/core/modules/views/views.theme.inc b/core/modules/views/views.theme.inc
index 9f4e6ba..922a42f 100644
--- a/core/modules/views/views.theme.inc
+++ b/core/modules/views/views.theme.inc
@@ -543,7 +543,7 @@ function template_preprocess_views_view_table(&$variables) {
'#style' => $initial,
);
$markup = drupal_render($tablesort_indicator);
- $label = SafeMarkup::implode('', array($label, $markup));
+ $label = SafeMarkup::set($label . $markup);
}
$query['order'] = $field;
@@ -634,7 +634,7 @@ function template_preprocess_views_view_table(&$variables) {
$field_output = $handler->getField($num, $field);
$element_type = $fields[$field]->elementType(TRUE, TRUE);
if ($element_type) {
- $field_output = SafeMarkup::implode('', array(SafeMarkup::set('<' . $element_type . '>'), $field_output, SafeMarkup::set('' . $element_type . '>')));
+ $field_output = SafeMarkup::set('<' . $element_type . '>' . SafeMarkup::escape($field_output) . '' . $element_type . '>');
}
// Only bother with separators and stuff if the field shows up.
@@ -642,13 +642,17 @@ function template_preprocess_views_view_table(&$variables) {
// Place the field into the column, along with an optional separator.
if (!empty($column_reference['content'])) {
if (!empty($options['info'][$column]['separator'])) {
- $column_reference['content'] = SafeMarkup::implode('', array($column_reference['content'], Xss::filterAdmin($options['info'][$column]['separator'])));
+ $safe_content = SafeMarkup::escape($column_reference['content']);
+ $safe_separator = Xss::filterAdmin($options['info'][$column]['separator']);
+ $column_reference['content'] = SafeMarkup::set($safe_content . $safe_separator);
}
}
else {
$column_reference['content'] = '';
}
- $column_reference['content'] = SafeMarkup::implode('', array($column_reference['content'], $field_output));
+ $safe_content = SafeMarkup::escape($column_reference['content']);
+ $safe_field_output = SafeMarkup::escape($field_output);
+ $column_reference['content'] = SafeMarkup::set($safe_content . $safe_field_output);
}
}
$column_reference['attributes'] = new Attribute($column_reference['attributes']);
diff --git a/core/modules/views_ui/src/Controller/ViewsUIController.php b/core/modules/views_ui/src/Controller/ViewsUIController.php
index 8ad44fd..0138266 100644
--- a/core/modules/views_ui/src/Controller/ViewsUIController.php
+++ b/core/modules/views_ui/src/Controller/ViewsUIController.php
@@ -93,7 +93,7 @@ public function reportFields() {
foreach ($views as $view) {
$rows[$field_name]['data'][1][] = $this->l($view, 'views_ui.edit', array('view' => $view));
}
- $rows[$field_name]['data'][1] = SafeMarkup::implode(', ', $rows[$field_name]['data'][1]);
+ $rows[$field_name]['data'][1] = SafeMarkup::set(implode(', ', $rows[$field_name]['data'][1]));
}
// Sort rows by field name.
@@ -121,7 +121,7 @@ public function reportPlugins() {
foreach ($row['views'] as $row_name => $view) {
$row['views'][$row_name] = $this->l($view, 'views_ui.edit', array('view' => $view));
}
- $row['views'] = SafeMarkup::implode(', ', $row['views']);
+ $row['views'] = SafeMarkup::set(implode(', ', $row['views']));
}
// Sort rows by field name.
diff --git a/core/modules/views_ui/src/ViewListBuilder.php b/core/modules/views_ui/src/ViewListBuilder.php
index 191a2aa..7321712 100644
--- a/core/modules/views_ui/src/ViewListBuilder.php
+++ b/core/modules/views_ui/src/ViewListBuilder.php
@@ -81,6 +81,12 @@ public function load() {
*/
public function buildRow(EntityInterface $view) {
$row = parent::buildRow($view);
+ $display_paths = '';
+ $separator = '';
+ foreach ($this->getDisplayPaths($view) as $display_path) {
+ $display_paths .= $separator . SafeMarkup::escape($display_path);
+ $separator = ', ';
+ }
return array(
'data' => array(
'view_name' => array(
@@ -97,7 +103,7 @@ public function buildRow(EntityInterface $view) {
'class' => array('views-table-filter-text-source'),
),
'tag' => $view->get('tag'),
- 'path' => SafeMarkup::implode(', ', $this->getDisplayPaths($view)),
+ 'path' => SafeMarkup::set($display_paths),
'operations' => $row['operations'],
),
'title' => $this->t('Machine name: @name', array('@name' => $view->id())),
diff --git a/core/modules/views_ui/views_ui.theme.inc b/core/modules/views_ui/views_ui.theme.inc
index 6fe4d76..efa54d9 100644
--- a/core/modules/views_ui/views_ui.theme.inc
+++ b/core/modules/views_ui/views_ui.theme.inc
@@ -89,7 +89,19 @@ function template_preprocess_views_ui_display_tab_bucket(&$variables) {
*/
function template_preprocess_views_ui_view_info(&$variables) {
$variables['title'] = $variables['view']->label();
- $variables['displays'] = empty($variables['displays']) ? t('None') : SafeMarkup::set(format_plural(count($variables['displays']), 'Display', 'Displays') . ': ' . '' . SafeMarkup::implode(', ', $variables['displays']) . '');
+ if (empty($variables['displays'])) {
+ $displays = t('None');
+ }
+ else {
+ $displays = format_plural(count($variables['displays']), 'Display', 'Displays') . ': ';
+ $separator = '';
+ foreach ($variables['displays'] as $displays_item) {
+ $displays .= $separator . SafeMarkup::escape($displays_item);
+ $separator = ', ';
+ }
+ $displays = SafeMarkup::set($displays . '');
+ }
+ $variables['displays'] = $displays;
}
/**
diff --git a/core/tests/Drupal/Tests/Component/Utility/SafeMarkupTest.php b/core/tests/Drupal/Tests/Component/Utility/SafeMarkupTest.php
index 7aeb2b4..bb82c90 100644
--- a/core/tests/Drupal/Tests/Component/Utility/SafeMarkupTest.php
+++ b/core/tests/Drupal/Tests/Component/Utility/SafeMarkupTest.php
@@ -8,7 +8,6 @@
namespace Drupal\Tests\Component\Utility;
use Drupal\Component\Utility\SafeMarkup;
-use Drupal\Component\Utility\String;
use Drupal\Tests\UnitTestCase;
/**
@@ -78,43 +77,6 @@ public function testStrategy() {
}
/**
- * Tests string formatting with SafeMarkup::implode().
- *
- * @dataProvider providerImplode
- *
- * @param string $delimiter
- * The delimiter to run through SafeMarkup::implode().
- * @param string $args
- * The arguments to pass into SafeMarkup::implode().
- * @param string $expected
- * The expected result from calling the function.
- * @param string $message
- * The message to display as output to the test.
- *
- * @covers ::implode()
- */
- public function testImplode($delimiter, $args, $expected, $message) {
- $result = SafeMarkup::implode($delimiter, $args);
- $this->assertEquals($expected, $result, $message);
- $this->assertTrue(SafeMarkup::isSafe($result), 'The return value has been marked as safe');
- }
-
- /**
- * Data provider for testImplode().
- *
- * @see testImplode()
- */
- public function providerImplode() {
- $tests[] = array('|', array('Simple text'), 'Simple text', 'SafeMarkup::implode() leaves simple text alone.');
- $tests[] = array(' | ', array('Escaped text: