3 namespace Drupal\Core\Config\Entity;
5 use Drupal\Core\Entity\EntityInterface;
6 use Drupal\Core\Entity\EntityStorageInterface;
7 use Drupal\Core\Entity\EntityTypeInterface;
8 use Drupal\Core\Form\FormInterface;
9 use Drupal\Core\Form\FormStateInterface;
12 * Defines a class to build a draggable listing of configuration entities.
14 abstract class DraggableListBuilder extends ConfigEntityListBuilder implements FormInterface {
17 * The key to use for the form element containing the entities.
21 protected $entitiesKey = 'entities';
24 * The entities being listed.
26 * @var \Drupal\Core\Entity\EntityInterface[]
28 protected $entities = [];
31 * Name of the entity's weight field or FALSE if no field is provided.
35 protected $weightKey = FALSE;
40 protected $limit = FALSE;
45 * @var \Drupal\Core\Form\FormBuilderInterface
47 protected $formBuilder;
52 public function __construct(EntityTypeInterface $entity_type, EntityStorageInterface $storage) {
53 parent::__construct($entity_type, $storage);
55 // Check if the entity type supports weighting.
56 if ($this->entityType->hasKey('weight')) {
57 $this->weightKey = $this->entityType->getKey('weight');
64 public function buildHeader() {
66 if (!empty($this->weightKey)) {
67 $header['weight'] = t('Weight');
69 return $header + parent::buildHeader();
75 public function buildRow(EntityInterface $entity) {
77 if (!empty($this->weightKey)) {
78 // Override default values to markup elements.
79 $row['#attributes']['class'][] = 'draggable';
80 $row['#weight'] = $entity->get($this->weightKey);
84 '#title' => t('Weight for @title', ['@title' => $entity->label()]),
85 '#title_display' => 'invisible',
86 '#default_value' => $entity->get($this->weightKey),
87 '#attributes' => ['class' => ['weight']],
90 return $row + parent::buildRow($entity);
96 public function render() {
97 if (!empty($this->weightKey)) {
98 return $this->formBuilder()->getForm($this);
100 return parent::render();
106 public function buildForm(array $form, FormStateInterface $form_state) {
107 $form[$this->entitiesKey] = [
109 '#header' => $this->buildHeader(),
110 '#empty' => t('There are no @label yet.', ['@label' => $this->entityType->getPluralLabel()]),
114 'relationship' => 'sibling',
120 $this->entities = $this->load();
122 // Change the delta of the weight field if have more than 20 entities.
123 if (!empty($this->weightKey)) {
124 $count = count($this->entities);
126 $delta = ceil($count / 2);
129 foreach ($this->entities as $entity) {
130 $row = $this->buildRow($entity);
131 if (isset($row['label'])) {
132 $row['label'] = ['#markup' => $row['label']];
134 if (isset($row['weight'])) {
135 $row['weight']['#delta'] = $delta;
137 $form[$this->entitiesKey][$entity->id()] = $row;
140 $form['actions']['#type'] = 'actions';
141 $form['actions']['submit'] = [
143 '#value' => t('Save'),
144 '#button_type' => 'primary',
153 public function validateForm(array &$form, FormStateInterface $form_state) {
160 public function submitForm(array &$form, FormStateInterface $form_state) {
161 foreach ($form_state->getValue($this->entitiesKey) as $id => $value) {
162 if (isset($this->entities[$id]) && $this->entities[$id]->get($this->weightKey) != $value['weight']) {
163 // Save entity only when its weight was changed.
164 $this->entities[$id]->set($this->weightKey, $value['weight']);
165 $this->entities[$id]->save();
171 * Returns the form builder.
173 * @return \Drupal\Core\Form\FormBuilderInterface
176 protected function formBuilder() {
177 if (!$this->formBuilder) {
178 $this->formBuilder = \Drupal::formBuilder();
180 return $this->formBuilder;