You are here

public function ProductAttributeForm::buildValuesForm in Commerce Core 8.2

Builds the attribute values form.

Parameters

array $form: An associative array containing the structure of the form.

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

Return value

array The attribute values form.

1 call to ProductAttributeForm::buildValuesForm()
ProductAttributeForm::form in modules/product/src/Form/ProductAttributeForm.php
Gets the actual form array to be built.

File

modules/product/src/Form/ProductAttributeForm.php, line 158

Class

ProductAttributeForm

Namespace

Drupal\commerce_product\Form

Code

public function buildValuesForm(array $form, FormStateInterface $form_state) {

  /** @var \Drupal\commerce_product\Entity\ProductAttributeInterface $attribute */
  $attribute = $this->entity;
  $values = $attribute
    ->getValues();
  $user_input = $form_state
    ->getUserInput();

  // Reorder the values by name, if requested.
  if ($form_state
    ->get('reset_alphabetical')) {
    $value_names = EntityHelper::extractLabels($values);
    asort($value_names);
    foreach (array_keys($value_names) as $weight => $id) {
      $values[$id]
        ->setWeight($weight);
    }
  }

  // The value map allows new values to be added and removed before saving.
  // An array in the $index => $id format. $id is '_new' for unsaved values.
  $value_map = (array) $form_state
    ->get('value_map');
  if (empty($value_map)) {
    $value_map = $values ? array_keys($values) : [
      '_new',
    ];
    $form_state
      ->set('value_map', $value_map);
  }
  $wrapper_id = Html::getUniqueId('product-attribute-values-ajax-wrapper');
  $form['values'] = [
    '#type' => 'table',
    '#header' => [
      [
        'data' => $this
          ->t('Value'),
        'colspan' => 2,
      ],
      $this
        ->t('Weight'),
      $this
        ->t('Operations'),
    ],
    '#tabledrag' => [
      [
        'action' => 'order',
        'relationship' => 'sibling',
        'group' => 'product-attribute-value-order-weight',
      ],
    ],
    '#weight' => 5,
    '#prefix' => '<div id="' . $wrapper_id . '">',
    '#suffix' => '</div>',
    // #input defaults to TRUE, which breaks file fields on the value form.
    // This table is used for visual grouping only, the element itself
    // doesn't have any values of its own that need processing.
    '#input' => FALSE,
  ];

  // Make the weight list always reflect the current number of values.
  // Taken from WidgetBase::formMultipleElements().
  $max_weight = count($value_map);
  foreach ($value_map as $index => $id) {
    $value_form =& $form['values'][$index];

    // The tabledrag element is always added to the first cell in the row,
    // so we add an empty cell to guide it there, for better styling.
    $value_form['#attributes']['class'][] = 'draggable';
    $value_form['tabledrag'] = [
      '#markup' => '',
    ];
    if ($id == '_new') {
      $value = $this->entityTypeManager
        ->getStorage('commerce_product_attribute_value')
        ->create([
        'attribute' => $attribute
          ->id(),
        'langcode' => $attribute
          ->get('langcode'),
      ]);
      $default_weight = $max_weight;
      $remove_access = TRUE;
    }
    else {
      $value = $values[$id];
      $default_weight = $value
        ->getWeight();
      $remove_access = $value
        ->access('delete');
    }
    $inline_form = $this->inlineFormManager
      ->createInstance('content_entity', [
      'skip_save' => TRUE,
    ], $value);
    $value_form['entity'] = [
      '#parents' => [
        'values',
        $index,
        'entity',
      ],
      '#inline_form' => $inline_form,
    ];
    $value_form['entity'] = $inline_form
      ->buildInlineForm($value_form['entity'], $form_state);
    $value_form['weight'] = [
      '#type' => 'weight',
      '#title' => $this
        ->t('Weight'),
      '#title_display' => 'invisible',
      '#delta' => $max_weight,
      '#default_value' => $default_weight,
      '#attributes' => [
        'class' => [
          'product-attribute-value-order-weight',
        ],
      ],
    ];

    // Used by SortArray::sortByWeightProperty to sort the rows.
    if (isset($user_input['values'][$index])) {
      $input_weight = $user_input['values'][$index]['weight'];

      // If the weights were just reset, reflect it in the user input.
      if ($form_state
        ->get('reset_alphabetical')) {
        $input_weight = $default_weight;
      }

      // Make sure the weight is not out of bounds due to removals.
      if ($user_input['values'][$index]['weight'] > $max_weight) {
        $input_weight = $max_weight;
      }

      // Reflect the updated user input on the element.
      $value_form['weight']['#value'] = $input_weight;
      $value_form['#weight'] = $input_weight;
    }
    else {
      $value_form['#weight'] = $default_weight;
    }
    $value_form['remove'] = [
      '#type' => 'submit',
      '#name' => 'remove_value' . $index,
      '#value' => $this
        ->t('Remove'),
      '#limit_validation_errors' => [],
      '#submit' => [
        '::removeValueSubmit',
      ],
      '#value_index' => $index,
      '#ajax' => [
        'callback' => '::valuesAjax',
        'wrapper' => $wrapper_id,
      ],
      '#access' => $remove_access,
    ];
  }

  // Sort the values by weight. Ensures weight is preserved on ajax refresh.
  uasort($form['values'], [
    '\\Drupal\\Component\\Utility\\SortArray',
    'sortByWeightProperty',
  ]);
  $access_handler = $this->entityTypeManager
    ->getAccessControlHandler('commerce_product_attribute_value');
  if ($access_handler
    ->createAccess($attribute
    ->id())) {
    $form['values']['_add_new'] = [
      '#tree' => FALSE,
    ];
    $form['values']['_add_new']['entity'] = [
      '#type' => 'container',
      '#wrapper_attributes' => [
        'colspan' => 2,
      ],
    ];
    $form['values']['_add_new']['entity']['add_value'] = [
      '#type' => 'submit',
      '#value' => $this
        ->t('Add value'),
      '#submit' => [
        '::addValueSubmit',
      ],
      '#limit_validation_errors' => [],
      '#ajax' => [
        'callback' => '::valuesAjax',
        'wrapper' => $wrapper_id,
      ],
    ];
    $form['values']['_add_new']['entity']['reset_alphabetical'] = [
      '#type' => 'submit',
      '#value' => $this
        ->t('Reset to alphabetical'),
      '#submit' => [
        '::resetAlphabeticalSubmit',
      ],
      '#limit_validation_errors' => [],
      '#ajax' => [
        'callback' => '::valuesAjax',
        'wrapper' => $wrapper_id,
      ],
    ];
    $form['values']['_add_new']['operations'] = [
      'data' => [],
    ];
  }
  return $form;
}