/** * Shows a list of blocks that can be added to a theme's layout. * * @param \Symfony\Component\HttpFoundation\Request $request * The current request. * @param string $theme * Theme key of the block list. * * @return array * A render array as expected by the renderer. */ public function listBlocks(Request $request, $theme) { // Since modals do not render any other part of the page, we need to render // them manually as part of this listing. if ($request->query->get(MainContentViewSubscriber::WRAPPER_FORMAT) === 'drupal_modal') { $build['local_actions'] = $this->buildLocalActions(); } $headers = [['data' => $this->t('Block')], ['data' => $this->t('Category')], ['data' => $this->t('Operations')]]; // Only add blocks which work without any available context. $definitions = $this->blockManager->getDefinitionsForContexts(); // Order by category, and then by admin label. $definitions = $this->blockManager->getSortedDefinitions($definitions); $region = $request->query->get('region'); $rows = []; foreach ($definitions as $plugin_id => $plugin_definition) { $row = []; $row['title']['data'] = ['#markup' => $plugin_definition['admin_label'], '#prefix' => '<div class="block-filter-text-source">', '#suffix' => '</div>']; $row['category']['data'] = $plugin_definition['category']; $links['add'] = ['title' => $this->t('Place block'), 'url' => Url::fromRoute('block.admin_add', ['plugin_id' => $plugin_id, 'theme' => $theme]), 'attributes' => ['class' => ['use-ajax'], 'data-dialog-type' => 'modal', 'data-dialog-options' => Json::encode(['width' => 700])]]; if ($region) { $links['add']['query']['region'] = $region; } $row['operations']['data'] = ['#type' => 'operations', '#links' => $links]; $rows[] = $row; } $build['#attached']['library'][] = 'block/drupal.block.admin'; $build['filter'] = ['#type' => 'search', '#title' => $this->t('Filter'), '#title_display' => 'invisible', '#size' => 30, '#placeholder' => $this->t('Filter by block name'), '#attributes' => ['class' => ['block-filter-text'], 'data-element' => '.block-add-table', 'title' => $this->t('Enter a part of the block name to filter by.')]]; $build['blocks'] = ['#type' => 'table', '#header' => $headers, '#rows' => $rows, '#empty' => $this->t('No blocks available.'), '#attributes' => ['class' => ['block-add-table']]]; return $build; }
/** * Get a list of blocks that can be placed in a mega menu. * * @param Request $request * @param MegaMenuInterface $mega_menu * @return array */ public function blockLibrary(Request $request, MegaMenuInterface $mega_menu) { // Get the query parameters needed. $link = $request->query->get('link'); $region = $request->query->get('region'); // Only add blocks which work without any available context. $blocks = $this->blockManager->getDefinitionsForContexts($this->contextRepository->getAvailableContexts()); // Order by category, and then by admin label. $blocks = $this->blockManager->getSortedDefinitions($blocks); $build['filter'] = ['#type' => 'search', '#title' => $this->t('Filter'), '#title_display' => 'invisible', '#size' => 30, '#placeholder' => $this->t('Filter by block name'), '#attributes' => ['class' => ['block-filter-text'], 'data-element' => '.block-add-table', 'title' => $this->t('Enter a part of the block name to filter by.')]]; $headers = [$this->t('Block'), $this->t('Category'), $this->t('Operations')]; $build['blocks'] = ['#type' => 'table', '#header' => $headers, '#rows' => [], '#empty' => $this->t('No blocks available.'), '#attributes' => ['class' => ['block-add-table']]]; // Add each block definition to the table. foreach ($blocks as $block_id => $block) { $links = ['add' => ['title' => $this->t('Place block'), 'url' => Url::fromRoute('mega_menu.block_add', ['mega_menu' => $mega_menu->id(), 'block_id' => $block_id], ['query' => ['link' => $link, 'region' => $region]]), 'attributes' => ['class' => ['use-ajax'], 'data-dialog-type' => 'modal', 'data-dialog-options' => Json::encode(['width' => 700])]]]; $build['blocks']['#rows'][] = ['title' => ['data' => ['#type' => 'inline_template', '#template' => '<div class="block-filter-text-source">{{ label }}</div>', '#context' => ['label' => $block['admin_label']]]], 'category' => ['data' => $block['category']], 'operations' => ['data' => ['#type' => 'operations', '#links' => $links]]]; } return $build; }
/** * Presents a list of blocks to add to the variant. * * @param \Symfony\Component\HttpFoundation\Request $request * The current request. * @param \Drupal\page_manager\PageVariantInterface $page_variant * The page entity. * * @return array * The block selection page. */ public function selectBlock(Request $request, PageVariantInterface $page_variant) { // Add a section containing the available blocks to be added to the variant. $build = ['#type' => 'container', '#attached' => ['library' => ['core/drupal.ajax']]]; $available_plugins = $this->blockManager->getDefinitionsForContexts($page_variant->getContexts()); // Order by category, and then by admin label. $available_plugins = $this->blockManager->getSortedDefinitions($available_plugins); foreach ($available_plugins as $plugin_id => $plugin_definition) { // Make a section for each region. $category = $plugin_definition['category']; $category_key = 'category-' . $category; if (!isset($build[$category_key])) { $build[$category_key] = ['#type' => 'fieldgroup', '#title' => $category, 'content' => ['#theme' => 'links']]; } // Add a link for each available block within each region. $build[$category_key]['content']['#links'][$plugin_id] = ['title' => $plugin_definition['admin_label'], 'url' => Url::fromRoute('page_manager.variant_add_block', ['page' => $page_variant->get('page'), 'page_variant' => $page_variant->id(), 'block_id' => $plugin_id, 'region' => $request->query->get('region')]), 'attributes' => $this->getAjaxAttributes()]; } return $build; }
/** * Implements \Drupal\Core\Form\FormInterface::buildForm(). * * Form constructor for the main block administration form. */ public function buildForm(array $form, FormStateInterface $form_state) { $placement = FALSE; if ($this->request->query->has('block-placement')) { $placement = $this->request->query->get('block-placement'); $form['#attached']['drupalSettings']['blockPlacement'] = $placement; } $entities = $this->load(); $form['#theme'] = array('block_list'); $form['#attached']['library'][] = 'core/drupal.tableheader'; $form['#attached']['library'][] = 'block/drupal.block'; $form['#attached']['library'][] = 'block/drupal.block.admin'; $form['#attributes']['class'][] = 'clearfix'; // Add a last region for disabled blocks. $block_regions_with_disabled = $this->regions + array(BlockInterface::BLOCK_REGION_NONE => BlockInterface::BLOCK_REGION_NONE); $form['block_regions'] = array('#type' => 'value', '#value' => $block_regions_with_disabled); // Weights range from -delta to +delta, so delta should be at least half // of the amount of blocks present. This makes sure all blocks in the same // region get an unique weight. $weight_delta = round(count($entities) / 2); // Build the form tree. $form['edited_theme'] = array('#type' => 'value', '#value' => $this->theme); $form['blocks'] = array('#type' => 'table', '#header' => array(t('Block'), t('Category'), t('Region'), t('Weight'), t('Operations')), '#attributes' => array('id' => 'blocks')); // Build blocks first for each region. foreach ($entities as $entity_id => $entity) { $definition = $entity->getPlugin()->getPluginDefinition(); $blocks[$entity->getRegion()][$entity_id] = array('label' => $entity->label(), 'entity_id' => $entity_id, 'weight' => $entity->getWeight(), 'entity' => $entity, 'category' => $definition['category']); } // Loop over each region and build blocks. foreach ($block_regions_with_disabled as $region => $title) { $form['blocks']['#tabledrag'][] = array('action' => 'match', 'relationship' => 'sibling', 'group' => 'block-region-select', 'subgroup' => 'block-region-' . $region, 'hidden' => FALSE); $form['blocks']['#tabledrag'][] = array('action' => 'order', 'relationship' => 'sibling', 'group' => 'block-weight', 'subgroup' => 'block-weight-' . $region); $form['blocks'][$region] = array('#attributes' => array('class' => array('region-title', 'region-title-' . $region), 'no_striping' => TRUE)); $form['blocks'][$region]['title'] = array('#markup' => $region != BlockInterface::BLOCK_REGION_NONE ? $title : t('Disabled', array(), array('context' => 'Plural')), '#wrapper_attributes' => array('colspan' => 5)); $form['blocks'][$region . '-message'] = array('#attributes' => array('class' => array('region-message', 'region-' . $region . '-message', empty($blocks[$region]) ? 'region-empty' : 'region-populated'))); $form['blocks'][$region . '-message']['message'] = array('#markup' => '<em>' . t('No blocks in this region') . '</em>', '#wrapper_attributes' => array('colspan' => 5)); if (isset($blocks[$region])) { foreach ($blocks[$region] as $info) { $entity_id = $info['entity_id']; $form['blocks'][$entity_id] = array('#attributes' => array('class' => array('draggable'))); if ($placement && $placement == Html::getClass($entity_id)) { $form['blocks'][$entity_id]['#attributes']['class'][] = 'color-warning'; $form['blocks'][$entity_id]['#attributes']['class'][] = 'js-block-placed'; } $form['blocks'][$entity_id]['info'] = array('#markup' => SafeMarkup::checkPlain($info['label']), '#wrapper_attributes' => array('class' => array('block'))); $form['blocks'][$entity_id]['type'] = array('#markup' => $info['category']); $form['blocks'][$entity_id]['region-theme']['region'] = array('#type' => 'select', '#default_value' => $region, '#empty_value' => BlockInterface::BLOCK_REGION_NONE, '#title' => t('Region for @block block', array('@block' => $info['label'])), '#title_display' => 'invisible', '#options' => $this->regions, '#attributes' => array('class' => array('block-region-select', 'block-region-' . $region)), '#parents' => array('blocks', $entity_id, 'region')); $form['blocks'][$entity_id]['region-theme']['theme'] = array('#type' => 'hidden', '#value' => $this->theme, '#parents' => array('blocks', $entity_id, 'theme')); $form['blocks'][$entity_id]['weight'] = array('#type' => 'weight', '#default_value' => $info['weight'], '#delta' => $weight_delta, '#title' => t('Weight for @block block', array('@block' => $info['label'])), '#title_display' => 'invisible', '#attributes' => array('class' => array('block-weight', 'block-weight-' . $region))); $form['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; } $form['actions'] = array('#tree' => FALSE, '#type' => 'actions'); $form['actions']['submit'] = array('#type' => 'submit', '#value' => t('Save blocks'), '#button_type' => 'primary'); $form['place_blocks']['title'] = array('#type' => 'container', '#markup' => '<h3>' . t('Place blocks') . '</h3>', '#attributes' => array('class' => array('entity-meta-header'))); $form['place_blocks']['filter'] = 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.'))); $form['place_blocks']['list']['#type'] = 'container'; $form['place_blocks']['list']['#attributes']['class'][] = 'entity-meta'; // Only add blocks which work without any available context. $definitions = $this->blockManager->getDefinitionsForContexts(); $sorted_definitions = $this->blockManager->getSortedDefinitions($definitions); foreach ($sorted_definitions as $plugin_id => $plugin_definition) { $category = SafeMarkup::checkPlain($plugin_definition['category']); $category_key = 'category-' . $category; if (!isset($form['place_blocks']['list'][$category_key])) { $form['place_blocks']['list'][$category_key] = array('#type' => 'details', '#title' => $category, '#open' => TRUE, 'content' => array('#theme' => 'links', '#links' => array(), '#attributes' => array('class' => array('block-list')))); } $form['place_blocks']['list'][$category_key]['content']['#links'][$plugin_id] = array('title' => $plugin_definition['admin_label'], 'url' => Url::fromRoute('block.admin_add', ['plugin_id' => $plugin_id, 'theme' => $this->theme]), 'attributes' => array('class' => array('use-ajax', 'block-filter-text-source'), 'data-dialog-type' => 'modal', 'data-dialog-options' => Json::encode(array('width' => 700)))); } return $form; }
/** * Gets a list of all available blocks sorted by category and label. * * @return array[] */ public function getSystemBlocks() { $contexts = $this->contextRepository->getAvailableContexts(); $blocks = $this->blockManager->getDefinitionsForContexts($contexts); return $this->blockManager->getSortedDefinitions($blocks); }