From fb68de2d4f21fc26d41dac3673af6925d2500888 Mon Sep 17 00:00:00 2001
From: "Frederic G. MARAND" <fgm@osinet.fr>
Date: Sun, 28 Sep 2014 18:28:36 +0200
Subject: [PATCH] Issue #2339475 by fgm: Introduce a mutable HTML fragment
 interface.

---
 core/lib/Drupal/Core/Ajax/AjaxResponseRenderer.php |    4 +-
 .../Drupal/Core/Controller/HtmlControllerBase.php  |    9 +--
 .../Core/EventSubscriber/HtmlViewSubscriber.php    |    3 +-
 .../Core/Page/DefaultHtmlFragmentRenderer.php      |    4 +-
 core/lib/Drupal/Core/Page/HtmlFragment.php         |   48 ++-----------
 .../Core/Page/HtmlMutableFragmentInterface.php     |   75 ++++++++++++++++++++
 .../Core/Page/RenderHtmlRendererInterface.php      |    6 +-
 7 files changed, 93 insertions(+), 56 deletions(-)
 create mode 100644 core/lib/Drupal/Core/Page/HtmlMutableFragmentInterface.php

diff --git a/core/lib/Drupal/Core/Ajax/AjaxResponseRenderer.php b/core/lib/Drupal/Core/Ajax/AjaxResponseRenderer.php
index bb55433..af4530e 100644
--- a/core/lib/Drupal/Core/Ajax/AjaxResponseRenderer.php
+++ b/core/lib/Drupal/Core/Ajax/AjaxResponseRenderer.php
@@ -7,7 +7,7 @@
 
 namespace Drupal\Core\Ajax;
 
