Code Coverage |
||||||||||
Classes and Traits |
Functions and Methods |
Lines |
||||||||
Total | |
0.00% |
0 / 1 |
|
0.00% |
0 / 24 |
CRAP | |
0.00% |
0 / 194 |
ConfigurableLanguageManager | |
0.00% |
0 / 1 |
|
0.00% |
0 / 24 |
3422 | |
0.00% |
0 / 194 |
rebuildServices | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 2 |
|||
__construct | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 6 |
|||
init | |
0.00% |
0 / 1 |
12 | |
0.00% |
0 / 7 |
|||
isMultilingual | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 2 |
|||
getLanguageTypes | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 3 |
|||
getDefinedLanguageTypes | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 3 |
|||
loadLanguageTypesConfiguration | |
0.00% |
0 / 1 |
12 | |
0.00% |
0 / 5 |
|||
getDefinedLanguageTypesInfo | |
0.00% |
0 / 1 |
6 | |
0.00% |
0 / 9 |
|||
saveLanguageTypesConfiguration | |
0.00% |
0 / 1 |
12 | |
0.00% |
0 / 9 |
|||
getCurrentLanguage | |
0.00% |
0 / 1 |
42 | |
0.00% |
0 / 17 |
|||
reset | |
0.00% |
0 / 1 |
20 | |
0.00% |
0 / 17 |
|||
getNegotiator | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 2 |
|||
setNegotiator | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 4 |
|||
getLanguages | |
0.00% |
0 / 1 |
20 | |
0.00% |
0 / 21 |
|||
getNativeLanguages | |
0.00% |
0 / 1 |
6 | |
0.00% |
0 / 11 |
|||
updateLockedLanguageWeights | |
0.00% |
0 / 1 |
12 | |
0.00% |
0 / 12 |
|||
getFallbackCandidates | |
0.00% |
0 / 1 |
42 | |
0.00% |
0 / 23 |
|||
getLanguageSwitchLinks | |
0.00% |
0 / 1 |
30 | |
0.00% |
0 / 16 |
|||
setConfigOverrideLanguage | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 3 |
|||
getConfigOverrideLanguage | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 2 |
|||
getLanguageConfigOverride | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 2 |
|||
getLanguageConfigOverrideStorage | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 2 |
|||
getStandardLanguageListWithoutConfigured | |
0.00% |
0 / 1 |
12 | |
0.00% |
0 / 12 |
|||
getNegotiatedLanguageMethod | |
0.00% |
0 / 1 |
12 | |
0.00% |
0 / 4 |
<?php | |
/** | |
* @file | |
* Contains \Drupal\language\ConfigurableLanguageManager. | |
*/ | |
namespace Drupal\language; | |
use Drupal\Core\Language\LanguageInterface; | |
use Drupal\Core\Config\ConfigFactoryInterface; | |
use Drupal\Core\Extension\ModuleHandlerInterface; | |
use Drupal\Core\Language\Language; | |
use Drupal\Core\Language\LanguageDefault; | |
use Drupal\Core\Language\LanguageManager; | |
use Drupal\Core\StringTranslation\TranslatableMarkup; | |
use Drupal\Core\Url; | |
use Drupal\language\Config\LanguageConfigFactoryOverrideInterface; | |
use Drupal\language\Entity\ConfigurableLanguage; | |
use Symfony\Component\HttpFoundation\RequestStack; | |
/** | |
* Overrides default LanguageManager to provide configured languages. | |
*/ | |
class ConfigurableLanguageManager extends LanguageManager implements ConfigurableLanguageManagerInterface { | |
/** | |
* The configuration storage service. | |
* | |
* @var \Drupal\Core\Config\ConfigFactoryInterface | |
*/ | |
protected $configFactory; | |
/** | |
* The module handler service. | |
* | |
* @var \Drupal\Core\Extension\ModuleHandlerInterface | |
*/ | |
protected $moduleHandler; | |
/** | |
* The language configuration override service. | |
* | |
* @var \Drupal\language\Config\LanguageConfigFactoryOverrideInterface | |
*/ | |
protected $configFactoryOverride; | |
/** | |
* The request object. | |
* | |
* @var \Symfony\Component\HttpFoundation\RequestStack | |
*/ | |
protected $requestStack; | |
/** | |
* The language negotiator. | |
* | |
* @var \Drupal\language\LanguageNegotiatorInterface | |
*/ | |
protected $negotiator; | |
/** | |
* Local cache for language type configuration data. | |
* | |
* @var array | |
*/ | |
protected $languageTypes; | |
/** | |
* Local cache for language type information. | |
* | |
* @var array | |
*/ | |
protected $languageTypesInfo; | |
/** | |
* An array of language objects keyed by language type. | |
* | |
* @var \Drupal\Core\Language\LanguageInterface[] | |
*/ | |
protected $negotiatedLanguages; | |
/** | |
* An array of language negotiation method IDs keyed by language type. | |
* | |
* @var array | |
*/ | |
protected $negotiatedMethods; | |
/** | |
* Whether or not the language manager has been initialized. | |
* | |
* @var bool | |
*/ | |
protected $initialized = FALSE; | |
/** | |
* Whether already in the process of language initialization. | |
* | |
* @var bool | |
*/ | |
protected $initializing = FALSE; | |
/** | |
* {@inheritdoc} | |
*/ | |
public static function rebuildServices() { | |
\Drupal::service('kernel')->invalidateContainer(); | |
} | |
/** | |
* Constructs a new ConfigurableLanguageManager object. | |
* | |
* @param \Drupal\Core\Language\LanguageDefault $default_language | |
* The default language service. | |
* @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory | |
* The configuration factory service. | |
* @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler | |
* The module handler service. | |
* @param \Drupal\language\Config\LanguageConfigFactoryOverrideInterface $config_override | |
* The language configuration override service. | |
* @param \Symfony\Component\HttpFoundation\RequestStack $request_stack | |
* The request stack object. | |
*/ | |
public function __construct(LanguageDefault $default_language, ConfigFactoryInterface $config_factory, ModuleHandlerInterface $module_handler, LanguageConfigFactoryOverrideInterface $config_override, RequestStack $request_stack) { | |
$this->defaultLanguage = $default_language; | |
$this->configFactory = $config_factory; | |
$this->moduleHandler = $module_handler; | |
$this->configFactoryOverride = $config_override; | |
$this->requestStack = $request_stack; | |
} | |
/** | |
* {@inheritdoc} | |
*/ | |
public function init() { | |
if (!$this->initialized) { | |
foreach ($this->getDefinedLanguageTypes() as $type) { | |
$this->getCurrentLanguage($type); | |
} | |
$this->initialized = TRUE; | |
} | |
} | |
/** | |
* {@inheritdoc} | |
*/ | |
public function isMultilingual() { | |
return count($this->getLanguages(LanguageInterface::STATE_CONFIGURABLE)) > 1; | |
} | |
/** | |
* {@inheritdoc} | |
*/ | |
public function getLanguageTypes() { | |
$this->loadLanguageTypesConfiguration(); | |
return $this->languageTypes['configurable']; | |
} | |
/** | |
* {@inheritdoc} | |
*/ | |
public function getDefinedLanguageTypes() { | |
$this->loadLanguageTypesConfiguration(); | |
return $this->languageTypes['all']; | |
} | |
/** | |
* Retrieves language types from the configuration storage. | |
* | |
* @return array | |
* An array of language type names. | |
*/ | |
protected function loadLanguageTypesConfiguration() { | |
if (!$this->languageTypes) { | |
$this->languageTypes = $this->configFactory->get('language.types')->get() ?: array('configurable' => array(), 'all' => parent::getLanguageTypes()); | |
} | |
return $this->languageTypes; | |
} | |
/** | |
* {@inheritdoc} | |
*/ | |
public function getDefinedLanguageTypesInfo() { | |
if (!isset($this->languageTypesInfo)) { | |
$defaults = parent::getDefinedLanguageTypesInfo(); | |
$info = $this->moduleHandler->invokeAll('language_types_info'); | |
$language_info = $info + $defaults; | |
// Let other modules alter the list of language types. | |
$this->moduleHandler->alter('language_types_info', $language_info); | |
$this->languageTypesInfo = $language_info; | |
} | |
return $this->languageTypesInfo; | |
} | |
/** | |
* {@inheritdoc} | |
*/ | |
public function saveLanguageTypesConfiguration(array $values) { | |
$config = $this->configFactory->getEditable('language.types'); | |
if (isset($values['configurable'])) { | |
$config->set('configurable', $values['configurable']); | |
} | |
if (isset($values['all'])) { | |
$config->set('all', $values['all']); | |
} | |
$config->save(); | |
} | |
/** | |
* {@inheritdoc} | |
*/ | |
public function getCurrentLanguage($type = LanguageInterface::TYPE_INTERFACE) { | |
if (!isset($this->negotiatedLanguages[$type])) { | |
// Ensure we have a valid value for this language type. | |
$this->negotiatedLanguages[$type] = $this->getDefaultLanguage(); | |
if ($this->negotiator && $this->isMultilingual()) { | |
if (!$this->initializing) { | |
$this->initializing = TRUE; | |
$negotiation = $this->negotiator->initializeType($type); | |
$this->negotiatedLanguages[$type] = reset($negotiation); | |
$this->negotiatedMethods[$type] = key($negotiation); | |
$this->initializing = FALSE; | |
} | |
// If the current interface language needs to be retrieved during | |
// initialization we return the system language. This way string | |
// translation calls happening during initialization will return the | |
// original strings which can be translated by calling them again | |
// afterwards. This can happen for instance while parsing negotiation | |
// method definitions. | |
elseif ($type == LanguageInterface::TYPE_INTERFACE) { | |
return new Language(array('id' => LanguageInterface::LANGCODE_SYSTEM)); | |
} | |
} | |
} | |
return $this->negotiatedLanguages[$type]; | |
} | |
/** | |
* {@inheritdoc} | |
*/ | |
public function reset($type = NULL) { | |
if (!isset($type)) { | |
$this->initialized = FALSE; | |
$this->negotiatedLanguages = array(); | |
$this->negotiatedMethods = array(); | |
$this->languageTypes = NULL; | |
$this->languageTypesInfo = NULL; | |
$this->languages = array(); | |
if ($this->negotiator) { | |
$this->negotiator->reset(); | |
} | |
} | |
elseif (isset($this->negotiatedLanguages[$type])) { | |
unset($this->negotiatedLanguages[$type]); | |
unset($this->negotiatedMethods[$type]); | |
} | |
return $this; | |
} | |
/** | |
* {@inheritdoc} | |
*/ | |
public function getNegotiator() { | |
return $this->negotiator; | |
} | |
/** | |
* {@inheritdoc} | |
*/ | |
public function setNegotiator(LanguageNegotiatorInterface $negotiator) { | |
$this->negotiator = $negotiator; | |
$this->initialized = FALSE; | |
$this->negotiatedLanguages = array(); | |
} | |
/** | |
* {@inheritdoc} | |
*/ | |
public function getLanguages($flags = LanguageInterface::STATE_CONFIGURABLE) { | |
// If a config override is set, cache using that language's ID. | |
if ($override_language = $this->getConfigOverrideLanguage()) { | |
$static_cache_id = $override_language->getId(); | |
} | |
else { | |
$static_cache_id = $this->getCurrentLanguage()->getId(); | |
} | |
if (!isset($this->languages[$static_cache_id][$flags])) { | |
// Initialize the language list with the default language and default | |
// locked languages. These cannot be removed. This serves as a fallback | |
// list if this method is invoked while the language module is installed | |
// and the configuration entities for languages are not yet fully | |
// imported. | |
$default = $this->getDefaultLanguage(); | |
$languages = array($default->getId() => $default); | |
$languages += $this->getDefaultLockedLanguages($default->getWeight()); | |
// Load configurable languages on top of the defaults. Ideally this could | |
// use the entity API to load and instantiate ConfigurableLanguage | |
// objects. However the entity API depends on the language system, so that | |
// would result in infinite loops. We use the configuration system | |
// directly and instantiate runtime Language objects. When language | |
// entities are imported those cover the default and locked languages, so | |
// site-specific configuration will prevail over the fallback values. | |
// Having them in the array already ensures if this is invoked in the | |
// middle of importing language configuration entities, the defaults are | |
// always present. | |
$config_ids = $this->configFactory->listAll('language.entity.'); | |
foreach ($this->configFactory->loadMultiple($config_ids) as $config) { | |
$data = $config->get(); | |
$data['name'] = $data['label']; | |
$languages[$data['id']] = new Language($data); | |
} | |
Language::sort($languages); | |
// Filter the full list of languages based on the value of $flags. | |
$this->languages[$static_cache_id][$flags] = $this->filterLanguages($languages, $flags); | |
} | |
return $this->languages[$static_cache_id][$flags]; | |
} | |
/** | |
* {@inheritdoc} | |
*/ | |
public function getNativeLanguages() { | |
$languages = $this->getLanguages(LanguageInterface::STATE_CONFIGURABLE); | |
$natives = array(); | |
$original_language = $this->getConfigOverrideLanguage(); | |
foreach ($languages as $langcode => $language) { | |
$this->setConfigOverrideLanguage($language); | |
$natives[$langcode] = ConfigurableLanguage::load($langcode); | |
} | |
$this->setConfigOverrideLanguage($original_language); | |
Language::sort($natives); | |
return $natives; | |
} | |
/** | |
* {@inheritdoc} | |
*/ | |
public function updateLockedLanguageWeights() { | |
// Get the weight of the last configurable language. | |
$configurable_languages = $this->getLanguages(LanguageInterface::STATE_CONFIGURABLE); | |
$max_weight = end($configurable_languages)->getWeight(); | |
$locked_languages = $this->getLanguages(LanguageInterface::STATE_LOCKED); | |
// Update locked language weights to maintain the existing order, if | |
// necessary. | |
if (reset($locked_languages)->getWeight() <= $max_weight) { | |
foreach ($locked_languages as $language) { | |
// Update system languages weight. | |
$max_weight++; | |
ConfigurableLanguage::load($language->getId()) | |
->setWeight($max_weight) | |
->save(); | |
} | |
} | |
} | |
/** | |
* {@inheritdoc} | |
*/ | |
public function getFallbackCandidates(array $context = array()) { | |
if ($this->isMultilingual()) { | |
$candidates = array(); | |
if (empty($context['operation']) || $context['operation'] != 'locale_lookup') { | |
// If the fallback context is not locale_lookup, initialize the | |
// candidates with languages ordered by weight and add | |
// LanguageInterface::LANGCODE_NOT_SPECIFIED at the end. Interface | |
// translation fallback should only be based on explicit configuration | |
// gathered via the alter hooks below. | |
$candidates = array_keys($this->getLanguages()); | |
$candidates[] = LanguageInterface::LANGCODE_NOT_SPECIFIED; | |
$candidates = array_combine($candidates, $candidates); | |
// The first candidate should always be the desired language if | |
// specified. | |
if (!empty($context['langcode'])) { | |
$candidates = array($context['langcode'] => $context['langcode']) + $candidates; | |
} | |
} | |
// Let other modules hook in and add/change candidates. | |
$type = 'language_fallback_candidates'; | |
$types = array(); | |
if (!empty($context['operation'])) { | |
$types[] = $type . '_' . $context['operation']; | |
} | |
$types[] = $type; | |
$this->moduleHandler->alter($types, $candidates, $context); | |
} | |
else { | |
$candidates = parent::getFallbackCandidates($context); | |
} | |
return $candidates; | |
} | |
/** | |
* {@inheritdoc} | |
*/ | |
public function getLanguageSwitchLinks($type, Url $url) { | |
$links = FALSE; | |
if ($this->negotiator) { | |
foreach ($this->negotiator->getNegotiationMethods($type) as $method_id => $method) { | |
$reflector = new \ReflectionClass($method['class']); | |
if ($reflector->implementsInterface('\Drupal\language\LanguageSwitcherInterface')) { | |
$result = $this->negotiator->getNegotiationMethodInstance($method_id)->getLanguageSwitchLinks($this->requestStack->getCurrentRequest(), $type, $url); | |
if (!empty($result)) { | |
// Allow modules to provide translations for specific links. | |
$this->moduleHandler->alter('language_switch_links', $result, $type, $path); | |
$links = (object) array('links' => $result, 'method_id' => $method_id); | |
break; | |
} | |
} | |
} | |
} | |
return $links; | |
} | |
/** | |
* {@inheritdoc} | |
*/ | |
public function setConfigOverrideLanguage(LanguageInterface $language = NULL) { | |
$this->configFactoryOverride->setLanguage($language); | |
return $this; | |
} | |
/** | |
* {@inheritdoc} | |
*/ | |
public function getConfigOverrideLanguage() { | |
return $this->configFactoryOverride->getLanguage(); | |
} | |
/** | |
* {@inheritdoc} | |
*/ | |
public function getLanguageConfigOverride($langcode, $name) { | |
return $this->configFactoryOverride->getOverride($langcode, $name); | |
} | |
/** | |
* {@inheritdoc} | |
*/ | |
public function getLanguageConfigOverrideStorage($langcode) { | |
return $this->configFactoryOverride->getStorage($langcode); | |
} | |
/** | |
* {@inheritdoc} | |
*/ | |
public function getStandardLanguageListWithoutConfigured() { | |
$languages = $this->getLanguages(); | |
$predefined = $this->getStandardLanguageList(); | |
foreach ($predefined as $key => $value) { | |
if (isset($languages[$key])) { | |
unset($predefined[$key]); | |
continue; | |
} | |
$predefined[$key] = new TranslatableMarkup($value[0]); | |
} | |
asort($predefined); | |
return $predefined; | |
} | |
/** | |
* {@inheritdoc} | |
*/ | |
public function getNegotiatedLanguageMethod($type = LanguageInterface::TYPE_INTERFACE) { | |
if (isset($this->negotiatedLanguages[$type]) && isset($this->negotiatedMethods[$type])) { | |
return $this->negotiatedMethods[$type]; | |
} | |
} | |
} |