Issue #1217394 by dawehner, jsacksick, MichaelCole, rutcreate, damiankloip: Fixed "Display even if view has no result" not working.

8.0.x
Alex Pott 2013-09-26 16:19:29 +02:00
parent 00c06fcfed
commit 2a43a1bd8b
6 changed files with 178 additions and 6 deletions

View File

@ -49,6 +49,7 @@ class Block extends DisplayPluginBase {
$options['block_description'] = array('default' => '', 'translatable' => TRUE);
$options['block_category'] = array('default' => 'Views', 'translatable' => TRUE);
$options['block_caching'] = array('default' => DRUPAL_NO_CACHE);
$options['block_hide_empty'] = array('default' => FALSE);
$options['allow'] = array(
'contains' => array(
@ -83,11 +84,12 @@ class Block extends DisplayPluginBase {
// Prior to this being called, the $view should already be set to this
// display, and arguments should be set on the view.
$element = $this->view->render();
if (!empty($this->view->result) || $this->getOption('empty') || !empty($this->view->style_plugin->definition['even empty'])) {
if ($this->outputIsEmpty() && $this->getOption('block_hide_empty') && empty($this->view->style_plugin->definition['even empty'])) {
return array();
}
else {
return $element;
}
return array();
}
/**
@ -137,6 +139,12 @@ class Block extends DisplayPluginBase {
'title' => t('Block caching'),
'value' => $types[$this->getCacheType()],
);
$options['block_hide_empty'] = array(
'category' => 'other',
'title' => t('Hide block if the view output is empty'),
'value' => $this->getOption('block_hide_empty') ? t('Hide') : t('Show'),
);
}
/**
@ -200,6 +208,16 @@ class Block extends DisplayPluginBase {
'#default_value' => $this->getCacheType(),
);
break;
case 'block_hide_empty':
$form['#title'] .= t('Block empty settings');
$form['block_hide_empty'] = array(
'#title' => t('Hide block if no result/empty text'),
'#type' => 'checkbox',
'#description' => t('Hide the block if there is no result and no empty text and no header/footer which is shown on empty result'),
'#default_value' => $this->getOption('block_hide_empty'),
);
break;
case 'exposed_form_options':
$this->view->initHandlers();
if (!$this->usesExposed() && parent::usesExposed()) {
@ -237,6 +255,7 @@ class Block extends DisplayPluginBase {
case 'block_category':
case 'block_caching':
case 'allow':
case 'block_hide_empty':
$this->setOption($form_state['section'], $form_state['values'][$form_state['section']]);
break;
}

View File

@ -106,6 +106,19 @@ abstract class AreaPluginBase extends HandlerBase {
*/
public abstract function render($empty = FALSE);
/**
* Does that area have nothing to show.
*
* This method should be overridden by more complex handlers where the output
* is not static and maybe itself be empty if it's rendered.
*
* @return bool
* Return TRUE if the area is empty, else FALSE.
*/
public function isEmpty() {
return empty($this->options['empty']);
}
/**
* Area handlers shouldn't have groupby.
*/

View File

@ -18,6 +18,16 @@ use Drupal\Component\Annotation\PluginID;
*/
class View extends AreaPluginBase {
/**
* Stores whether the embedded view is actually empty.
*
* @var bool
*/
protected $isEmpty;
/**
* {@inheritdoc}
*/
protected function defineOptions() {
$options = parent::defineOptions();
@ -77,14 +87,28 @@ class View extends AreaPluginBase {
}
else {
if (!empty($this->options['inherit_arguments']) && !empty($this->view->args)) {
return $view->preview($display_id, $this->view->args);
$output = $view->preview($display_id, $this->view->args);
}
else {
return $view->preview($display_id);
$output = $view->preview($display_id);
}
$this->isEmpty = $view->display_handler->outputIsEmpty();
return $output;
}
}
return array();
}
/**
* {@inheritdoc}
*/
public function isEmpty() {
if (isset($this->isEmpty)) {
return $this->isEmpty;
}
else {
return parent::isEmpty();
}
}
}

View File

@ -2723,6 +2723,34 @@ abstract class DisplayPluginBase extends PluginBase {
return TRUE;
}
/**
* Is the output of the view empty.
*
* If a view has no result and neither the empty, nor the footer nor the header
* does show anything return FALSE.
*
* @return bool
* Returns TRUE if the output is empty, else FALSE.
*/
public function outputIsEmpty() {
if (!empty($this->view->result)) {
return FALSE;
}
// Check whether all of the area handlers are empty.
foreach (array('empty', 'footer', 'header') as $type) {
$handlers = $this->getHandlers($type);
foreach ($handlers as $handler) {
// If one is not empty, return FALSE now.
if (!$handler->isEmpty()) {
return FALSE;
}
}
}
return TRUE;
}
/**
* Provide the block system with any exposed widget blocks for this display.
*/

View File

@ -7,6 +7,7 @@
namespace Drupal\views\Tests\Plugin;
use Drupal\views\Views;
use Drupal\views_test_data\Plugin\views\display\DisplayTest as DisplayTestPlugin;
/**
@ -19,7 +20,7 @@ class DisplayTest extends PluginTestBase {
*
* @var array
*/
public static $testViews = array('test_filter_groups', 'test_get_attach_displays', 'test_view', 'test_display_more', 'test_display_invalid');
public static $testViews = array('test_filter_groups', 'test_get_attach_displays', 'test_view', 'test_display_more', 'test_display_invalid', 'test_display_empty');
/**
* Modules to enable.
@ -273,4 +274,47 @@ class DisplayTest extends PluginTestBase {
$this->assertNoBlockAppears($block);
}
/**
* Tests the outputIsEmpty method on the display.
*/
public function testOutputIsEmpty() {
$view = Views::getView('test_display_empty');
$this->executeView($view);
$this->assertTrue(count($view->result) > 0, 'Ensure the result of the view is not empty.');
$this->assertFalse($view->display_handler->outputIsEmpty(), 'Ensure the view output is marked as not empty.');
$view->destroy();
// Add a filter, so the view result is empty.
$view->setDisplay('default');
$item = array(
'table' => 'views_test_data',
'field' => 'id',
'id' => 'id',
'value' => array('value' => 7297)
);
$view->setItem('default', 'filter', 'id', $item);
$this->executeView($view);
$this->assertFalse(count($view->result), 'Ensure the result of the view is empty.');
$this->assertFalse($view->display_handler->outputIsEmpty(), 'Ensure the view output is marked as not empty, because the empty text still appears.');
$view->destroy();
// Remove the empty area, but mark the header area to still appear.
$view->removeItem('default', 'empty', 'area');
$item = $view->getItem('default', 'header', 'area');
$item['empty'] = TRUE;
$view->setItem('default', 'header', 'area', $item);
$this->executeView($view);
$this->assertFalse(count($view->result), 'Ensure the result of the view is empty.');
$this->assertFalse($view->display_handler->outputIsEmpty(), 'Ensure the view output is marked as not empty, because the header text still appears.');
$view->destroy();
// Hide the header on empty results.
$item = $view->getItem('default', 'header', 'area');
$item['empty'] = FALSE;
$view->setItem('default', 'header', 'area', $item);
$this->executeView($view);
$this->assertFalse(count($view->result), 'Ensure the result of the view is empty.');
$this->assertTrue($view->display_handler->outputIsEmpty(), 'Ensure the view output is marked as empty.');
}
}

View File

@ -0,0 +1,44 @@
base_table: views_test_data
core: '8'
description: ''
status: '1'
display:
default:
display_options:
defaults:
fields: '0'
pager: '0'
pager_options: '0'
sorts: '0'
fields:
id:
field: id
id: id
relationship: none
table: views_test_data
plugin_id: numeric
pager:
options:
offset: '0'
type: none
pager_options: { }
header:
area:
field: area
id: area
table: views
plugin_id: text
empty:
area:
field: area
id: area
table: views
plugin_id: text
display_plugin: default
display_title: Master
id: default
position: '0'
label: ''
langcode: en
id: test_display_empty
tag: ''