Commit 3f0ff219 authored by alexpott's avatar alexpott
Browse files

Revert "Issue #2501931 by alexpott, alimac, cmanalansan, davidhernandez,...

Revert "Issue #2501931 by alexpott, alimac, cmanalansan, davidhernandez, scotself, cilefen, RavindraSingh, peezy, YesCT, pwolanin: Remove SafeMarkup::set in twig_render_template() and ThemeManager and FieldPluginBase:advancedRender"

This reverts commit 9ccb44e2.
parent 9ccb44e2
......@@ -518,7 +518,7 @@ protected function doRender(&$elements, $is_root_call = FALSE) {
$prefix = isset($elements['#prefix']) ? $this->xssFilterAdminIfUnsafe($elements['#prefix']) : '';
$suffix = isset($elements['#suffix']) ? $this->xssFilterAdminIfUnsafe($elements['#suffix']) : '';
$elements['#markup'] = SafeString::create($prefix . $elements['#children'] . $suffix);
$elements['#markup'] = $prefix . $elements['#children'] . $suffix;
// We've rendered this element (and its subtree!), now update the context.
$context->update($elements);
......@@ -553,7 +553,7 @@ protected function doRender(&$elements, $is_root_call = FALSE) {
$context->bubble();
$elements['#printed'] = TRUE;
return $elements['#markup'];
return SafeString::create($elements['#markup']);
}
/**
......
......@@ -7,13 +7,12 @@
namespace Drupal\Core\Theme;
use Drupal\Component\Utility\SafeStringInterface;
use Drupal\Core\Render\SafeString;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\Routing\StackedRouteMatchInterface;
use Symfony\Component\HttpFoundation\RequestStack;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\Template\Attribute;
use Drupal\Component\Utility\SafeMarkup;
/**
* Provides the default implementation of a theme manager.
......@@ -318,10 +317,7 @@ public function render($hook, array $variables) {
$output = '';
if (isset($info['function'])) {
if (function_exists($info['function'])) {
// Theme functions do not render via the theme engine, so the output is
// not autoescaped. However, we can only presume that the theme function
// has been written correctly and that the markup is safe.
$output = SafeString::create($info['function']($variables));
$output = SafeMarkup::set($info['function']($variables));
}
}
else {
......@@ -391,7 +387,7 @@ public function render($hook, array $variables) {
$output = $render_function($template_file, $variables);
}
return ($output instanceof SafeStringInterface) ? $output : (string) $output;
return (string) $output;
}
/**
......
......@@ -26,8 +26,8 @@ interface ThemeManagerInterface {
* @param array $variables
* An associative array of theme variables.
*
* @return string|\Drupal\Component\Utility\SafeStringInterface
* The rendered output, or a SafeString object.
* @return string
* The rendered output.
*/
public function render($hook, array $variables);
......
......@@ -91,11 +91,11 @@ public function testCommentFieldName() {
$output = $renderer->executeInRenderContext(new RenderContext(), function () use ($view) {
return $view->field['field_name']->advancedRender($view->result[0]);
});
$this->assertEqual($this->comment->getFieldName(), $output);
$this->assertIdentical($this->comment->getFieldName(), $output);
$output = $renderer->executeInRenderContext(new RenderContext(), function () use ($view) {
return $view->field['field_name']->advancedRender($view->result[1]);
});
$this->assertEqual($this->customComment->getFieldName(), $output);
$this->assertIdentical($this->customComment->getFieldName(), $output);
}
}
......@@ -30,10 +30,6 @@ services:
arguments: ['Drupal\Core\Field\Plugin\Field\FieldType\PasswordItem']
tags:
- { name: normalizer, priority: 20 }
serializer.normalizer.safe_string:
class: Drupal\serialization\Normalizer\SafeStringNormalizer
tags:
- { name: normalizer }
serializer.normalizer.typed_data:
class: Drupal\serialization\Normalizer\TypedDataNormalizer
tags:
......
<?php
/**
* @file
* Contains \Drupal\serialization\Normalizer\SafeStringNormalizer.
*/
namespace Drupal\serialization\Normalizer;
/**
* Normalizes SafeStringInterface objects into a string.
*/
class SafeStringNormalizer extends NormalizerBase {
/**
* The interface or class that this Normalizer supports.
*
* @var array
*/
protected $supportedInterfaceOrClass = array('Drupal\Component\Utility\SafeStringInterface');
/**
* {@inheritdoc}
*/
public function normalize($object, $format = NULL, array $context = array()) {
return (string) $object;
}
}
......@@ -815,10 +815,7 @@ protected function assertThemeOutput($callback, array $variables = array(), $exp
/** @var \Drupal\Core\Render\RendererInterface $renderer */
$renderer = \Drupal::service('renderer');
// The string cast is necessary because theme functions return
// SafeStringInterface objects. This means we can assert that $expected
// matches the theme output without having to worry about 0 == ''.
$output = (string) $renderer->executeInRenderContext(new RenderContext(), function() use ($callback, $variables) {
$output = $renderer->executeInRenderContext(new RenderContext(), function() use ($callback, $variables) {
return \Drupal::theme()->render($callback, $variables);
});
$this->verbose(
......
......@@ -13,7 +13,6 @@
use Symfony\Cmf\Component\Routing\RouteObjectInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Route;
use Drupal\Component\Utility\SafeStringInterface;
/**
* Tests low-level theme functions.
......@@ -60,19 +59,12 @@ function testAttributeMerging() {
* Test that _theme() returns expected data types.
*/
function testThemeDataTypes() {
// theme_test_false is an implemented theme hook so \Drupal::theme() service
// should return a string or an object that implements SafeStringInterface,
// even though the theme function itself can return anything.
$foos = array('null' => NULL, 'false' => FALSE, 'integer' => 1, 'string' => 'foo', 'empty_string' => '');
// theme_test_false is an implemented theme hook so \Drupal::theme() service should
// return a string, even though the theme function itself can return anything.
$foos = array('null' => NULL, 'false' => FALSE, 'integer' => 1, 'string' => 'foo');
foreach ($foos as $type => $example) {
$output = \Drupal::theme()->render('theme_test_foo', array('foo' => $example));
$this->assertTrue($output instanceof SafeStringInterface || is_string($output), format_string('\Drupal::theme() returns an object that implements SafeStringInterface or a string for data type !type.', array('!type' => $type)));
if ($output instanceof SafeStringInterface) {
$this->assertIdentical((string) $example, $output->__toString());
}
elseif (is_string($output)) {
$this->assertIdentical($output, '', 'A string will be return when the theme returns an empty string.');
}
$this->assertTrue(is_string($output), format_string('\Drupal::theme() returns a string for data type !type.', array('!type' => $type)));
}
// suggestionnotimplemented is not an implemented theme hook so \Drupal::theme() service
......
......@@ -63,7 +63,7 @@ public function testUserName() {
$render = $renderer->executeInRenderContext(new RenderContext(), function () use ($view) {
return $view->field['name']->advancedRender($view->result[0]);
});
$this->assertEqual($render, $username, 'If the user is not linked the username should be printed out for a normal user.');
$this->assertIdentical($render, $username, 'If the user is not linked the username should be printed out for a normal user.');
}
......
......@@ -167,10 +167,8 @@ public function preRender(&$values);
* @param \Drupal\views\ResultRow $values
* The values retrieved from a single row of a view's query result.
*
* @return string|\Drupal\Component\Utility\SafeStringInterface
* The rendered output. If the output is safe it will be wrapped in an
* object that implements SafeStringInterface. If it is empty or unsafe it
* will be a string.
* @return string
* The rendered output.
*
*/
public function render(ResultRow $values);
......@@ -204,10 +202,8 @@ public function postRender(ResultRow $row, $output);
* @param \Drupal\views\ResultRow $values
* The values retrieved from a single row of a view's query result.
*
* @return string|\Drupal\Component\Utility\SafeStringInterface
* The advanced rendered output. If the output is safe it will be wrapped in
* an object that implements SafeStringInterface. If it is empty or unsafe
* it will be a string.
* @return string
* The advanced rendered output.
*
*/
public function advancedRender(ResultRow $values);
......@@ -240,13 +236,29 @@ public function isValueEmpty($value, $empty_zero, $no_skip_empty = TRUE);
* - ellipsis: Show an ellipsis (…) at the end of the trimmed string.
* - html: Make sure that the html is correct.
*
* @return string|\Drupal\Component\Utility\SafeStringInterface
* The rendered output. If the output is safe it will be wrapped in an
* object that implements SafeStringInterface. If it is empty or unsafe it
* will be a string.
* @return string
* The rendered string.
*/
public function renderText($alter);
/**
* Trims the field down to the specified length.
*
* @param array $alter
* The alter array of options to use.
* - max_length: Maximum length of the string, the rest gets truncated.
* - word_boundary: Trim only on a word boundary.
* - ellipsis: Show an ellipsis (…) at the end of the trimmed string.
* - html: Make sure that the html is correct.
*
* @param string $value
* The string which should be trimmed.
*
* @return string
* The rendered trimmed string.
*/
public function renderTrimText($alter, $value);
/**
* Gets the 'render' tokens to use for advanced rendering.
*
......@@ -268,10 +280,8 @@ public function getRenderTokens($item);
* @param \Drupal\views\ResultRow $values
* Holds single row of a view's result set.
*
* @return string|\Drupal\Component\Utility\SafeStringInterface
* Returns rendered output of the given theme implementation. If the output
* is safe it will be wrapped in an object that implements
* SafeStringInterface. If it is empty or unsafe it will be a string.
* @return string|false
* Returns rendered output of the given theme implementation.
*/
function theme(ResultRow $values);
......
......@@ -10,7 +10,6 @@
use Drupal\Component\Utility\Html;
use Drupal\Component\Utility\NestedArray;
use Drupal\Component\Utility\SafeMarkup;
use Drupal\Component\Utility\SafeStringInterface;
use Drupal\Component\Utility\Unicode;
use Drupal\Component\Utility\UrlHelper;
use Drupal\Component\Utility\Xss;
......@@ -1139,7 +1138,7 @@ public function advancedRender(ResultRow $values) {
else {
$value = $this->render($values);
if (is_array($value)) {
$value = $this->getRenderer()->render($value);
$value = (string) $this->getRenderer()->render($value);
}
$this->last_render = $value;
$this->original_value = $value;
......@@ -1170,16 +1169,14 @@ public function advancedRender(ResultRow $values) {
}
if (is_array($value)) {
$value = $this->getRenderer()->render($value);
$value = (string) $this->getRenderer()->render($value);
}
// This happens here so that renderAsLink can get the unaltered value of
// this field as a token rather than the altered value.
$this->last_render = $value;
}
// String cast is necessary to test emptiness of SafeStringInterface
// objects.
if (empty((string) $this->last_render)) {
if (empty($this->last_render)) {
if ($this->isValueEmpty($this->last_render, $this->options['empty_zero'], FALSE)) {
$alter = $this->options['alter'];
$alter['alter_text'] = 1;
......@@ -1188,6 +1185,9 @@ public function advancedRender(ResultRow $values) {
$this->last_render = $this->renderText($alter);
}
}
// @todo Fix this in https://www.drupal.org/node/2280961.
$this->last_render = SafeMarkup::set($this->last_render);
return $this->last_render;
}
......@@ -1196,10 +1196,6 @@ public function advancedRender(ResultRow $values) {
* {@inheritdoc}
*/
public function isValueEmpty($value, $empty_zero, $no_skip_empty = TRUE) {
// Convert SafeStringInterface to a string for checking.
if ($value instanceof SafeStringInterface) {
$value = (string) $value;
}
if (!isset($value)) {
$empty = TRUE;
}
......@@ -1217,14 +1213,7 @@ public function isValueEmpty($value, $empty_zero, $no_skip_empty = TRUE) {
* {@inheritdoc}
*/
public function renderText($alter) {
// We need to preserve the safeness of the value regardless of the
// alterations made by this method. Any alterations or replacements made
// within this method need to ensure that at the minimum the result is
// XSS admin filtered. See self::renderAltered() as an example that does.
$value_is_safe = SafeMarkup::isSafe($this->last_render);
// Cast to a string so that empty checks and string functions work as
// expected.
$value = (string) $this->last_render;
$value = $this->last_render;
if (!empty($alter['alter_text']) && $alter['text'] !== '') {
$tokens = $this->getRenderTokens($alter);
......@@ -1250,9 +1239,6 @@ public function renderText($alter) {
if ($alter['phase'] == static::RENDER_TEXT_PHASE_EMPTY && $no_rewrite_for_empty) {
// If we got here then $alter contains the value of "No results text"
// and so there is nothing left to do.
if ($value_is_safe) {
$value = ViewsRenderPipelineSafeString::create($value);
}
return $value;
}
......@@ -1289,12 +1275,6 @@ public function renderText($alter) {
if (!empty($alter['nl2br'])) {
$value = nl2br($value);
}
// Preserve whether or not the string is safe. Since $suffix comes from
// \Drupal::l(), it is safe to append.
if ($value_is_safe) {
$value = ViewsRenderPipelineSafeString::create($value . $suffix);
}
$this->last_render_text = $value;
if (!empty($alter['make_link']) && (!empty($alter['path']) || !empty($alter['url']))) {
......@@ -1304,42 +1284,20 @@ public function renderText($alter) {
$value = $this->renderAsLink($alter, $value, $tokens);
}
// Preserve whether or not the string is safe. Since $suffix comes from
// \Drupal::l(), it is safe to append.
if ($value_is_safe) {
return ViewsRenderPipelineSafeString::create($value . $suffix);
}
else {
// If the string is not already marked safe, it is still OK to return it
// because it will be sanitized by Twig.
return $value . $suffix;
}
return $value . $suffix;
}
/**
* Render this field as user-defined altered text.
*/
protected function renderAltered($alter, $tokens) {
return $this->viewsTokenReplace($alter['text'], $tokens);
return ViewsRenderPipelineSafeString::create($this->viewsTokenReplace($alter['text'], $tokens));
}
/**
* Trims the field down to the specified length.
*
* @param array $alter
* The alter array of options to use.
* - max_length: Maximum length of the string, the rest gets truncated.
* - word_boundary: Trim only on a word boundary.
* - ellipsis: Show an ellipsis (…) at the end of the trimmed string.
* - html: Make sure that the html is correct.
*
* @param string $value
* The string which should be trimmed.
*
* @return string
* The rendered trimmed string.
* {@inheritdoc}
*/
protected function renderTrimText($alter, $value) {
public function renderTrimText($alter, $value) {
if (!empty($alter['strip_tags'])) {
// NOTE: It's possible that some external fields might override the
// element type.
......
......@@ -64,9 +64,9 @@ public function testFieldFileSize() {
// Test with the bytes option.
$view->field['age']->options['file_size_display'] = 'bytes';
$this->assertEqual($view->field['age']->advancedRender($view->result[0]), '');
$this->assertEqual($view->field['age']->advancedRender($view->result[1]), '10');
$this->assertEqual($view->field['age']->advancedRender($view->result[2]), '1000');
$this->assertEqual($view->field['age']->advancedRender($view->result[3]), '10000');
$this->assertEqual($view->field['age']->advancedRender($view->result[1]), 10);
$this->assertEqual($view->field['age']->advancedRender($view->result[2]), 1000);
$this->assertEqual($view->field['age']->advancedRender($view->result[3]), 10000);
}
}
......@@ -324,8 +324,7 @@ function testEmpty() {
/**
* Tests the hide if empty functionality.
*
* This tests alters the result to get easier and less coupled results. It is
* important that assertIdentical() is used in this test since in PHP 0 == ''.
* This tests alters the result to get easier and less coupled results.
*/
function _testHideIfEmpty() {
/** @var \Drupal\Core\Render\RendererInterface $renderer */
......@@ -350,7 +349,7 @@ function _testHideIfEmpty() {
$render = $renderer->executeInRenderContext(new RenderContext(), function () use ($view) {
return $view->field['name']->advancedRender($view->result[0]);
});
$this->assertIdentical((string) $render, $random_name, 'By default, a string should not be treated as empty.');
$this->assertIdentical($render, $random_name, 'By default, a string should not be treated as empty.');
// Test an empty string.
$view->result[0]->{$column_map_reversed['name']} = "";
......@@ -364,14 +363,14 @@ function _testHideIfEmpty() {
$render = $renderer->executeInRenderContext(new RenderContext(), function () use ($view) {
return $view->field['name']->advancedRender($view->result[0]);
});
$this->assertIdentical((string) $render, '0', 'By default, 0 should not be treated as empty.');
$this->assertIdentical($render, '0', 'By default, 0 should not be treated as empty.');
// Test zero as a string.
$view->result[0]->{$column_map_reversed['name']} = "0";
$render = $renderer->executeInRenderContext(new RenderContext(), function () use ($view) {
return $view->field['name']->advancedRender($view->result[0]);
});
$this->assertIdentical((string) $render, "0", 'By default, "0" should not be treated as empty.');
$this->assertIdentical($render, "0", 'By default, "0" should not be treated as empty.');
// Test when results are not rewritten and non-zero empty values are hidden.
$view->field['name']->options['hide_alter_empty'] = TRUE;
......@@ -383,7 +382,7 @@ function _testHideIfEmpty() {
$render = $renderer->executeInRenderContext(new RenderContext(), function () use ($view) {
return $view->field['name']->advancedRender($view->result[0]);
});
$this->assertIdentical((string) $render, $random_name, 'If hide_empty is checked, a string should not be treated as empty.');
$this->assertIdentical($render, $random_name, 'If hide_empty is checked, a string should not be treated as empty.');
// Test an empty string.
$view->result[0]->{$column_map_reversed['name']} = "";
......@@ -397,14 +396,14 @@ function _testHideIfEmpty() {
$render = $renderer->executeInRenderContext(new RenderContext(), function () use ($view) {
return $view->field['name']->advancedRender($view->result[0]);
});
$this->assertIdentical((string) $render, '0', 'If hide_empty is checked, but not empty_zero, 0 should not be treated as empty.');
$this->assertIdentical($render, '0', 'If hide_empty is checked, but not empty_zero, 0 should not be treated as empty.');
// Test zero as a string.
$view->result[0]->{$column_map_reversed['name']} = "0";
$render = $renderer->executeInRenderContext(new RenderContext(), function () use ($view) {
return $view->field['name']->advancedRender($view->result[0]);
});
$this->assertIdentical((string) $render, "0", 'If hide_empty is checked, but not empty_zero, "0" should not be treated as empty.');
$this->assertIdentical($render, "0", 'If hide_empty is checked, but not empty_zero, "0" should not be treated as empty.');
// Test when results are not rewritten and all empty values are hidden.
$view->field['name']->options['hide_alter_empty'] = TRUE;
......@@ -438,28 +437,28 @@ function _testHideIfEmpty() {
$render = $renderer->executeInRenderContext(new RenderContext(), function () use ($view) {
return $view->field['name']->advancedRender($view->result[0]);
});
$this->assertIdentical((string) $render, $random_name, 'If the rewritten string is not empty, it should not be treated as empty.');
$this->assertIdentical($render, $random_name, 'If the rewritten string is not empty, it should not be treated as empty.');
// Test an empty string.
$view->result[0]->{$column_map_reversed['name']} = "";
$render = $renderer->executeInRenderContext(new RenderContext(), function () use ($view) {
return $view->field['name']->advancedRender($view->result[0]);
});
$this->assertIdentical((string) $render, $random_name, 'If the rewritten string is not empty, "" should not be treated as empty.');
$this->assertIdentical($render, $random_name, 'If the rewritten string is not empty, "" should not be treated as empty.');
// Test zero as an integer.
$view->result[0]->{$column_map_reversed['name']} = 0;
$render = $renderer->executeInRenderContext(new RenderContext(), function () use ($view) {
return $view->field['name']->advancedRender($view->result[0]);
});
$this->assertIdentical((string) $render, $random_name, 'If the rewritten string is not empty, 0 should not be treated as empty.');
$this->assertIdentical($render, $random_name, 'If the rewritten string is not empty, 0 should not be treated as empty.');
// Test zero as a string.
$view->result[0]->{$column_map_reversed['name']} = "0";
$render = $renderer->executeInRenderContext(new RenderContext(), function () use ($view) {
return $view->field['name']->advancedRender($view->result[0]);
});
$this->assertIdentical((string) $render, $random_name, 'If the rewritten string is not empty, "0" should not be treated as empty.');
$this->assertIdentical($render, $random_name, 'If the rewritten string is not empty, "0" should not be treated as empty.');
// Test when results are rewritten to an empty string and non-zero empty results are hidden.
$view->field['name']->options['hide_alter_empty'] = TRUE;
......@@ -473,7 +472,7 @@ function _testHideIfEmpty() {
$render = $renderer->executeInRenderContext(new RenderContext(), function () use ($view) {
return $view->field['name']->advancedRender($view->result[0]);
});
$this->assertIdentical((string) $render, $random_name, 'If the rewritten string is empty, it should not be treated as empty.');
$this->assertIdentical($render, $random_name, 'If the rewritten string is empty, it should not be treated as empty.');
// Test an empty string.
$view->result[0]->{$column_map_reversed['name']} = "";
......@@ -487,14 +486,14 @@ function _testHideIfEmpty() {
$render = $renderer->executeInRenderContext(new RenderContext(), function () use ($view) {
return $view->field['name']->advancedRender($view->result[0]);
});
$this->assertIdentical((string) $render, '0', 'If the rewritten string is empty, 0 should not be treated as empty.');
$this->assertIdentical($render, '0', 'If the rewritten string is empty, 0 should not be treated as empty.');
// Test zero as a string.
$view->result[0]->{$column_map_reversed['name']} = "0";
$render = $renderer->executeInRenderContext(new RenderContext(), function () use ($view) {
return $view->field['name']->advancedRender($view->result[0]);
});
$this->assertIdentical((string) $render, "0", 'If the rewritten string is empty, "0" should not be treated as empty.');
$this->assertIdentical($render, "0", 'If the rewritten string is empty, "0" should not be treated as empty.');
// Test when results are rewritten to zero as a string and non-zero empty
// results are hidden.
......@@ -509,28 +508,28 @@ function _testHideIfEmpty() {
$render = $renderer->executeInRenderContext(new RenderContext(), function () use ($view) {
return $view->field['name']->advancedRender($view->result[0]);
});
$this->assertIdentical((string) $render, "0", 'If the rewritten string is zero and empty_zero is not checked, the string rewritten as 0 should not be treated as empty.');
$this->assertIdentical($render, "0", 'If the rewritten string is zero and empty_zero is not checked, the string rewritten as 0 should not be treated as empty.');
// Test an empty string.
$view->result[0]->{$column_map_reversed['name']} = "";
$render = $renderer->executeInRenderContext(new RenderContext(), function () use ($view) {
return $view->field['name']->advancedRender($view->result[0]);
});
$this->assertIdentical((string) $render, "0", 'If the rewritten string is zero and empty_zero is not checked, "" rewritten as 0 should not be treated as empty.');
$this->assertIdentical($render, "0", 'If the rewritten string is zero and empty_zero is not checked, "" rewritten as 0 should not be treated as empty.');
// Test zero as an integer.
$view->result[0]->{$column_map_reversed['name']} = 0;
$render = $renderer->executeInRenderContext(new RenderContext(), function () use ($view) {
return $view->field['name']->advancedRender($view->result[0]);
});
$this->assertIdentical((string) $render, "0", 'If the rewritten string is zero and empty_zero is not checked, 0 should not be treated as empty.');
$this->assertIdentical($render, "0", 'If the rewritten string is zero and empty_zero is not checked, 0 should not be treated as empty.');
// Test zero as a string.
$view->result[0]->{$column_map_reversed['name']} = "0";
$render = $renderer->executeInRenderContext(new RenderContext(), function () use ($view) {
return $view->field['name']->advancedRender($view->result[0]);
});
$this->assertIdentical((string) $render, "0", 'If the rewritten string is zero and empty_zero is not checked, "0" should not be treated as empty.');
$this->assertIdentical($render, "0", 'If the rewritten string is zero and empty_zero is not checked, "0" should not be treated as empty.');
// Test when results are rewritten to a valid string and non-zero empty
// results are hidden.
......@@ -545,7 +544,7 @@ function _testHideIfEmpty() {
$render = $renderer->executeInRenderContext(new RenderContext(), function () use ($view) {
return $view->field['name']->advancedRender($view->result[0]);
});
$this->assertIdentical((string) $render, $random_value, 'If the original and rewritten strings are valid, it should not be treated as empty.');
$this->assertIdentical($render, $random_value, 'If the original and rewritten strings are valid, it should not be treated as empty.');
// Test an empty string.
$view->result[0]->{$column_map_reversed['name']} = "";
......@@ -559,14 +558,14 @@ function _testHideIfEmpty() {
$render = $renderer->executeInRenderContext(new RenderContext(), function () use ($view) {
return $view->field['name']->advancedRender($view->result[0]);
});
$this->assertIdentical((string) $render, $random_value, 'If the original and rewritten strings are valid, 0 should not be treated as empty.');
$this->assertIdentical($render, $random_value, 'If the original and rewritten strings are valid, 0 should not be treated as empty.');
// Test zero as a string.
$view->result[0]->{$column_map_reversed['name']} = "0";
$render = $renderer->executeInRenderContext(new RenderContext(), function () use ($view) {
return $view->field['name']->advancedRender($view->result[0]);
});
$this->assertIdentical((string) $render, $random_value, 'If the original and rewritten strings are valid, "0" should not be treated as empty.');
$this->assertIdentical($render, $random_value, 'If the original and rewritten strings are valid, "0" should not be treated as empty.');
// Test when results are rewritten to zero as a string and all empty
// original values and results are hidden.
...