diff --git a/core/lib/Drupal/Core/Language/LanguageManager.php b/core/lib/Drupal/Core/Language/LanguageManager.php index 4221efc..ba65c6d 100644 --- a/core/lib/Drupal/Core/Language/LanguageManager.php +++ b/core/lib/Drupal/Core/Language/LanguageManager.php @@ -12,6 +12,7 @@ use Drupal\Component\Utility\MapArray; use Drupal\Core\Extension\ModuleHandlerInterface; use Drupal\Core\KeyValueStore\KeyValueStoreInterface; +use Drupal\Core\Language\Plugin\LanguageNegotiation\LanguageNegotiationSelected; use Drupal\Core\Session\AccountInterface; use Symfony\Component\HttpFoundation\Request; diff --git a/core/lib/Drupal/Core/Language/LanguageManagerInterface.php b/core/lib/Drupal/Core/Language/LanguageManagerInterface.php index 114a5ce..5ca6466 100644 --- a/core/lib/Drupal/Core/Language/LanguageManagerInterface.php +++ b/core/lib/Drupal/Core/Language/LanguageManagerInterface.php @@ -59,6 +59,16 @@ public function getLanguage($type = Language::TYPE_INTERFACE); public function getNegotiationMethods($type); /** + * Returns an instance of the specified language negotiation method. + * + * @param string $method_id + * The method identifier. + * + * @return \Drupal\Core\Language\LanguageNegotiationMethodInterface + */ + public function getNegotiationMethodInstance($method_id); + + /** * Returns the ID of the language type's primary language negotiation method. * * @param $type diff --git a/core/lib/Drupal/Core/Language/LanguageNegotiationMethodBase.php b/core/lib/Drupal/Core/Language/LanguageNegotiationMethodBase.php index 846bdb0..7a7e217 100644 --- a/core/lib/Drupal/Core/Language/LanguageNegotiationMethodBase.php +++ b/core/lib/Drupal/Core/Language/LanguageNegotiationMethodBase.php @@ -17,7 +17,7 @@ /** * The language manager. * - * @var \Drupal\Core\Language\LanguageManager + * @var \Drupal\Core\Language\LanguageManagerInterface */ protected $languageManager; @@ -40,7 +40,7 @@ public function __construct(array $config) { /** * {@inheritdoc} */ - public function setLanguageManager(LanguageManager $language_manager) { + public function setLanguageManager(LanguageManagerInterface $language_manager) { $this->languageManager = $language_manager; } diff --git a/core/lib/Drupal/Core/Language/LanguageNegotiationMethodInterface.php b/core/lib/Drupal/Core/Language/LanguageNegotiationMethodInterface.php index 1db6de7..db2499e 100644 --- a/core/lib/Drupal/Core/Language/LanguageNegotiationMethodInterface.php +++ b/core/lib/Drupal/Core/Language/LanguageNegotiationMethodInterface.php @@ -18,11 +18,11 @@ /** * Sets the language manager. * - * @param LanguageManager $language_manager + * @param LanguageManagerInterface $language_manager * The language manager to be used to retrieve the language list and the * already negotiated languages. */ - public function setLanguageManager(LanguageManager $language_manager); + public function setLanguageManager(LanguageManagerInterface $language_manager); /** * Performs language negotiation. diff --git a/core/lib/Drupal/Core/Language/Plugin/LanguageNegotiation/LanguageNegotiationBrowser.php b/core/lib/Drupal/Core/Language/Plugin/LanguageNegotiation/LanguageNegotiationBrowser.php index 28e9895..47af61d 100644 --- a/core/lib/Drupal/Core/Language/Plugin/LanguageNegotiation/LanguageNegotiationBrowser.php +++ b/core/lib/Drupal/Core/Language/Plugin/LanguageNegotiation/LanguageNegotiationBrowser.php @@ -37,7 +37,7 @@ class LanguageNegotiationBrowser extends LanguageNegotiationMethodBase { public function negotiateLanguage(AccountInterface $current_user, Request $request = NULL) { $langcode = FALSE; - if ($request && $request->server->get('HTTP_ACCEPT_LANGUAGE')) { + if ($this->languageManager && $request && $request->server->get('HTTP_ACCEPT_LANGUAGE')) { $http_accept_language = $request->server->get('HTTP_ACCEPT_LANGUAGE'); $langcodes = array_keys($this->languageManager->getLanguageList()); $langcode = Browser::getLangcode($http_accept_language, $langcodes, $this->config['browser']['mappings']); diff --git a/core/lib/Drupal/Core/Language/Plugin/LanguageNegotiation/LanguageNegotiationSelected.php b/core/lib/Drupal/Core/Language/Plugin/LanguageNegotiation/LanguageNegotiationSelected.php index 3faba52..7d679c7 100644 --- a/core/lib/Drupal/Core/Language/Plugin/LanguageNegotiation/LanguageNegotiationSelected.php +++ b/core/lib/Drupal/Core/Language/Plugin/LanguageNegotiation/LanguageNegotiationSelected.php @@ -33,14 +33,17 @@ class LanguageNegotiationSelected extends LanguageNegotiationMethodBase { * {@inheritdoc} */ public function negotiateLanguage(AccountInterface $current_user, Request $request = NULL) { - // Replace the site's default langcode by its real value. - $langcode = isset($this->config['selected_langcode']) ? $this->config['selected_langcode'] : FALSE; - // Replace the site's default langcode by its real value. - if ($langcode == 'site_default') { - $langcode = $this->languageManager->getDefaultLanguage()->id; + $langcode = FALSE; + + if ($this->languageManager) { + $languages = $this->languageManager->getLanguageList(); + $langcode = isset($this->config['selected_langcode']) ? $this->config['selected_langcode'] : FALSE; + if (!isset($languages[$langcode])) { + $langcode = $this->languageManager->getDefaultLanguage()->id; + } } - $languages = $this->languageManager->getLanguageList(); - return isset($languages[$langcode]) ? $langcode : $this->languageManager->getDefaultLanguage()->id; + + return $langcode; } } diff --git a/core/lib/Drupal/Core/Language/Plugin/LanguageNegotiation/LanguageNegotiationSession.php b/core/lib/Drupal/Core/Language/Plugin/LanguageNegotiation/LanguageNegotiationSession.php index 8aa1334..712c934 100644 --- a/core/lib/Drupal/Core/Language/Plugin/LanguageNegotiation/LanguageNegotiationSession.php +++ b/core/lib/Drupal/Core/Language/Plugin/LanguageNegotiation/LanguageNegotiationSession.php @@ -61,7 +61,7 @@ public function negotiateLanguage(AccountInterface $current_user, Request $reque // Request parameter: we need to update the session parameter only if we // have an authenticated user. - if ($langcode) { + if ($langcode && $this->languageManager) { $languages = $this->languageManager->getLanguageList(); if ($current_user->isAuthenticated() && isset($languages[$langcode])) { $_SESSION[$param] = $langcode; diff --git a/core/lib/Drupal/Core/Language/Plugin/LanguageNegotiation/LanguageNegotiationUI.php b/core/lib/Drupal/Core/Language/Plugin/LanguageNegotiation/LanguageNegotiationUI.php index 112a204..7808d89 100644 --- a/core/lib/Drupal/Core/Language/Plugin/LanguageNegotiation/LanguageNegotiationUI.php +++ b/core/lib/Drupal/Core/Language/Plugin/LanguageNegotiation/LanguageNegotiationUI.php @@ -33,7 +33,7 @@ class LanguageNegotiationUI extends LanguageNegotiationMethodBase { * {@inheritdoc} */ public function negotiateLanguage(AccountInterface $current_user, Request $request = NULL) { - return $this->languageManager->getLanguage()->id; + return $this->languageManager ? $this->languageManager->getLanguage()->id : FALSE; } } diff --git a/core/lib/Drupal/Core/Language/Plugin/LanguageNegotiation/LanguageNegotiationUrl.php b/core/lib/Drupal/Core/Language/Plugin/LanguageNegotiation/LanguageNegotiationUrl.php index aad39ea..cbf9052 100644 --- a/core/lib/Drupal/Core/Language/Plugin/LanguageNegotiation/LanguageNegotiationUrl.php +++ b/core/lib/Drupal/Core/Language/Plugin/LanguageNegotiation/LanguageNegotiationUrl.php @@ -50,7 +50,7 @@ class LanguageNegotiationUrl extends LanguageNegotiationMethodBase implements In public function negotiateLanguage(AccountInterface $current_user, Request $request = NULL) { $langcode = FALSE; - if ($request) { + if ($request && $this->languageManager) { $languages = $this->languageManager->getLanguageList(); switch ($this->config['url']['source']) { diff --git a/core/lib/Drupal/Core/Language/Plugin/LanguageNegotiation/LanguageNegotiationUrlFallback.php b/core/lib/Drupal/Core/Language/Plugin/LanguageNegotiation/LanguageNegotiationUrlFallback.php index ce63c3b..e75deb6 100644 --- a/core/lib/Drupal/Core/Language/Plugin/LanguageNegotiation/LanguageNegotiationUrlFallback.php +++ b/core/lib/Drupal/Core/Language/Plugin/LanguageNegotiation/LanguageNegotiationUrlFallback.php @@ -52,20 +52,26 @@ class LanguageNegotiationUrlFallback extends LanguageNegotiationMethodBase { * {@inheritdoc} */ public function negotiateLanguage(AccountInterface $current_user, Request $request = NULL) { - $default = $this->languageManager->getDefaultLanguage(); - $prefix = ($this->config['url']['source'] == LanguageNegotiationUrl::CONFIG_PATH_PREFIX); + $langcode = FALSE; - // If the default language is not configured to convey language information, - // a missing URL language information indicates that URL language should be - // the default one, otherwise we fall back to an already detected language. - $domains = $this->config['url']['domains']; - $prefixes = $this->config['url']['prefixes']; - if (($prefix && empty($prefixes[$default->id])) || (!$prefix && empty($domains[$default->id]))) { - return $default->id; - } - else { - return $this->languageManager->getLanguage()->id; + if ($this->languageManager) { + $default = $this->languageManager->getDefaultLanguage(); + $prefix = ($this->config['url']['source'] == LanguageNegotiationUrl::CONFIG_PATH_PREFIX); + + // If the default language is not configured to convey language information, + // a missing URL language information indicates that URL language should be + // the default one, otherwise we fall back to an already detected language. + $domains = $this->config['url']['domains']; + $prefixes = $this->config['url']['prefixes']; + if (($prefix && empty($prefixes[$default->id])) || (!$prefix && empty($domains[$default->id]))) { + $langcode = $default->id; + } + else { + $langcode = $this->languageManager->getLanguage()->id; + } } + + return $langcode; } } diff --git a/core/lib/Drupal/Core/Language/Plugin/LanguageNegotiation/LanguageNegotiationUser.php b/core/lib/Drupal/Core/Language/Plugin/LanguageNegotiation/LanguageNegotiationUser.php index fd4c072..b766961 100644 --- a/core/lib/Drupal/Core/Language/Plugin/LanguageNegotiation/LanguageNegotiationUser.php +++ b/core/lib/Drupal/Core/Language/Plugin/LanguageNegotiation/LanguageNegotiationUser.php @@ -35,7 +35,7 @@ public function negotiateLanguage(AccountInterface $current_user, Request $reque $langcode = FALSE; // User preference (only for authenticated users). - if ($current_user->isAuthenticated()) { + if ($this->languageManager && $current_user->isAuthenticated()) { $preferred_langcode = $current_user->getPreferredLangcode(); $default_langcode = $this->languageManager->getDefaultLanguage()->id; $languages = $this->languageManager->getLanguageList(); diff --git a/core/lib/Drupal/Core/Language/Plugin/LanguageNegotiation/LanguageNegotiationUserAdmin.php b/core/lib/Drupal/Core/Language/Plugin/LanguageNegotiation/LanguageNegotiationUserAdmin.php index b191aad..09f5157 100644 --- a/core/lib/Drupal/Core/Language/Plugin/LanguageNegotiation/LanguageNegotiationUserAdmin.php +++ b/core/lib/Drupal/Core/Language/Plugin/LanguageNegotiation/LanguageNegotiationUserAdmin.php @@ -38,7 +38,7 @@ public function negotiateLanguage(AccountInterface $current_user, Request $reque // User preference (only for authenticated users). // @todo Avoid calling _current_path() and path_is_admin() directly. $request_path = $request ? urldecode(trim($request->getPathInfo(), '/')) : _current_path(); - if ($current_user->isAuthenticated() && path_is_admin($request_path)) { + if ($this->languageManager && $current_user->isAuthenticated() && path_is_admin($request_path)) { $preferred_admin_langcode = $current_user->getPreferredAdminLangcode(); $default_langcode = $this->languageManager->getDefaultLanguage()->id; $languages = $this->languageManager->getLanguageList(); diff --git a/core/tests/Drupal/Tests/Core/Language/LanguageNegotiationUrlTest.php b/core/tests/Drupal/Tests/Core/Language/LanguageNegotiationUrlTest.php index 3188853..610a7af 100644 --- a/core/tests/Drupal/Tests/Core/Language/LanguageNegotiationUrlTest.php +++ b/core/tests/Drupal/Tests/Core/Language/LanguageNegotiationUrlTest.php @@ -8,6 +8,7 @@ namespace Drupal\Tests\Core\Language; use Drupal\Core\Language\Plugin\LanguageNegotiation\LanguageNegotiationUrl; +use Drupal\Core\Session\UserSession; use Drupal\Tests\UnitTestCase; use Symfony\Component\HttpFoundation\Request; @@ -20,6 +21,9 @@ */ class LanguageNegotiationUrlTest extends UnitTestCase { + protected $languageManager; + protected $user; + public static function getInfo() { return array( 'name' => 'Language negotiation URL', @@ -29,11 +33,42 @@ public static function getInfo() { } /** + * {@inheritdoc} + */ + public function setUp() { + + // Set up some languages to be used by the language-based path processor. + $languages = array( + 'de' => (object) array( + 'id' => 'de', + ), + 'en' => (object) array( + 'id' => 'en', + ), + ); + + // Create a language manager stub. + $language_manager = $this->getMockBuilder('Drupal\Core\Language\LanguageManagerInterface') + ->getMock(); + $language_manager->expects($this->any()) + ->method('getLanguage') + ->will($this->returnValue($languages['en'])); + $language_manager->expects($this->any()) + ->method('getLanguageList') + ->will($this->returnValue($languages)); + $this->languageManager = $language_manager; + + // Create a user stub. + $this->user = $this->getMockBuilder('Drupal\Core\Session\AccountInterface') + ->getMock(); + } + + /** * Test domain language negotiation. * * @dataProvider providerTestDomain */ - public function testDomain($http_host, $domains, $languages, $expected_langcode) { + public function testDomain($http_host, $domains, $expected_langcode) { $config = array( 'url' => array( 'source' => LanguageNegotiationUrl::CONFIG_DOMAIN, @@ -42,8 +77,9 @@ public function testDomain($http_host, $domains, $languages, $expected_langcode) ); $request = Request::create('', 'GET', array(), array(), array(), array('HTTP_HOST' => $http_host)); - $negotiation = new LanguageNegotiationUrl($config); - $this->assertEquals($expected_langcode, $negotiation->negotiateLanguage($languages, $request)); + $method = new LanguageNegotiationUrl($config); + $method->setLanguageManager($this->languageManager); + $this->assertEquals($expected_langcode, $method->negotiateLanguage($this->user, $request)); } /** @@ -53,28 +89,18 @@ public function testDomain($http_host, $domains, $languages, $expected_langcode) * An array of data for checking domain negotation. */ public function providerTestDomain() { - $default_languages = array( - 'de' => (object) array( - 'id' => 'de', - ), - 'en' => (object) array( - 'id' => 'en', - ), - ); $domain_configuration[] = array( 'http_host' => 'example.de', 'domains' => array( 'de' => 'http://example.de', ), - 'languages' => $default_languages, 'expected_langocde' => 'de', ); // No configuration. $domain_configuration[] = array( 'http_host' => 'example.de', 'domains' => array(), - 'languages' => $default_languages, 'expected_langocde' => FALSE, ); // HTTP host with a port. @@ -83,7 +109,6 @@ public function providerTestDomain() { 'domains' => array( 'de' => 'http://example.de', ), - 'languages' => $default_languages, 'expected_langocde' => 'de', ); // Domain configuration with https://. @@ -92,7 +117,6 @@ public function providerTestDomain() { 'domains' => array( 'de' => 'https://example.de', ), - 'languages' => $default_languages, 'expected_langocde' => 'de', ); // Non-matching HTTP host. @@ -101,19 +125,13 @@ public function providerTestDomain() { 'domains' => array( 'de' => 'http://example.com', ), - 'languages' => $default_languages, 'expected_langocde' => 'de', ); // Testing a non-existing language. $domain_configuration[] = array( 'http_host' => 'example.com', 'domains' => array( - 'de' => 'http://example.com', - ), - 'languages' => array( - 'en' => (object) array( - 'id' => 'en', - ), + 'it' => 'http://example.it', ), 'expected_langocde' => FALSE, ); @@ -124,7 +142,6 @@ public function providerTestDomain() { 'de' => 'http://example.de', 'en' => 'http://example.com', ), - 'languages' => $default_languages, 'expected_langocde' => 'en', ); return $domain_configuration; diff --git a/core/tests/Drupal/Tests/Core/PathProcessor/PathProcessorTest.php b/core/tests/Drupal/Tests/Core/PathProcessor/PathProcessorTest.php index b29aa18..9638c0c 100644 --- a/core/tests/Drupal/Tests/Core/PathProcessor/PathProcessorTest.php +++ b/core/tests/Drupal/Tests/Core/PathProcessor/PathProcessorTest.php @@ -8,6 +8,8 @@ namespace Drupal\Tests\Core\PathProcessor; use Drupal\Component\Utility\Settings; +use Drupal\Core\Language\Language; +use Drupal\Core\Language\Plugin\LanguageNegotiation\LanguageNegotiationUrl; use Drupal\Core\PathProcessor\PathProcessorAlias; use Drupal\Core\PathProcessor\PathProcessorDecode; use Drupal\Core\PathProcessor\PathProcessorFront; @@ -19,6 +21,8 @@ /** * Tests path processor functionality. + * + * @group PathApi */ class PathProcessorTest extends UnitTestCase { @@ -45,9 +49,26 @@ public function setUp() { } $this->languages = $languages; + // Create a stub configuration. + $language_prefixes = array_keys($this->languages); + $config = array( + 'url' => array( + 'prefixes' => array_combine($language_prefixes, $language_prefixes) + ) + ); + + // Create a URL-based language negotiation method definition. + $method_definitions = array( + LanguageNegotiationUrl::METHOD_ID => array( + 'class' => '\Drupal\Core\Language\Plugin\LanguageNegotiation\LanguageNegotiationUrl', + ), + ); + + // Create a URL-based language negotiation method. + $method_instance = new LanguageNegotiationUrl($config); + // Create a language manager stub. - $language_manager = $this->getMockBuilder('Drupal\Core\Language\LanguageManager') - ->disableOriginalConstructor() + $language_manager = $this->getMockBuilder('Drupal\Core\Language\LanguageManagerInterface') ->getMock(); $language_manager->expects($this->any()) ->method('getLanguage') @@ -55,7 +76,17 @@ public function setUp() { $language_manager->expects($this->any()) ->method('getLanguageList') ->will($this->returnValue($this->languages)); + $language_manager->expects($this->any()) + ->method('getConfigurableLanguageTypes') + ->will($this->returnValue(array(Language::TYPE_INTERFACE))); + $language_manager->expects($this->any()) + ->method('getNegotiationMethods') + ->will($this->returnValue($method_definitions)); + $language_manager->expects($this->any()) + ->method('getNegotiationMethodInstance') + ->will($this->returnValue($method_instance)); + $method_instance->setLanguageManager($language_manager); $this->languageManager = $language_manager; } @@ -84,15 +115,11 @@ function testProcessInbound() { // Create a stub config factory with all config settings that will be checked // during this test. - $language_prefixes = array_keys($this->languages); $config_factory_stub = $this->getConfigFactoryStub( array( 'system.site' => array( 'page.front' => 'user' ), - 'language.negotiation' => array( - 'url.prefixes' => array_combine($language_prefixes, $language_prefixes) - ) ) );