From da4a1df3b747b52f342678e3865761e750b20824 Mon Sep 17 00:00:00 2001
From: webchick <webchick@24967.no-reply.drupal.org>
Date: Fri, 6 Dec 2013 14:33:20 -0800
Subject: [PATCH] Issue #1957276 by dawehner, xjm, yoroy, yoroy, Bojhan,
 tim.plunkett: Let users set the block instance title for Views blocks in the
 Block UI.

---
 .../lib/Drupal/block/Annotation/Block.php     |  2 +-
 .../block/lib/Drupal/block/Entity/Block.php   |  8 +-
 .../block/Tests/Views/DisplayBlockTest.php    | 31 +++++++
 .../Drupal/views/Plugin/Block/ViewsBlock.php  | 13 ++-
 .../views/Plugin/Block/ViewsBlockBase.php     | 84 ++++++++++++++++++-
 .../Tests/Plugin/Block/ViewsBlockTest.php     | 12 ++-
 6 files changed, 140 insertions(+), 10 deletions(-)

diff --git a/core/modules/block/lib/Drupal/block/Annotation/Block.php b/core/modules/block/lib/Drupal/block/Annotation/Block.php
index 62541ab14916..64987e6bef57 100644
--- a/core/modules/block/lib/Drupal/block/Annotation/Block.php
+++ b/core/modules/block/lib/Drupal/block/Annotation/Block.php
@@ -30,6 +30,6 @@ class Block extends Plugin {
    *
    * @ingroup plugin_translatable
    */
-  public $admin_label;
+  public $admin_label = '';
 
 }
