diff --git a/core/modules/block/lib/Drupal/block/Plugin/views/display/Block.php b/core/modules/block/lib/Drupal/block/Plugin/views/display/Block.php index 4a3bf10..c65f341 100644 --- a/core/modules/block/lib/Drupal/block/Plugin/views/display/Block.php +++ b/core/modules/block/lib/Drupal/block/Plugin/views/display/Block.php @@ -42,6 +42,7 @@ protected function defineOptions() { $options['block_description'] = array('default' => '', 'translatable' => TRUE); $options['block_caching'] = array('default' => DRUPAL_NO_CACHE); + $options['block_hide_empty'] = array('default' => FALSE); return $options; } @@ -53,7 +54,7 @@ public function execute() { // 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->getOption('block_hide_empty') && !$this->outputIsEmpty()) || !empty($this->view->style_plugin->definition['even empty'])) { return drupal_render($element); } } @@ -91,6 +92,12 @@ public function optionsSummary(&$categories, &$options) { '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'), + ); } /** @@ -145,6 +152,15 @@ public function buildOptionsForm(&$form, &$form_state) { '#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'), + '#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()) { @@ -164,10 +180,9 @@ public function submitOptionsForm(&$form, &$form_state) { parent::submitOptionsForm($form, $form_state); switch ($form_state['section']) { case 'block_description': - $this->setOption('block_description', $form_state['values']['block_description']); - break; case 'block_caching': - $this->setOption('block_caching', $form_state['values']['block_caching']); + case 'block_hide_empty': + $this->setOption($form_state['section'], $form_state['values'][$form_state['section']]); break; } } diff --git a/core/modules/views/lib/Drupal/views/Plugin/views/area/AreaPluginBase.php b/core/modules/views/lib/Drupal/views/Plugin/views/area/AreaPluginBase.php index a8cfb8a..6efb3b7 100644 --- a/core/modules/views/lib/Drupal/views/Plugin/views/area/AreaPluginBase.php +++ b/core/modules/views/lib/Drupal/views/Plugin/views/area/AreaPluginBase.php @@ -161,6 +161,19 @@ public function preRender(array $results) { public abstract function render($empty = FALSE); /** + * Is the area empty. + * + * 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. */ public function usesGroupBy() { diff --git a/core/modules/views/lib/Drupal/views/Plugin/views/area/View.php b/core/modules/views/lib/Drupal/views/Plugin/views/area/View.php index 26cce16..1eb5a34 100644 --- a/core/modules/views/lib/Drupal/views/Plugin/views/area/View.php +++ b/core/modules/views/lib/Drupal/views/Plugin/views/area/View.php @@ -18,6 +18,16 @@ */ 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 @@ function render($empty = FALSE) { } 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(); + } + } + } diff --git a/core/modules/views/lib/Drupal/views/Plugin/views/display/DisplayPluginBase.php b/core/modules/views/lib/Drupal/views/Plugin/views/display/DisplayPluginBase.php index 7f6b104..360a415 100644 --- a/core/modules/views/lib/Drupal/views/Plugin/views/display/DisplayPluginBase.php +++ b/core/modules/views/lib/Drupal/views/Plugin/views/display/DisplayPluginBase.php @@ -2670,6 +2670,31 @@ public function isIdentifierUnique($id, $identifier) { return TRUE; } + /** + * Does the view shows anything. + * + * 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; + } + $empty = TRUE; + // Check whether any of the area handlers aren't empty. + $area_types = array('empty', 'footer', 'header'); + foreach ($area_types as $type) { + $handlers = $this->getHandlers($type); + foreach ($handlers as $handler) { + $empty &= $handler->isEmpty(); + } + } + return $empty; + } + /** * Provide the block system with any exposed widget blocks for this display. */ diff --git a/core/modules/views/lib/Drupal/views/Tests/Plugin/DisplayTest.php b/core/modules/views/lib/Drupal/views/Tests/Plugin/DisplayTest.php index 2c7230d..9c2090a 100644 --- a/core/modules/views/lib/Drupal/views/Tests/Plugin/DisplayTest.php +++ b/core/modules/views/lib/Drupal/views/Tests/Plugin/DisplayTest.php @@ -19,7 +19,7 @@ class DisplayTest extends PluginTestBase { * * @var array */ - public static $testViews = array('test_filter_groups', 'test_get_attach_displays', 'test_view', 'test_display_more'); + public static $testViews = array('test_filter_groups', 'test_get_attach_displays', 'test_view', 'test_display_more', 'test_display_empty'); /** * Modules to enable. @@ -197,4 +197,47 @@ public function testReadMore() { $this->assertEqual($more_text, $expected_more_text, 'The right more text is chosen.'); } + /** + * Tests the outputIsEmpty method on the display. + */ + public function testOutputIsEmpty() { + $view = views_get_view('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.'); + } + } diff --git a/core/modules/views/tests/views_test_config/test_views/views.view.test_display_empty.yml b/core/modules/views/tests/views_test_config/test_views/views.view.test_display_empty.yml new file mode 100644 index 0000000..e0768d4 --- /dev/null +++ b/core/modules/views/tests/views_test_config/test_views/views.view.test_display_empty.yml @@ -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' +human_name: '' +langcode: en +id: test_display_empty +tag: ''