View source
<?php
namespace Drupal\address\Plugin\views\filter;
use CommerceGuys\Addressing\AddressFormat\AddressFormatRepositoryInterface;
use CommerceGuys\Addressing\Country\CountryRepositoryInterface;
use CommerceGuys\Addressing\Subdivision\SubdivisionRepositoryInterface;
use Drupal\Core\Entity\EntityFieldManagerInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\address\LabelHelper;
use Symfony\Component\DependencyInjection\ContainerInterface;
class AdministrativeArea extends CountryAwareInOperatorBase {
protected $addressFormatRepository;
protected $subdivisionRepository;
protected $formState;
protected $currentCountryCode;
public function __construct(array $configuration, $plugin_id, $plugin_definition, CountryRepositoryInterface $country_repository, EntityTypeManagerInterface $entity_type_manager, EntityFieldManagerInterface $entity_field_manager, AddressFormatRepositoryInterface $address_format_repository, SubdivisionRepositoryInterface $subdivision_repository) {
parent::__construct($configuration, $plugin_id, $plugin_definition, $country_repository, $entity_type_manager, $entity_field_manager);
$this->addressFormatRepository = $address_format_repository;
$this->subdivisionRepository = $subdivision_repository;
$this->formState = NULL;
$this->currentCountryCode = '';
}
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
return new static($configuration, $plugin_id, $plugin_definition, $container
->get('address.country_repository'), $container
->get('entity_type.manager'), $container
->get('entity_field.manager'), $container
->get('address.address_format_repository'), $container
->get('address.subdivision_repository'));
}
protected function defineOptions() {
$options = parent::defineOptions();
$options['country'] = [
'contains' => [
'country_source' => [
'default' => '',
],
'country_argument_id' => [
'default' => '',
],
'country_filter_id' => [
'default' => '',
],
'country_static_code' => [
'default' => '',
],
],
];
$options['expose']['contains']['label_type']['default'] = 'static';
return $options;
}
protected function canBuildGroup() {
return FALSE;
}
public function buildOptionsForm(&$form, FormStateInterface $form_state) {
$this->formState = $form_state;
$form['country'] = [
'#type' => 'container',
'#weight' => -300,
];
$form['country']['country_source'] = [
'#type' => 'radios',
'#title' => $this
->t('Country source'),
'#options' => [
'static' => $this
->t('A predefined country code'),
'argument' => $this
->t('The value of a contextual filter'),
'filter' => $this
->t('The value of an exposed filter'),
],
'#default_value' => $this->options['country']['country_source'],
'#ajax' => [
'callback' => [
get_class($this),
'ajaxRefreshCountry',
],
'wrapper' => 'admin-area-value-options-ajax-wrapper',
],
];
$argument_options = [];
foreach ($this->view->display_handler
->getHandlers('argument') as $name => $argument) {
$argument_options[$name] = $argument
->adminLabel();
}
if (!empty($argument_options)) {
$form['country']['country_argument_id'] = [
'#type' => 'select',
'#title' => $this
->t('Country contextual filter'),
'#options' => $argument_options,
'#default_value' => $this->options['country']['country_argument_id'],
];
}
else {
$form['country']['country_argument_id'] = [
'#type' => 'container',
];
$form['country']['country_argument_id']['error'] = [
'#type' => 'markup',
'#markup' => $this
->t('You must add a contextual filter for the country code to use this filter for administrative areas.'),
];
}
$form['country']['country_argument_id']['#states'] = [
'visible' => [
':input[name="options[country][country_source]"]' => [
'value' => 'argument',
],
],
];
$filter_options = [];
foreach ($this->view->display_handler
->getHandlers('filter') as $name => $filter) {
$definition = $filter->pluginDefinition;
if ($definition['provider'] === 'address' && ($definition['id'] === 'country' || $definition['id'] === 'country_code')) {
$filter_options[$name] = $filter
->adminLabel();
}
}
if (!empty($filter_options)) {
$form['country']['country_filter_id'] = [
'#type' => 'select',
'#title' => $this
->t('Exposed country filter to determine values'),
'#options' => $filter_options,
'#default_value' => $this->options['country']['country_filter_id'],
];
}
else {
$form['country']['country_filter_id'] = [
'#type' => 'container',
];
$form['country']['country_filter_id']['error'] = [
'#type' => 'markup',
'#markup' => $this
->t('You must add a filter for the country code to use this filter for administrative areas.'),
];
}
$form['country']['country_filter_id']['#states'] = [
'visible' => [
':input[name="options[country][country_source]"]' => [
'value' => 'filter',
],
],
];
$countries = $this
->getAdministrativeAreaCountries();
$form['country']['country_static_code'] = [
'#type' => 'select',
'#title' => $this
->t('Predefined country for administrative areas'),
'#options' => $countries,
'#empty_value' => '',
'#default_value' => $this->options['country']['country_static_code'],
'#ajax' => [
'callback' => [
get_class($this),
'ajaxRefreshCountry',
],
'wrapper' => 'admin-area-value-options-ajax-wrapper',
],
'#states' => [
'visible' => [
':input[name="options[country][country_source]"]' => [
'value' => 'static',
],
],
],
];
$form['expose']['label_type'] = [
'#type' => 'radios',
'#title' => $this
->t('Label type'),
'#options' => [
'static' => $this
->t('Static'),
'dynamic' => $this
->t('Dynamic (an appropriate label will be set based on the active country)'),
],
'#default_value' => $this->options['expose']['label_type'],
'#states' => [
'visible' => [
':input[name="options[expose_button][checkbox][checkbox]"]' => [
'checked' => TRUE,
],
],
],
];
parent::buildOptionsForm($form, $form_state);
}
public function validateOptionsForm(&$form, FormStateInterface $form_state) {
if (empty($form_state)) {
return;
}
$is_exposed = !empty($this->options['exposed']);
$country_source = $form_state
->getValue([
'options',
'country',
'country_source',
]);
switch ($country_source) {
case 'argument':
$country_argument = $form_state
->getValue([
'options',
'country',
'country_argument_id',
]);
if (empty($country_argument)) {
$error = $this
->t("The country contextual filter must be defined for this filter to work using 'contextual filter' for the 'Country source'.");
$form_state
->setError($form['country']['country_source'], $error);
}
if (empty($is_exposed)) {
$error = $this
->t('This filter must be exposed to use a contextual filter to specify the country.');
$form_state
->setError($form['country']['country_source'], $error);
}
break;
case 'filter':
$country_filter = $form_state
->getValue([
'options',
'country',
'country_filter_id',
]);
if (empty($country_filter)) {
$error = $this
->t("The country filter must be defined for this filter to work using 'exposed filter' for the 'Country source'.");
$form_state
->setError($form['country']['country_source'], $error);
}
if (empty($is_exposed)) {
$error = $this
->t('This filter must be exposed to use a filter to specify the country.');
$form_state
->setError($form['country']['country_source'], $error);
}
break;
case 'static':
$country_code = $form_state
->getValue([
'options',
'country',
'country_static_code',
]);
if (empty($country_code)) {
$error = $this
->t('The predefined country must be set for this filter to work.');
$form_state
->setError($form['country']['country_static_code'], $error);
}
break;
default:
$error = $this
->t('The source for the country must be defined for this filter to work.');
$form_state
->setError($form['country']['country_source'], $error);
break;
}
parent::validateOptionsForm($form, $form_state);
}
public function buildExposeForm(&$form, FormStateInterface $form_state) {
parent::buildExposeForm($form, $form_state);
$form['expose']['label']['#states'] = [
'visible' => [
':input[name="options[expose][label_type]"]' => [
'value' => 'static',
],
],
];
$form['expose']['reduce']['#states'] = [
'visible' => [
':input[name="options[country][country_source]"]' => [
'value' => 'static',
],
],
];
$form['value']['#prefix'] = '<div id="admin-area-value-options-ajax-wrapper" class="views-group-box views-right-60">';
$form['value']['#suffix'] = '</div>';
return $form;
}
public function submitExposeForm($form, FormStateInterface $form_state) {
$country_source = $form_state
->getValue([
'options',
'country',
'country_source',
]);
if ($country_source != 'static') {
$form_state
->setValue([
'options',
'expose',
'reduce',
], FALSE);
$form_state
->setValue([
'options',
'value',
], []);
}
parent::submitExposeForm($form, $form_state);
}
protected function showValueForm(&$form, FormStateInterface $form_state) {
$this
->valueForm($form, $form_state);
$form['value']['#prefix'] = '<div id="admin-area-value-options-ajax-wrapper">';
$form['value']['#suffix'] = '</div>';
}
public function valueForm(&$form, FormStateInterface $form_state) {
$this->valueOptions = [];
$this->formState = $form_state;
$country_source = $this
->getCountrySource();
if ($country_source == 'static' || $form_state
->get('exposed')) {
$this
->getCurrentCountry();
parent::valueForm($form, $form_state);
$form['value']['#after_build'][] = [
get_class($this),
'clearValues',
];
}
else {
$form['value'] = [
'#type' => 'container',
'#attributes' => [
'id' => 'admin-area-value-options-ajax-wrapper',
],
];
$form['value']['message'] = [
'#type' => 'markup',
'#markup' => $this
->t("You can only select options here if you use a predefined country for the 'Country source'."),
];
}
}
protected function valueSubmit($form, FormStateInterface $form_state) {
$this->formState = $form_state;
$country_source = $this
->getCountrySource();
if ($country_source == 'static') {
parent::valueSubmit($form, $form_state);
}
}
public function exposedInfo() {
$info = parent::exposedInfo();
if ($this->options['expose']['label_type'] == 'dynamic') {
$current_country = $this
->getCurrentCountry();
if (!empty($current_country)) {
$address_format = $this->addressFormatRepository
->get($current_country);
$labels = LabelHelper::getFieldLabels($address_format);
if (!empty($labels['administrativeArea'])) {
$info['label'] = $labels['administrativeArea'];
}
}
}
return $info;
}
protected function getCountrySource() {
$country_source = '';
if (!empty($this->formState)) {
$form_value_country_source = $this->formState
->getValue([
'options',
'country',
'country_source',
]);
if (!empty($form_value_country_source)) {
$country_source = $form_value_country_source;
}
else {
$input = $this->formState
->getUserInput();
if (!empty($input['options']['country']['country_source'])) {
$country_source = $input['options']['country']['country_source'];
}
}
}
if (empty($country_source)) {
$country_source = $this->options['country']['country_source'];
}
return $country_source;
}
protected function getCurrentCountry() {
$this->currentCountryCode = '';
switch ($this
->getCountrySource()) {
case 'argument':
$country_argument = $this->view->display_handler
->getHandler('argument', $this->options['country']['country_argument_id']);
if (!empty($country_argument)) {
$this->currentCountryCode = $country_argument
->getValue();
}
break;
case 'filter':
$country_filter = $this->view->display_handler
->getHandler('filter', $this->options['country']['country_filter_id']);
if (!empty($country_filter) && !empty($this->formState)) {
$input = $this->formState
->getUserInput();
$country_filter_identifier = $country_filter->options['expose']['identifier'];
if (!empty($input[$country_filter_identifier])) {
if (is_array($input[$country_filter_identifier])) {
if (count($input[$country_filter_identifier]) == 1) {
$this->currentCountryCode = array_shift($input[$country_filter_identifier]);
}
}
else {
$this->currentCountryCode = $input[$country_filter_identifier];
}
}
}
break;
case 'static':
if (!empty($this->formState)) {
$input = $this->formState
->getUserInput();
if (!empty($input['options']['country']['country_static_code'])) {
$form_input_country_code = $input['options']['country']['country_static_code'];
}
}
$this->currentCountryCode = !empty($form_input_country_code) ? $form_input_country_code : $this->options['country']['country_static_code'];
break;
}
if (!empty($this->currentCountryCode)) {
$all_countries = $this->countryRepository
->getList();
if (empty($all_countries[$this->currentCountryCode])) {
$this->currentCountryCode = '';
}
}
return $this->currentCountryCode;
}
public function getValueOptions() {
$this->valueOptions = [];
if ($country_code = $this
->getCurrentCountry()) {
$parents[] = $country_code;
$locale = \Drupal::languageManager()
->getConfigOverrideLanguage()
->getId();
$subdivisions = $this->subdivisionRepository
->getList($parents, $locale);
$this->valueOptions = $subdivisions;
}
return $this->valueOptions;
}
public function buildExposedForm(&$form, FormStateInterface $form_state) {
parent::buildExposedForm($form, $form_state);
if (empty($this->valueOptions)) {
$identifier = $this->options['expose']['identifier'];
$form[$identifier]['#access'] = FALSE;
}
}
public function adminSummary() {
switch ($this->options['country']['country_source']) {
case 'argument':
return $this
->t('exposed: country set via contextual filter');
case 'filter':
return $this
->t('exposed: country set via exposed filter');
case 'static':
if (!empty($this->options['exposed'])) {
return $this
->t('exposed: fixed country: @country', [
'@country' => $this->options['country']['country_static_code'],
]);
}
return $this
->t('fixed country: @country', [
'@country' => $this->options['country']['country_static_code'],
]);
}
return $this
->t('broken configuration');
}
public function getAdministrativeAreaCountries(array $available_countries = NULL) {
if (!isset($available_countries)) {
$available_countries = $this
->getAvailableCountries();
}
$countries = [];
foreach ($available_countries as $country_code => $country_name) {
$address_format = $this->addressFormatRepository
->get($country_code);
$subdivision_depth = $address_format
->getSubdivisionDepth();
if ($subdivision_depth > 0) {
$countries[$country_code] = $country_name;
}
}
return $countries;
}
public static function ajaxRefreshCountry(array $form, FormStateInterface $form_state) {
return $form['options']['value'];
}
public static function clearValues(array $element, FormStateInterface $form_state) {
$triggering_element = $form_state
->getTriggeringElement();
if (!$triggering_element) {
return $element;
}
$triggering_element_name = end($triggering_element['#parents']);
if ($triggering_element_name == 'country_static_code' || $triggering_element_name == 'country_source') {
foreach ($element['#options'] as $key => $option) {
$element[$key]['#value'] = 0;
}
$element['#value'] = [];
$input =& $form_state
->getUserInput();
$input['options']['value'] = [];
}
return $element;
}
}