DraggableListBuilder.php 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. <?php
  2. namespace Drupal\Core\Config\Entity;
  3. use Drupal\Core\Entity\EntityInterface;
  4. use Drupal\Core\Entity\EntityStorageInterface;
  5. use Drupal\Core\Entity\EntityTypeInterface;
  6. use Drupal\Core\Form\FormInterface;
  7. use Drupal\Core\Form\FormStateInterface;
  8. /**
  9. * Defines a class to build a draggable listing of configuration entities.
  10. */
  11. abstract class DraggableListBuilder extends ConfigEntityListBuilder implements FormInterface {
  12. /**
  13. * The key to use for the form element containing the entities.
  14. *
  15. * @var string
  16. */
  17. protected $entitiesKey = 'entities';
  18. /**
  19. * The entities being listed.
  20. *
  21. * @var \Drupal\Core\Entity\EntityInterface[]
  22. */
  23. protected $entities = [];
  24. /**
  25. * Name of the entity's weight field or FALSE if no field is provided.
  26. *
  27. * @var string|bool
  28. */
  29. protected $weightKey = FALSE;
  30. /**
  31. * {@inheritdoc}
  32. */
  33. protected $limit = FALSE;
  34. /**
  35. * The form builder.
  36. *
  37. * @var \Drupal\Core\Form\FormBuilderInterface
  38. */
  39. protected $formBuilder;
  40. /**
  41. * {@inheritdoc}
  42. */
  43. public function __construct(EntityTypeInterface $entity_type, EntityStorageInterface $storage) {
  44. parent::__construct($entity_type, $storage);
  45. // Check if the entity type supports weighting.
  46. if ($this->entityType->hasKey('weight')) {
  47. $this->weightKey = $this->entityType->getKey('weight');
  48. }
  49. }
  50. /**
  51. * {@inheritdoc}
  52. */
  53. public function buildHeader() {
  54. $header = [];
  55. if (!empty($this->weightKey)) {
  56. $header['weight'] = t('Weight');
  57. }
  58. return $header + parent::buildHeader();
  59. }
  60. /**
  61. * {@inheritdoc}
  62. */
  63. public function buildRow(EntityInterface $entity) {
  64. $row = [];
  65. if (!empty($this->weightKey)) {
  66. // Override default values to markup elements.
  67. $row['#attributes']['class'][] = 'draggable';
  68. $row['#weight'] = $entity->get($this->weightKey);
  69. // Add weight column.
  70. $row['weight'] = [
  71. '#type' => 'weight',
  72. '#title' => t('Weight for @title', ['@title' => $entity->label()]),
  73. '#title_display' => 'invisible',
  74. '#default_value' => $entity->get($this->weightKey),
  75. '#attributes' => ['class' => ['weight']],
  76. ];
  77. }
  78. return $row + parent::buildRow($entity);
  79. }
  80. /**
  81. * {@inheritdoc}
  82. */
  83. public function render() {
  84. if (!empty($this->weightKey)) {
  85. return $this->formBuilder()->getForm($this);
  86. }
  87. return parent::render();
  88. }
  89. /**
  90. * {@inheritdoc}
  91. */
  92. public function buildForm(array $form, FormStateInterface $form_state) {
  93. $form[$this->entitiesKey] = [
  94. '#type' => 'table',
  95. '#header' => $this->buildHeader(),
  96. '#empty' => t('There are no @label yet.', ['@label' => $this->entityType->getPluralLabel()]),
  97. '#tabledrag' => [
  98. [
  99. 'action' => 'order',
  100. 'relationship' => 'sibling',
  101. 'group' => 'weight',
  102. ],
  103. ],
  104. ];
  105. $this->entities = $this->load();
  106. $delta = 10;
  107. // Change the delta of the weight field if have more than 20 entities.
  108. if (!empty($this->weightKey)) {
  109. $count = count($this->entities);
  110. if ($count > 20) {
  111. $delta = ceil($count / 2);
  112. }
  113. }
  114. foreach ($this->entities as $entity) {
  115. $row = $this->buildRow($entity);
  116. if (isset($row['label'])) {
  117. $row['label'] = ['#markup' => $row['label']];
  118. }
  119. if (isset($row['weight'])) {
  120. $row['weight']['#delta'] = $delta;
  121. }
  122. $form[$this->entitiesKey][$entity->id()] = $row;
  123. }
  124. $form['actions']['#type'] = 'actions';
  125. $form['actions']['submit'] = [
  126. '#type' => 'submit',
  127. '#value' => t('Save'),
  128. '#button_type' => 'primary',
  129. ];
  130. return $form;
  131. }
  132. /**
  133. * {@inheritdoc}
  134. */
  135. public function validateForm(array &$form, FormStateInterface $form_state) {
  136. // No validation.
  137. }
  138. /**
  139. * {@inheritdoc}
  140. */
  141. public function submitForm(array &$form, FormStateInterface $form_state) {
  142. foreach ($form_state->getValue($this->entitiesKey) as $id => $value) {
  143. if (isset($this->entities[$id]) && $this->entities[$id]->get($this->weightKey) != $value['weight']) {
  144. // Save entity only when its weight was changed.
  145. $this->entities[$id]->set($this->weightKey, $value['weight']);
  146. $this->entities[$id]->save();
  147. }
  148. }
  149. }
  150. /**
  151. * Returns the form builder.
  152. *
  153. * @return \Drupal\Core\Form\FormBuilderInterface
  154. * The form builder.
  155. */
  156. protected function formBuilder() {
  157. if (!$this->formBuilder) {
  158. $this->formBuilder = \Drupal::formBuilder();
  159. }
  160. return $this->formBuilder;
  161. }
  162. }