-use Drupal\Core\Page\HtmlFragment;
+use Drupal\Core\Page\HtmlFragmentInterface;
 use Symfony\Component\HttpFoundation\Response;
 
 /**
@@ -32,7 +32,7 @@ public function render($content) {
     }
 
     // Allow controllers to return an HtmlFragment directly.
-    if ($content instanceof HtmlFragment) {
+    if ($content instanceof HtmlFragmentInterface) {
       $content = $content->getContent();
     }
     // Most controllers return a render array, but some return a string.
diff --git a/core/lib/Drupal/Core/Controller/HtmlControllerBase.php b/core/lib/Drupal/Core/Controller/HtmlControllerBase.php
index b2a639b..dc8b202 100644
--- a/core/lib/Drupal/Core/Controller/HtmlControllerBase.php
+++ b/core/lib/Drupal/Core/Controller/HtmlControllerBase.php
@@ -8,6 +8,7 @@
 namespace Drupal\Core\Controller;
 
 use Drupal\Core\Page\HtmlFragment;
+use Drupal\Core\Page\HtmlMutableFragmentInterface;
 use Drupal\Core\Page\RenderHtmlRendererInterface;
 use Drupal\Core\Utility\Title;
 use Symfony\Cmf\Component\Routing\RouteObjectInterface;
@@ -54,12 +55,12 @@ public function __construct(TitleResolverInterface $title_resolver, RenderHtmlRe
    * @param \Symfony\Component\HttpFoundation\Request $request
    *   The request object.
    *
-   * @return \Drupal\Core\Page\HtmlPage
-   *   A page object.
+   * @return \Drupal\Core\Page\HtmlMutableFragmentInterface|\Symfony\Component\HttpFoundation\Response
+   *   A page or response object.
    */
   protected function createHtmlFragment($page_content, Request $request) {
-    // Allow controllers to return a HtmlFragment or a Response object directly.
-    if ($page_content instanceof HtmlFragment || $page_content instanceof Response) {
+    // Allow controllers to return a HtmlMutableFragmentInterface or a Response object directly.
+    if ($page_content instanceof HtmlMutableFragmentInterface || $page_content instanceof Response) {
       return $page_content;
     }
 
diff --git a/core/lib/Drupal/Core/EventSubscriber/HtmlViewSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/HtmlViewSubscriber.php
index b51e491..688e96e 100644
--- a/core/lib/Drupal/Core/EventSubscriber/HtmlViewSubscriber.php
+++ b/core/lib/Drupal/Core/EventSubscriber/HtmlViewSubscriber.php
@@ -8,6 +8,7 @@
 namespace Drupal\Core\EventSubscriber;
 
 use Drupal\Core\Page\HtmlFragment;
+use Drupal\Core\Page\HtmlFragmentInterface;
 use Drupal\Core\Page\HtmlPage;
 use Drupal\Core\Page\HtmlFragmentRendererInterface;
 use Drupal\Core\Page\HtmlPageRendererInterface;
@@ -56,7 +57,7 @@ public function __construct(HtmlFragmentRendererInterface $fragment_renderer, Ht
    */
   public function onHtmlFragment(GetResponseForControllerResultEvent $event) {
     $fragment = $event->getControllerResult();
-    if ($fragment instanceof HtmlFragment && !$fragment instanceof HtmlPage) {
+    if ($fragment instanceof HtmlFragmentInterface && !$fragment instanceof HtmlPage) {
       $page = $this->fragmentRenderer->render($fragment);
       $event->setControllerResult($page);
     }
diff --git a/core/lib/Drupal/Core/Page/DefaultHtmlFragmentRenderer.php b/core/lib/Drupal/Core/Page/DefaultHtmlFragmentRenderer.php
index 164f7f5..74570e4 100644
--- a/core/lib/Drupal/Core/Page/DefaultHtmlFragmentRenderer.php
+++ b/core/lib/Drupal/Core/Page/DefaultHtmlFragmentRenderer.php
@@ -135,10 +135,10 @@ public function preparePage(HtmlPage $page, &$page_array) {
   /**
    * Apply the default meta tags to the page object.
    *
-   * @param \Drupal\Core\Page\HtmlPage $page
+   * @param \Drupal\Core\Page\HtmlMutableFragmentInterface $page
    *   The html page.
    */
-  protected function setDefaultMetaTags(HtmlPage $page) {
+  protected function setDefaultMetaTags(HtmlMutableFragmentInterface $page) {
     // Add default elements. Make sure the Content-Type comes first because the
     // IE browser may be vulnerable to XSS via encoding attacks from any content
     // that comes before this META tag, such as a TITLE tag.
diff --git a/core/lib/Drupal/Core/Page/HtmlFragment.php b/core/lib/Drupal/Core/Page/HtmlFragment.php
index a4e0e29..6d968b9 100644
--- a/core/lib/Drupal/Core/Page/HtmlFragment.php
+++ b/core/lib/Drupal/Core/Page/HtmlFragment.php
@@ -15,7 +15,7 @@
 /**
  * Basic mutable implementation of an HTML fragment.
  */
-class HtmlFragment implements CacheableInterface, HtmlFragmentInterface {
+class HtmlFragment implements CacheableInterface, HtmlMutableFragmentInterface {
 
   /**
    * An array of Link elements.
@@ -71,12 +71,7 @@ public function __construct($content = '', array $cache_info = array()) {
   }
 
   /**
-   * Adds a link element to the page.
-   *
-   * @param \Drupal\Core\Page\LinkElement $link
-   *   A link element to enqueue.
-   *
-   * @return $this
+   * {@inheritdoc}
    */
   public function addLinkElement(LinkElement $link) {
     $this->links[] = $link;
@@ -104,12 +99,7 @@ public function getFeedLinkElements() {
   }
 
   /**
-   * Adds a meta element to the page.
-   *
-   * @param \Drupal\Core\Page\MetaElement $meta
-   *   A meta element to add.
-   *
-   * @return $this
+   * {@inheritdoc}
    */
   public function addMetaElement(MetaElement $meta) {
     $this->metatags[] = $meta;
@@ -124,18 +114,7 @@ public function &getMetaElements() {
   }
 
   /**
-   * Sets the response content.
-   *
-   * This should be the bulk of the page content, and will ultimately be placed
-   * within the <body> tag in final HTML output.
-   *
-   * Valid types are strings, numbers, and objects that implement a __toString()
-   * method.
-   *
-   * @param mixed $content
-   *   The content for this fragment.
-   *
-   * @return $this
+   * {@inheritdoc}
    */
   public function setContent($content) {
     $this->content = $content;
@@ -150,24 +129,7 @@ public function getContent() {
   }
 
   /**
-   * Sets the title of this HtmlFragment.
-   *
-   * Handling of this title varies depending on what is consuming this
-   * HtmlFragment object. If it's a block, it may only be used as the block's
-   * title; if it's at the page level, it will be used in a number of places,
-   * including the html <head> title.
-   *
-   * @param string $title
-   *   Value to assign to the page title.
-   * @param int $output
-   *   (optional) normally should be left as Title::CHECK_PLAIN. Only set to
-   *   Title::PASS_THROUGH if you have already removed any possibly dangerous
-   *   code from $title using a function like
-   *   \Drupal\Component\Utility\String::checkPlain() or
-   *   \Drupal\Component\Utility\Xss::filterAdmin(). With this flag the string
-   *   will be passed through unchanged.
-   *
-   * @return $this
+   * {@inheritdoc}
    */
   public function setTitle($title, $output = Title::CHECK_PLAIN) {
     if ($output == Title::CHECK_PLAIN) {
diff --git a/core/lib/Drupal/Core/Page/HtmlMutableFragmentInterface.php b/core/lib/Drupal/Core/Page/HtmlMutableFragmentInterface.php
new file mode 100644
index 0000000..7f7e849
--- /dev/null
+++ b/core/lib/Drupal/Core/Page/HtmlMutableFragmentInterface.php
@@ -0,0 +1,75 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Core\Page\HtmlMutableFragmentInterface.
+ */
+
+namespace Drupal\Core\Page;
+
+use Drupal\Core\Utility\Title;
+
+/**
+ * Mutator interface for the domain object for a portion of an HTML page.
+ */
+interface HtmlMutableFragmentInterface extends HtmlFragmentInterface {
+
+  /**
+   * Adds a link element to the page.
+   *
+   * @param \Drupal\Core\Page\LinkElement $link
+   *   A link element to enqueue.
+   *
+   * @return $this
+   */
+  public function addLinkElement(LinkElement $link);
+
+  /**
+   * Adds a meta element to the page.
+   *
+   * @param \Drupal\Core\Page\MetaElement $meta
+   *   A meta element to add.
+   *
+   * @return $this
+   */
+  public function addMetaElement(MetaElement $meta);
+
+  /**
+   * Sets the response content.
+   *
+   * This should be the bulk of the page content, and will ultimately be placed
+   * within the <body> tag in final HTML output.
+   *
+   * Valid types are strings, numbers, and objects that implement a __toString()
+   * method.
+   *
+   * @param mixed $content
+   *   The content for this fragment.
+   *
+   * @return $this
+   */
+  public function setContent($content);
+
+  /**
+   * Sets the title of this HtmlFragment.
+   *
+   * Handling of this title varies depending on what is consuming this
+   * HtmlFragment object. If it's a block, it may only be used as the block's
+   * title; if it's at the page level, it will be used in a number of places,
+   * including the html <head> title.
+   *
+   * @param string $title
+   *   Value to assign to the page title.
+   * @param int $output
+   *   (optional) normally should be left as Title::CHECK_PLAIN. Only set to
+   *   Title::PASS_THROUGH if you have already removed any possibly dangerous
+   *   code from $title using a function like
+   *   \Drupal\Component\Utility\String::checkPlain() or
+   *   \Drupal\Component\Utility\Xss::filterAdmin(). With this flag the string
+   *   will be passed through unchanged.
+   *
+   * @return $this
+   */
+  public function setTitle($title, $output = Title::CHECK_PLAIN);
+
+}
diff --git a/core/lib/Drupal/Core/Page/RenderHtmlRendererInterface.php b/core/lib/Drupal/Core/Page/RenderHtmlRendererInterface.php
index 4807be9..466f287 100644
--- a/core/lib/Drupal/Core/Page/RenderHtmlRendererInterface.php
+++ b/core/lib/Drupal/Core/Page/RenderHtmlRendererInterface.php
@@ -16,15 +16,13 @@
 interface RenderHtmlRendererInterface {
 
   /**
-   * Converts a render array into a corresponding HtmlFragment object.
+   * Converts a render array into a corresponding HtmlMutableFragmentInterface.
    *
    * @param array $render_array
    *   The render array to convert.
    *
-   * @return \Drupal\Core\Page\HtmlFragment
+   * @return \Drupal\Core\Page\HtmlMutableFragmentInterface
    *   The equivalent HtmlFragment object.
-   *
-   * @todo Change this documentation once https://www.drupal.org/node/2339475 lands.
    */
   public function render(array $render_array);
 
-- 
1.7.9.5

