Version 1
[yaffs-website] / web / core / modules / block / src / BlockListBuilder.php
diff --git a/web/core/modules/block/src/BlockListBuilder.php b/web/core/modules/block/src/BlockListBuilder.php
new file mode 100644 (file)
index 0000000..37b2e8b
--- /dev/null
@@ -0,0 +1,383 @@
+<?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\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;
+
+  /**
+   * 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) {
+    parent::__construct($entity_type, $storage);
+
+    $this->themeManager = $theme_manager;
+    $this->formBuilder = $form_builder;
+  }
+
+  /**
+   * {@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')
+    );
+  }
+
+  /**
+   * {@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();
+    }
+    drupal_set_message(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);
+  }
+
+}