1<?php
2
3namespace Drupal\tabledrag_test\Form;
4
5use Drupal\Core\Form\FormBase;
6use Drupal\Core\Form\FormStateInterface;
7use Drupal\Core\State\StateInterface;
8use Symfony\Component\DependencyInjection\ContainerInterface;
9
10/**
11 * Provides a form for draggable table testing.
12 */
13class TableDragTestForm extends FormBase {
14
15  /**
16   * The state service.
17   *
18   * @var \Drupal\Core\State\StateInterface
19   */
20  protected $state;
21
22  /**
23   * Constructs a TableDragTestForm object.
24   *
25   * @param \Drupal\Core\State\StateInterface $state
26   *   The state service.
27   */
28  public function __construct(StateInterface $state) {
29    $this->state = $state;
30  }
31
32  /**
33   * {@inheritdoc}
34   */
35  public static function create(ContainerInterface $container) {
36    return new static($container->get('state'));
37  }
38
39  /**
40   * {@inheritdoc}
41   */
42  public function getFormId() {
43    return 'tabledrag_test_form';
44  }
45
46  /**
47   * Builds the draggable test table.
48   *
49   * @param array $rows
50   *   (optional) Rows that should be shown on the table. Default value is an
51   *   empty array.
52   * @param string $table_id
53   *   (optional) An HTML ID for the table, defaults to 'tabledrag-test-table'.
54   * @param string $group_prefix
55   *   (optional) A prefix for HTML classes generated in the method, defaults to
56   *   'tabledrag-test'.
57   * @param bool $indentation
58   *   (optional) A boolean indicating whether the rows can be indented,
59   *   defaults to TRUE.
60   *
61   * @return array
62   *   The renderable array of the draggable table used for testing.
63   */
64  protected function buildTestTable(array $rows = [], $table_id = 'tabledrag-test-table', $group_prefix = 'tabledrag-test', $indentation = TRUE) {
65    $tabledrag = [
66      [
67        'action' => 'order',
68        'relationship' => 'sibling',
69        'group' => "$group_prefix-weight",
70      ],
71    ];
72
73    if ($indentation) {
74      $tabledrag[] = [
75        'action' => 'match',
76        'relationship' => 'parent',
77        'group' => "$group_prefix-parent",
78        'subgroup' => "$group_prefix-parent",
79        'source' => "$group_prefix-id",
80        'hidden' => TRUE,
81        'limit' => 2,
82      ];
83      $tabledrag[] = [
84        'action' => 'depth',
85        'relationship' => 'group',
86        'group' => "$group_prefix-depth",
87        'hidden' => TRUE,
88      ];
89    }
90
91    $table = [
92      '#type' => 'table',
93      '#header' => [
94        [
95          'data' => $this->t('Text'),
96          'colspan' => $indentation ? 4 : 2,
97        ],
98        $this->t('Weight'),
99      ],
100      '#tabledrag' => $tabledrag,
101      '#attributes' => ['id' => $table_id],
102      '#attached' => ['library' => ['tabledrag_test/tabledrag']],
103    ];
104
105    // Provide a default set of five rows.
106    $rows = !empty($rows) ? $rows :
107      $this->state->get('tabledrag_test_table', array_flip(range(1, 5)));
108
109    foreach ($rows as $id => $row) {
110      if (!is_array($row)) {
111        $row = [];
112      }
113
114      $row += [
115        'parent' => '',
116        'weight' => 0,
117        'depth' => 0,
118        'classes' => [],
119        'draggable' => TRUE,
120      ];
121
122      if (!empty($row['draggable'])) {
123        $row['classes'][] = 'draggable';
124      }
125
126      $table[$id] = [
127        'title' => [
128          'indentation' => [
129            '#theme' => 'indentation',
130            '#size' => $indentation ? $row['depth'] : 0,
131          ],
132          '#plain_text' => "Row with id $id",
133        ],
134        'id' => [
135          '#type' => 'hidden',
136          '#value' => $id,
137          '#parents' => ['table', $id, 'id'],
138          '#attributes' => ['class' => ["$group_prefix-id"]],
139        ],
140        '#attributes' => ['class' => $row['classes']],
141      ];
142
143      if ($indentation) {
144        $table[$id]['parent'] = [
145          '#type' => 'hidden',
146          '#default_value' => $row['parent'],
147          '#parents' => ['table', $id, 'parent'],
148          '#attributes' => ['class' => ["$group_prefix-parent"]],
149        ];
150        $table[$id]['depth'] = [
151          '#type' => 'hidden',
152          '#default_value' => $row['depth'],
153          '#parents' => ['table', $id, 'depth'],
154          '#attributes' => ['class' => ["$group_prefix-depth"]],
155        ];
156      }
157
158      $table[$id]['weight'] = [
159        '#type' => 'weight',
160        '#default_value' => $row['weight'],
161        '#parents' => ['table', $id, 'weight'],
162        '#attributes' => ['class' => ["$group_prefix-weight"]],
163      ];
164    }
165
166    return $table;
167  }
168
169  /**
170   * {@inheritdoc}
171   */
172  public function buildForm(array $form, FormStateInterface $form_state) {
173    // Provide a default set of five rows.
174    $form['table'] = $this->buildTestTable();
175    $form['actions'] = $this->buildFormActions();
176
177    return $form;
178  }
179
180  /**
181   * {@inheritdoc}
182   */
183  public function submitForm(array &$form, FormStateInterface $form_state) {
184    $operation = isset($form_state->getTriggeringElement()['#op']) ?
185      $form_state->getTriggeringElement()['#op'] :
186      'save';
187
188    switch ($operation) {
189      case 'reset':
190        $this->state->set('tabledrag_test_table', array_flip(range(1, 5)));
191        break;
192
193      default:
194        $test_table = [];
195        foreach ($form_state->getValue('table') as $row) {
196          $test_table[$row['id']] = $row;
197        }
198        $this->state->set('tabledrag_test_table', $test_table);
199        break;
200    }
201  }
202
203  /**
204   * Builds the test table form actions.
205   *
206   * @return array
207   *   The renderable array of form actions.
208   */
209  protected function buildFormActions() {
210    return [
211      '#type' => 'actions',
212      'save' => [
213        '#type' => 'submit',
214        '#value' => $this->t('Save'),
215      ],
216      'reset' => [
217        '#type' => 'submit',
218        '#op' => 'reset',
219        '#value' => $this->t('Reset'),
220      ],
221    ];
222  }
223
224}
225