Issue #2057831 by damiankloip: Fixed Exposed filter blocks do not work anymore.

8.0.x
Nathaniel Catchpole 2013-08-08 13:59:18 +01:00
parent 503103058f
commit 917cd10a20
5 changed files with 224 additions and 113 deletions

View File

@ -7,13 +7,10 @@
namespace Drupal\views\Plugin\Block;
use Drupal\block\BlockBase;
use Drupal\Component\Annotation\Plugin;
use Drupal\Core\Annotation\Translation;
use Drupal\Core\Entity\EntityStorageControllerInterface;
use Drupal\Component\Utility\Xss;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\views\ViewExecutableFactory;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
@ -26,85 +23,7 @@ use Symfony\Component\DependencyInjection\ContainerInterface;
* derivative = "Drupal\views\Plugin\Derivative\ViewsBlock"
* )
*/
class ViewsBlock extends BlockBase implements ContainerFactoryPluginInterface {
/**
* The View executable object.
*
* @var \Drupal\views\ViewExecutable
*/
protected $view;
/**
* The display ID being used for this View.
*
* @var string
*/
protected $displayID;
/**
* Indicates whether the display was successfully set.
*
* @var bool
*/
protected $displaySet;
/**
* Constructs a Drupal\Component\Plugin\PluginBase object.
*
* @param array $configuration
* A configuration array containing information about the plugin instance.
* @param string $plugin_id
* The plugin_id for the plugin instance.
* @param array $plugin_definition
* The plugin implementation definition.
* @param \Drupal\views\ViewExecutableFactory $executable_factory
* The view executable factory.
* @param \Drupal\Core\Entity\EntityStorageControllerInterface $storage_controller
* The views storage controller.
*/
public function __construct(array $configuration, $plugin_id, array $plugin_definition, ViewExecutableFactory $executable_factory, EntityStorageControllerInterface $storage_controller) {
$this->pluginId = $plugin_id;
list($plugin, $delta) = explode(':', $this->getPluginId());
list($name, $this->displayID) = explode('-', $delta, 2);
// Load the view.
$view = $storage_controller->load($name);
$this->view = $executable_factory->get($view);
$this->displaySet = $this->view->setDisplay($this->displayID);
parent::__construct($configuration, $plugin_id, $plugin_definition);
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container, array $configuration, $plugin_id, array $plugin_definition) {
return new static(
$configuration, $plugin_id, $plugin_definition,
$container->get('views.executable'),
$container->get('plugin.manager.entity')->getStorageController('view')
);
}
/**
* Overrides \Drupal\block\BlockBase::access().
*/
public function access() {
return $this->view->access($this->displayID);
}
/**
* Overrides \Drupal\block\BlockBase::form().
*/
public function buildConfigurationForm(array $form, array &$form_state) {
$form = parent::buildConfigurationForm($form, $form_state);
// Set the default label to '' so the views internal title is used.
$form['label']['#default_value'] = '';
$form['label']['#access'] = FALSE;
return $form;
}
class ViewsBlock extends ViewsBlockBase {
/**
* {@inheritdoc}
@ -144,6 +63,8 @@ class ViewsBlock extends BlockBase implements ContainerFactoryPluginInterface {
if ($this->displaySet) {
return $this->view->display_handler->blockForm($this, $form, $form_state);
}
return array();
}
/**
@ -164,31 +85,6 @@ class ViewsBlock extends BlockBase implements ContainerFactoryPluginInterface {
}
}
/**
* Converts Views block content to a renderable array with contextual links.
*
* @param string|array $output
* An string|array representing the block. This will be modified to be a
* renderable array, containing the optional '#contextual_links' property (if
* there are any contextual links associated with the block).
* @param string $block_type
* The type of the block. If it's 'block' it's a regular views display,
* but 'exposed_filter' exist as well.
*/
protected function addContextualLinks(&$output, $block_type = 'block') {
// Do not add contextual links to an empty block.
if (!empty($output)) {
// Contextual links only work on blocks whose content is a renderable
// array, so if the block contains a string of already-rendered markup,
// convert it to an array.
if (is_string($output)) {
$output = array('#markup' => $output);
}
// Add the contextual links.
views_add_contextual_links($output, $block_type, $this->view, $this->displayID);
}
}
/**
* Generates a views block instance ID.
*

View File

@ -0,0 +1,124 @@
<?php
/**
* @file
* Contains \Drupal\views\Plugin\Block\ViewsBlockBase.
*/
namespace Drupal\views\Plugin\Block;
use Drupal\block\BlockBase;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\views\ViewExecutableFactory;
use Drupal\Core\Entity\EntityStorageControllerInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Base class for Views block plugins.
*/
abstract class ViewsBlockBase extends BlockBase implements ContainerFactoryPluginInterface {
/**
* The View executable object.
*
* @var \Drupal\views\ViewExecutable
*/
protected $view;
/**
* The display ID being used for this View.
*
* @var string
*/
protected $displayID;
/**
* Indicates whether the display was successfully set.
*
* @var bool
*/
protected $displaySet;
/**
* Constructs a Drupal\Component\Plugin\PluginBase object.
*
* @param array $configuration
* A configuration array containing information about the plugin instance.
* @param string $plugin_id
* The plugin_id for the plugin instance.
* @param array $plugin_definition
* The plugin implementation definition.
* @param \Drupal\views\ViewExecutableFactory $executable_factory
* The view executable factory.
* @param \Drupal\Core\Entity\EntityStorageControllerInterface $storage_controller
* The views storage controller.
*/
public function __construct(array $configuration, $plugin_id, array $plugin_definition, ViewExecutableFactory $executable_factory, EntityStorageControllerInterface $storage_controller) {
$this->pluginId = $plugin_id;
list($plugin, $delta) = explode(':', $this->getPluginId());
list($name, $this->displayID) = explode('-', $delta, 2);
// Load the view.
$view = $storage_controller->load($name);
$this->view = $executable_factory->get($view);
$this->displaySet = $this->view->setDisplay($this->displayID);
parent::__construct($configuration, $plugin_id, $plugin_definition);
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container, array $configuration, $plugin_id, array $plugin_definition) {
return new static(
$configuration, $plugin_id, $plugin_definition,
$container->get('views.executable'),
$container->get('plugin.manager.entity')->getStorageController('view')
);
}
/**
* {@inheritdoc}
*/
public function access() {
return $this->view->access($this->displayID);
}
/**
* {@inheritdoc}
*/
public function buildConfigurationForm(array $form, array &$form_state) {
$form = parent::buildConfigurationForm($form, $form_state);
// Set the default label to '' so the views internal title is used.
$form['label']['#default_value'] = '';
$form['label']['#access'] = FALSE;
return $form;
}
/**
* Converts Views block content to a renderable array with contextual links.
*
* @param string|array $output
* An string|array representing the block. This will be modified to be a
* renderable array, containing the optional '#contextual_links' property (if
* there are any contextual links associated with the block).
* @param string $block_type
* The type of the block. If it's 'block' it's a regular views display,
* but 'exposed_filter' exist as well.
*/
protected function addContextualLinks(&$output, $block_type = 'block') {
// Do not add contextual links to an empty block.
if (!empty($output)) {
// Contextual links only work on blocks whose content is a renderable
// array, so if the block contains a string of already-rendered markup,
// convert it to an array.
if (is_string($output)) {
$output = array('#markup' => $output);
}
// Add the contextual links.
views_add_contextual_links($output, $block_type, $this->view, $this->displayID);
}
}
}

View File

@ -20,7 +20,7 @@ use Drupal\Core\Annotation\Translation;
* derivative = "Drupal\views\Plugin\Derivative\ViewsExposedFilterBlock"
* )
*/
class ViewsExposedFilterBlock extends ViewsBlock {
class ViewsExposedFilterBlock extends ViewsBlockBase {
/**
* {@inheritdoc}
@ -31,7 +31,6 @@ class ViewsExposedFilterBlock extends ViewsBlock {
// contextual links.
$this->addContextualLinks($output, 'exposed_filter');
$this->view->destroy();
return $output;
}

View File

@ -8,6 +8,8 @@
namespace Drupal\views\Tests\Plugin;
use Drupal\views\Tests\ViewTestBase;
use Drupal\views\ViewExecutable;
use Drupal\views\Views;
/**
* Tests exposed forms.
@ -19,14 +21,14 @@ class ExposedFormTest extends ViewTestBase {
*
* @var array
*/
public static $testViews = array('test_reset_button');
public static $testViews = array('test_reset_button', 'test_exposed_block');
/**
* Modules to enable.
*
* @var array
*/
public static $modules = array('views_ui');
public static $modules = array('views_ui', 'block');
public static function getInfo() {
return array(
@ -102,11 +104,45 @@ class ExposedFormTest extends ViewTestBase {
$output = $exposed_form->renderExposedForm();
$this->drupalSetContent(drupal_render($output));
$expected_id = drupal_clean_css_identifier('views-exposed-form-' . $view->storage->id() . '-' . $view->current_display);
$this->assertFieldByXpath('//form/@id', $expected_id, 'Expected form ID found.');
$this->assertFieldByXpath('//form/@id', $this->getExpectedExposedFormId($view), 'Expected form ID found.');
$expected_action = url($view->display_handler->getUrl());
$this->assertFieldByXPath('//form/@action', $expected_action, 'The expected value for the action attribute was found.');
}
/**
* Tests the exposed block functionality.
*/
public function testExposedBlock() {
$view = Views::getView('test_exposed_block');
$view->setDisplay('page_1');
$block = $this->drupalPlaceBlock('views_exposed_filter_block:test_exposed_block-page_1');
$this->drupalGet('test_exposed_block');
// Test there is an exposed form in a block.
$xpath = $this->buildXPathQuery('//div[@id=:id]/div/form/@id', array(':id' => 'block-' . $block->get('machine_name')));
$this->assertFieldByXpath($xpath, $this->getExpectedExposedFormId($view), 'Expected form found in views block.');
// Test there is not an exposed form in the view page content area.
$xpath = $this->buildXPathQuery('//div[@class="view-content"]/form/@id', array(':id' => 'block-' . $block->get('machine_name')));
$this->assertNoFieldByXpath($xpath, $this->getExpectedExposedFormId($view), 'No exposed form found in views content region.');
// Test there is only one views exposed form on the page.
$elements = $this->xpath('//form[@id=:id]', array(':id' => $this->getExpectedExposedFormId($view)));
$this->assertEqual(count($elements), 1, 'One exposed form block found.');
}
/**
* Returns a views exposed form ID.
*
* @param \Drupal\views\ViewExecutable $view
* The view to create an ID for.
*
* @return string
* The form ID.
*/
protected function getExpectedExposedFormId(ViewExecutable $view) {
return drupal_clean_css_identifier('views-exposed-form-' . $view->storage->id() . '-' . $view->current_display);
}
}

View File

@ -0,0 +1,56 @@
base_table: node
core: '8'
description: ''
status: '1'
display:
default:
display_options:
access:
type: none
cache:
type: none
exposed_form:
options:
reset_button: '1'
type: basic
filters:
type:
expose:
identifier: type
label: 'Content: Type'
operator_id: type_op
reduce: '0'
exposed: '1'
field: type
id: type
table: node_field_data
plugin_id: node_type
provider: views
pager:
type: full
query:
options:
query_comment: '0'
type: views_query
style:
type: default
row:
type: 'entity:node'
options:
comments: '0'
links: '1'
display_plugin: default
display_title: Master
id: default
position: '0'
page_1:
display_options:
path: test_exposed_block
exposed_block: '1'
display_plugin: page
display_title: Page
id: page_1
position: '0'
label: ''
id: test_exposed_block
tag: ''