Drupal 8.0.0 beta 12. More info: https://www.drupal.org/node/2514176
This commit is contained in:
commit
9921556621
13277 changed files with 1459781 additions and 0 deletions
366
core/modules/language/src/LanguageNegotiator.php
Normal file
366
core/modules/language/src/LanguageNegotiator.php
Normal file
|
|
@ -0,0 +1,366 @@
|
|||
<?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);
|
||||
}
|
||||
|
||||
}
|
||||
Reference in a new issue