From 0cbd30d5d62037b97d7ee3edebbc583aba1d5019 Mon Sep 17 00:00:00 2001
From: Nathaniel Catchpole <catch@35733.no-reply.drupal.org>
Date: Tue, 19 Apr 2016 17:32:54 +0900
Subject: [PATCH] Issue #2707109 by alexpott, jhodgdon: Help block should not
 be displayed when hook_help() implementations return an empty string

---
 .../help/src/Plugin/Block/HelpBlock.php       | 42 +++++-------------
 core/modules/help/src/Tests/HelpBlockTest.php | 44 +++++++++++++++++++
 .../help_page_test/help_page_test.module      |  5 +++
 .../help_page_test/help_page_test.routing.yml | 13 ++++++
 .../src/HelpPageTestController.php            | 30 +++++++++++++
 5 files changed, 102 insertions(+), 32 deletions(-)
 create mode 100644 core/modules/help/src/Tests/HelpBlockTest.php
 create mode 100644 core/modules/help/tests/modules/help_page_test/help_page_test.routing.yml
 create mode 100644 core/modules/help/tests/modules/help_page_test/src/HelpPageTestController.php

diff --git a/core/modules/help/src/Plugin/Block/HelpBlock.php b/core/modules/help/src/Plugin/Block/HelpBlock.php
index 4e6c775826aa..cf6467effa08 100644
--- a/core/modules/help/src/Plugin/Block/HelpBlock.php
+++ b/core/modules/help/src/Plugin/Block/HelpBlock.php
@@ -80,46 +80,24 @@ public static function create(ContainerInterface $container, array $configuratio
   }
 
   /**
-   * Returns the help associated with the active menu item.
-   *
-   * @param \Symfony\Component\HttpFoundation\Request $request
-   *   The current request.
-   *
-   * @return array|string
-   *   Render array or string containing the help of the matched route item.
+   * {@inheritdoc}
    */
-  protected function getActiveHelp(Request $request) {
+  public function build() {
     // Do not show on a 403 or 404 page.
-    if ($request->attributes->has('exception')) {
-      return '';
+    if ($this->request->attributes->has('exception')) {
+      return [];
     }
 
     $help = $this->moduleHandler->invokeAll('help', array($this->routeMatch->getRouteName(), $this->routeMatch));
     $build = [];
-    foreach ($help as $item) {
-      if (!is_array($item)) {
-        $item = ['#markup' => $item];
-      }
-      $build[] = $item;
-    }
 
-    return $build;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function build() {
-    $help = $this->getActiveHelp($this->request);
-    if (!$help) {
-      return [];
-    }
-    elseif (!is_array($help)) {
-      return ['#markup' => $help];
-    }
-    else {
-      return $help;
+    // Remove any empty strings from $help.
+    foreach (array_filter($help) as $item) {
+      // Convert strings to #markup render arrays so that they will XSS admin
+      // filtered.
+      $build[] = is_array($item) ? $item : ['#markup' => $item];
     }
+    return $build;
   }
 
   /**
diff --git a/core/modules/help/src/Tests/HelpBlockTest.php b/core/modules/help/src/Tests/HelpBlockTest.php
new file mode 100644
index 000000000000..3a7a1723b0a9
--- /dev/null
+++ b/core/modules/help/src/Tests/HelpBlockTest.php
@@ -0,0 +1,44 @@
+<?php
+
+namespace Drupal\help\Tests;
+
+use Drupal\simpletest\WebTestBase;
+
+/**
+ * Tests display of help block.
+ *
+ * @group help
+ */
+class HelpBlockTest extends WebTestBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public static $modules = ['help', 'help_page_test', 'block'];
+
+  /**
+   * The help block instance.
+   *
+   * @var \Drupal\block\Entity\Block
+   */
+  protected $helpBlock;
+
+  protected function setUp() {
+    parent::setUp();
+    $this->helpBlock = $this->placeBlock('help_block');
+  }
+
+  /**
+   * Logs in users, tests help pages.
+   */
+  public function testHelp() {
+    $this->drupalGet('help_page_test/has_help');
+    $this->assertText(t('I have help!'));
+    $this->assertText($this->helpBlock->label());
+
+    $this->drupalGet('help_page_test/no_help');
+    // The help block should not appear when there is no help.
+    $this->assertNoText($this->helpBlock->label());
+  }
+
+}
diff --git a/core/modules/help/tests/modules/help_page_test/help_page_test.module b/core/modules/help/tests/modules/help_page_test/help_page_test.module
index 68639a8c8b3d..2ad72255a837 100644
--- a/core/modules/help/tests/modules/help_page_test/help_page_test.module
+++ b/core/modules/help/tests/modules/help_page_test/help_page_test.module
@@ -17,6 +17,11 @@ function help_page_test_help($route_name, RouteMatchInterface $route_match) {
       // Make the help text conform to core standards. See
       // \Drupal\system\Tests\Module\InstallUninstallTest::assertHelp().
       return t('Read the <a href=":url">online documentation for the Help Page Test module</a>.', [':url' => 'http://www.example.com']);
+    case 'help_page_test.has_help':
+      return t('I have help!');
   }
 
+  // Ensure that hook_help() can return an empty string and not cause the block
+  // to display.
+  return '';
 }
diff --git a/core/modules/help/tests/modules/help_page_test/help_page_test.routing.yml b/core/modules/help/tests/modules/help_page_test/help_page_test.routing.yml
new file mode 100644
index 000000000000..7450e58869cd
--- /dev/null
+++ b/core/modules/help/tests/modules/help_page_test/help_page_test.routing.yml
@@ -0,0 +1,13 @@
+help_page_test.has_help:
+  path: '/help_page_test/has_help'
+  defaults:
+    _controller: '\Drupal\help_page_test\HelpPageTestController::hasHelp'
+  requirements:
+    _access: 'TRUE'
+
+help_page_test.no_help:
+  path: '/help_page_test/no_help'
+  defaults:
+    _controller: '\Drupal\help_page_test\HelpPageTestController::noHelp'
+  requirements:
+    _access: 'TRUE'
diff --git a/core/modules/help/tests/modules/help_page_test/src/HelpPageTestController.php b/core/modules/help/tests/modules/help_page_test/src/HelpPageTestController.php
new file mode 100644
index 000000000000..02c4e65fcd54
--- /dev/null
+++ b/core/modules/help/tests/modules/help_page_test/src/HelpPageTestController.php
@@ -0,0 +1,30 @@
+<?php
+
+namespace Drupal\help_page_test;
+
+/**
+ * Provides controllers for testing the help block.
+ */
+class HelpPageTestController {
+
+  /**
+   * Provides a route with help.
+   *
+   * @return array
+   *   A render array.
+   */
+  public function hasHelp() {
+    return ['#markup' => 'A route with help.'];
+  }
+
+  /**
+   * Provides a route with no help.
+   *
+   * @return array
+   *   A render array.
+   */
+  public function noHelp() {
+    return ['#markup' => 'A route without help.'];
+  }
+
+}
-- 
GitLab