diff --git a/core/lib/Drupal/Core/Field/Plugin/Field/FieldWidget/StringTextfieldWidget.php b/core/lib/Drupal/Core/Field/Plugin/Field/FieldWidget/StringTextfieldWidget.php index 4262380..b93d9ee 100644 --- a/core/lib/Drupal/Core/Field/Plugin/Field/FieldWidget/StringTextfieldWidget.php +++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldWidget/StringTextfieldWidget.php @@ -2,7 +2,10 @@ namespace Drupal\Core\Field\Plugin\Field\FieldWidget; +use Drupal\Component\Utility\Html; +use Drupal\Component\Utility\NestedArray; use Drupal\Core\Field\FieldItemListInterface; +use Drupal\Core\Field\FieldStorageDefinitionInterface; use Drupal\Core\Field\WidgetBase; use Drupal\Core\Form\FormStateInterface; @@ -23,29 +26,29 @@ class StringTextfieldWidget extends WidgetBase { * {@inheritdoc} */ public static function defaultSettings() { - return [ + return array( 'size' => 60, 'placeholder' => '', - ] + parent::defaultSettings(); + ) + parent::defaultSettings(); } /** * {@inheritdoc} */ public function settingsForm(array $form, FormStateInterface $form_state) { - $element['size'] = [ + $element['size'] = array( '#type' => 'number', '#title' => t('Size of textfield'), '#default_value' => $this->getSetting('size'), '#required' => TRUE, '#min' => 1, - ]; - $element['placeholder'] = [ + ); + $element['placeholder'] = array( '#type' => 'textfield', '#title' => t('Placeholder'), '#default_value' => $this->getSetting('placeholder'), '#description' => t('Text that will be shown inside the field until a value is entered. This hint is usually a sample value or a brief description of the expected format.'), - ]; + ); return $element; } @@ -53,12 +56,12 @@ public function settingsForm(array $form, FormStateInterface $form_state) { * {@inheritdoc} */ public function settingsSummary() { - $summary = []; + $summary = array(); - $summary[] = t('Textfield size: @size', ['@size' => $this->getSetting('size')]); + $summary[] = t('Textfield size: @size', array('@size' => $this->getSetting('size'))); $placeholder = $this->getSetting('placeholder'); if (!empty($placeholder)) { - $summary[] = t('Placeholder: @placeholder', ['@placeholder' => $placeholder]); + $summary[] = t('Placeholder: @placeholder', array('@placeholder' => $placeholder)); } return $summary; @@ -68,16 +71,127 @@ public function settingsSummary() { * {@inheritdoc} */ public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state) { - $element['value'] = $element + [ + + $field_name = $this->fieldDefinition->getName(); + $parents = array_merge($element['#field_parents'], array($field_name, $delta)); + $element['value'] = $element + array( '#type' => 'textfield', '#default_value' => isset($items[$delta]->value) ? $items[$delta]->value : NULL, '#size' => $this->getSetting('size'), '#placeholder' => $this->getSetting('placeholder'), '#maxlength' => $this->getFieldSetting('max_length'), - '#attributes' => ['class' => ['js-text-full', 'text-full']], + '#attributes' => array('class' => array('js-text-full', 'text-full')), + ); + if ($this->fieldDefinition->getFieldStorageDefinition()->getCardinality() == FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED) { + $element['actions'] = [ + '#type' => 'actions', + 'remove_button' => [ + '#delta' => $delta, + '#name' => implode('_', $parents) . '_remove_button', + '#type' => 'submit', + '#value' => t('Remove'), + '#validate' => [], + '#submit' => [[static::class, 'ajaxcallbackremove']], + '#limit_validation_errors' => [], + '#attributes' => array('class' => array('remove-field-delta--' . $delta, 'custom-class')), + '#ajax' => [ + 'callback' => array($this, 'removeAjaxCallbac'), + //'options' => $options, + 'effect' => 'fade', + 'wrapper' => $form['#wrapper_id'], + ], + ], + '#weight' => 1000, ]; - + } return $element; } + /** + * @param FieldItemListInterface $items + * @param array $form + * @param FormStateInterface $form_state + * @return array + */ + protected function formMultipleElements(FieldItemListInterface $items, array &$form, FormStateInterface $form_state) { + if ((count($items) > 0) && !$form_state->isRebuilding() && !$items->getEntity()->isNew()) { + $field_name = $this->fieldDefinition->getName(); + $cardinality = $this->fieldDefinition->getFieldStorageDefinition()->getCardinality(); + $parents = $form['#parents']; + if ($cardinality == FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED) { + $field_state = static::getWidgetState($parents, $field_name, $form_state); + $field_state['items_count']--; + static::setWidgetState($parents, $field_name, $form_state, $field_state); + } + } + $form['#wrapper_id'] = Html::getUniqueID($items->getName()); + $elements = parent::formMultipleElements($items, $form, $form_state); + $elements['#prefix'] = '
'; + $elements['#suffix'] = '
'; + $elements['add_more']['#ajax']['wrapper'] = $form['#wrapper_id']; + return $elements; + } + + /** + * @param $form + * @param FormStateInterface $form_state + */ + public function ajaxcallbackremove($form, FormStateInterface $form_state) { + + $button = $form_state->getTriggeringElement(); + $delta = $button['#delta']; + $address = array_slice($button['#array_parents'], 0, -4); + $address_state = array_slice($button['#parents'], 0, -3); + $parent_element = NestedArray::getValue($form, array_merge($address, array('widget'))); + $field_name = $parent_element['#field_name']; + $parents = $parent_element['#field_parents']; + $field_state = static::getWidgetState($parents, $field_name, $form_state); + + for ($i = $delta; $i <= $field_state['items_count']; $i++) { + + $old_element_address = array_merge($address, array('widget', $i + 1)); + $old_element_state_address = array_merge($address_state, array($i + 1)); + $new_element_state_address = array_merge($address_state, array($i)); + $moving_element = NestedArray::getValue($form, $old_element_address); + $moving_element_value = NestedArray::getValue($form_state->getValues(), $old_element_state_address); + $moving_element_input = NestedArray::getValue($form_state->getUserInput(), $old_element_state_address); + + // Tell the element where it's being moved to. + $moving_element['#parents'] = $new_element_state_address; + + // Move the element around. + $form_state->setValueForElement($moving_element, $moving_element_value); + $user_input = $form_state->getUserInput(); + NestedArray::setValue($user_input, $moving_element['#parents'], $moving_element_input); + $form_state->setUserInput($user_input); + } + + if ($field_state['items_count'] > 0) { + $field_state['items_count']--; + } + $input = NestedArray::getValue($form_state->getUserInput(), $address); + $weight = -1 * $field_state['items_count']; + foreach ($input as $key => $item) { + if ($item) { + $input[$key]['_weight'] = $weight++; + } + } + $user_input = $form_state->getUserInput(); + NestedArray::setValue($user_input, $address, $input); + $form_state->setUserInput($user_input); + + static::setWidgetState($parents, $field_name, $form_state, $field_state); + + $form_state->setRebuild(); + } + + /** + * @param array $form + * @param FormStateInterface $form_state + * @return mixed + */ + public function removeAjaxCallbac(array &$form, FormStateInterface $form_state) { + $button = $form_state->getTriggeringElement(); + return NestedArray::getValue($form, array_slice($button['#array_parents'], 0, -3)); + } }