summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlex Pott2015-05-09 14:10:38 -0700
committerAlex Pott2015-05-09 15:17:52 -0700
commit0a89a7a0b9995de3cfa6f1e204fa4d529f05bd7e (patch)
treebaa3d359a0ba001992ef4ff66e55a830eecd9637
parent20e4edaac7ee3ffda9785e9d32701982cda9adf9 (diff)
Issue #2375589 by larowlan, pameeela, jibran, kim.pepper, Wim Leers, Bojhan: Convert custom block library page to views
-rw-r--r--core/modules/block_content/config/optional/views.view.block_content.yml489
-rw-r--r--core/modules/block_content/src/BlockContentViewsData.php7
-rw-r--r--core/modules/block_content/src/Plugin/views/area/ListingEmpty.php94
-rw-r--r--core/modules/block_content/src/Tests/BlockContentListTest.php5
-rw-r--r--core/modules/block_content/src/Tests/BlockContentListViewsTest.php118
5 files changed, 711 insertions, 2 deletions
diff --git a/core/modules/block_content/config/optional/views.view.block_content.yml b/core/modules/block_content/config/optional/views.view.block_content.yml
new file mode 100644
index 0000000..7c2bba8
--- /dev/null
+++ b/core/modules/block_content/config/optional/views.view.block_content.yml
@@ -0,0 +1,489 @@
+langcode: en
+status: true
+dependencies:
+ module:
+ - block_content
+ - user
+id: block_content
+label: 'Custom block library'
+module: views
+description: 'Find and manage custom blocks.'
+tag: ''
+base_table: block_content_field_data
+base_field: id
+core: 8.x
+display:
+ default:
+ display_plugin: default
+ id: default
+ display_title: Master
+ position: 0
+ display_options:
+ access:
+ type: perm
+ options:
+ perm: 'administer blocks'
+ cache:
+ type: none
+ options: { }
+ query:
+ type: views_query
+ options:
+ disable_sql_rewrite: false
+ distinct: false
+ replica: false
+ query_comment: ''
+ query_tags: { }
+ exposed_form:
+ type: basic
+ options:
+ submit_button: Apply
+ reset_button: false
+ reset_button_label: Reset
+ exposed_sorts_label: 'Sort by'
+ expose_sort_order: true
+ sort_asc_label: Asc
+ sort_desc_label: Desc
+ pager:
+ type: mini
+ options:
+ items_per_page: 50
+ offset: 0
+ id: 0
+ total_pages: null
+ tags:
+ previous: '‹ previous'
+ next: 'next ›'
+ expose:
+ items_per_page: false
+ items_per_page_label: 'Items per page'
+ items_per_page_options: '5, 10, 25, 50'
+ items_per_page_options_all: false
+ items_per_page_options_all_label: '- All -'
+ offset: false
+ offset_label: Offset
+ style:
+ type: table
+ options:
+ grouping: { }
+ row_class: ''
+ default_row_class: true
+ override: true
+ sticky: false
+ caption: ''
+ summary: ''
+ description: ''
+ columns:
+ info: info
+ type: type
+ changed: changed
+ operations: operations
+ info:
+ info:
+ sortable: true
+ default_sort_order: asc
+ align: ''
+ separator: ''
+ empty_column: false
+ responsive: ''
+ type:
+ sortable: true
+ default_sort_order: asc
+ align: ''
+ separator: ''
+ empty_column: false
+ responsive: ''
+ changed:
+ sortable: true
+ default_sort_order: desc
+ align: ''
+ separator: ''
+ empty_column: false
+ responsive: ''
+ operations:
+ sortable: false
+ default_sort_order: asc
+ align: ''
+ separator: ''
+ empty_column: false
+ responsive: ''
+ default: changed
+ empty_table: true
+ row:
+ type: fields
+ fields:
+ info:
+ id: info
+ table: block_content_field_data
+ field: info
+ relationship: none
+ group_type: group
+ admin_label: ''
+ label: 'Block description'
+ exclude: false
+ alter:
+ alter_text: false
+ text: ''
+ make_link: false
+ path: ''
+ absolute: false
+ external: false
+ replace_spaces: false
+ path_case: none
+ trim_whitespace: false
+ alt: ''
+ rel: ''
+ link_class: ''
+ prefix: ''
+ suffix: ''
+ target: ''
+ nl2br: false
+ max_length: 0
+ word_boundary: true
+ ellipsis: true
+ more_link: false
+ more_link_text: ''
+ more_link_path: ''
+ strip_tags: false
+ trim: false
+ preserve_tags: ''
+ html: false
+ element_type: ''
+ element_class: ''
+ element_label_type: ''
+ element_label_class: ''
+ element_label_colon: true
+ element_wrapper_type: ''
+ element_wrapper_class: ''
+ element_default_classes: true
+ empty: ''
+ hide_empty: false
+ empty_zero: false
+ hide_alter_empty: true
+ click_sort_column: value
+ type: string
+ settings:
+ link_to_entity: true
+ group_column: value
+ group_columns: { }
+ group_rows: true
+ delta_limit: 0
+ delta_offset: 0
+ delta_reversed: false
+ delta_first_last: false
+ multi_type: separator
+ separator: ', '
+ field_api_classes: false
+ entity_type: null
+ entity_field: info
+ plugin_id: field
+ type:
+ id: type
+ table: block_content_field_data
+ field: type
+ relationship: none
+ group_type: group
+ admin_label: ''
+ label: 'Block type'
+ exclude: false
+ alter:
+ alter_text: false
+ text: ''
+ make_link: false
+ path: ''
+ absolute: false
+ external: false
+ replace_spaces: false
+ path_case: none
+ trim_whitespace: false
+ alt: ''
+ rel: ''
+ link_class: ''
+ prefix: ''
+ suffix: ''
+ target: ''
+ nl2br: false
+ max_length: 0
+ word_boundary: true
+ ellipsis: true
+ more_link: false
+ more_link_text: ''
+ more_link_path: ''
+ strip_tags: false
+ trim: false
+ preserve_tags: ''
+ html: false
+ element_type: ''
+ element_class: ''
+ element_label_type: ''
+ element_label_class: ''
+ element_label_colon: true
+ element_wrapper_type: ''
+ element_wrapper_class: ''
+ element_default_classes: true
+ empty: ''
+ hide_empty: false
+ empty_zero: false
+ hide_alter_empty: true
+ click_sort_column: target_id
+ type: entity_reference_label
+ settings:
+ link: false
+ group_column: target_id
+ group_columns: { }
+ group_rows: true
+ delta_limit: 0
+ delta_offset: 0
+ delta_reversed: false
+ delta_first_last: false
+ multi_type: separator
+ separator: ', '
+ field_api_classes: false
+ entity_type: block_content
+ entity_field: type
+ plugin_id: field
+ changed:
+ id: changed
+ table: block_content_field_data
+ field: changed
+ relationship: none
+ group_type: group
+ admin_label: ''
+ label: Updated
+ exclude: false
+ alter:
+ alter_text: false
+ text: ''
+ make_link: false
+ path: ''
+ absolute: false
+ external: false
+ replace_spaces: false
+ path_case: none
+ trim_whitespace: false
+ alt: ''
+ rel: ''
+ link_class: ''
+ prefix: ''
+ suffix: ''
+ target: ''
+ nl2br: false
+ max_length: 0
+ word_boundary: true
+ ellipsis: true
+ more_link: false
+ more_link_text: ''
+ more_link_path: ''
+ strip_tags: false
+ trim: false
+ preserve_tags: ''
+ html: false
+ element_type: ''
+ element_class: ''
+ element_label_type: ''
+ element_label_class: ''
+ element_label_colon: true
+ element_wrapper_type: ''
+ element_wrapper_class: ''
+ element_default_classes: true
+ empty: ''
+ hide_empty: false
+ empty_zero: false
+ hide_alter_empty: true
+ date_format: short
+ custom_date_format: ''
+ timezone: ''
+ entity_type: block_content
+ entity_field: changed
+ plugin_id: date
+ operations:
+ id: operations
+ table: block_content
+ field: operations
+ relationship: none
+ group_type: group
+ admin_label: ''
+ label: Operations
+ exclude: false
+ alter:
+ alter_text: false
+ text: ''
+ make_link: false
+ path: ''
+ absolute: false
+ external: false
+ replace_spaces: false
+ path_case: none
+ trim_whitespace: false
+ alt: ''
+ rel: ''
+ link_class: ''
+ prefix: ''
+ suffix: ''
+ target: ''
+ nl2br: false
+ max_length: 0
+ word_boundary: true
+ ellipsis: true
+ more_link: false
+ more_link_text: ''
+ more_link_path: ''
+ strip_tags: false
+ trim: false
+ preserve_tags: ''
+ html: false
+ element_type: ''
+ element_class: ''
+ element_label_type: ''
+ element_label_class: ''
+ element_label_colon: true
+ element_wrapper_type: ''
+ element_wrapper_class: ''
+ element_default_classes: true
+ empty: ''
+ hide_empty: false
+ empty_zero: false
+ hide_alter_empty: true
+ destination: true
+ entity_type: block_content
+ plugin_id: entity_operations
+ filters:
+ info:
+ id: info
+ table: block_content_field_data
+ field: info
+ relationship: none
+ group_type: group
+ admin_label: ''
+ operator: contains
+ value: ''
+ group: 1
+ exposed: true
+ expose:
+ operator_id: info_op
+ label: 'Block description'
+ description: ''
+ use_operator: false
+ operator: info_op
+ identifier: info
+ required: false
+ remember: false
+ multiple: false
+ remember_roles:
+ authenticated: authenticated
+ anonymous: '0'
+ administrator: '0'
+ is_grouped: false
+ group_info:
+ label: ''
+ description: ''
+ identifier: ''
+ optional: true
+ widget: select
+ multiple: false
+ remember: false
+ default_group: All
+ default_group_multiple: { }
+ group_items: { }
+ entity_type: block_content
+ entity_field: info
+ plugin_id: string
+ type:
+ id: type
+ table: block_content
+ field: type
+ relationship: none
+ group_type: group
+ admin_label: ''
+ operator: in
+ value: { }
+ group: 1
+ exposed: true
+ expose:
+ operator_id: type_op
+ label: 'Block type'
+ description: ''
+ use_operator: false
+ operator: type_op
+ identifier: type
+ required: false
+ remember: false
+ multiple: false
+ remember_roles:
+ authenticated: authenticated
+ anonymous: '0'
+ administrator: '0'
+ reduce: false
+ is_grouped: false
+ group_info:
+ label: ''
+ description: ''
+ identifier: ''
+ optional: true
+ widget: select
+ multiple: false
+ remember: false
+ default_group: All
+ default_group_multiple: { }
+ group_items: { }
+ entity_type: block_content
+ entity_field: type
+ plugin_id: bundle
+ sorts: { }
+ title: 'Custom block library'
+ header: { }
+ footer: { }
+ empty:
+ area_text_custom:
+ id: area_text_custom
+ table: views
+ field: area_text_custom
+ relationship: none
+ group_type: group
+ admin_label: ''
+ empty: true
+ tokenize: false
+ content: 'There are no custom blocks available. '
+ plugin_id: text_custom
+ block_content_listing_empty:
+ admin_label: ''
+ empty: true
+ field: block_content_listing_empty
+ group_type: group
+ id: block_content_listing_empty
+ label: ''
+ relationship: none
+ table: block_content
+ plugin_id: block_content_listing_empty
+ entity_type: block_content
+ relationships: { }
+ arguments: { }
+ display_extenders: { }
+ cache_metadata:
+ contexts:
+ - 'languages:language_content'
+ - 'languages:language_interface'
+ - url
+ cacheable: false
+ page_1:
+ display_plugin: page
+ id: page_1
+ display_title: Page
+ position: 1
+ display_options:
+ display_extenders: { }
+ path: admin/structure/block/block-content
+ menu:
+ type: tab
+ title: 'Custom block library'
+ description: ''
+ parent: block.admin_display
+ weight: 0
+ context: '0'
+ menu_name: admin
+ cache_metadata:
+ contexts:
+ - 'languages:language_content'
+ - 'languages:language_interface'
+ - url
+ cacheable: false
diff --git a/core/modules/block_content/src/BlockContentViewsData.php b/core/modules/block_content/src/BlockContentViewsData.php
index 09d49b7..abb2cb2 100644
--- a/core/modules/block_content/src/BlockContentViewsData.php
+++ b/core/modules/block_content/src/BlockContentViewsData.php
@@ -28,6 +28,13 @@ class BlockContentViewsData extends EntityViewsData {
$data['block_content_field_data']['type']['field']['id'] = 'field';
+ $data['block_content']['block_content_listing_empty'] = array(
+ 'title' => t('Empty block library behavior'),
+ 'help' => t('Provides a link to add a new block.'),
+ 'area' => array(
+ 'id' => 'block_content_listing_empty',
+ ),
+ );
// Advertise this table as a possible base table.
$data['block_content_revision']['table']['base']['help'] = $this->t('Block Content revision is a history of changes to block content.');
$data['block_content_revision']['table']['base']['defaults']['title'] = 'info';
diff --git a/core/modules/block_content/src/Plugin/views/area/ListingEmpty.php b/core/modules/block_content/src/Plugin/views/area/ListingEmpty.php
new file mode 100644
index 0000000..0e25190
--- /dev/null
+++ b/core/modules/block_content/src/Plugin/views/area/ListingEmpty.php
@@ -0,0 +1,94 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\block_content\Plugin\views\area\ListingEmpty.
+ */
+
+namespace Drupal\block_content\Plugin\views\area;
+
+use Drupal\Core\Access\AccessManagerInterface;
+use Drupal\Core\Session\AccountInterface;
+use Drupal\Core\Url;
+use Drupal\views\Plugin\views\area\AreaPluginBase;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+
+/**
+ * Defines an area plugin to display a block add link.
+ *
+ * @ingroup views_area_handlers
+ *
+ * @ViewsArea("block_content_listing_empty")
+ */
+class ListingEmpty extends AreaPluginBase {
+
+ /**
+ * The access manager.
+ *
+ * @var \Drupal\Core\Access\AccessManagerInterface
+ */
+ protected $accessManager;
+
+ /**
+ * The current user.
+ *
+ * @var \Drupal\Core\Session\AccountInterface
+ */
+ protected $currentUser;
+
+ /**
+ * Constructs a new ListingEmpty.
+ *
+ * @param array $configuration
+ * A configuration array containing information about the plugin instance.
+ * @param string $plugin_id
+ * The plugin ID for the plugin instance.
+ * @param mixed $plugin_definition
+ * The plugin implementation definition.
+ * @param \Drupal\Core\Access\AccessManagerInterface $access_manager
+ * The access manager.
+ * @param \Drupal\Core\Session\AccountInterface $current_user
+ * The current user.
+ */
+ public function __construct(array $configuration, $plugin_id, $plugin_definition, AccessManagerInterface $access_manager, AccountInterface $current_user) {
+ parent::__construct($configuration, $plugin_id, $plugin_definition);
+
+ $this->accessManager = $access_manager;
+ $this->currentUser = $current_user;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
+ return new static(
+ $configuration,
+ $plugin_id,
+ $plugin_definition,
+ $container->get('access_manager'),
+ $container->get('current_user')
+ );
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function render($empty = FALSE) {
+ if (!$empty || !empty($this->options['empty'])) {
+ /** @var \Drupal\Core\Access\AccessResultInterface|\Drupal\Core\Cache\CacheableDependencyInterface $access_result */
+ $access_result = $this->accessManager->checkNamedRoute('block_content.add_page', array(), $this->currentUser, TRUE);
+ $element = array(
+ '#markup' => $this->t('Add a <a href="!url">custom block</a>.', array('!url' => Url::fromRoute('block_content.add_page')->toString())),
+ '#access' => $access_result->isAllowed(),
+ '#cache' => [
+ 'contexts' => $access_result->getCacheContexts(),
+ 'tags' => $access_result->getCacheTags(),
+ 'max-age' => $access_result->getCacheMaxAge(),
+ ],
+ );
+ return $element;
+ }
+ return array();
+ }
+
+}
diff --git a/core/modules/block_content/src/Tests/BlockContentListTest.php b/core/modules/block_content/src/Tests/BlockContentListTest.php
index 03b60e3..aeed4dc 100644
--- a/core/modules/block_content/src/Tests/BlockContentListTest.php
+++ b/core/modules/block_content/src/Tests/BlockContentListTest.php
@@ -7,13 +7,14 @@
namespace Drupal\block_content\Tests;
-use Drupal\simpletest\WebTestBase;
-
/**
* Tests the listing of custom blocks.
*
+ * Tests the fallback block content list when Views is disabled.
+ *
* @group block_content
* @see \Drupal\block\BlockContentListBuilder
+ * @see \Drupal\block_content\Tests\BlockContentListViewsTest
*/
class BlockContentListTest extends BlockContentTestBase {
diff --git a/core/modules/block_content/src/Tests/BlockContentListViewsTest.php b/core/modules/block_content/src/Tests/BlockContentListViewsTest.php
new file mode 100644
index 0000000..ba84f2b
--- /dev/null
+++ b/core/modules/block_content/src/Tests/BlockContentListViewsTest.php
@@ -0,0 +1,118 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\block_content\Tests\BlockContentListViewsTest.
+ */
+
+namespace Drupal\block_content\Tests;
+
+/**
+ * Tests the Views-powered listing of custom blocks.
+ *
+ * @group block_content
+ * @see \Drupal\block\BlockContentListBuilder
+ * @see \Drupal\block_content\Tests\BlockContentListTest
+ */
+class BlockContentListViewsTest extends BlockContentTestBase {
+
+ /**
+ * Modules to enable.
+ *
+ * @var array
+ */
+ public static $modules = ['block', 'block_content', 'config_translation', 'views'];
+
+ /**
+ * Tests the custom block listing page.
+ */
+ public function testListing() {
+ $this->drupalLogin($this->drupalCreateUser(array('administer blocks', 'translate configuration')));
+ $this->drupalGet('admin/structure/block/block-content');
+
+ // Test for the page title.
+ $this->assertTitle(t('Custom block library') . ' | Drupal');
+
+ // Test for the table.
+ $element = $this->xpath('//div[@class="layout-content"]//table');
+ $this->assertTrue($element, 'Views table found.');
+
+ // Test the table header.
+ $elements = $this->xpath('//div[@class="layout-content"]//table/thead/tr/th');
+ $this->assertEqual(count($elements), 4, 'Correct number of table header cells found.');
+
+ // Test the contents of each th cell.
+ $expected_items = [t('Block description'), t('Block type'), t('Updated'), t('Operations')];
+ foreach ($elements as $key => $element) {
+ if ($element->xpath('a')) {
+ $this->assertIdentical(trim((string) $element->xpath('a')[0]), $expected_items[$key]);
+ }
+ else {
+ $this->assertIdentical(trim((string) $element[0]), $expected_items[$key]);
+ }
+ }
+
+ $label = 'Antelope';
+ $new_label = 'Albatross';
+ // Add a new entity using the operations link.
+ $link_text = t('Add custom block');
+ $this->assertLink($link_text);
+ $this->clickLink($link_text);
+ $this->assertResponse(200);
+ $edit = array();
+ $edit['info[0][value]'] = $label;
+ $edit['body[0][value]'] = $this->randomMachineName(16);
+ $this->drupalPostForm(NULL, $edit, t('Save'));
+
+ // Confirm that once the user returns to the listing, the text of the label
+ // (versus elsewhere on the page).
+ $this->assertFieldByXpath('//td/a', $label, 'Label found for added block.');
+
+ // Check the number of table row cells.
+ $elements = $this->xpath('//div[@class="layout-content"]//table/tbody/tr/td');
+ $this->assertEqual(count($elements), 4, 'Correct number of table row cells found.');
+ // Check the contents of each row cell. The first cell contains the label,
+ // the second contains the machine name, and the third contains the
+ // operations list.
+ $this->assertIdentical((string) $elements[0]->xpath('a')[0], $label);
+
+ // Edit the entity using the operations link.
+ $blocks = $this->container
+ ->get('entity.manager')
+ ->getStorage('block_content')
+ ->loadByProperties(array('info' => $label));
+ $block = reset($blocks);
+ if (!empty($block)) {
+ $this->assertLinkByHref('block/' . $block->id());
+ $this->clickLink(t('Edit'));
+ $this->assertResponse(200);
+ $this->assertTitle(strip_tags(t('Edit custom block %label', array('%label' => $label)) . ' | Drupal'));
+ $edit = array('info[0][value]' => $new_label);
+ $this->drupalPostForm(NULL, $edit, t('Save'));
+ }
+ else {
+ $this->fail('Did not find Albatross block in the database.');
+ }
+
+ // Confirm that once the user returns to the listing, the text of the label
+ // (versus elsewhere on the page).
+ $this->assertFieldByXpath('//td/a', $new_label, 'Label found for updated custom block.');
+
+ // Delete the added entity using the operations link.
+ $this->assertLinkByHref('block/' . $block->id() . '/delete');
+ $delete_text = t('Delete');
+ $this->clickLink($delete_text);
+ $this->assertResponse(200);
+ $this->assertTitle(strip_tags(t('Are you sure you want to delete the custom block %label?', array('%label' => $new_label)) . ' | Drupal'));
+ $this->drupalPostForm(NULL, array(), $delete_text);
+
+ // Verify that the text of the label and machine name does not appear in
+ // the list (though it may appear elsewhere on the page).
+ $this->assertNoFieldByXpath('//td', $new_label, 'No label found for deleted custom block.');
+
+ // Confirm that the empty text is displayed.
+ $this->assertText('There are no custom blocks available.');
+ $this->assertLink('custom block');
+ }
+
+}