diff --git a/core/includes/common.inc b/core/includes/common.inc
index c465349..4ecbec2 100644
--- a/core/includes/common.inc
+++ b/core/includes/common.inc
@@ -20,7 +20,6 @@
use Drupal\Core\Cache\Cache;
use Drupal\Core\Language\Language;
use Drupal\Core\Site\Settings;
-use Drupal\Core\Template\SafeMarkup;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Request;
use Drupal\Core\PhpStorage\PhpStorageFactory;
@@ -29,6 +28,7 @@
use Drupal\Core\EventSubscriber\HtmlViewSubscriber;
use Drupal\Core\Routing\GeneratorNotInitializedException;
use Drupal\Core\Template\Attribute;
+use Drupal\Core\Template\SafeMarkup;
use Drupal\Core\Render\Element;
use Drupal\Core\Session\AnonymousUserSession;
@@ -915,6 +915,7 @@ function l($text, $path, array $options = array()) {
// Sanitize the link text if necessary.
$text = $variables['options']['html'] ? $variables['text'] : String::checkPlain($variables['text']);
+
// $attributes and $url is known to be safe.
$safe = $text instanceof SafeMarkup;
$link = '' . $text . '';
@@ -1471,6 +1472,9 @@ function drupal_html_class($class) {
// static instead of drupal_static().
static $classes = array();
+ // @todo Needs safe makrup preservation or should be cast to string before
+ // arg is passed to this function?
+ $class = (string) $class;
if (!isset($classes[$class])) {
$classes[$class] = drupal_clean_css_identifier(drupal_strtolower($class));
}
@@ -2873,7 +2877,8 @@ function drupal_pre_render_conditional_comments($elements) {
function drupal_pre_render_html_tag($element) {
$attributes = isset($element['#attributes']) ? new Attribute($element['#attributes']) : '';
if (!isset($element['#value'])) {
- // Attributes is safe.
+ // Attributes are safe and we are assuming people don't use this function
+ // and second they don't pass unsafe variables to #tag.
$markup = new SafeMarkup('<' . $element['#tag'] . $attributes . " />\n");
}
else {
@@ -2886,7 +2891,7 @@ function drupal_pre_render_html_tag($element) {
$markup .= $element['#value_suffix'];
}
$markup .= '' . $element['#tag'] . ">\n";
- // @TODO!
+ // @TODO Creating safe markup, avoid if possible!
$markup = new SafeMarkup($markup);
}
if (!empty($element['#noscript'])) {
@@ -3386,6 +3391,9 @@ function drupal_render(&$elements, $is_recursive_call = FALSE) {
// is common for theme suggestions.
$theme_is_implemented = ($elements['#children'] !== FALSE);
}
+
+ // Assume still safe unless the element or it's __toString return value aren't
+ // instances of Twig_Markup.
$safe = TRUE;
$get_string = function ($element) use (&$safe) {
if (is_object($element) && method_exists($element, '__toString')) {
@@ -3394,7 +3402,7 @@ function drupal_render(&$elements, $is_recursive_call = FALSE) {
else {
$markup = $element;
}
- $safe = $safe && (!$markup || $element instanceof SafeMarkup || $markup instanceof SafeMarkup);
+ $safe = $safe && (!$markup || $element instanceof \Twig_Markup || $markup instanceof \Twig_Markup);
return $markup;
};
diff --git a/core/includes/form.inc b/core/includes/form.inc
index 3be1d3e..8bc313c 100644
--- a/core/includes/form.inc
+++ b/core/includes/form.inc
@@ -1660,7 +1660,7 @@ function theme_tableselect($variables) {
foreach ($element['#header'] as $fieldname => $title) {
// A row cell can span over multiple headers, which means less row cells
// than headers could be present.
- if (isset($element['#options'][$key][$fieldname])) {
+ if (isset($element['#options'][$key][$fieldname]) && is_array($element['#options'][$key][$fieldname])) {
// A header can span over multiple cells and in this case the cells
// are passed in an array. The order of this array determines the
// order in which they are added.
diff --git a/core/includes/theme.inc b/core/includes/theme.inc
index e5a917f..5c5ae2b 100644
--- a/core/includes/theme.inc
+++ b/core/includes/theme.inc
@@ -2053,7 +2053,9 @@ function template_preprocess_html(&$variables) {
// Wrap function calls in an object so they can be called when printed.
$variables['head'] = new RenderWrapper(function() use ($page) {
+ // @todo Creates safe makrup, maybe should preserve?
return new SafeMarkup(implode("\n", $page->getMetaElements()) . implode("\n", $page->getLinkElements()));
+ // return String::concat(String::implode("\n", $page->getMetaElements()), String::implode("\n", $page->getLinkElements()));
});
$variables['styles'] = new RenderWrapper('drupal_get_css');
$variables['scripts'] = new RenderWrapper('drupal_get_js');
diff --git a/core/lib/Drupal/Component/Utility/String.php b/core/lib/Drupal/Component/Utility/String.php
index a71dc1a..fed1c73 100644
--- a/core/lib/Drupal/Component/Utility/String.php
+++ b/core/lib/Drupal/Component/Utility/String.php
@@ -6,6 +6,7 @@
*/
namespace Drupal\Component\Utility;
+
use Drupal\Core\Template\SafeMarkup;
/**
@@ -128,12 +129,18 @@ public static function placeholder($text) {
return new SafeMarkup('' . static::checkPlain($text) . '');
}
+ /**
+ * @todo.
+ */
public static function concat($string1, $string2) {
$string = $string1 . $string2;
$safe = $string1 instanceof SafeMarkup && $string2 instanceof SafeMarkup;
return $safe ? new SafeMarkup($string) : $string;
}
+ /**
+ * @todo.
+ */
public static function implode($delimiter, array $array) {
$real_delimiter = '';
$safe = TRUE;
@@ -145,4 +152,5 @@ public static function implode($delimiter, array $array) {
}
return $safe ? new SafeMarkup($imploded) : $imploded;
}
+
}
diff --git a/core/lib/Drupal/Component/Utility/Xss.php b/core/lib/Drupal/Component/Utility/Xss.php
index 8117ccf..dd0df76 100644
--- a/core/lib/Drupal/Component/Utility/Xss.php
+++ b/core/lib/Drupal/Component/Utility/Xss.php
@@ -6,6 +6,7 @@
*/
namespace Drupal\Component\Utility;
+
use Drupal\Core\Template\SafeMarkup;
/**
diff --git a/core/lib/Drupal/Core/Extension/ThemeHandler.php b/core/lib/Drupal/Core/Extension/ThemeHandler.php
index 791a927..8354bea 100644
--- a/core/lib/Drupal/Core/Extension/ThemeHandler.php
+++ b/core/lib/Drupal/Core/Extension/ThemeHandler.php
@@ -626,6 +626,7 @@ public function getName($theme) {
if (!isset($themes[$theme])) {
throw new \InvalidArgumentException(String::format('Requested the name of a non-existing theme @theme', array('@theme' => $theme)));
}
+ // @todo For testing please remove before commit.
return \Drupal::config('system.site')->get('name');
return String::checkPlain($themes[$theme]->info['name']);
}
diff --git a/core/lib/Drupal/Core/Form/OptGroup.php b/core/lib/Drupal/Core/Form/OptGroup.php
index f94d62d..21e9855 100644
--- a/core/lib/Drupal/Core/Form/OptGroup.php
+++ b/core/lib/Drupal/Core/Form/OptGroup.php
@@ -43,7 +43,7 @@ public static function flattenOptions(array $array) {
*/
protected static function doFlattenOptions(array $array, array &$options) {
foreach ($array as $key => $value) {
- if (is_object($value)) {
+ if (is_object($value) && isset($value->option)) {
static::doFlattenOptions($value->option, $options);
}
elseif (is_array($value)) {
diff --git a/core/lib/Drupal/Core/Template/Attribute.php b/core/lib/Drupal/Core/Template/Attribute.php
index 18a7430..e80bf7c 100644
--- a/core/lib/Drupal/Core/Template/Attribute.php
+++ b/core/lib/Drupal/Core/Template/Attribute.php
@@ -31,7 +31,7 @@
* // Produces
* @endcode
*/
-class Attribute extends SafeMarkup implements \ArrayAccess, \IteratorAggregate {
+class Attribute extends \Twig_Markup implements \ArrayAccess, \IteratorAggregate {
/**
* Stores the attribute data.
diff --git a/core/lib/Drupal/Core/Template/SafeMarkup.php b/core/lib/Drupal/Core/Template/SafeMarkup.php
index a874c62..31cbf4e 100644
--- a/core/lib/Drupal/Core/Template/SafeMarkup.php
+++ b/core/lib/Drupal/Core/Template/SafeMarkup.php
@@ -12,11 +12,24 @@
*/
class SafeMarkup extends \Twig_Markup {
- function __construct($content) {
+ /**
+ * Constructs a SafeMarkup object.
+ *
+ * @param string $content
+ * The callback function name.
+ */
+ public function __construct($content) {
return parent::__construct($content, 'utf-8');
}
+ /**
+ * Renders the markup.
+ *
+ * @return string
+ * The results of the callback function.
+ */
public function render() {
return $this->__toString();
}
+
}
diff --git a/core/lib/Drupal/Core/Utility/LinkGenerator.php b/core/lib/Drupal/Core/Utility/LinkGenerator.php
index 88d5d60..c793786 100644
--- a/core/lib/Drupal/Core/Utility/LinkGenerator.php
+++ b/core/lib/Drupal/Core/Utility/LinkGenerator.php
@@ -11,8 +11,8 @@
use Drupal\Component\Utility\String;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\Path\AliasManagerInterface;
-use Drupal\Core\Template\Attribute;
use Drupal\Core\Routing\UrlGeneratorInterface;
+use Drupal\Core\Template\Attribute;
use Drupal\Core\Template\SafeMarkup;
use Drupal\Core\Url;
@@ -123,6 +123,7 @@ public function generateFromUrl($text, Url $url) {
// Sanitize the link text if necessary.
$text = $variables['options']['html'] ? $variables['text'] : String::checkPlain($variables['text']);
+
// $attributes and $url is known to be safe.
$safe = $text instanceof SafeMarkup;
$link = '' . $text . '';
diff --git a/core/modules/contextual/lib/Drupal/contextual/ContextualController.php b/core/modules/contextual/lib/Drupal/contextual/ContextualController.php
index aeee4a6..fcc47de 100644
--- a/core/modules/contextual/lib/Drupal/contextual/ContextualController.php
+++ b/core/modules/contextual/lib/Drupal/contextual/ContextualController.php
@@ -44,7 +44,10 @@ public function render(Request $request) {
'#type' => 'contextual_links',
'#contextual_links' => _contextual_id_to_links($id),
);
- $rendered[$id] = drupal_render($element);
+ // Cast any returned safe markup to string so that it is created
+ // as correct JSON.
+ // @todo Maybe check safeness and checkplain the results?
+ $rendered[$id] = (string) drupal_render($element);
}
return new JsonResponse($rendered);
diff --git a/core/modules/datetime/datetime.module b/core/modules/datetime/datetime.module
index 3d13b7b..4ded696 100644
--- a/core/modules/datetime/datetime.module
+++ b/core/modules/datetime/datetime.module
@@ -8,6 +8,7 @@
use Drupal\Component\Utility\NestedArray;
use Drupal\Core\Datetime\DrupalDateTime;
use Drupal\Core\Template\Attribute;
+use Drupal\Core\Template\SafeMarkup;
use Drupal\datetime\DateHelper;
use Drupal\node\NodeInterface;
diff --git a/core/modules/field_ui/lib/Drupal/field_ui/FieldConfigListBuilder.php b/core/modules/field_ui/lib/Drupal/field_ui/FieldConfigListBuilder.php
index e1d96c6..11ef3f4 100644
--- a/core/modules/field_ui/lib/Drupal/field_ui/FieldConfigListBuilder.php
+++ b/core/modules/field_ui/lib/Drupal/field_ui/FieldConfigListBuilder.php
@@ -12,6 +12,7 @@
use Drupal\Core\Entity\EntityManagerInterface;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Field\FieldTypePluginManagerInterface;
+use Drupal\Core\Template\SafeMarkup;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
@@ -117,7 +118,8 @@ public function buildRow(EntityInterface $field) {
$usage[] = $this->bundles[$field->entity_type][$bundle]['label'];
}
}
- $row['data']['usage'] = implode(', ', $usage);
+ // @todo Needs to preserve safe markup.
+ $row['data']['usage'] = new SafeMarkup(implode(', ', $usage));
return $row;
}
diff --git a/core/modules/node/node.install b/core/modules/node/node.install
index b075d93..7888e2b 100644
--- a/core/modules/node/node.install
+++ b/core/modules/node/node.install
@@ -7,6 +7,7 @@
use Drupal\Component\Uuid\Uuid;
use Drupal\Core\Language\Language;
+use Drupal\Core\Template\SafeMarkup;
/**
* Implements hook_requirements().
@@ -29,7 +30,9 @@ function node_requirements($phase) {
$requirements['node_access'] = array(
'title' => t('Node Access Permissions'),
'value' => $value,
- 'description' => $description . ' ' . l(t('Rebuild permissions'), 'admin/reports/status/rebuild'),
+ // The results of t() is safe and so is the results of l(). Preserving
+ // safe object.
+ 'description' => new SafeMarkup($description . ' ' . l(t('Rebuild permissions'), 'admin/reports/status/rebuild')),
);
}
return $requirements;
diff --git a/core/modules/simpletest/lib/Drupal/simpletest/Form/SimpletestResultsForm.php b/core/modules/simpletest/lib/Drupal/simpletest/Form/SimpletestResultsForm.php
index 299f305..2786a3a 100644
--- a/core/modules/simpletest/lib/Drupal/simpletest/Form/SimpletestResultsForm.php
+++ b/core/modules/simpletest/lib/Drupal/simpletest/Form/SimpletestResultsForm.php
@@ -9,6 +9,7 @@
use Drupal\Core\Database\Connection;
use Drupal\Core\Form\FormBase;
+use Drupal\Core\Template\SafeMarkup;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
@@ -155,7 +156,8 @@ public function buildForm(array $form, array &$form_state, $test_id = NULL) {
$rows = array();
foreach ($assertions as $assertion) {
$row = array();
- $row[] = $assertion->message;
+ // @todo Need to preserve safe markup, not create it.
+ $row[] = new SafeMarkup($assertion->message);
$row[] = $assertion->message_group;
$row[] = drupal_basename($assertion->file);
$row[] = $assertion->line;
diff --git a/core/modules/system/system.install b/core/modules/system/system.install
index a14cd7b..b8b4d6d 100644
--- a/core/modules/system/system.install
+++ b/core/modules/system/system.install
@@ -10,6 +10,7 @@
use Drupal\Core\Language\Language;
use Drupal\Core\Site\Settings;
use Drupal\Core\StreamWrapper\PublicStream;
+use Drupal\Core\Template\SafeMarkup;
/**
* Implements hook_requirements().
@@ -56,7 +57,8 @@ function system_requirements($phase) {
if (function_exists('phpinfo')) {
$requirements['php'] = array(
'title' => t('PHP'),
- 'value' => ($phase == 'runtime') ? $phpversion .' ('. l(t('more information'), 'admin/reports/status/php') .')' : $phpversion,
+ // $phpversion is safe and output of l() is safe, so this value is safe.
+ 'value' => new SafeMarkup(($phase == 'runtime') ? $phpversion . ' (' . l(t('more information'), 'admin/reports/status/php') . ')' : $phpversion),
);
}
else {
@@ -318,7 +320,8 @@ function system_requirements($phase) {
'title' => t('Cron maintenance tasks'),
'severity' => $severity,
'value' => $summary,
- 'description' => $description
+ // @todo Needs to preserve safe markup.
+ 'description' => new SafeMarkup($description),
);
}
if ($phase != 'install') {
diff --git a/core/modules/views/lib/Drupal/views/Plugin/views/filter/FilterPluginBase.php b/core/modules/views/lib/Drupal/views/Plugin/views/filter/FilterPluginBase.php
index 902b543..42b8d0b 100644
--- a/core/modules/views/lib/Drupal/views/Plugin/views/filter/FilterPluginBase.php
+++ b/core/modules/views/lib/Drupal/views/Plugin/views/filter/FilterPluginBase.php
@@ -1159,8 +1159,7 @@ protected function prepareFilterSelectOptions(&$options) {
$this->prepareFilterSelectOptions($options[$value]);
}
// FAPI has some special value to allow hierarchy.
- // @see _form_options_flatten
- elseif (is_object($label)) {
+ elseif (is_object($label) && isset($options[$value]->option)) {
$this->prepareFilterSelectOptions($options[$value]->option);
}
else {
diff --git a/core/modules/views_ui/views_ui.theme.inc b/core/modules/views_ui/views_ui.theme.inc
index 430f14a..bb10ee1 100644
--- a/core/modules/views_ui/views_ui.theme.inc
+++ b/core/modules/views_ui/views_ui.theme.inc
@@ -7,6 +7,7 @@
use Drupal\Core\Render\Element;
use Drupal\Core\Template\Attribute;
+use Drupal\Core\Template\SafeMarkup;
/**
* Prepares variables for Views UI display tab setting templates.
diff --git a/core/vendor/twig/twig/lib/Twig/Extension/Core.php b/core/vendor/twig/twig/lib/Twig/Extension/Core.php
index 968b292..cdb5874 100644
--- a/core/vendor/twig/twig/lib/Twig/Extension/Core.php
+++ b/core/vendor/twig/twig/lib/Twig/Extension/Core.php
@@ -922,6 +922,7 @@ function twig_escape_filter(Twig_Environment $env, $string, $strategy = 'html',
if (!is_string($string)) {
if (is_object($string) && method_exists($string, '__toString')) {
+ // @todo Move to twig engine.
$string = $string->__toString();
if ($autoescape && $string instanceof Twig_Markup) {
return $string;