diff --git a/core/modules/block/block.admin.inc b/core/modules/block/block.admin.inc index 093769e..f849833 100644 --- a/core/modules/block/block.admin.inc +++ b/core/modules/block/block.admin.inc @@ -16,7 +16,9 @@ function block_admin_demo($theme = NULL) { return array( '#attached' => array( - 'css' => array(drupal_get_path('module', 'block') . '/css/block.admin.css'), + 'library' => array( + array('block', 'drupal.block.admin'), + ), ), ); } diff --git a/core/modules/block/block.module b/core/modules/block/block.module index 8eeb57f..641037a 100644 --- a/core/modules/block/block.module +++ b/core/modules/block/block.module @@ -61,7 +61,7 @@ function block_help($path, $arg) { $output .= '
' . t('Blocks can be configured to be visible only on certain pages, only to users of certain roles, or only on pages displaying certain content types. Some dynamic blocks, such as those generated by modules, will be displayed only on certain pages.', array('@content-type' => url('admin/structure/types'), '@user' => url('user'))) . '
'; if (module_exists('custom_block')) { $output .= '
' . t('Creating custom blocks') . '
'; - $output .= '
' . t('Users with the Administer blocks permission can add custom blocks, which are then listed on the Blocks administration page. Once created, custom blocks behave just like default and module-generated blocks.', array('@blocks' => url('admin/structure/block'), '@block-add' => url('admin/structure/block/list/' . config('system.theme')->get('default') . '/add/custom_blocks'))) . '
'; + $output .= '
' . t('Users with the Administer blocks permission can add custom blocks, which are then listed on the Blocks administration page. Once created, custom blocks behave just like default and module-generated blocks.', array('@blocks' => url('admin/structure/block'))) . '
'; } $output .= ''; return $output; @@ -142,11 +142,6 @@ function block_menu() { 'type' => $key == $default_theme ? MENU_DEFAULT_LOCAL_TASK : MENU_LOCAL_TASK, 'route_name' => "block_admin_display.$key", ); - $items["admin/structure/block/list/$key/add"] = array( - 'title' => 'Place blocks', - 'type' => MENU_LOCAL_ACTION, - 'route_name' => "block_plugin_ui.$key", - ); $items["admin/structure/block/demo/$key"] = array( 'title' => check_plain($theme->info['name']), 'page callback' => 'block_admin_demo', @@ -634,6 +629,20 @@ function block_library_info() { array('system', 'drupal'), ), ); + $libraries['drupal.block.admin'] = array( + 'title' => 'Block admin', + 'version' => VERSION, + 'js' => array( + drupal_get_path('module', 'block') . '/js/block.admin.js' => array(), + ), + 'css' => array( + drupal_get_path('module', 'block') . '/css/block.admin.css' => array(), + ), + 'dependencies' => array( + array('system', 'jquery'), + array('system', 'drupal'), + ), + ); return $libraries; } diff --git a/core/modules/block/block.routing.yml b/core/modules/block/block.routing.yml index 669e0a2..cabd4cb 100644 --- a/core/modules/block/block.routing.yml +++ b/core/modules/block/block.routing.yml @@ -26,10 +26,3 @@ block_admin_add: _content: '\Drupal\block\Controller\BlockAddController::blockAddConfigureForm' requirements: _permission: 'administer blocks' - -block_autocomplete: - pattern: '/block/autocomplete' - defaults: - _controller: '\Drupal\block\Controller\BlockAutocompleteController::autocomplete' - requirements: - _permission: 'administer blocks' diff --git a/core/modules/block/css/block.admin.css b/core/modules/block/css/block.admin.css index 831ad44..edfacaa 100644 --- a/core/modules/block/css/block.admin.css +++ b/core/modules/block/css/block.admin.css @@ -31,3 +31,43 @@ a.block-demo-backlink:visited { a.block-demo-backlink:hover { text-decoration: underline; } + +.block-list-region { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} +.block-list-left { + float: left; /* LTR */ + padding-right: 2em; /* LTR */ + width: 75%; +} +[dir="rtl"] .block-list-left { + float: right; + padding-left: 2em; + padding-right: 0; +} +.block-list-right { + border: 1px solid #bfbfbf; + border-bottom-width: 0; + float: right; /* LTR */ + width: 25%; +} +[dir="rtl"] .block-list-right { + float: left; +} + +.block-list { + padding: 0 0.75em; + margin: 0; +} +.block-list li { + list-style: none; + padding: 0.1em 0; +} +.block-list a:before { + content: '+ '; +} +.block-list-right .form-type-search { + padding: 0 1em; +} diff --git a/core/modules/block/custom_block/custom_block.module b/core/modules/block/custom_block/custom_block.module index 2752ee8..d013c7c 100644 --- a/core/modules/block/custom_block/custom_block.module +++ b/core/modules/block/custom_block/custom_block.module @@ -9,20 +9,14 @@ use Drupal\custom_block\Plugin\Core\Entity\CustomBlock; /** - * Implements hook_menu_local_tasks(). + * Implements hook_menu_local_actions_alter(). */ -function custom_block_menu_local_tasks(&$data, $router_item, $root_path) { - // Add the "Add custom block" action link to the theme-specific block library - // listing page. - // @todo This should just be $root_path == 'admin/structure/block/list/%/add' - // but block_menu() registers static router paths instead of dynamic ones. - if (preg_match('@^admin/structure/block/list/(.*)/add$@', $root_path)) { - $item = menu_get_item('block/add'); - if ($item['access']) { - $data['actions']['block/add'] = array( - '#theme' => 'menu_local_action', - '#link' => $item, - ); +function custom_block_menu_local_actions_alter(&$actions) { + if (isset($actions['custom_block_add_action'])) { + foreach (list_themes() as $theme => $theme_info) { + if ($theme_info->status) { + $actions['custom_block_add_action']['appears_on'][] = "block_admin_display.$theme"; + } } } } @@ -93,21 +87,6 @@ function custom_block_menu() { } /** - * Implements hook_local_actions(). - */ -function custom_block_local_actions() { - return array( - array( - 'route_name' => 'custom_block_type_add', - 'title' => t('Add custom block type'), - 'appears_on' => array( - 'custom_block_type_list', - ), - ), - ); -} - -/** * Implements hook_theme(). */ function custom_block_theme($existing, $type, $theme, $path) { @@ -221,27 +200,6 @@ function custom_block_add_body_field($block_type_id, $label = 'Block body') { } /** - * Implements hook_form_FORM_ID_alter() for block_plugin_ui(). - */ -function custom_block_form_block_plugin_ui_alter(&$form, $form_state) { - foreach ($form['left']['plugin_library']['#rows'] as $plugin_id => &$row) { - // @todo Clean up when http://drupal.org/node/1874498 lands. - if (strpos($plugin_id, ':') === FALSE) { - continue; - } - list($base, $derivative) = explode(':', $plugin_id); - if ($base !== 'custom_block') { - continue; - } - $custom_block = entity_load_by_uuid('custom_block', $derivative); - $row['1']['data']['#links']['edit'] = array( - 'title' => t('Edit'), - 'href' => 'block/' . $custom_block->id(), - ); - } -} - -/** * Implements hook_admin_paths(). */ function custom_block_admin_paths() { diff --git a/core/modules/block/custom_block/lib/Drupal/custom_block/Plugin/Menu/LocalAction/CustomBlockAddLocalAction.php b/core/modules/block/custom_block/lib/Drupal/custom_block/Plugin/Menu/LocalAction/CustomBlockAddLocalAction.php new file mode 100644 index 0000000..212c799 --- /dev/null +++ b/core/modules/block/custom_block/lib/Drupal/custom_block/Plugin/Menu/LocalAction/CustomBlockAddLocalAction.php @@ -0,0 +1,24 @@ + element for a category if it has no visible blocks. + */ + function hideCategoryDetails(index, element) { + var $details = $(element); + $details.toggle($details.find('li:visible').length > 0); + } + + /** + * Filters the block list. + */ + function filterBlockList (e) { + var query = $(e.target).val().toLowerCase(); + + /** + * Shows or hides the block entry based on the query. + */ + function showBlockEntry (index, block) { + var $block = $(block); + var $sources = $block.find('.block-filter-text-source'); + var textMatch = $sources.text().toLowerCase().indexOf(query) !== -1; + $block.toggle(textMatch); + } + + // Filter if the length of the query is at least 2 characters. + if (query.length >= 2) { + $blocks.each(showBlockEntry); + + // Hide the category
if they don't have any visible rows. + // Note that we first open all
to be able to use ':visible'. + $details.attr('open', 'open').each(hideCategoryDetails); + } + else { + $blocks.show(); + $details.show(); + } + // Once the query is completely gone, close all details elements. + if (query.length === 0) { + $details.removeAttr('open'); + } + } + + if ($element.length) { + $details = $element.find('details'); + $blocks = $details.find('li'); + + $input.on('keyup', filterBlockList); + } + } +}; + +}(jQuery, Drupal)); diff --git a/core/modules/block/lib/Drupal/block/BlockListController.php b/core/modules/block/lib/Drupal/block/BlockListController.php index 9ba757b..618b901 100644 --- a/core/modules/block/lib/Drupal/block/BlockListController.php +++ b/core/modules/block/lib/Drupal/block/BlockListController.php @@ -7,15 +7,20 @@ namespace Drupal\block; +use Drupal\Component\Plugin\PluginManagerInterface; +use Drupal\Component\Utility\Json; use Drupal\Core\Config\Entity\ConfigEntityListController; -use Drupal\block\Plugin\Core\Entity\Block; +use Drupal\Core\Entity\EntityControllerInterface; use Drupal\Core\Entity\EntityInterface; +use Drupal\Core\Entity\EntityStorageControllerInterface; +use Drupal\Core\Extension\ModuleHandlerInterface; use Drupal\Core\Form\FormInterface; +use Symfony\Component\DependencyInjection\ContainerInterface; /** * Defines the block list controller. */ -class BlockListController extends ConfigEntityListController implements FormInterface { +class BlockListController extends ConfigEntityListController implements FormInterface, EntityControllerInterface { /** * The regions containing the blocks. @@ -32,6 +37,46 @@ class BlockListController extends ConfigEntityListController implements FormInte protected $theme; /** + * The block manager. + * + * @var \Drupal\Component\Plugin\PluginManagerInterface + */ + protected $blockManager; + + /** + * Constructs a new BlockListController object. + * + * @param string $entity_type + * The type of entity to be listed. + * @param array $entity_info + * An array of entity info for the entity type. + * @param \Drupal\Core\Entity\EntityStorageControllerInterface $storage + * The entity storage controller class. + * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler + * The module handler to invoke hooks on. + * @param \Drupal\Component\Plugin\PluginManagerInterface $block_manager + * The block manager. + */ + public function __construct($entity_type, array $entity_info, EntityStorageControllerInterface $storage, ModuleHandlerInterface $module_handler, PluginManagerInterface $block_manager) { + parent::__construct($entity_type, $entity_info, $storage, $module_handler); + + $this->blockManager = $block_manager; + } + + /** + * {@inheritdoc} + */ + public static function createInstance(ContainerInterface $container, $entity_type, array $entity_info) { + return new static( + $entity_type, + $entity_info, + $container->get('plugin.manager.entity')->getStorageController($entity_type), + $container->get('module_handler'), + $container->get('plugin.manager.block') + ); + } + + /** * Overrides \Drupal\Core\Config\Entity\ConfigEntityListController::load(). */ public function load() { @@ -75,14 +120,20 @@ public function getFormID() { */ public function buildForm(array $form, array &$form_state) { $entities = $this->load(); - $form['#attached']['css'][] = drupal_get_path('module', 'block') . '/css/block.admin.css'; $form['#attached']['library'][] = array('system', 'drupal.tableheader'); $form['#attached']['library'][] = array('block', 'drupal.block'); + $form['#attached']['library'][] = array('block', 'drupal.block.admin'); + $form['#attributes']['class'][] = 'clearfix'; // Add a last region for disabled blocks. $block_regions_with_disabled = $this->regions + array(BLOCK_REGION_NONE => BLOCK_REGION_NONE); + $form['left']['#type'] = 'container'; + $form['left']['#attributes']['class'] = array( + 'block-list-region', + 'block-list-left', + ); - $form['block_regions'] = array( + $form['left']['block_regions'] = array( '#type' => 'value', '#value' => $block_regions_with_disabled, ); @@ -93,11 +144,11 @@ public function buildForm(array $form, array &$form_state) { $weight_delta = round(count($entities) / 2); // Build the form tree. - $form['edited_theme'] = array( + $form['left']['edited_theme'] = array( '#type' => 'value', '#value' => $this->theme, ); - $form['blocks'] = array( + $form['left']['blocks'] = array( '#type' => 'table', '#header' => array( t('Block'), @@ -123,7 +174,7 @@ public function buildForm(array $form, array &$form_state) { // Loop over each region and build blocks. foreach ($block_regions_with_disabled as $region => $title) { - $form['blocks']['#tabledrag'][] = array( + $form['left']['blocks']['#tabledrag'][] = array( 'match', 'sibling', 'block-region-select', @@ -131,27 +182,27 @@ public function buildForm(array $form, array &$form_state) { NULL, FALSE, ); - $form['blocks']['#tabledrag'][] = array( + $form['left']['blocks']['#tabledrag'][] = array( 'order', 'sibling', 'block-weight', 'block-weight-' . $region, ); - $form['blocks'][$region] = array( + $form['left']['blocks'][$region] = array( '#attributes' => array( 'class' => array('region-title', 'region-title-' . $region, 'odd'), 'no_striping' => TRUE, ), ); - $form['blocks'][$region]['title'] = array( + $form['left']['blocks'][$region]['title'] = array( '#markup' => $region != BLOCK_REGION_NONE ? $title : t('Disabled'), '#wrapper_attributes' => array( 'colspan' => 5, ), ); - $form['blocks'][$region . '-message'] = array( + $form['left']['blocks'][$region . '-message'] = array( '#attributes' => array( 'class' => array( 'region-message', @@ -160,7 +211,7 @@ public function buildForm(array $form, array &$form_state) { ), ), ); - $form['blocks'][$region . '-message']['message'] = array( + $form['left']['blocks'][$region . '-message']['message'] = array( '#markup' => '' . t('No blocks in this region') . '', '#wrapper_attributes' => array( 'colspan' => 5, @@ -171,19 +222,19 @@ public function buildForm(array $form, array &$form_state) { foreach ($blocks[$region] as $info) { $entity_id = $info['entity_id']; - $form['blocks'][$entity_id] = array( + $form['left']['blocks'][$entity_id] = array( '#attributes' => array( 'class' => array('draggable'), ), ); - $form['blocks'][$entity_id]['info'] = array( + $form['left']['blocks'][$entity_id]['info'] = array( '#markup' => check_plain($info['admin_label']), '#wrapper_attributes' => array( 'class' => array('block'), ), ); - $form['blocks'][$entity_id]['region-theme']['region'] = array( + $form['left']['blocks'][$entity_id]['region-theme']['region'] = array( '#type' => 'select', '#default_value' => $region, '#empty_value' => BLOCK_REGION_NONE, @@ -195,12 +246,12 @@ public function buildForm(array $form, array &$form_state) { ), '#parents' => array('blocks', $entity_id, 'region'), ); - $form['blocks'][$entity_id]['region-theme']['theme'] = array( + $form['left']['blocks'][$entity_id]['region-theme']['theme'] = array( '#type' => 'hidden', '#value' => $this->theme, '#parents' => array('blocks', $entity_id, 'theme'), ); - $form['blocks'][$entity_id]['weight'] = array( + $form['left']['blocks'][$entity_id]['weight'] = array( '#type' => 'weight', '#default_value' => $info['weight'], '#delta' => $weight_delta, @@ -210,25 +261,95 @@ public function buildForm(array $form, array &$form_state) { 'class' => array('block-weight', 'block-weight-' . $region), ), ); - $form['blocks'][$entity_id]['operations'] = $this->buildOperations($info['entity']); + $form['left']['blocks'][$entity_id]['operations'] = $this->buildOperations($info['entity']); } } } // Do not allow disabling the main system content block when it is present. - if (isset($form['blocks']['system_main']['region'])) { - $form['blocks']['system_main']['region']['#required'] = TRUE; + if (isset($form['left']['blocks']['system_main']['region'])) { + $form['left']['blocks']['system_main']['region']['#required'] = TRUE; } - $form['actions'] = array( + $form['left']['actions'] = array( '#tree' => FALSE, '#type' => 'actions', ); - $form['actions']['submit'] = array( + $form['left']['actions']['submit'] = array( '#type' => 'submit', '#value' => t('Save blocks'), '#button_type' => 'primary', ); + + $form['right']['#type'] = 'container'; + $form['right']['#attributes']['class'] = array( + 'block-list-region', + 'block-list-right', + ); + + $form['right']['list']['#type'] = 'container'; + $form['right']['list']['#attributes']['class'][] = 'entity-meta'; + + $form['right']['list']['title'] = array( + '#type' => 'container', + '#children' => '

