You are here

public static function Table::processTable in Drupal 9

Same name and namespace in other branches
  1. 8 core/lib/Drupal/Core/Render/Element/Table.php \Drupal\Core\Render\Element\Table::processTable()
  2. 10 core/lib/Drupal/Core/Render/Element/Table.php \Drupal\Core\Render\Element\Table::processTable()

#process callback for #type 'table' to add tableselect support.

Parameters

array $element: An associative array containing the properties and children of the table element.

\Drupal\Core\Form\FormStateInterface $form_state: The current state of the form.

array $complete_form: The complete form structure.

Return value

array The processed element.

File

core/lib/Drupal/Core/Render/Element/Table.php, line 134

Class

Table
Provides a render element for a table.

Namespace

Drupal\Core\Render\Element

Code

public static function processTable(&$element, FormStateInterface $form_state, &$complete_form) {
  if ($element['#tableselect']) {
    if ($element['#multiple']) {
      $value = is_array($element['#value']) ? $element['#value'] : [];
    }
    else {
      $element['#js_select'] = FALSE;
    }

    // Add a "Select all" checkbox column to the header.
    // @todo D8: Rename into #select_all?
    if ($element['#js_select']) {
      $element['#attached']['library'][] = 'core/drupal.tableselect';
      array_unshift($element['#header'], [
        'class' => [
          'select-all',
        ],
      ]);
    }
    else {
      array_unshift($element['#header'], '');
    }
    if (!isset($element['#default_value']) || $element['#default_value'] === 0) {
      $element['#default_value'] = [];
    }

    // Create a checkbox or radio for each row in a way that the value of the
    // tableselect element behaves as if it had been of #type checkboxes or
    // radios.
    foreach (Element::children($element) as $key) {
      $row =& $element[$key];

      // Prepare the element #parents for the tableselect form element.
      // Their values have to be located in child keys (#tree is ignored),
      // since Table::validateTable() has to be able to validate whether input
      // (for the parent #type 'table' element) has been submitted.
      $element_parents = array_merge($element['#parents'], [
        $key,
      ]);

      // Since the #parents of the tableselect form element will equal the
      // #parents of the row element, prevent FormBuilder from auto-generating
      // an #id for the row element, since
      // \Drupal\Component\Utility\Html::getUniqueId() would automatically
      // append a suffix to the tableselect form element's #id otherwise.
      $row['#id'] = HtmlUtility::getUniqueId('edit-' . implode('-', $element_parents) . '-row');

      // Do not overwrite manually created children.
      if (!isset($row['select'])) {

        // Determine option label; either an assumed 'title' column, or the
        // first available column containing a #title or #markup.
        // @todo Consider to add an optional $element[$key]['#title_key']
        //   defaulting to 'title'?
        unset($label_element);
        $title = NULL;
        if (isset($row['title']['#type']) && $row['title']['#type'] == 'label') {
          $label_element =& $row['title'];
        }
        else {
          if (!empty($row['title']['#title'])) {
            $title = $row['title']['#title'];
          }
          else {
            foreach (Element::children($row) as $column) {
              if (isset($row[$column]['#title'])) {
                $title = $row[$column]['#title'];
                break;
              }
              if (isset($row[$column]['#markup'])) {
                $title = $row[$column]['#markup'];
                break;
              }
            }
          }
          if (isset($title) && $title !== '') {
            $title = t('Update @title', [
              '@title' => $title,
            ]);
          }
        }

        // Prepend the select column to existing columns.
        $row = [
          'select' => [],
        ] + $row;
        $row['select'] += [
          '#type' => $element['#multiple'] ? 'checkbox' : 'radio',
          '#id' => HtmlUtility::getUniqueId('edit-' . implode('-', $element_parents)),
          // @todo If rows happen to use numeric indexes instead of string keys,
          //   this results in a first row with $key === 0, which is always FALSE.
          '#return_value' => $key,
          '#attributes' => $element['#attributes'],
          '#wrapper_attributes' => [
            'class' => [
              'table-select',
            ],
          ],
        ];
        if ($element['#multiple']) {
          $row['select']['#default_value'] = isset($value[$key]) ? $key : NULL;
          $row['select']['#parents'] = $element_parents;
        }
        else {
          $row['select']['#default_value'] = $element['#default_value'] == $key ? $key : NULL;
          $row['select']['#parents'] = $element['#parents'];
        }
        if (isset($label_element)) {
          $label_element['#id'] = $row['select']['#id'] . '--label';
          $label_element['#for'] = $row['select']['#id'];
          $row['select']['#attributes']['aria-labelledby'] = $label_element['#id'];
          $row['select']['#title_display'] = 'none';
        }
        else {
          $row['select']['#title'] = $title;
          $row['select']['#title_display'] = 'invisible';
        }
      }
    }
  }
  return $element;
}