diff --git a/core/modules/block/lib/Drupal/block/Entity/Block.php b/core/modules/block/lib/Drupal/block/Entity/Block.php
index 44fa16904933..02b1d766c355 100644
--- a/core/modules/block/lib/Drupal/block/Entity/Block.php
+++ b/core/modules/block/lib/Drupal/block/Entity/Block.php
@@ -121,7 +121,13 @@ public function getPlugin() {
    */
   public function label($langcode = NULL) {
     $settings = $this->get('settings');
-    return $settings['label'];
+    if ($settings['label']) {
+      return $settings['label'];
+    }
+    else {
+      $definition = $this->getPlugin()->getPluginDefinition();
+      return $definition['admin_label'];
+    }
   }
 
   /**
diff --git a/core/modules/block/lib/Drupal/block/Tests/Views/DisplayBlockTest.php b/core/modules/block/lib/Drupal/block/Tests/Views/DisplayBlockTest.php
index 5d90a05692d7..fd9d254717f5 100644
--- a/core/modules/block/lib/Drupal/block/Tests/Views/DisplayBlockTest.php
+++ b/core/modules/block/lib/Drupal/block/Tests/Views/DisplayBlockTest.php
@@ -221,6 +221,37 @@ public function testViewsBlockForm() {
 
     $config = $block->getPlugin()->getConfiguration();
     $this->assertEqual(5, $config['items_per_page'], "'Items per page' is properly saved.");
+
+    // Tests the override of the label capability.
+    $edit = array();
+    $edit['settings[views_label_checkbox]'] = 1;
+    $edit['settings[views_label]'] = 'Custom title';
+    $this->drupalPostForm('admin/structure/block/add/views_block:test_view_block-block_1/' . $default_theme, $edit, t('Save block'));
+
+    $block = $storage->load('views_block__test_view_block_block_1_5');
+    $config = $block->getPlugin()->getConfiguration();
+    $this->assertEqual('Custom title', $config['views_label'], "'Label' is properly saved.");
+  }
+
+  /**
+   * Tests the actual rendering of the views block.
+   */
+  public function testBlockRendering() {
+    // Create a block and set a custom title.
+    $block = $this->drupalPlaceBlock('views_block:test_view_block-block_1', array('title' => 'test_view_block-block_1:1', 'views_label' => 'Custom title'));
+    $this->drupalGet('');
+
+    $result = $this->xpath('//div[contains(@class, "region-sidebar-first")]/div[contains(@class, "block-views")]/h2');
+    $this->assertEqual((string) $result[0], 'Custom title');
+
+    // Don't override the title anymore.
+    $plugin = $block->getPlugin();
+    $plugin->setConfigurationValue('views_label', '');
+    $block->save();
+
+    $this->drupalGet('');
+    $result = $this->xpath('//div[contains(@class, "region-sidebar-first")]/div[contains(@class, "block-views")]/h2');
+    $this->assertEqual((string) $result[0], 'test_view_block');
   }
 
   /**
diff --git a/core/modules/views/lib/Drupal/views/Plugin/Block/ViewsBlock.php b/core/modules/views/lib/Drupal/views/Plugin/Block/ViewsBlock.php
index 3f3fe30e69c2..dac57a0c0107 100644
--- a/core/modules/views/lib/Drupal/views/Plugin/Block/ViewsBlock.php
+++ b/core/modules/views/lib/Drupal/views/Plugin/Block/ViewsBlock.php
@@ -32,7 +32,13 @@ public function build() {
 
     if ($output = $this->view->executeDisplay($this->displayID)) {
       // Set the label to the title configured in the view.
-      $this->configuration['label'] = Xss::filterAdmin($this->view->getTitle());
+      if (empty($this->configuration['views_label'])) {
+        $this->configuration['label'] = Xss::filterAdmin($this->view->getTitle());
+      }
+      else {
+        $this->configuration['label'] = $this->configuration['views_label'];
+      }
+      $this->configuration['label_display'] = TRUE;
       // Before returning the block output, convert it to a renderable array
       // with contextual links.
       $this->addContextualLinks($output);
@@ -46,10 +52,10 @@ public function build() {
    * {@inheritdoc}
    */
   public function defaultConfiguration() {
-    $settings = array();
+    $settings = parent::defaultConfiguration();
 
     if ($this->displaySet) {
-      return $this->view->display_handler->blockSettings($settings);
+      $settings += $this->view->display_handler->blockSettings($settings);
     }
 
     return $settings;
@@ -79,6 +85,7 @@ public function blockValidate($form, &$form_state) {
    * {@inheritdoc}
    */
   public function blockSubmit($form, &$form_state) {
+    parent::blockSubmit($form, $form_state);
     if ($this->displaySet) {
       $this->view->display_handler->blockSubmit($this, $form, $form_state);
     }
diff --git a/core/modules/views/lib/Drupal/views/Plugin/Block/ViewsBlockBase.php b/core/modules/views/lib/Drupal/views/Plugin/Block/ViewsBlockBase.php
index e20f146760e2..572c253570b9 100644
--- a/core/modules/views/lib/Drupal/views/Plugin/Block/ViewsBlockBase.php
+++ b/core/modules/views/lib/Drupal/views/Plugin/Block/ViewsBlockBase.php
@@ -41,7 +41,14 @@ abstract class ViewsBlockBase extends BlockBase implements ContainerFactoryPlugi
   protected $displaySet;
 
   /**
-   * Constructs a Drupal\Component\Plugin\PluginBase object.
+   * The current user.
+   *
+   * @var \Drupal\Core\Session\AccountInterface
+   */
+  protected $user;
+
+  /**
+   * Constructs a \Drupal\views\Plugin\Block\ViewsBlockBase object.
    *
    * @param array $configuration
    *   A configuration array containing information about the plugin instance.
@@ -53,8 +60,10 @@ abstract class ViewsBlockBase extends BlockBase implements ContainerFactoryPlugi
    *   The view executable factory.
    * @param \Drupal\Core\Entity\EntityStorageControllerInterface $storage_controller
    *   The views storage controller.
+   * @param \Drupal\Core\Session\AccountInterface $user
+   *   The current user.
    */
-  public function __construct(array $configuration, $plugin_id, array $plugin_definition, ViewExecutableFactory $executable_factory, EntityStorageControllerInterface $storage_controller) {
+  public function __construct(array $configuration, $plugin_id, array $plugin_definition, ViewExecutableFactory $executable_factory, EntityStorageControllerInterface $storage_controller, AccountInterface $user) {
     $this->pluginId = $plugin_id;
     list($plugin, $delta) = explode(':', $this->getPluginId());
     list($name, $this->displayID) = explode('-', $delta, 2);
@@ -62,6 +71,7 @@ public function __construct(array $configuration, $plugin_id, array $plugin_defi
     $view = $storage_controller->load($name);
     $this->view = $executable_factory->get($view);
     $this->displaySet = $this->view->setDisplay($this->displayID);
+    $this->user = $user;
 
     parent::__construct($configuration, $plugin_id, $plugin_definition);
   }
@@ -73,7 +83,8 @@ public static function create(ContainerInterface $container, array $configuratio
     return new static(
       $configuration, $plugin_id, $plugin_definition,
       $container->get('views.executable'),
-      $container->get('entity.manager')->getStorageController('view')
+      $container->get('entity.manager')->getStorageController('view'),
+      $container->get('current_user')
     );
   }
 
@@ -84,6 +95,16 @@ public function access(AccountInterface $account) {
     return $this->view->access($this->displayID);
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public function defaultConfiguration() {
+    $settings = array();
+    $settings['views_label'] = '';
+
+    return $settings;
+  }
+
   /**
    * {@inheritdoc}
    */
@@ -94,9 +115,66 @@ public function buildConfigurationForm(array $form, array &$form_state) {
     $form['label']['#default_value'] = '';
     $form['label']['#access'] = FALSE;
 
+    // Unset the machine_name provided by BlockFormController.
+    unset($form['id']['#machine_name']['source']);
+    // Prevent users from changing the auto-generated block machine_name.
+    $form['id']['#access'] = FALSE;
+    $form['#pre_render'][] = '\Drupal\views\Plugin\views\PluginBase::preRenderAddFieldsetMarkup';
+
+    // Allow to override the label on the actual page.
+    $form['views_label_checkbox'] = array(
+      '#type' => 'checkbox',
+      '#title' => $this->t('Override title'),
+      '#default_value' => !empty($this->configuration['views_label']),
+    );
+
+    $form['views_label_fieldset'] = array(
+      '#type' => 'fieldset',
+      '#states' => array(
+        'visible' => array(
+          array(
+            ':input[name="settings[views_label_checkbox]"]' => array('checked' => TRUE),
+          ),
+        ),
+      ),
+    );
+
+    $form['views_label'] = array(
+      '#title' => $this->t('Title'),
+      '#type' => 'textfield',
+      '#default_value' => $this->configuration['views_label'] ?: $this->view->getTitle(),
+      '#states' => array(
+        'visible' => array(
+          array(
+            ':input[name="settings[views_label_checkbox]"]' => array('checked' => TRUE),
+          ),
+        ),
+      ),
+      '#fieldset' => 'views_label_fieldset',
+    );
+
+    if ($this->view->storage->access('edit') && \Drupal::moduleHandler()->moduleExists('views_ui')) {
+      $form['views_label']['#description'] = $this->t('Changing the title here means it cannot be dynamically altered anymore. (Try changing it directly in <a href="@url">@name</a>.)', array('@url' => \Drupal::url('views_ui.edit_display', array('view' => $this->view->storage->id(), 'display_id' => $this->displayID)), '@name' => $this->view->storage->label()));
+    }
+    else {
+      $form['views_label']['#description'] = $this->t('Changing the title here means it cannot be dynamically altered anymore.');
+    }
+
     return $form;
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public function blockSubmit($form, &$form_state) {
+    if (!empty($form_state['values']['views_label_checkbox'])) {
+      $this->configuration['views_label'] = $form_state['values']['views_label'];
+    }
+    else {
+      $this->configuration['views_label'] = '';
+    }
+  }
+
   /**
    * Converts Views block content to a renderable array with contextual links.
    *
diff --git a/core/modules/views/tests/Drupal/views/Tests/Plugin/Block/ViewsBlockTest.php b/core/modules/views/tests/Drupal/views/Tests/Plugin/Block/ViewsBlockTest.php
index 89e46aa71421..bcfd88b74630 100644
--- a/core/modules/views/tests/Drupal/views/Tests/Plugin/Block/ViewsBlockTest.php
+++ b/core/modules/views/tests/Drupal/views/Tests/Plugin/Block/ViewsBlockTest.php
@@ -54,6 +54,13 @@ class ViewsBlockTest extends UnitTestCase {
    */
   protected $storageController;
 
+  /**
+   * The mocked user account.
+   *
+   * @var \Drupal\Core\Session\AccountInterface|\PHPUnit_Framework_MockObject_MockObject
+   */
+  protected $account;
+
   public static function getInfo() {
     return array(
       'name' => ' Block: Views block',
@@ -101,6 +108,7 @@ protected function setUp() {
       ->method('load')
       ->with('test_view')
       ->will($this->returnValue($this->view));
+    $this->account = $this->getMock('Drupal\Core\Session\AccountInterface');
   }
 
   /**
@@ -120,7 +128,7 @@ public function testBuild() {
     $config = array();
     $definition = array();
     $definition['module'] = 'views';
-    $plugin = new ViewsBlock($config, $block_id, $definition, $this->executableFactory, $this->storageController);
+    $plugin = new ViewsBlock($config, $block_id, $definition, $this->executableFactory, $this->storageController, $this->account);
 
     $this->assertEquals($build, $plugin->build());
   }
@@ -141,7 +149,7 @@ public function testBuildFailed() {
     $config = array();
     $definition = array();
     $definition['module'] = 'views';
-    $plugin = new ViewsBlock($config, $block_id, $definition, $this->executableFactory, $this->storageController);
+    $plugin = new ViewsBlock($config, $block_id, $definition, $this->executableFactory, $this->storageController, $this->account);
 
     $this->assertEquals(array(), $plugin->build());
   }
-- 
GitLab