' . t('Place blocks') . '

', + '#attributes' => array( + 'class' => array( + 'entity-meta-header', + ), + ), + ); + $form['right']['list']['search'] = array( + '#type' => 'search', + '#title' => t('Filter'), + '#title_display' => 'invisible', + '#size' => 30, + '#placeholder' => t('Filter by block name'), + '#attributes' => array( + 'class' => array('block-filter-text'), + 'data-element' => '.entity-meta', + 'title' => t('Enter a part of the block name to filter by.'), + ), + ); + + // Sort the plugins first by category, then by label. + $plugins = $this->blockManager->getDefinitions(); + uasort($plugins, function ($a, $b) { + if ($a['category'] != $b['category']) { + return strnatcasecmp($a['category'], $b['category']); + } + return strnatcasecmp($a['admin_label'], $b['admin_label']); + }); + foreach ($plugins as $plugin_id => $plugin_definition) { + $category = $plugin_definition['category']; + if (!isset($form['right']['list'][$category])) { + $form['right']['list'][$category] = array( + '#type' => 'details', + '#title' => $category, + '#collapsed' => TRUE, + 'content' => array( + '#theme' => 'links', + '#links' => array(), + '#attributes' => array( + 'class' => array( + 'block-list', + ), + ), + ), + ); + } + $form['right']['list'][$category]['content']['#links'][$plugin_id] = array( + 'title' => $plugin_definition['admin_label'], + 'href' => 'admin/structure/block/add/' . $plugin_id . '/' . $this->theme, + 'attributes' => array( + 'class' => array('use-ajax', 'block-filter-text-source'), + 'data-accepts' => 'application/vnd.drupal-modal', + 'data-dialog-options' => Json::encode(array( + 'width' => 700, + )), + ), + ); + } return $form; } diff --git a/core/modules/block/lib/Drupal/block/Controller/BlockAutocompleteController.php b/core/modules/block/lib/Drupal/block/Controller/BlockAutocompleteController.php deleted file mode 100644 index 539a8c1..0000000 --- a/core/modules/block/lib/Drupal/block/Controller/BlockAutocompleteController.php +++ /dev/null @@ -1,78 +0,0 @@ -manager = $manager; - } - - /** - * {@inheritdoc} - */ - public static function create(ContainerInterface $container) { - return new static( - $container->get('plugin.manager.block') - ); - } - - /** - * Autocompletes a block plugin ID. - * - * @param \Symfony\Component\HttpFoundation\Request $request - * The request object. - * - * @return \Symfony\Component\HttpFoundation\JsonResponse - * The matched plugins as JSON. - */ - public function autocomplete(Request $request) { - $string_typed = $request->query->get('q'); - // The passed string may be comma or space separated. - $string_typed = Tags::explode($string_typed); - // Take the last result and lowercase it. - $string = Unicode::strtolower(array_pop($string_typed)); - $matches = array(); - if ($string) { - $titles = array(); - // Gather all block plugins and their admin titles. - foreach($this->manager->getDefinitions() as $plugin_id => $plugin) { - $titles[$plugin_id] = $plugin['admin_label']; - } - // Find any matching block plugin IDs. - $matches = preg_grep("/\b". $string . "/i", $titles); - } - - return new JsonResponse($matches); - } - -} diff --git a/core/modules/block/lib/Drupal/block/Form/PlaceBlocksForm.php b/core/modules/block/lib/Drupal/block/Form/PlaceBlocksForm.php deleted file mode 100644 index ffc4b9e..0000000 --- a/core/modules/block/lib/Drupal/block/Form/PlaceBlocksForm.php +++ /dev/null @@ -1,157 +0,0 @@ -manager = $manager; - } - - /** - * {@inheritdoc} - */ - public static function create(ContainerInterface $container) { - return new static( - $container->get('plugin.manager.block') - ); - } - - /** - * {@inheritdoc} - */ - public function getFormID() { - return 'block_plugin_ui'; - } - - /** - * {@inheritdoc} - */ - public function buildForm(array $form, array &$form_state, $theme = NULL, $category = NULL) { - $this->theme = $theme; - $form['#theme'] = 'system_plugin_ui_form'; - $rows = array(); - $categories = array(); - foreach ($this->manager->getDefinitions() as $plugin_id => $plugin_definition) { - if (empty($category) || $plugin_definition['category'] == $category) { - $rows[$plugin_id] = $this->row($plugin_id, $plugin_definition); - } - $categories[$plugin_definition['category']] = array( - 'title' => $plugin_definition['category'], - 'href' => 'admin/structure/block/list/' . $this->theme . '/add/' . $plugin_definition['category'], - ); - } - - $form['right']['block'] = array( - '#type' => 'textfield', - '#title' => t('Search'), - '#autocomplete_path' => 'block/autocomplete', - ); - $form['right']['submit'] = array( - '#type' => 'submit', - '#button_type' => 'primary', - '#value' => t('Next'), - ); - $form['right']['all_plugins'] = array( - '#type' => 'link', - '#title' => t('All blocks'), - '#href' => 'admin/structure/block/list/' . $this->theme . '/add', - ); - if (!empty($categories)) { - $form['right']['categories'] = array( - '#theme' => 'links', - '#heading' => array( - 'text' => t('Categories'), - 'level' => 'h3', - ), - '#links' => $categories, - ); - } - - // Sort rows alphabetically. - asort($rows); - $form['left']['plugin_library'] = array( - '#theme' => 'table', - '#header' => array(t('Subject'), t('Operations')), - '#rows' => $rows, - ); - return $form; - } - - /** - * Generates the row data for a single block plugin. - * - * @param string $plugin_id - * The plugin ID. - * @param array $plugin_definition - * The plugin definition. - * - * @return array - * The row data for a single block plugin. - */ - protected function row($plugin_id, array $plugin_definition) { - $row = array(); - $row[] = String::checkPlain($plugin_definition['admin_label']); - $row[] = array('data' => array( - '#type' => 'operations', - '#links' => array( - 'configure' => array( - 'title' => t('Place block'), - 'href' => 'admin/structure/block/add/' . $plugin_id . '/' . $this->theme, - ), - ), - )); - return $row; - } - - /** - * {@inheritdoc} - */ - public function validateForm(array &$form, array &$form_state) { - if (!$this->manager->getDefinition($form_state['values']['block'])) { - form_set_error('block', t('You must select a valid block.')); - } - } - - /** - * {@inheritdoc} - */ - public function submitForm(array &$form, array &$form_state) { - $form_state['redirect'] = 'admin/structure/block/add/' . $form_state['values']['block'] . '/' . $this->theme; - } - -} diff --git a/core/modules/block/lib/Drupal/block/Routing/RouteSubscriber.php b/core/modules/block/lib/Drupal/block/Routing/RouteSubscriber.php index de32cd1..576ea80 100644 --- a/core/modules/block/lib/Drupal/block/Routing/RouteSubscriber.php +++ b/core/modules/block/lib/Drupal/block/Routing/RouteSubscriber.php @@ -50,18 +50,6 @@ public function routes(RouteBuildEvent $event) { ) ); $collection->add("block_admin_display.$key", $route); - - // The block plugin listing page. - $route = new Route( - "admin/structure/block/list/$key/add/{category}", - array( - '_form' => '\Drupal\block\Form\PlaceBlocksForm', - 'category' => NULL, - 'theme' => $key, - ), - array('_block_themes_access' => 'TRUE') - ); - $collection->add("block_plugin_ui.$key", $route); } } diff --git a/core/modules/block/lib/Drupal/block/Tests/BlockLanguageCacheTest.php b/core/modules/block/lib/Drupal/block/Tests/BlockLanguageCacheTest.php index 126aff0..91ee298 100644 --- a/core/modules/block/lib/Drupal/block/Tests/BlockLanguageCacheTest.php +++ b/core/modules/block/lib/Drupal/block/Tests/BlockLanguageCacheTest.php @@ -70,7 +70,6 @@ public function testBlockLinks() { // Create the block cache for all languages. foreach ($this->langcodes as $langcode) { $this->drupalGet('admin/structure/block', array('language' => $langcode)); - $this->clickLink(t('Place blocks')); } // Create a feed in the default language. @@ -80,7 +79,6 @@ public function testBlockLinks() { // Check that the block is listed for all languages. foreach ($this->langcodes as $langcode) { $this->drupalGet('admin/structure/block', array('language' => $langcode)); - $this->clickLink(t('Place blocks')); $this->assertText($feed->label()); } } diff --git a/core/modules/block/lib/Drupal/block/Tests/BlockLibrarySearchTest.php b/core/modules/block/lib/Drupal/block/Tests/BlockLibrarySearchTest.php deleted file mode 100644 index 8dcfeaa..0000000 --- a/core/modules/block/lib/Drupal/block/Tests/BlockLibrarySearchTest.php +++ /dev/null @@ -1,60 +0,0 @@ - 'Block library search', - 'description' => 'Checks that the block library search works correctly.', - 'group' => 'Block', - ); - } - - protected function setUp() { - parent::setUp(); - // Create and log in an administrative user. - $this->adminUser = $this->drupalCreateUser(array( - 'administer blocks', - 'access administration pages', - )); - $this->drupalLogin($this->adminUser); - } - - /** - * Test block library search. - */ - function testBlockLibrarySearch() { - // Check that the block plugin is valid. - $this->drupalPost('admin/structure/block/list/stark/add', array('block' => 'invalid_block'), t('Next')); - $this->assertText('You must select a valid block.'); - - // Check that the block search form redirects to the correct block form. - $this->drupalPost('admin/structure/block/list/stark/add', array('block' => 'system_main_block'), t('Next')); - $this->assertUrl('admin/structure/block/add/system_main_block/stark'); - } - -} diff --git a/core/modules/block/lib/Drupal/block/Tests/BlockTest.php b/core/modules/block/lib/Drupal/block/Tests/BlockTest.php index c766053..4ea9648 100644 --- a/core/modules/block/lib/Drupal/block/Tests/BlockTest.php +++ b/core/modules/block/lib/Drupal/block/Tests/BlockTest.php @@ -274,7 +274,7 @@ function testBlockModuleDisable() { } // Ensure that the disabled module's block plugin is no longer available. - $this->drupalGet('admin/structure/block/list/' . config('system.theme')->get('default') . '/add'); + $this->drupalGet('admin/structure/block/list/' . config('system.theme')->get('default')); $this->assertNoText(t('Test block caching')); // Confirm that the block is no longer displayed on the front page. diff --git a/core/modules/block/lib/Drupal/block/Tests/BlockTitleXSSTest.php b/core/modules/block/lib/Drupal/block/Tests/BlockTitleXSSTest.php index 3036ecd..0276553 100644 --- a/core/modules/block/lib/Drupal/block/Tests/BlockTitleXSSTest.php +++ b/core/modules/block/lib/Drupal/block/Tests/BlockTitleXSSTest.php @@ -45,7 +45,7 @@ function testXSSInTitle() { $this->drupalLogin($this->drupalCreateUser(array('administer blocks', 'access administration pages'))); $default_theme = config('system.theme')->get('default'); - $this->drupalGet('admin/structure/block/list/' . $default_theme . '/add'); + $this->drupalGet('admin/structure/block/list/' . $default_theme); $this->assertNoRaw("", 'The block title was properly sanitized in Block Plugin UI Admin page.'); } diff --git a/core/modules/block/lib/Drupal/block/Tests/BlockUiTest.php b/core/modules/block/lib/Drupal/block/Tests/BlockUiTest.php index 62d2498..b5df464 100644 --- a/core/modules/block/lib/Drupal/block/Tests/BlockUiTest.php +++ b/core/modules/block/lib/Drupal/block/Tests/BlockUiTest.php @@ -106,15 +106,6 @@ function testBlockAdminUiPage() { } /** - * Test block search. - */ - function testBlockSearch() { - $block = t('Administration'); - $blocks = drupal_json_decode($this->drupalGet('block/autocomplete', array('query' => array('q' => $block)))); - $this->assertEqual($blocks['system_menu_block:menu-admin'], $block, t('Can search for block with name !block.', array('!block' => $block))); - } - - /** * Tests that the BlockFormController populates machine name correctly. */ public function testMachineNameSuggestion() { diff --git a/core/modules/menu/lib/Drupal/menu/Tests/MenuTest.php b/core/modules/menu/lib/Drupal/menu/Tests/MenuTest.php index 0ae93d4..0de975e 100644 --- a/core/modules/menu/lib/Drupal/menu/Tests/MenuTest.php +++ b/core/modules/menu/lib/Drupal/menu/Tests/MenuTest.php @@ -161,7 +161,7 @@ function addCustomMenu() { // Enable the custom menu block. $menu_name = 'menu-' . $menu_name; // Drupal prepends the name with 'menu-'. // Confirm that the custom menu block is available. - $this->drupalGet('admin/structure/block/list/' . config('system.theme')->get('default') . '/add'); + $this->drupalGet('admin/structure/block/list/' . config('system.theme')->get('default')); $this->assertText($label); // Enable the block. @@ -379,7 +379,7 @@ function testSystemMenuRename() { // Make sure menu shows up with new name in block addition. $default_theme = variable_get('theme_default', 'stark'); - $this->drupalget('admin/structure/block/list/' . $default_theme . '/add'); + $this->drupalget('admin/structure/block/list/' . $default_theme); $this->assertText($edit['label']); } diff --git a/core/modules/system/css/system.plugin.ui.css b/core/modules/system/css/system.plugin.ui.css deleted file mode 100644 index c932788..0000000 --- a/core/modules/system/css/system.plugin.ui.css +++ /dev/null @@ -1,29 +0,0 @@ -#block-library .left-col, -#block-library .right-col { - float:left; - width:66%; - height:100%; - background-color:#ffffff; -} - -#block-library .right-col { - width:34%; - background-color:#f7f7f7; -} - -#block-library .right-col h3 { - margin: 1em -20px; - background-color:#d7d7d7; - color:#333333; - padding:8px 15px; - font-size:1.1em; -} - -#block-library .inside { - margin:0 20px; -} - -#block-library .bottom-bar { - width:100%; - clear:both; -} diff --git a/core/modules/system/lib/Drupal/system/Plugin/Block/SystemMenuBlock.php b/core/modules/system/lib/Drupal/system/Plugin/Block/SystemMenuBlock.php index 1daf4bf..d636ea3 100644 --- a/core/modules/system/lib/Drupal/system/Plugin/Block/SystemMenuBlock.php +++ b/core/modules/system/lib/Drupal/system/Plugin/Block/SystemMenuBlock.php @@ -18,6 +18,7 @@ * id = "system_menu_block", * admin_label = @Translation("System Menu"), * module = "system", + * category = "menu", * derivative = "Drupal\system\Plugin\Derivative\SystemMenuBlock" * ) */ diff --git a/core/modules/system/system.module b/core/modules/system/system.module index 1935f5c..7756051 100644 --- a/core/modules/system/system.module +++ b/core/modules/system/system.module @@ -190,10 +190,6 @@ function system_theme() { 'system_date_format_localize_form' => array( 'render element' => 'form', ), - 'system_plugin_ui_form' => array( - 'template' => 'system-plugin-ui-form', - 'render element' => 'form', - ), )); } @@ -2350,19 +2346,6 @@ function system_preprocess_block(&$variables) { } /** - * Prepares variables for system plugin UI form templates. - * - * Default template: system-plugin-ui-form.html.twig. - * - * @param array $variables - * An associative array containing: - * - form: The plugin form elements. -*/ -function template_preprocess_system_plugin_ui_form(&$variables) { - drupal_add_css(drupal_get_path('module', 'system') . '/css/system.plugin.ui.css'); -} - -/** * Provide a single block on the administration overview page. * * @param $item diff --git a/core/modules/system/templates/system-plugin-ui-form.html.twig b/core/modules/system/templates/system-plugin-ui-form.html.twig deleted file mode 100644 index 5987888..0000000 --- a/core/modules/system/templates/system-plugin-ui-form.html.twig +++ /dev/null @@ -1,30 +0,0 @@ -{# -/** - * @file - * Default theme implementation to configure blocks. - * - * Available variables: - * - form: The form elements which contains: - * - left: Form elements that appear in the left column. - * - right: Form elements that appear in the right column. - * - * @see template_preprocess_system_plugin_ui_form() - * - * @ingroup themeable - */ -#} -
-
-
- {{ form.left }} -
-
-
-
- {{ form.right }} -
-
- {% if form -%} -
{{ form }}
- {%- endif -%} -
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 d3cada4..c749a19 100644 --- a/core/modules/views/lib/Drupal/views/Plugin/Block/ViewsBlock.php +++ b/core/modules/views/lib/Drupal/views/Plugin/Block/ViewsBlock.php @@ -7,10 +7,13 @@ 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; /** @@ -23,7 +26,85 @@ * derivative = "Drupal\views\Plugin\Derivative\ViewsBlock" * ) */ -class ViewsBlock extends ViewsBlockBase { +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; + } /** * {@inheritdoc} @@ -63,8 +144,6 @@ public function blockForm($form, &$form_state) { if ($this->displaySet) { return $this->view->display_handler->blockForm($this, $form, $form_state); } - - return array(); } /** @@ -86,6 +165,31 @@ public function blockSubmit($form, &$form_state) { } /** + * 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. * * @param \Drupal\Core\Entity\EntityStorageControllerInterface $manager diff --git a/core/modules/views/lib/Drupal/views/Plugin/Block/ViewsBlockBase.php b/core/modules/views/lib/Drupal/views/Plugin/Block/ViewsBlockBase.php deleted file mode 100644 index b90b3e6..0000000 --- a/core/modules/views/lib/Drupal/views/Plugin/Block/ViewsBlockBase.php +++ /dev/null @@ -1,124 +0,0 @@ -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); - } - } - -} diff --git a/core/modules/views/lib/Drupal/views/Plugin/Block/ViewsExposedFilterBlock.php b/core/modules/views/lib/Drupal/views/Plugin/Block/ViewsExposedFilterBlock.php index 3ef4ecd..577caa5 100644 --- a/core/modules/views/lib/Drupal/views/Plugin/Block/ViewsExposedFilterBlock.php +++ b/core/modules/views/lib/Drupal/views/Plugin/Block/ViewsExposedFilterBlock.php @@ -20,7 +20,7 @@ * derivative = "Drupal\views\Plugin\Derivative\ViewsExposedFilterBlock" * ) */ -class ViewsExposedFilterBlock extends ViewsBlockBase { +class ViewsExposedFilterBlock extends ViewsBlock { /** * {@inheritdoc} @@ -31,6 +31,7 @@ public function build() { // contextual links. $this->addContextualLinks($output, 'exposed_filter'); + $this->view->destroy(); return $output; } diff --git a/core/modules/views/lib/Drupal/views/Tests/Plugin/ExposedFormTest.php b/core/modules/views/lib/Drupal/views/Tests/Plugin/ExposedFormTest.php index 05b7035..d491d1b 100644 --- a/core/modules/views/lib/Drupal/views/Tests/Plugin/ExposedFormTest.php +++ b/core/modules/views/lib/Drupal/views/Tests/Plugin/ExposedFormTest.php @@ -8,8 +8,6 @@ namespace Drupal\views\Tests\Plugin; use Drupal\views\Tests\ViewTestBase; -use Drupal\views\ViewExecutable; -use Drupal\views\Views; /** * Tests exposed forms. @@ -21,14 +19,14 @@ class ExposedFormTest extends ViewTestBase { * * @var array */ - public static $testViews = array('test_reset_button', 'test_exposed_block'); + public static $testViews = array('test_reset_button'); /** * Modules to enable. * * @var array */ - public static $modules = array('views_ui', 'block'); + public static $modules = array('views_ui'); public static function getInfo() { return array( @@ -104,45 +102,11 @@ public function testExposedFormRender() { $output = $exposed_form->renderExposedForm(); $this->drupalSetContent(drupal_render($output)); - $this->assertFieldByXpath('//form/@id', $this->getExpectedExposedFormId($view), 'Expected form ID found.'); + $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.'); $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); - } - } diff --git a/core/modules/views/lib/Drupal/views/Tests/Wizard/BasicTest.php b/core/modules/views/lib/Drupal/views/Tests/Wizard/BasicTest.php index 8f3f4eb..40638fc 100644 --- a/core/modules/views/lib/Drupal/views/Tests/Wizard/BasicTest.php +++ b/core/modules/views/lib/Drupal/views/Tests/Wizard/BasicTest.php @@ -122,7 +122,7 @@ function testViewsWizardAndListing() { $this->assertLinkByHref(url($view3['page[path]'])); // Confirm that the block is available in the block administration UI. - $this->drupalGet('admin/structure/block/list/' . config('system.theme')->get('default') . '/add'); + $this->drupalGet('admin/structure/block/list/' . config('system.theme')->get('default')); $this->assertText('View: ' . $view3['label']); // Place the block. diff --git a/core/modules/views/lib/Drupal/views/Tests/Wizard/ItemsPerPageTest.php b/core/modules/views/lib/Drupal/views/Tests/Wizard/ItemsPerPageTest.php index 485f048..be9d40e 100644 --- a/core/modules/views/lib/Drupal/views/Tests/Wizard/ItemsPerPageTest.php +++ b/core/modules/views/lib/Drupal/views/Tests/Wizard/ItemsPerPageTest.php @@ -75,7 +75,7 @@ function testItemsPerPage() { $this->assertTrue($pos5 < $pos4 && $pos4 < $pos3 && $pos3 < $pos2, 'The nodes appear in the expected order in the page display.'); // Confirm that the block is listed in the block administration UI. - $this->drupalGet('admin/structure/block/list/' . config('system.theme')->get('default') . '/add'); + $this->drupalGet('admin/structure/block/list/' . config('system.theme')->get('default')); $this->assertText('View: ' . $view['label']); // Place the block, visit a page that displays the block, and check that the diff --git a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_exposed_block.yml b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_exposed_block.yml deleted file mode 100644 index 0528a1d..0000000 --- a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_exposed_block.yml +++ /dev/null @@ -1,56 +0,0 @@ -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: '' diff --git a/core/modules/views_ui/lib/Drupal/views_ui/Tests/OverrideDisplaysTest.php b/core/modules/views_ui/lib/Drupal/views_ui/Tests/OverrideDisplaysTest.php index 1dab1f6..f94e01f 100644 --- a/core/modules/views_ui/lib/Drupal/views_ui/Tests/OverrideDisplaysTest.php +++ b/core/modules/views_ui/lib/Drupal/views_ui/Tests/OverrideDisplaysTest.php @@ -54,7 +54,7 @@ function testOverrideDisplays() { $this->assertText($original_title); // Confirm that the view block is available in the block administration UI. - $this->drupalGet('admin/structure/block/list/' . config('system.theme')->get('default') . '/add'); + $this->drupalGet('admin/structure/block/list/' . config('system.theme')->get('default')); $this->assertText('View: ' . $view['label']); // Place the block. @@ -112,7 +112,7 @@ function testWizardMixedDefaultOverriddenDisplays() { $this->assertNoText($view['block[title]']); // Confirm that the block is available in the block administration UI. - $this->drupalGet('admin/structure/block/list/' . config('system.theme')->get('default') . '/add'); + $this->drupalGet('admin/structure/block/list/' . config('system.theme')->get('default')); $this->assertText('View: ' . $view['label']); // Put the block into the first sidebar region, and make sure it will not