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