From 14979055d10af29b944eb83fcec68576e52a42f3 Mon Sep 17 00:00:00 2001 From: webchick <drupal@webchick.net> Date: Sat, 24 Oct 2015 14:05:04 -0700 Subject: [PATCH] Issue #2579427 by lauriii, ibullock, joelpittet, bigjim: Outputting markup from custom text field is not possible --- .../views/src/Plugin/views/field/Custom.php | 4 +- .../src/Tests/Handler/FieldCustomTest.php | 69 ++++++++++++++++++- 2 files changed, 71 insertions(+), 2 deletions(-) diff --git a/core/modules/views/src/Plugin/views/field/Custom.php b/core/modules/views/src/Plugin/views/field/Custom.php index 4696cd6b3025..55f235321172 100644 --- a/core/modules/views/src/Plugin/views/field/Custom.php +++ b/core/modules/views/src/Plugin/views/field/Custom.php @@ -7,7 +7,9 @@ namespace Drupal\views\Plugin\views\field; +use Drupal\Component\Utility\Xss; use Drupal\Core\Form\FormStateInterface; +use Drupal\views\Render\ViewsRenderPipelineMarkup; use Drupal\views\ResultRow; /** @@ -63,7 +65,7 @@ public function buildOptionsForm(&$form, FormStateInterface $form_state) { */ public function render(ResultRow $values) { // Return the text, so the code never thinks the value is empty. - return $this->options['alter']['text']; + return ViewsRenderPipelineMarkup::create(Xss::filterAdmin($this->options['alter']['text'])); } /** diff --git a/core/modules/views/src/Tests/Handler/FieldCustomTest.php b/core/modules/views/src/Tests/Handler/FieldCustomTest.php index a94e46dbfbbd..cc3d92bca708 100644 --- a/core/modules/views/src/Tests/Handler/FieldCustomTest.php +++ b/core/modules/views/src/Tests/Handler/FieldCustomTest.php @@ -7,6 +7,9 @@ namespace Drupal\views\Tests\Handler; +use Drupal\Component\Utility\Xss; +use Drupal\Core\Render\RenderContext; +use Drupal\views\Plugin\views\PluginBase; use Drupal\views\Tests\ViewKernelTestBase; use Drupal\views\Views; @@ -24,18 +27,24 @@ class FieldCustomTest extends ViewKernelTestBase { */ public static $testViews = array('test_view'); + /** + * {@inheritdoc} + */ function viewsData() { $data = parent::viewsData(); $data['views_test_data']['name']['field']['id'] = 'custom'; return $data; } + /** + * Ensure that custom fields work and doesn't escape unnecessary markup. + */ public function testFieldCustom() { $view = Views::getView('test_view'); $view->setDisplay(); // Alter the text of the field to a random string. - $random = $this->randomMachineName(); + $random = '<div>' . $this->randomMachineName() . '</div>'; $view->displayHandlers->get('default')->overrideOption('fields', array( 'name' => array( 'id' => 'name', @@ -53,4 +62,62 @@ public function testFieldCustom() { $this->assertEqual($random, $view->style_plugin->getField(0, 'name')); } + /** + * Ensure that custom fields can use tokens. + */ + public function testFieldCustomTokens() { + $view = Views::getView('test_view'); + $view->setDisplay(); + + $view->displayHandlers->get('default')->overrideOption('fields', [ + 'age' => [ + 'id' => 'age', + 'exclude' => TRUE, + 'table' => 'views_test_data', + 'field' => 'age', + ], + 'name' => [ + 'id' => 'name', + 'table' => 'views_test_data', + 'field' => 'name', + 'relationship' => 'none', + 'alter' => [ + 'text' => 'Amount of kittens: {{ age }}', + ], + ], + ]); + + /** @var \Drupal\Core\Render\RendererInterface $renderer */ + $renderer = \Drupal::service('renderer'); + $preview = $view->preview(); + $output = $renderer->renderRoot($preview); + + $expected_text = 'Amount of kittens: ' . $view->style_plugin->getField(0, 'age'); + $this->assertTrue(strpos((string) $output, $expected_text), 'The views token has been successfully replaced.'); + } + + /** + * Ensure that custom field content is XSS filtered. + */ + public function testCustomFieldXss() { + $view = Views::getView('test_view'); + $view->setDisplay(); + + // Alter the text of the field to include XSS. + $text = '<script>alert("kittens")</script>'; + $view->displayHandlers->get('default')->overrideOption('fields', array( + 'name' => array( + 'id' => 'name', + 'table' => 'views_test_data', + 'field' => 'name', + 'relationship' => 'none', + 'alter' => array( + 'text' => $text, + ), + ), + )); + $this->executeView($view); + $this->assertEqual(Xss::filter($text), $view->style_plugin->getField(0, 'name')); + } + } -- GitLab