View source
<?php
namespace Drupal\commerce_tax\Plugin\Field\FieldWidget;
use Drupal\address\Element\Address;
use Drupal\address\Element\Country;
use Drupal\commerce_tax\TaxNumberTypeManagerInterface;
use Drupal\Component\Utility\Html;
use Drupal\Component\Utility\NestedArray;
use Drupal\Core\Entity\FieldableEntityInterface;
use Drupal\Core\Field\FieldDefinitionInterface;
use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Field\WidgetBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
class TaxNumberDefaultWidget extends WidgetBase implements ContainerFactoryPluginInterface {
protected $taxNumberTypeManager;
public function __construct($plugin_id, $plugin_definition, FieldDefinitionInterface $field_definition, array $settings, array $third_party_settings, TaxNumberTypeManagerInterface $tax_number_type_manager) {
parent::__construct($plugin_id, $plugin_definition, $field_definition, $settings, $third_party_settings);
$this->taxNumberTypeManager = $tax_number_type_manager;
}
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
return new static($plugin_id, $plugin_definition, $configuration['field_definition'], $configuration['settings'], $configuration['third_party_settings'], $container
->get('plugin.manager.commerce_tax_number_type'));
}
public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state) {
if ($this
->isDefaultValueWidget($form_state)) {
return [];
}
$this
->prepareForm($form);
$item = $items[$delta];
$selected_country = $this
->getSelectedCountry($item
->getEntity(), $form, $form_state);
$allowed_countries = $item
->getAllowedCountries();
if ($selected_country && !in_array($selected_country, $allowed_countries)) {
$element['#access'] = FALSE;
$element['value'] = [
'#type' => 'value',
'#value' => '',
];
return $element;
}
$allowed_types = $item
->getAllowedTypes();
if (count($allowed_types) == 1) {
$type = reset($allowed_types);
}
elseif ($selected_country) {
$type = $this->taxNumberTypeManager
->getPluginId($selected_country);
}
else {
$type = 'other';
}
$element['original'] = [
'#type' => 'value',
'#value' => $item
->getValue() + [
'type' => NULL,
'value' => NULL,
'verification_state' => NULL,
'verification_timestamp' => NULL,
'verification_result' => NULL,
],
];
$element['type'] = [
'#type' => 'value',
'#value' => $type,
];
$element['value'] = [
'#type' => 'textfield',
'#title' => $this->fieldDefinition
->getLabel(),
'#description' => $this->fieldDefinition
->getDescription(),
'#required' => $this->fieldDefinition
->isRequired(),
'#default_value' => $item->value,
'#size' => 20,
];
return $element;
}
public function massageFormValues(array $values, array $form, FormStateInterface $form_state) {
foreach ($values as $delta => $value) {
if (empty($value['value'])) {
continue;
}
$type_plugin = $this->taxNumberTypeManager
->createInstance($value['type']);
$value['value'] = $type_plugin
->canonicalize($value['value']);
$original = $value['original'];
if ($original['type'] == $value['type'] && $original['value'] == $value['value']) {
$value['verification_state'] = $original['verification_state'];
$value['verification_timestamp'] = $original['verification_timestamp'];
$value['verification_result'] = $original['verification_result'];
}
unset($value['original']);
$values[$delta] = $value;
}
return $values;
}
protected function prepareForm(array &$form) {
if (empty($form['address']['widget'][0]['address']['#required'])) {
return $form;
}
$wrapper_id = Html::getUniqueId(implode('-', $form['#parents']) . '-ajax-form');
$form += [
'#wrapper_id' => $wrapper_id,
'#prefix' => '<div id="' . $wrapper_id . '">',
'#suffix' => '</div>',
];
$form['address']['widget'][0]['address']['#form_wrapper'] = $form['#wrapper_id'];
$form['address']['widget'][0]['address']['#process'] = [
[
Address::class,
'processAddress',
],
[
Address::class,
'processGroup',
],
[
get_class($this),
'replaceAjaxCallback',
],
];
return $form;
}
public static function replaceAjaxCallback(array &$element, FormStateInterface $form_state, array &$complete_form) {
if (isset($element['country_code']['#ajax'])) {
$element['country_code']['#ajax'] = [
'callback' => [
get_called_class(),
'ajaxRefresh',
],
'wrapper' => $element['#form_wrapper'],
];
}
return $element;
}
public static function ajaxRefresh(array $form, FormStateInterface $form_state) {
$triggering_element = $form_state
->getTriggeringElement();
$parents = array_slice($triggering_element['#array_parents'], 0, -6);
return NestedArray::getValue($form, $parents);
}
protected function getSelectedCountry(FieldableEntityInterface $entity, array $form, FormStateInterface $form_state) {
if (!$entity
->hasField('address')) {
return NULL;
}
$parents = array_merge($form['#parents'], [
'address',
0,
'address',
'country_code',
]);
$selected_country = NestedArray::getValue($form_state
->getUserInput(), $parents);
if (!$selected_country && !$entity
->get('address')
->isEmpty()) {
$address = $entity
->get('address')
->first();
$selected_country = $address
->getCountryCode();
}
elseif (!$selected_country && !empty($form['address']['widget'][0]['address'])) {
$address_element = $form['address']['widget'][0]['address'];
$selected_country = Country::getDefaultCountry($address_element['#available_countries']);
}
return $selected_country;
}
}