Code Coverage |
||||||||||
Classes and Traits |
Functions and Methods |
Lines |
||||||||
| Total | |
0.00% |
0 / 1 |
|
0.00% |
0 / 14 |
CRAP | |
0.00% |
0 / 134 |
| LanguageNegotiator | |
0.00% |
0 / 1 |
|
0.00% |
0 / 14 |
1806 | |
0.00% |
0 / 134 |
| __construct | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 6 |
|||
| initLanguageManager | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 2 |
|||
| reset | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 3 |
|||
| setCurrentUser | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 3 |
|||
| initializeType | |
0.00% |
0 / 1 |
56 | |
0.00% |
0 / 19 |
|||
| getEnabledNegotiators | |
0.00% |
0 / 1 |
6 | |
0.00% |
0 / 2 |
|||
| negotiateLanguage | |
0.00% |
0 / 1 |
20 | |
0.00% |
0 / 8 |
|||
| getNegotiationMethods | |
0.00% |
0 / 1 |
6 | |
0.00% |
0 / 7 |
|||
| getNegotiationMethodInstance | |
0.00% |
0 / 1 |
6 | |
0.00% |
0 / 9 |
|||
| getPrimaryNegotiationMethod | |
0.00% |
0 / 1 |
6 | |
0.00% |
0 / 3 |
|||
| isNegotiationMethodEnabled | |
0.00% |
0 / 1 |
20 | |
0.00% |
0 / 11 |
|||
| saveConfiguration | |
0.00% |
0 / 1 |
30 | |
0.00% |
0 / 18 |
|||
| purgeConfiguration | |
0.00% |
0 / 1 |
6 | |
0.00% |
0 / 6 |
|||
| updateConfiguration | |
0.00% |
0 / 1 |
72 | |
0.00% |
0 / 37 |
|||
| <?php | |
| /** | |
| * @file | |
| * Contains \Drupal\language\LanguageNegotiator. | |
| */ | |
| namespace Drupal\language; | |
| use Drupal\Component\Plugin\PluginManagerInterface; | |
| use Drupal\Core\Config\ConfigFactoryInterface; | |
| use Drupal\Core\Session\AccountInterface; | |
| use Drupal\Core\Site\Settings; | |
| use Drupal\language\Plugin\LanguageNegotiation\LanguageNegotiationUI; | |
| use Symfony\Component\HttpFoundation\RequestStack; | |
| /** | |
| * Class responsible for performing language negotiation. | |
| */ | |
| class LanguageNegotiator implements LanguageNegotiatorInterface { | |
| /** | |
| * The language negotiation method plugin manager. | |
| * | |
| * @var \Drupal\Component\Plugin\PluginManagerInterface | |
| */ | |
| protected $negotiatorManager; | |
| /** | |
| * The language manager. | |
| * | |
| * @var \Drupal\language\ConfigurableLanguageManagerInterface | |
| */ | |
| protected $languageManager; | |
| /** | |
| * The configuration factory. | |
| * | |
| * @var \Drupal\Core\Config\ConfigFactoryInterface | |
| */ | |
| protected $configFactory; | |
| /** | |
| * The settings instance. | |
| * | |
| * @return \Drupal\Core\Site\Settings | |
| */ | |
| protected $settings; | |
| /** | |
| * The request stack object. | |
| * | |
| * @var \Symfony\Component\HttpFoundation\RequestStack | |
| */ | |
| protected $requestStack; | |
| /** | |
| * The current active user. | |
| * | |
| * @return \Drupal\Core\Session\AccountInterface | |
| */ | |
| protected $currentUser; | |
| /** | |
| * Local cache for language negotiation method instances. | |
| * | |
| * @var array | |
| */ | |
| protected $methods; | |
| /** | |
| * An array of language objects keyed by method id. | |
| * | |
| * @var \Drupal\Core\Language\LanguageInterface[] | |
| */ | |
| protected $negotiatedLanguages = array(); | |
| /** | |
| * Constructs a new LanguageNegotiator object. | |
| * | |
| * @param \Drupal\language\ConfigurableLanguageManagerInterface $language_manager | |
| * The language manager. | |
| * @param \Drupal\Component\Plugin\PluginManagerInterface $negotiator_manager | |
| * The language negotiation methods plugin manager | |
| * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory | |
| * The configuration factory. | |
| * @param \Drupal\Core\Site\Settings $settings | |
| * The settings instance. | |
| */ | |
| public function __construct(ConfigurableLanguageManagerInterface $language_manager, PluginManagerInterface $negotiator_manager, ConfigFactoryInterface $config_factory, Settings $settings, RequestStack $requestStack) { | |
| $this->languageManager = $language_manager; | |
| $this->negotiatorManager = $negotiator_manager; | |
| $this->configFactory = $config_factory; | |
| $this->settings = $settings; | |
| $this->requestStack = $requestStack; | |
| } | |
| /** | |
| * Initializes the injected language manager with the negotiator. | |
| * | |
| * This should be called right after instantiating the negotiator to make it | |
| * available to the language manager without introducing a circular | |
| * dependency. | |
| */ | |
| public function initLanguageManager() { | |
| $this->languageManager->setNegotiator($this); | |
| } | |
| /** | |
| * {@inheritdoc} | |
| */ | |
| public function reset() { | |
| $this->negotiatedLanguages = array(); | |
| $this->methods = array(); | |
| } | |
| /** | |
| * {@inheritdoc} | |
| */ | |
| public function setCurrentUser(AccountInterface $current_user) { | |
| $this->currentUser = $current_user; | |
| $this->reset(); | |
| } | |
| /** | |
| * {@inheritdoc} | |
| */ | |
| public function initializeType($type) { | |
| $language = NULL; | |
| if ($this->currentUser) { | |
| // Execute the language negotiation methods in the order they were set up | |
| // and return the first valid language found. | |
| foreach ($this->getEnabledNegotiators($type) as $method_id => $info) { | |
| if (!isset($this->negotiatedLanguages[$method_id])) { | |
| $this->negotiatedLanguages[$method_id] = $this->negotiateLanguage($type, $method_id); | |
| } | |
| // Since objects are references, we need to return a clone to prevent | |
| // the language negotiation method cache from being unintentionally | |
| // altered. The same methods might be used with different language types | |
| // based on configuration. | |
| $language = !empty($this->negotiatedLanguages[$method_id]) ? clone($this->negotiatedLanguages[$method_id]) : NULL; | |
| if ($language) { | |
| $this->getNegotiationMethodInstance($method_id)->persist($language); | |
| break; | |
| } | |
| } | |
| } | |
| if (!$language) { | |
| // If no other language was found use the default one. | |
| $language = $this->languageManager->getDefaultLanguage(); | |
| $method_id = static::METHOD_ID; | |
| } | |
| return array($method_id => $language); | |
| } | |
| /** | |
| * Gets enabled detection methods for the provided language type. | |
| * | |
| * @param string $type | |
| * The language type. | |
| * | |
| * @return array | |
| * An array of enabled detection methods for the provided language type. | |
| */ | |
| protected function getEnabledNegotiators($type) { | |
| return $this->configFactory->get('language.types')->get('negotiation.' . $type . '.enabled') ?: array(); | |
| } | |
| /** | |
| * Performs language negotiation using the specified negotiation method. | |
| * | |
| * @param string $type | |
| * The language type to be initialized. | |
| * @param string $method_id | |
| * The string identifier of the language negotiation method to use to detect | |
| * language. | |
| * | |
| * @return \Drupal\Core\Language\LanguageInterface|null | |
| * Negotiated language object for given type and method, FALSE otherwise. | |
| */ | |
| protected function negotiateLanguage($type, $method_id) { | |
| $langcode = NULL; | |
| $method = $this->negotiatorManager->getDefinition($method_id); | |
| if (!isset($method['types']) || in_array($type, $method['types'])) { | |
| $langcode = $this->getNegotiationMethodInstance($method_id)->getLangcode($this->requestStack->getCurrentRequest()); | |
| } | |
| $languages = $this->languageManager->getLanguages(); | |
| return isset($languages[$langcode]) ? $languages[$langcode] : NULL; | |
| } | |
| /** | |
| * {@inheritdoc} | |
| */ | |
| public function getNegotiationMethods($type = NULL) { | |
| $definitions = $this->negotiatorManager->getDefinitions(); | |
| if (isset($type)) { | |
| $enabled_methods = $this->getEnabledNegotiators($type); | |
| $definitions = array_intersect_key($definitions, $enabled_methods); | |
| } | |
| return $definitions; | |
| } | |
| /** | |
| * {@inheritdoc} | |
| */ | |
| public function getNegotiationMethodInstance($method_id) { | |
| if (!isset($this->methods[$method_id])) { | |
| $instance = $this->negotiatorManager->createInstance($method_id, array()); | |
| $instance->setLanguageManager($this->languageManager); | |
| $instance->setConfig($this->configFactory); | |
| $instance->setCurrentUser($this->currentUser); | |
| $this->methods[$method_id] = $instance; | |
| } | |
| return $this->methods[$method_id]; | |
| } | |
| /** | |
| * {@inheritdoc} | |
| */ | |
| public function getPrimaryNegotiationMethod($type) { | |
| $enabled_methods = $this->getEnabledNegotiators($type); | |
| return empty($enabled_methods) ? LanguageNegotiatorInterface::METHOD_ID : key($enabled_methods); | |
| } | |
| /** | |
| * {@inheritdoc} | |
| */ | |
| public function isNegotiationMethodEnabled($method_id, $type = NULL) { | |
| $enabled = FALSE; | |
| $language_types = !empty($type) ? array($type) : $this->languageManager->getLanguageTypes(); | |
| foreach ($language_types as $type) { | |
| $enabled_methods = $this->getEnabledNegotiators($type); | |
| if (isset($enabled_methods[$method_id])) { | |
| $enabled = TRUE; | |
| break; | |
| } | |
| } | |
| return $enabled; | |
| } | |
| /** | |
| * {@inheritdoc} | |
| */ | |
| function saveConfiguration($type, $enabled_methods) { | |
| // As configurable language types might have changed, we reset the cache. | |
| $this->languageManager->reset(); | |
| $definitions = $this->getNegotiationMethods(); | |
| $default_types = $this->languageManager->getLanguageTypes(); | |
| // Order the language negotiation method list by weight. | |
| asort($enabled_methods); | |
| foreach ($enabled_methods as $method_id => $weight) { | |
| if (isset($definitions[$method_id])) { | |
| $method = $definitions[$method_id]; | |
| // If the language negotiation method does not express any preference | |
| // about types, make it available for any configurable type. | |
| $types = array_flip(!empty($method['types']) ? $method['types'] : $default_types); | |
| // Check whether the method is defined and has the right type. | |
| if (!isset($types[$type])) { | |
| unset($enabled_methods[$method_id]); | |
| } | |
| } | |
| else { | |
| unset($enabled_methods[$method_id]); | |
| } | |
| } | |
| $this->configFactory->getEditable('language.types')->set('negotiation.' . $type . '.enabled', $enabled_methods)->save(); | |
| } | |
| /** | |
| * {@inheritdoc} | |
| */ | |
| function purgeConfiguration() { | |
| // Ensure that we are getting the defined language negotiation information. | |
| // An invocation of \Drupal\Core\Extension\ModuleHandler::install() or | |
| // \Drupal\Core\Extension\ModuleHandler::uninstall() could invalidate the | |
| // cached information. | |
| $this->negotiatorManager->clearCachedDefinitions(); | |
| $this->languageManager->reset(); | |
| foreach ($this->languageManager->getDefinedLanguageTypesInfo() as $type => $info) { | |
| $this->saveConfiguration($type, $this->getEnabledNegotiators($type)); | |
| } | |
| } | |
| /** | |
| * {@inheritdoc} | |
| */ | |
| function updateConfiguration(array $types) { | |
| // Ensure that we are getting the defined language negotiation information. | |
| // An invocation of \Drupal\Core\Extension\ModuleHandler::install() or | |
| // \Drupal\Core\Extension\ModuleHandler::uninstall() could invalidate the | |
| // cached information. | |
| $this->negotiatorManager->clearCachedDefinitions(); | |
| $this->languageManager->reset(); | |
| $language_types = array(); | |
| $language_types_info = $this->languageManager->getDefinedLanguageTypesInfo(); | |
| $method_definitions = $this->getNegotiationMethods(); | |
| foreach ($language_types_info as $type => $info) { | |
| $configurable = in_array($type, $types); | |
| // The default language negotiation settings, if available, are stored in | |
| // $info['fixed']. | |
| $has_default_settings = !empty($info['fixed']); | |
| // Check whether the language type is unlocked. Only the status of | |
| // unlocked language types can be toggled between configurable and | |
| // non-configurable. | |
| if (empty($info['locked'])) { | |
| if (!$configurable && !$has_default_settings) { | |
| // If we have an unlocked non-configurable language type without | |
| // default language negotiation settings, we use the values | |
| // negotiated for the interface language which, should always be | |
| // available. | |
| $method_weights = array(LanguageNegotiationUI::METHOD_ID); | |
| $method_weights = array_flip($method_weights); | |
| $this->saveConfiguration($type, $method_weights); | |
| } | |
| } | |
| else { | |
| // The language type is locked. Locked language types with default | |
| // settings are always considered non-configurable. In turn if default | |
| // settings are missing, the language type is always considered | |
| // configurable. | |
| // If the language type is locked we can just store its default language | |
| // negotiation settings if it has some, since it is not configurable. | |
| if ($has_default_settings) { | |
| $method_weights = array(); | |
| // Default settings are in $info['fixed']. | |
| foreach ($info['fixed'] as $weight => $method_id) { | |
| if (isset($method_definitions[$method_id])) { | |
| $method_weights[$method_id] = $weight; | |
| } | |
| } | |
| $this->saveConfiguration($type, $method_weights); | |
| } | |
| else { | |
| // It was missing default settings, so force it to be configurable. | |
| $configurable = TRUE; | |
| } | |
| } | |
| // Accumulate information for each language type so it can be saved later. | |
| $language_types[$type] = $configurable; | |
| } | |
| // Store the language type configuration. | |
| $config = array( | |
| 'configurable' => array_keys(array_filter($language_types)), | |
| 'all' => array_keys($language_types), | |
| ); | |
| $this->languageManager->saveLanguageTypesConfiguration($config); | |
| } | |
| } |