global_gateway-8.x-1.x-dev/src/Form/GlobalGatewaySwitcherForm.php
src/Form/GlobalGatewaySwitcherForm.php
<?php namespace Drupal\global_gateway\Form; use Drupal\Core\Entity\EntityInterface; use Drupal\Component\Utility\Xss; use Drupal\Core\Ajax\AjaxResponse; use Drupal\Core\Ajax\InvokeCommand; use Drupal\Core\Ajax\ReplaceCommand; use Drupal\Core\Form\FormBase; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Url; use Drupal\global_gateway\Helper; use Drupal\global_gateway\RegionNegotiatorInterface; use Drupal\global_gateway\SwitcherData\SwitcherDataPluginCollection; use Drupal\global_gateway\SwitcherData\SwitcherDataPluginInterface; use Drupal\global_gateway\SwitcherData\SwitcherDataPluginManager; use Symfony\Component\DependencyInjection\ContainerInterface; /** * Provides different switchers for region. */ class GlobalGatewaySwitcherForm extends FormBase { protected $limit; protected $nativeNames; protected $untranslatedContent; protected $languageList; /** * Region code. * * @var string */ protected $regionCode; /** * Global Gateway Helper. * * @var \Drupal\global_gateway\Helper */ protected $helper; /** * Region Negotiator Interface. * * @var \Drupal\global_gateway\RegionNegotiatorInterface */ protected $negotiator; /** * {@inheritdoc} */ public static function create(ContainerInterface $container) { return new static( $container->get('plugin.manager.global_gateway.switcher_data'), $container->get('global_gateway.helper'), $container->get('global_gateway_region_negotiator') ); } /** * GlobalGatewaySwitcherForm constructor. * * @param \Drupal\global_gateway\SwitcherData\SwitcherDataPluginManager $data_manager * The Switcher Plugin Manager object. * @param \Drupal\global_gateway\Helper $helper * Global Gateway Helper. */ public function __construct(SwitcherDataPluginManager $data_manager, Helper $helper, RegionNegotiatorInterface $negotiator, $providers = []) { $this->helper = $helper; $this->switcherProviders = [['id' => 'global_gateway_language_switcher_data']]; $this->switcherData = new SwitcherDataPluginCollection($data_manager, $this->switcherProviders); $this->negotiator = $negotiator; $this->languageList = \Drupal::languageManager()->getStandardLanguageList(); } /** * {@inheritdoc} */ public function getFormId() { return 'global_gateway_switcher_form'; } /** * Returns language native name by langcode. * * @param string $langcode * The language code, for example 'en'. * * @return array * The string with language native name. */ public function getLanguageNativeName(string $langcode = 'en') { return $this->languageList[$langcode][1]; } /** * Add links to links container. * * @param string $container * The links container. */ public function addItems(&$container) { $entities = []; $entity = NULL; $entity_type = NULL; foreach (\Drupal::routeMatch()->getParameters() as $key => $param) { if ($param instanceof EntityInterface) { $entities = [$key => $param]; } } if (!empty($entities)) { $entity_type = array_keys($entities)[0]; $entity = \Drupal::routeMatch()->getParameter($entity_type); } if (!is_null($entity) && !is_null($entity_type)) { $translations = $entity->getTranslationLanguages(); } else { $translations = []; } $nativeNames = (int) $this->nativeNames; $untranslatedContent = (int) $this->untranslatedContent; if ($this->limit === 0) { $this->regionCode = 'none'; } foreach ($this->switcherData as $item) { if ($item instanceof SwitcherDataPluginInterface) { $output = $item->getOutput($this->regionCode); } else { // Get Language Switch Links from language manager // if global_gateway_language is disabled. $links = \Drupal::languageManager() ->getLanguageSwitchLinks('language_interface', Url::fromRoute('<current>')); if ($links) { $links = (array) $links; foreach ($links["links"] as &$link) { if (!empty($link['query']['ajax_form'])) { unset($link['query']); } } unset($link); $output = [ '#theme' => 'links__language_block', '#links' => $links["links"], '#attributes' => [ 'class' => [ "language-switcher-{$links["method_id"]}", ], ], '#set_active_class' => TRUE, ]; } else { $output = NULL; } }; } // Check for native names settings. if ($nativeNames == 1) { // Load every language switch link. foreach ($output['#links'] as $langcode => $link) { // Check if there is native name for language. if (!is_null($this->getLanguageNativeName($langcode))) { // Change language link title to native. $output['#links'][$langcode]['title'] = $this->getLanguageNativeName($langcode); } } } if (!is_null($output['#links'])) { // Common lang codes between entity translations and switch links. $available_translations_links = array_intersect_key($output['#links'], $translations); // Different lang codes between entity translations and switch links. $unavailable_translations_links = array_diff_key($output['#links'], $translations); } // Deletes links for untranslated content. if ($untranslatedContent == 0 && !is_null($translations) && !is_null($output['#links'])) { $output['#links'] = $available_translations_links; } // Sets URLs to front page for untranslated content. if ($untranslatedContent == 2 && !is_null($translations) && !is_null($output['#links'])) { $modified_translations_links = $unavailable_translations_links; foreach ($modified_translations_links as $langcode => $link) { $modified_translations_links[$langcode]['url'] = Url::fromRoute('<front>'); } $output['#links'] = array_merge($modified_translations_links, $available_translations_links); } if (!is_null($output)) { $container['global_gateway_language_switcher_data'] = $output; } } /** * {@inheritdoc} */ public function buildForm(array $form, FormStateInterface $form_state) { $this->limit = $form_state->get('limit'); $this->regionCode = $form_state->get('current_region'); $this->nativeNames = $form_state->get('nativeNames'); $this->untranslatedContent = $form_state->get('untranslatedContent'); $regions = $this->getAvailableRegions(); /* Available Region select displays: 0 - None 1 - Select list 2 - select2boxes */ $region_displays = ['hidden', 'select', 'select']; $region_display = $form_state->get('region_display'); $languages_display = $form_state->get('languages_display'); $flag_icons = $form_state->get('flag_icons'); /* Sets the 'Select list' for Region select display if there are no settings for <select> display or Region select display is set to select2boxes, but select2boxes module doesn't exist. */ if (is_null($region_display) || ($region_display == 2 && !\Drupal::moduleHandler() ->moduleExists('select2boxes'))) { $region_display = 1; } $region = [ '#type' => $region_displays[$region_display], '#title' => $this->t('Region'), '#title_display' => 'invisible', '#options' => $regions, '#default_value' => $this->regionCode, '#empty_value' => 'none', '#empty_option' => '- Select Region -', '#ajax' => [ 'callback' => '::updateBlock', 'wrapper' => 'new-region-list', 'effect' => 'fade', 'event' => 'change', ], '#attributes' => [ 'class' => ['global-gateway-region'], ], '#weight' => $form_state->get('regionWeight'), ]; // Enable select2boxes for selected forms. if ($region_display == 2) { $region['#attributes'] = [ 'class' => [ 'global-gateway-region', 'select2-widget', ], 'data-jquery-once-autocomplete' => 'true', 'data-select2-autocomplete-list-widget' => 'true', ]; $form['#attached']['library'][] = 'select2boxes/widget'; } if (Helper::softDependenciesMeet()) { $region['#type'] = 'select_icons'; $region['#options_attributes'] = Helper::getOptionAttributes($regions); $form['#attached']['library'][] = 'flags/flags'; $form['#attached']['library'][] = 'select_icons/select_icons'; } $form['region'] = $region; $items_id = $form_state->get('items_id'); $form['items'] = [ '#type' => 'container', '#attributes' => ['data-replace-id' => $items_id], '#weight' => $form_state->get('languagesWeight'), ]; $form['items_id'] = [ '#type' => 'hidden', '#value' => $items_id, ]; $form['limit'] = [ '#type' => 'hidden', '#value' => $this->limit, ]; $form['nativeNames'] = [ '#type' => 'hidden', '#value' => $this->nativeNames, ]; $form['untranslatedContent'] = [ '#type' => 'hidden', '#value' => $this->untranslatedContent, ]; if (\Drupal::moduleHandler()->moduleExists('language')) { $this->addItems($form['items']); } if ($flag_icons == 1 && $region_display == 2) { $form['region']['#attributes']['class'][] = 'flag-icon'; $form['#attached']['library'][] = 'flags/flags'; $form['#attached']['drupalSettings']['flagsClasses'] = $this->getFlagsClasses(); } // Disable Languages display if it is set to None. if ($languages_display == 0) { $form['items'] = []; } $form_state->setCached(FALSE); return $form; } /** * Ajax callback for $form['region']. * * Rebuild switcher items. * * @param array $form * The entire form array. * @param \Drupal\Core\Form\FormStateInterface $form_state * The form state. * * @return \Drupal\Core\Ajax\AjaxResponse * The ajax response. */ public function updateBlock(array $form, FormStateInterface $form_state) { $ajax_response = new AjaxResponse(); $data = new \stdClass(); $this->limit = Xss::filter($form_state->getUserInput()['limit']); $this->nativeNames = Xss::filter($form_state->getUserInput()['nativeNames']); $this->untranslatedContent = Xss::filter($form_state->getUserInput()['untranslatedContent']); if ($this->limit == 0) { $current_code = 'none'; } else { $current_code = $form_state->getValue('region'); } $data->region = $form_state->getValue('region'); $this->regionCode = $current_code; $negotiator = $this->negotiator->getNegotiator('session'); $negotiator->persist($form_state->getValue('region')); $this->addItems($form['items']); $items_id = $form_state->getValue('items_id'); $selector = ".global-gateway-switcher-form [data-replace-id='" . $items_id . "']"; $ajax_response->addCommand(new ReplaceCommand($selector, $form['items'])); $ajax_response->addCommand(new InvokeCommand(NULL, 'globalGatewayEmmitRegionChange', [$data])); return $ajax_response; } /** * Build a list of regions. * * @return array * The sorted regions. */ protected function getAvailableRegions() { // @todo: Should we show here only regions that has some mapping. $regions = $this->helper->getRegionsList(); uasort($regions, function ($a, $b) { return strnatcasecmp($a, $b); }); return $regions; } /** * Build a list flags' CSS classes. * * @return array * The sorted regions. */ protected function getFlagsClasses() { $regions = $this->helper->getRegionsList(); uasort($regions, function ($a, $b) { return strnatcasecmp($a, $b); }); $regions_codes = array_keys($regions); $flags_classes = []; foreach ($regions_codes as $code) { $flags_classes[strtoupper($code)] = [ 'flag', 'flag-' . strtolower($code), 'country-flag', ]; } return $flags_classes; } /** * {@inheritdoc} */ public function submitForm(array &$form, FormStateInterface $form_state) { } }