Commit 0e507e42 authored by alexpott's avatar alexpott

Issue #1810394 by hchonov, plach, YesCT, David Hernández, Schnitzel,...

Issue #1810394 by hchonov, plach, YesCT, David Hernández, Schnitzel, vijaycs85, penyaskito, tstoeckler, alexpott, Gábor Hojtsy: Site configuration with domain based language negotiation results in redirecting authenticated users to a different domain when accessing a content entity route for translation language different from the interface language
parent 20621c28
...@@ -21,8 +21,27 @@ interface OutboundPathProcessorInterface { ...@@ -21,8 +21,27 @@ interface OutboundPathProcessorInterface {
* @param string $path * @param string $path
* The path to process, with a leading slash. * The path to process, with a leading slash.
* @param array $options * @param array $options
* An array of options such as would be passed to the generator's * (optional) An associative array of additional options, with the following
* generateFromRoute() method. * elements:
* - 'query': An array of query key/value-pairs (without any URL-encoding)
* to append to the URL.
* - 'fragment': A fragment identifier (named anchor) to append to the URL.
* Do not include the leading '#' character.
* - 'absolute': Defaults to FALSE. Whether to force the output to be an
* absolute link (beginning with http:). Useful for links that will be
* displayed outside the site, such as in an RSS feed.
* - 'language': An optional language object used to look up the alias
* for the URL. If $options['language'] is omitted, it defaults to the
* current language for the language type LanguageInterface::TYPE_URL.
* - 'https': Whether this URL should point to a secure location. If not
* defined, the current scheme is used, so the user stays on HTTP or HTTPS
* respectively. TRUE enforces HTTPS and FALSE enforces HTTP.
* - 'base_url': Only used internally by a path processor, for example, to
* modify the base URL when a language dependent URL requires so.
* - 'prefix': Only used internally, to modify the path when a language
* dependent URL requires so.
* - 'route': The route object for the given path. It will be set by
* \Drupal\Core\Routing\UrlGenerator::generateFromRoute().
* @param \Symfony\Component\HttpFoundation\Request $request * @param \Symfony\Component\HttpFoundation\Request $request
* The HttpRequest object representing the current request. * The HttpRequest object representing the current request.
* @param \Drupal\Core\Render\BubbleableMetadata $bubbleable_metadata * @param \Drupal\Core\Render\BubbleableMetadata $bubbleable_metadata
......
...@@ -309,6 +309,9 @@ public function generateFromRoute($name, $parameters = array(), $options = array ...@@ -309,6 +309,9 @@ public function generateFromRoute($name, $parameters = array(), $options = array
$name = $this->getRouteDebugMessage($name); $name = $this->getRouteDebugMessage($name);
$this->processRoute($name, $route, $parameters, $generated_url); $this->processRoute($name, $route, $parameters, $generated_url);
$path = $this->getInternalPathFromRoute($name, $route, $parameters, $query_params); $path = $this->getInternalPathFromRoute($name, $route, $parameters, $query_params);
// Outbound path processors might need the route object for the path, e.g.
// to get the path pattern.
$options['route'] = $route;
$path = $this->processPath($path, $options, $generated_url); $path = $this->processPath($path, $options, $generated_url);
if (!empty($options['prefix'])) { if (!empty($options['prefix'])) {
......
...@@ -29,3 +29,19 @@ function content_translation_enable() { ...@@ -29,3 +29,19 @@ function content_translation_enable() {
$message = t('<a href=":settings_url">Enable translation</a> for <em>content types</em>, <em>taxonomy vocabularies</em>, <em>accounts</em>, or any other element you wish to translate.', $t_args); $message = t('<a href=":settings_url">Enable translation</a> for <em>content types</em>, <em>taxonomy vocabularies</em>, <em>accounts</em>, or any other element you wish to translate.', $t_args);
drupal_set_message($message, 'warning'); drupal_set_message($message, 'warning');
} }
/**
* @addtogroup updates-8.0.0-rc
* @{
*/
/**
* Rebuild the routes as the content translation routes have now new names.
*/
function content_translation_update_8001() {
\Drupal::service('router.builder')->rebuild();
}
/**
* @} End of "addtogroup updates-8.0.0-rc".
*/
...@@ -53,7 +53,7 @@ function content_translation_help($route_name, RouteMatchInterface $route_match) ...@@ -53,7 +53,7 @@ function content_translation_help($route_name, RouteMatchInterface $route_match)
*/ */
function content_translation_module_implements_alter(&$implementations, $hook) { function content_translation_module_implements_alter(&$implementations, $hook) {
switch ($hook) { switch ($hook) {
// Move some of our hook implementations to the end of the list. // Move our hook_entity_type_alter() implementation to the end of the list.
case 'entity_type_alter': case 'entity_type_alter':
$group = $implementations['content_translation']; $group = $implementations['content_translation'];
unset($implementations['content_translation']); unset($implementations['content_translation']);
...@@ -140,7 +140,11 @@ function content_translation_entity_type_alter(array &$entity_types) { ...@@ -140,7 +140,11 @@ function content_translation_entity_type_alter(array &$entity_types) {
if ($entity_type->hasLinkTemplate('canonical')) { if ($entity_type->hasLinkTemplate('canonical')) {
// Provide default route names for the translation paths. // Provide default route names for the translation paths.
if (!$entity_type->hasLinkTemplate('drupal:content-translation-overview')) { if (!$entity_type->hasLinkTemplate('drupal:content-translation-overview')) {
$entity_type->setLinkTemplate('drupal:content-translation-overview', $entity_type->getLinkTemplate('canonical') . '/translations'); $translations_path = $entity_type->getLinkTemplate('canonical') . '/translations';
$entity_type->setLinkTemplate('drupal:content-translation-overview', $translations_path);
$entity_type->setLinkTemplate('drupal:content-translation-add', $translations_path . '/add/{source}/{target}');
$entity_type->setLinkTemplate('drupal:content-translation-edit', $translations_path . '/edit/{language}');
$entity_type->setLinkTemplate('drupal:content-translation-delete', $translations_path . '/delete/{language}');
} }
// @todo Remove this as soon as menu access checks rely on the // @todo Remove this as soon as menu access checks rely on the
// controller. See https://www.drupal.org/node/2155787. // controller. See https://www.drupal.org/node/2155787.
......
...@@ -652,7 +652,7 @@ public function entityFormSourceChange($form, FormStateInterface $form_state) { ...@@ -652,7 +652,7 @@ public function entityFormSourceChange($form, FormStateInterface $form_state) {
$source = $form_state->getValue(array('source_langcode', 'source')); $source = $form_state->getValue(array('source_langcode', 'source'));
$entity_type_id = $entity->getEntityTypeId(); $entity_type_id = $entity->getEntityTypeId();
$form_state->setRedirect('content_translation.translation_add_' . $entity_type_id, array( $form_state->setRedirect("entity.$entity_type_id.content_translation_add", array(
$entity_type_id => $entity->id(), $entity_type_id => $entity->id(),
'source' => $source, 'source' => $source,
'target' => $form_object->getFormLangcode($form_state), 'target' => $form_object->getFormLangcode($form_state),
...@@ -689,7 +689,7 @@ function entityFormDeleteTranslation($form, FormStateInterface $form_state) { ...@@ -689,7 +689,7 @@ function entityFormDeleteTranslation($form, FormStateInterface $form_state) {
$form_state->setRedirectUrl($entity->urlInfo('delete-form')); $form_state->setRedirectUrl($entity->urlInfo('delete-form'));
} }
else { else {
$form_state->setRedirect('content_translation.translation_delete_' . $entity_type_id, [ $form_state->setRedirect("entity.$entity_type_id.content_translation_delete", [
$entity_type_id => $entity->id(), $entity_type_id => $entity->id(),
'language' => $form_object->getFormLangcode($form_state), 'language' => $form_object->getFormLangcode($form_state),
]); ]);
......
...@@ -127,7 +127,7 @@ public function overview(RouteMatchInterface $route_match, $entity_type_id = NUL ...@@ -127,7 +127,7 @@ public function overview(RouteMatchInterface $route_match, $entity_type_id = NUL
$langcode = $language->getId(); $langcode = $language->getId();
$add_url = new Url( $add_url = new Url(
'content_translation.translation_add_' . $entity_type_id, "entity.$entity_type_id.content_translation_add",
array( array(
'source' => $original, 'source' => $original,
'target' => $language->getId(), 'target' => $language->getId(),
...@@ -138,7 +138,7 @@ public function overview(RouteMatchInterface $route_match, $entity_type_id = NUL ...@@ -138,7 +138,7 @@ public function overview(RouteMatchInterface $route_match, $entity_type_id = NUL
) )
); );
$edit_url = new Url( $edit_url = new Url(
'content_translation.translation_edit_' . $entity_type_id, "entity.$entity_type_id.content_translation_edit",
array( array(
'language' => $language->getId(), 'language' => $language->getId(),
$entity_type_id => $entity->id(), $entity_type_id => $entity->id(),
...@@ -148,7 +148,7 @@ public function overview(RouteMatchInterface $route_match, $entity_type_id = NUL ...@@ -148,7 +148,7 @@ public function overview(RouteMatchInterface $route_match, $entity_type_id = NUL
) )
); );
$delete_url = new Url( $delete_url = new Url(
'content_translation.translation_delete_' . $entity_type_id, "entity.$entity_type_id.content_translation_delete",
array( array(
'language' => $language->getId(), 'language' => $language->getId(),
$entity_type_id => $entity->id(), $entity_type_id => $entity->id(),
......
...@@ -112,7 +112,7 @@ protected function alterRoutes(RouteCollection $collection) { ...@@ -112,7 +112,7 @@ protected function alterRoutes(RouteCollection $collection) {
'_admin_route' => $is_admin, '_admin_route' => $is_admin,
) )
); );
$collection->add("content_translation.translation_add_$entity_type_id", $route); $collection->add("entity.$entity_type_id.content_translation_add", $route);
$route = new Route( $route = new Route(
$path . '/edit/{language}', $path . '/edit/{language}',
...@@ -137,7 +137,7 @@ protected function alterRoutes(RouteCollection $collection) { ...@@ -137,7 +137,7 @@ protected function alterRoutes(RouteCollection $collection) {
'_admin_route' => $is_admin, '_admin_route' => $is_admin,
) )
); );
$collection->add("content_translation.translation_edit_$entity_type_id", $route); $collection->add("entity.$entity_type_id.content_translation_edit", $route);
$route = new Route( $route = new Route(
$path . '/delete/{language}', $path . '/delete/{language}',
...@@ -162,7 +162,7 @@ protected function alterRoutes(RouteCollection $collection) { ...@@ -162,7 +162,7 @@ protected function alterRoutes(RouteCollection $collection) {
'_admin_route' => $is_admin, '_admin_route' => $is_admin,
) )
); );
$collection->add("content_translation.translation_delete_$entity_type_id", $route); $collection->add("entity.$entity_type_id.content_translation_delete", $route);
} }
} }
......
...@@ -107,7 +107,8 @@ protected function doTestBasicTranslation() { ...@@ -107,7 +107,8 @@ protected function doTestBasicTranslation() {
$language = ConfigurableLanguage::load($langcode); $language = ConfigurableLanguage::load($langcode);
$values[$langcode] = $this->getNewEntityValues($langcode); $values[$langcode] = $this->getNewEntityValues($langcode);
$add_url = Url::fromRoute('content_translation.translation_add_' . $entity->getEntityTypeId(), [ $entity_type_id = $entity->getEntityTypeId();
$add_url = Url::fromRoute("entity.$entity_type_id.content_translation_add", [
$entity->getEntityTypeId() => $entity->id(), $entity->getEntityTypeId() => $entity->id(),
'source' => $default_langcode, 'source' => $default_langcode,
'target' => $langcode 'target' => $langcode
...@@ -167,7 +168,8 @@ protected function doTestBasicTranslation() { ...@@ -167,7 +168,8 @@ protected function doTestBasicTranslation() {
$language = ConfigurableLanguage::load($langcode); $language = ConfigurableLanguage::load($langcode);
$source_langcode = 'it'; $source_langcode = 'it';
$edit = array('source_langcode[source]' => $source_langcode); $edit = array('source_langcode[source]' => $source_langcode);
$add_url = Url::fromRoute('content_translation.translation_add_' . $entity->getEntityTypeId(), [ $entity_type_id = $entity->getEntityTypeId();
$add_url = Url::fromRoute("entity.$entity_type_id.content_translation_add", [
$entity->getEntityTypeId() => $entity->id(), $entity->getEntityTypeId() => $entity->id(),
'source' => $default_langcode, 'source' => $default_langcode,
'target' => $langcode 'target' => $langcode
...@@ -180,7 +182,8 @@ protected function doTestBasicTranslation() { ...@@ -180,7 +182,8 @@ protected function doTestBasicTranslation() {
// Add another translation and mark the other ones as outdated. // Add another translation and mark the other ones as outdated.
$values[$langcode] = $this->getNewEntityValues($langcode); $values[$langcode] = $this->getNewEntityValues($langcode);
$edit = $this->getEditValues($values, $langcode) + array('content_translation[retranslate]' => TRUE); $edit = $this->getEditValues($values, $langcode) + array('content_translation[retranslate]' => TRUE);
$add_url = Url::fromRoute('content_translation.translation_add_' . $entity->getEntityTypeId(), [ $entity_type_id = $entity->getEntityTypeId();
$add_url = Url::fromRoute("entity.$entity_type_id.content_translation_add", [
$entity->getEntityTypeId() => $entity->id(), $entity->getEntityTypeId() => $entity->id(),
'source' => $source_langcode, 'source' => $source_langcode,
'target' => $langcode 'target' => $langcode
...@@ -207,13 +210,15 @@ protected function doTestBasicTranslation() { ...@@ -207,13 +210,15 @@ protected function doTestBasicTranslation() {
*/ */
protected function doTestTranslationOverview() { protected function doTestTranslationOverview() {
$entity = entity_load($this->entityTypeId, $this->entityId, TRUE); $entity = entity_load($this->entityTypeId, $this->entityId, TRUE);
$this->drupalGet($entity->urlInfo('drupal:content-translation-overview')); $translate_url = $entity->urlInfo('drupal:content-translation-overview');
$this->drupalGet($translate_url);
$translate_url->setAbsolute(FALSE);
foreach ($this->langcodes as $langcode) { foreach ($this->langcodes as $langcode) {
if ($entity->hasTranslation($langcode)) { if ($entity->hasTranslation($langcode)) {
$language = new Language(array('id' => $langcode)); $language = new Language(array('id' => $langcode));
$view_path = $entity->url('canonical', array('language' => $language)); $view_url = $entity->url('canonical', ['language' => $language]);
$elements = $this->xpath('//table//a[@href=:href]', array(':href' => $view_path)); $elements = $this->xpath('//table//a[@href=:href]', [':href' => $view_url]);
$this->assertEqual((string) $elements[0], $entity->getTranslation($langcode)->label(), format_string('Label correctly shown for %language translation.', array('%language' => $langcode))); $this->assertEqual((string) $elements[0], $entity->getTranslation($langcode)->label(), format_string('Label correctly shown for %language translation.', array('%language' => $langcode)));
$edit_path = $entity->url('edit-form', array('language' => $language)); $edit_path = $entity->url('edit-form', array('language' => $language));
$elements = $this->xpath('//table//ul[@class="dropbutton"]/li/a[@href=:href]', array(':href' => $edit_path)); $elements = $this->xpath('//table//ul[@class="dropbutton"]/li/a[@href=:href]', array(':href' => $edit_path));
...@@ -343,7 +348,7 @@ protected function doTestTranslationDeletion() { ...@@ -343,7 +348,7 @@ protected function doTestTranslationDeletion() {
// Check that the translator cannot delete the original translation. // Check that the translator cannot delete the original translation.
$args = [$this->entityTypeId => $entity->id(), 'language' => 'en']; $args = [$this->entityTypeId => $entity->id(), 'language' => 'en'];
$this->drupalGet(Url::fromRoute('content_translation.translation_delete_' . $this->entityTypeId, $args)); $this->drupalGet(Url::fromRoute("entity.$this->entityTypeId.content_translation_delete", $args));
$this->assertResponse(403); $this->assertResponse(403);
} }
......
...@@ -73,7 +73,7 @@ protected function setupEntity() { ...@@ -73,7 +73,7 @@ protected function setupEntity() {
// Create a translation. // Create a translation.
$this->drupalLogin($this->translator); $this->drupalLogin($this->translator);
$add_translation_url = Url::fromRoute('content_translation.translation_add_' . $this->entityTypeId, [$this->entityTypeId => $this->entity->id(), 'source' => $default_langcode, 'target' => $this->langcodes[2]]); $add_translation_url = Url::fromRoute("entity.$this->entityTypeId.content_translation_add", [$this->entityTypeId => $this->entity->id(), 'source' => $default_langcode, 'target' => $this->langcodes[2]]);
$this->drupalPostForm($add_translation_url, array(), t('Save')); $this->drupalPostForm($add_translation_url, array(), t('Save'));
$this->rebuildContainer(); $this->rebuildContainer();
} }
...@@ -175,7 +175,7 @@ protected function doTestWorkflows(UserInterface $user, $expected_status) { ...@@ -175,7 +175,7 @@ protected function doTestWorkflows(UserInterface $user, $expected_status) {
$this->assertResponse($expected_status['overview'], SafeMarkup::format('The @user_label has the expected translation overview access.', $args)); $this->assertResponse($expected_status['overview'], SafeMarkup::format('The @user_label has the expected translation overview access.', $args));
// Check whether the user is allowed to create a translation. // Check whether the user is allowed to create a translation.
$add_translation_url = Url::fromRoute('content_translation.translation_add_' . $this->entityTypeId, [$this->entityTypeId => $this->entity->id(), 'source' => $default_langcode, 'target' => $langcode], $options); $add_translation_url = Url::fromRoute("entity.$this->entityTypeId.content_translation_add", [$this->entityTypeId => $this->entity->id(), 'source' => $default_langcode, 'target' => $langcode], $options);
if ($expected_status['add_translation'] == 200) { if ($expected_status['add_translation'] == 200) {
$this->clickLink('Add'); $this->clickLink('Add');
$this->assertUrl($add_translation_url->toString(), [], 'The translation overview points to the translation form when creating translations.'); $this->assertUrl($add_translation_url->toString(), [], 'The translation overview points to the translation form when creating translations.');
...@@ -193,7 +193,7 @@ protected function doTestWorkflows(UserInterface $user, $expected_status) { ...@@ -193,7 +193,7 @@ protected function doTestWorkflows(UserInterface $user, $expected_status) {
// Check whether the user is allowed to edit a translation. // Check whether the user is allowed to edit a translation.
$langcode = $this->langcodes[2]; $langcode = $this->langcodes[2];
$options['language'] = $languages[$langcode]; $options['language'] = $languages[$langcode];
$edit_translation_url = Url::fromRoute('content_translation.translation_edit_' . $this->entityTypeId, [$this->entityTypeId => $this->entity->id(), 'language' => $langcode], $options); $edit_translation_url = Url::fromRoute("entity.$this->entityTypeId.content_translation_edit", [$this->entityTypeId => $this->entity->id(), 'language' => $langcode], $options);
if ($expected_status['edit_translation'] == 200) { if ($expected_status['edit_translation'] == 200) {
$this->drupalGet($translations_url); $this->drupalGet($translations_url);
$editor = $expected_status['edit'] == 200; $editor = $expected_status['edit'] == 200;
...@@ -221,7 +221,7 @@ protected function doTestWorkflows(UserInterface $user, $expected_status) { ...@@ -221,7 +221,7 @@ protected function doTestWorkflows(UserInterface $user, $expected_status) {
// Check whether the user is allowed to delete a translation. // Check whether the user is allowed to delete a translation.
$langcode = $this->langcodes[2]; $langcode = $this->langcodes[2];
$options['language'] = $languages[$langcode]; $options['language'] = $languages[$langcode];
$delete_translation_url = Url::fromRoute('content_translation.translation_delete_' . $this->entityTypeId, [$this->entityTypeId => $this->entity->id(), 'language' => $langcode], $options); $delete_translation_url = Url::fromRoute("entity.$this->entityTypeId.content_translation_delete", [$this->entityTypeId => $this->entity->id(), 'language' => $langcode], $options);
if ($expected_status['delete_translation'] == 200) { if ($expected_status['delete_translation'] == 200) {
$this->drupalGet($translations_url); $this->drupalGet($translations_url);
$editor = $expected_status['delete'] == 200; $editor = $expected_status['delete'] == 200;
......
<?php
/**
* @file
* Update functions for Language module.
*/
/**
* Rebuild the container as services changed.
*/
function language_update_8001() {
\Drupal::service('kernel')->invalidateContainer();
}
...@@ -9,7 +9,7 @@ services: ...@@ -9,7 +9,7 @@ services:
- [initLanguageManager] - [initLanguageManager]
language.config_subscriber: language.config_subscriber:
class: Drupal\language\EventSubscriber\ConfigSubscriber class: Drupal\language\EventSubscriber\ConfigSubscriber
arguments: ['@language_manager', '@language.default', '@config.factory'] arguments: ['@language_manager', '@language.default', '@config.factory', '@language_negotiator']
tags: tags:
- { name: event_subscriber } - { name: event_subscriber }
language.config_factory_override: language.config_factory_override:
......
...@@ -14,6 +14,8 @@ ...@@ -14,6 +14,8 @@
use Drupal\Core\Config\ConfigCrudEvent; use Drupal\Core\Config\ConfigCrudEvent;
use Drupal\Core\Config\ConfigEvents; use Drupal\Core\Config\ConfigEvents;
use Drupal\language\ConfigurableLanguageManager; use Drupal\language\ConfigurableLanguageManager;
use Drupal\language\HttpKernel\PathProcessorLanguage;
use Drupal\language\LanguageNegotiatorInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\EventDispatcher\EventSubscriberInterface;
/** /**
...@@ -42,6 +44,20 @@ class ConfigSubscriber implements EventSubscriberInterface { ...@@ -42,6 +44,20 @@ class ConfigSubscriber implements EventSubscriberInterface {
*/ */
protected $configFactory; protected $configFactory;
/**
* The language negotiator.
*
* @var \Drupal\language\LanguageNegotiatorInterface
*/
protected $languageNegotiator;
/**
* The language path processor.
*
* @var \Drupal\language\HttpKernel\PathProcessorLanguage
*/
protected $pathProcessorLanguage;
/** /**
* Constructs a new class object. * Constructs a new class object.
* *
...@@ -51,11 +67,14 @@ class ConfigSubscriber implements EventSubscriberInterface { ...@@ -51,11 +67,14 @@ class ConfigSubscriber implements EventSubscriberInterface {
* The default language. * The default language.
* @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
* The configuration factory. * The configuration factory.
* @param \Drupal\language\LanguageNegotiatorInterface $language_negotiator
* The language negotiator.
*/ */
public function __construct(LanguageManagerInterface $language_manager, LanguageDefault $language_default, ConfigFactoryInterface $config_factory) { public function __construct(LanguageManagerInterface $language_manager, LanguageDefault $language_default, ConfigFactoryInterface $config_factory, LanguageNegotiatorInterface $language_negotiator) {
$this->languageManager = $language_manager; $this->languageManager = $language_manager;
$this->languageDefault = $language_default; $this->languageDefault = $language_default;
$this->configFactory = $config_factory; $this->configFactory = $config_factory;
$this->languageNegotiator = $language_negotiator;
} }
/** /**
...@@ -102,6 +121,25 @@ public function onConfigSave(ConfigCrudEvent $event) { ...@@ -102,6 +121,25 @@ public function onConfigSave(ConfigCrudEvent $event) {
// Trigger a container rebuild on the next request by invalidating it. // Trigger a container rebuild on the next request by invalidating it.
ConfigurableLanguageManager::rebuildServices(); ConfigurableLanguageManager::rebuildServices();
} }
elseif ($saved_config->getName() == 'language.types' && $event->isChanged('negotiation')) {
// If the negotiation configuration changed the language negotiator and
// the language path processor have to be reset so that they regenerate
// the method instances and also sort them accordingly to the new config.
$this->languageNegotiator->reset();
if (isset($this->pathProcessorLanguage)) {
$this->pathProcessorLanguage->reset();
}
}
}
/**
* Injects the language path processors on multilingual site configuration.
*
* @param \Drupal\language\HttpKernel\PathProcessorLanguage $path_processor_language
* The language path processor.
*/
public function setPathProcessorLanguage(PathProcessorLanguage $path_processor_language) {
$this->pathProcessorLanguage = $path_processor_language;
} }
/** /**
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
use Drupal\Core\PathProcessor\OutboundPathProcessorInterface; use Drupal\Core\PathProcessor\OutboundPathProcessorInterface;
use Drupal\Core\Render\BubbleableMetadata; use Drupal\Core\Render\BubbleableMetadata;
use Drupal\language\ConfigurableLanguageManagerInterface; use Drupal\language\ConfigurableLanguageManagerInterface;
use Drupal\language\EventSubscriber\ConfigSubscriber;
use Drupal\language\LanguageNegotiatorInterface; use Drupal\language\LanguageNegotiatorInterface;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
use Drupal\Core\Session\AccountInterface; use Drupal\Core\Session\AccountInterface;
...@@ -57,6 +58,14 @@ class PathProcessorLanguage implements InboundPathProcessorInterface, OutboundPa ...@@ -57,6 +58,14 @@ class PathProcessorLanguage implements InboundPathProcessorInterface, OutboundPa
*/ */
protected $multilingual; protected $multilingual;
/**
* The language configuration event subscriber.
*
* @var \Drupal\language\EventSubscriber\ConfigSubscriber
*/
protected $configSubscriber;
/** /**
* Constructs a PathProcessorLanguage object. * Constructs a PathProcessorLanguage object.
* *
...@@ -68,12 +77,15 @@ class PathProcessorLanguage implements InboundPathProcessorInterface, OutboundPa ...@@ -68,12 +77,15 @@ class PathProcessorLanguage implements InboundPathProcessorInterface, OutboundPa
* The language negotiator. * The language negotiator.
* @param \Drupal\Core\Session\AccountInterface $current_user * @param \Drupal\Core\Session\AccountInterface $current_user
* The current active user. * The current active user.
* @param \Drupal\language\EventSubscriber\ConfigSubscriber $config_subscriber
* The language configuration event subscriber.
*/ */
public function __construct(ConfigFactoryInterface $config, ConfigurableLanguageManagerInterface $language_manager, LanguageNegotiatorInterface $negotiator, AccountInterface $current_user) { public function __construct(ConfigFactoryInterface $config, ConfigurableLanguageManagerInterface $language_manager, LanguageNegotiatorInterface $negotiator, AccountInterface $current_user, ConfigSubscriber $config_subscriber) {
$this->config = $config; $this->config = $config;
$this->languageManager = $language_manager; $this->languageManager = $language_manager;
$this->negotiator = $negotiator; $this->negotiator = $negotiator;
$this->negotiator->setCurrentUser($current_user); $this->negotiator->setCurrentUser($current_user);
$this->configSubscriber = $config_subscriber;
} }
/** /**
...@@ -152,4 +164,22 @@ protected function initProcessors($scope) { ...@@ -152,4 +164,22 @@ protected function initProcessors($scope) {
}); });
} }
/**
* Initializes the injected event subscriber with the language path processor.
*
* The language path processor service is registered only on multilingual
* site configuration, thus we inject it in the event subscriber only when
* it is initialized.
*/
public function initConfigSubscriber() {
$this->configSubscriber->setPathProcessorLanguage($this);
}
/**
* Resets the collected processors instances.
*/
public function reset() {
$this->processors = array();
}
} }
...@@ -39,7 +39,9 @@ public function register(ContainerBuilder $container) { ...@@ -39,7 +39,9 @@ public function register(ContainerBuilder $container) {
->addArgument(new Reference('config.factory')) ->addArgument(new Reference('config.factory'))
->addArgument(new Reference('language_manager')) ->addArgument(new Reference('language_manager'))
->addArgument(new Reference('language_negotiator')) ->addArgument(new Reference('language_negotiator'))
->addArgument(new Reference('current_user')); ->addArgument(new Reference('current_user'))
->addArgument(new Reference('language.config_subscriber'))
->addMethodCall('initConfigSubscriber');
} }
} }
......
...@@ -7,22 +7,34 @@ ...@@ -7,22 +7,34 @@
namespace Drupal\language\Tests; namespace Drupal\language\Tests;
use Drupal\Core\Language\LanguageInterface;
use Drupal\entity_test\Entity\EntityTest; use Drupal\entity_test\Entity\EntityTest;
use Drupal\language\Entity\ConfigurableLanguage; use Drupal\language\Entity\ConfigurableLanguage;
use Drupal\simpletest\KernelTestBase; use Drupal\language\Plugin\LanguageNegotiation\LanguageNegotiationContentEntity;
use Drupal\language\Plugin\LanguageNegotiation\LanguageNegotiationUrl;
use Symfony\Cmf\Component\Routing\RouteObjectInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Route;