123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393 |
- <?php
- namespace Drupal\block;
- use Drupal\Component\Utility\Html;
- use Drupal\Component\Serialization\Json;
- use Drupal\Core\Config\Entity\ConfigEntityListBuilder;
- use Drupal\Core\Entity\EntityInterface;
- use Drupal\Core\Entity\EntityStorageInterface;
- use Drupal\Core\Entity\EntityTypeInterface;
- use Drupal\Core\Form\FormBuilderInterface;
- use Drupal\Core\Form\FormInterface;
- use Drupal\Core\Form\FormStateInterface;
- use Drupal\Core\Messenger\MessengerInterface;
- use Drupal\Core\Theme\ThemeManagerInterface;
- use Drupal\Core\Url;
- use Symfony\Component\DependencyInjection\ContainerInterface;
- use Symfony\Component\HttpFoundation\Request;
- /**
- * Defines a class to build a listing of block entities.
- *
- * @see \Drupal\block\Entity\Block
- */
- class BlockListBuilder extends ConfigEntityListBuilder implements FormInterface {
- /**
- * The theme containing the blocks.
- *
- * @var string
- */
- protected $theme;
- /**
- * The current request.
- *
- * @var \Symfony\Component\HttpFoundation\Request
- */
- protected $request;
- /**
- * The theme manager.
- *
- * @var \Drupal\Core\Theme\ThemeManagerInterface
- */
- protected $themeManager;
- /**
- * The form builder.
- *
- * @var \Drupal\Core\Form\FormBuilderInterface
- */
- protected $formBuilder;
- /**
- * {@inheritdoc}
- */
- protected $limit = FALSE;
- /**
- * The messenger.
- *
- * @var \Drupal\Core\Messenger\MessengerInterface
- */
- protected $messenger;
- /**
- * Constructs a new BlockListBuilder object.
- *
- * @param \Drupal\Core\Entity\EntityTypeInterface $entity_type
- * The entity type definition.
- * @param \Drupal\Core\Entity\EntityStorageInterface $storage
- * The entity storage class.
- * @param \Drupal\Core\Theme\ThemeManagerInterface $theme_manager
- * The theme manager.
- * @param \Drupal\Core\Form\FormBuilderInterface $form_builder
- * The form builder.
- */
- public function __construct(EntityTypeInterface $entity_type, EntityStorageInterface $storage, ThemeManagerInterface $theme_manager, FormBuilderInterface $form_builder, MessengerInterface $messenger) {
- parent::__construct($entity_type, $storage);
- $this->themeManager = $theme_manager;
- $this->formBuilder = $form_builder;
- $this->messenger = $messenger;
- }
- /**
- * {@inheritdoc}
- */
- public static function createInstance(ContainerInterface $container, EntityTypeInterface $entity_type) {
- return new static(
- $entity_type,
- $container->get('entity.manager')->getStorage($entity_type->id()),
- $container->get('theme.manager'),
- $container->get('form_builder'),
- $container->get('messenger')
- );
- }
- /**
- * {@inheritdoc}
- *
- * @param string|null $theme
- * (optional) The theme to display the blocks for. If NULL, the current
- * theme will be used.
- * @param \Symfony\Component\HttpFoundation\Request $request
- * The current request.
- *
- * @return array
- * The block list as a renderable array.
- */
- public function render($theme = NULL, Request $request = NULL) {
- $this->request = $request;
- $this->theme = $theme;
- return $this->formBuilder->getForm($this);
- }
- /**
- * {@inheritdoc}
- */
- public function getFormId() {
- return 'block_admin_display_form';
- }
- /**
- * {@inheritdoc}
- */
- public function buildForm(array $form, FormStateInterface $form_state) {
- $form['#attached']['library'][] = 'core/drupal.tableheader';
- $form['#attached']['library'][] = 'block/drupal.block';
- $form['#attached']['library'][] = 'block/drupal.block.admin';
- $form['#attributes']['class'][] = 'clearfix';
- // Build the form tree.
- $form['blocks'] = $this->buildBlocksForm();
- $form['actions'] = [
- '#tree' => FALSE,
- '#type' => 'actions',
- ];
- $form['actions']['submit'] = [
- '#type' => 'submit',
- '#value' => $this->t('Save blocks'),
- '#button_type' => 'primary',
- ];
- return $form;
- }
- /**
- * Builds the main "Blocks" portion of the form.
- *
- * @return array
- */
- protected function buildBlocksForm() {
- // Build blocks first for each region.
- $blocks = [];
- $entities = $this->load();
- /** @var \Drupal\block\BlockInterface[] $entities */
- foreach ($entities as $entity_id => $entity) {
- $definition = $entity->getPlugin()->getPluginDefinition();
- $blocks[$entity->getRegion()][$entity_id] = [
- 'label' => $entity->label(),
- 'entity_id' => $entity_id,
- 'weight' => $entity->getWeight(),
- 'entity' => $entity,
- 'category' => $definition['category'],
- 'status' => $entity->status(),
- ];
- }
- $form = [
- '#type' => 'table',
- '#header' => [
- $this->t('Block'),
- $this->t('Category'),
- $this->t('Region'),
- $this->t('Weight'),
- $this->t('Operations'),
- ],
- '#attributes' => [
- 'id' => 'blocks',
- ],
- ];
- // 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);
- $placement = FALSE;
- if ($this->request->query->has('block-placement')) {
- $placement = $this->request->query->get('block-placement');
- $form['#attached']['drupalSettings']['blockPlacement'] = $placement;
- }
- // Loop over each region and build blocks.
- $regions = $this->systemRegionList($this->getThemeName(), REGIONS_VISIBLE);
- foreach ($regions as $region => $title) {
- $form['#tabledrag'][] = [
- 'action' => 'match',
- 'relationship' => 'sibling',
- 'group' => 'block-region-select',
- 'subgroup' => 'block-region-' . $region,
- 'hidden' => FALSE,
- ];
- $form['#tabledrag'][] = [
- 'action' => 'order',
- 'relationship' => 'sibling',
- 'group' => 'block-weight',
- 'subgroup' => 'block-weight-' . $region,
- ];
- $form['region-' . $region] = [
- '#attributes' => [
- 'class' => ['region-title', 'region-title-' . $region],
- 'no_striping' => TRUE,
- ],
- ];
- $form['region-' . $region]['title'] = [
- '#theme_wrappers' => [
- 'container' => [
- '#attributes' => ['class' => 'region-title__action'],
- ],
- ],
- '#prefix' => $title,
- '#type' => 'link',
- '#title' => $this->t('Place block <span class="visually-hidden">in the %region region</span>', ['%region' => $title]),
- '#url' => Url::fromRoute('block.admin_library', ['theme' => $this->getThemeName()], ['query' => ['region' => $region]]),
- '#wrapper_attributes' => [
- 'colspan' => 5,
- ],
- '#attributes' => [
- 'class' => ['use-ajax', 'button', 'button--small'],
- 'data-dialog-type' => 'modal',
- 'data-dialog-options' => Json::encode([
- 'width' => 700,
- ]),
- ],
- ];
- $form['region-' . $region . '-message'] = [
- '#attributes' => [
- 'class' => [
- 'region-message',
- 'region-' . $region . '-message',
- empty($blocks[$region]) ? 'region-empty' : 'region-populated',
- ],
- ],
- ];
- $form['region-' . $region . '-message']['message'] = [
- '#markup' => '<em>' . $this->t('No blocks in this region') . '</em>',
- '#wrapper_attributes' => [
- 'colspan' => 5,
- ],
- ];
- if (isset($blocks[$region])) {
- foreach ($blocks[$region] as $info) {
- $entity_id = $info['entity_id'];
- $form[$entity_id] = [
- '#attributes' => [
- 'class' => ['draggable'],
- ],
- ];
- $form[$entity_id]['#attributes']['class'][] = $info['status'] ? 'block-enabled' : 'block-disabled';
- if ($placement && $placement == Html::getClass($entity_id)) {
- $form[$entity_id]['#attributes']['class'][] = 'color-success';
- $form[$entity_id]['#attributes']['class'][] = 'js-block-placed';
- }
- $form[$entity_id]['info'] = [
- '#plain_text' => $info['status'] ? $info['label'] : $this->t('@label (disabled)', ['@label' => $info['label']]),
- '#wrapper_attributes' => [
- 'class' => ['block'],
- ],
- ];
- $form[$entity_id]['type'] = [
- '#markup' => $info['category'],
- ];
- $form[$entity_id]['region-theme']['region'] = [
- '#type' => 'select',
- '#default_value' => $region,
- '#required' => TRUE,
- '#title' => $this->t('Region for @block block', ['@block' => $info['label']]),
- '#title_display' => 'invisible',
- '#options' => $regions,
- '#attributes' => [
- 'class' => ['block-region-select', 'block-region-' . $region],
- ],
- '#parents' => ['blocks', $entity_id, 'region'],
- ];
- $form[$entity_id]['region-theme']['theme'] = [
- '#type' => 'hidden',
- '#value' => $this->getThemeName(),
- '#parents' => ['blocks', $entity_id, 'theme'],
- ];
- $form[$entity_id]['weight'] = [
- '#type' => 'weight',
- '#default_value' => $info['weight'],
- '#delta' => $weight_delta,
- '#title' => $this->t('Weight for @block block', ['@block' => $info['label']]),
- '#title_display' => 'invisible',
- '#attributes' => [
- 'class' => ['block-weight', 'block-weight-' . $region],
- ],
- ];
- $form[$entity_id]['operations'] = $this->buildOperations($info['entity']);
- }
- }
- }
- // Do not allow disabling the main system content block when it is present.
- if (isset($form['system_main']['region'])) {
- $form['system_main']['region']['#required'] = TRUE;
- }
- return $form;
- }
- /**
- * Gets the name of the theme used for this block listing.
- *
- * @return string
- * The name of the theme.
- */
- protected function getThemeName() {
- // If no theme was specified, use the current theme.
- if (!$this->theme) {
- $this->theme = $this->themeManager->getActiveTheme()->getName();
- }
- return $this->theme;
- }
- /**
- * {@inheritdoc}
- */
- protected function getEntityIds() {
- return $this->getStorage()->getQuery()
- ->condition('theme', $this->getThemeName())
- ->sort($this->entityType->getKey('id'))
- ->execute();
- }
- /**
- * {@inheritdoc}
- */
- public function getDefaultOperations(EntityInterface $entity) {
- $operations = parent::getDefaultOperations($entity);
- if (isset($operations['edit'])) {
- $operations['edit']['title'] = $this->t('Configure');
- }
- if (isset($operations['delete'])) {
- $operations['delete']['title'] = $this->t('Remove');
- }
- return $operations;
- }
- /**
- * {@inheritdoc}
- */
- public function validateForm(array &$form, FormStateInterface $form_state) {
- // No validation.
- }
- /**
- * {@inheritdoc}
- */
- public function submitForm(array &$form, FormStateInterface $form_state) {
- $entities = $this->storage->loadMultiple(array_keys($form_state->getValue('blocks')));
- /** @var \Drupal\block\BlockInterface[] $entities */
- foreach ($entities as $entity_id => $entity) {
- $entity_values = $form_state->getValue(['blocks', $entity_id]);
- $entity->setWeight($entity_values['weight']);
- $entity->setRegion($entity_values['region']);
- $entity->save();
- }
- $this->messenger->addStatus($this->t('The block settings have been updated.'));
- // Remove any previously set block placement.
- $this->request->query->remove('block-placement');
- }
- /**
- * Wraps system_region_list().
- */
- protected function systemRegionList($theme, $show = REGIONS_ALL) {
- return system_region_list($theme, $show);
- }
- }
|