diff --git a/includes/locale.inc b/includes/locale.inc index 75e5343956308c18801450bcd06b56a6b3cd79f1..b36bcd9e915b0be21ebe35bb64578b460f9743ca 100644 --- a/includes/locale.inc +++ b/includes/locale.inc @@ -321,11 +321,27 @@ function locale_language_switcher_session($type, $path) { * Rewrite URLs for the URL language provider. */ function locale_language_url_rewrite_url(&$path, &$options) { + static $drupal_static_fast; + if (!isset($drupal_static_fast)) { + $drupal_static_fast['languages'] = &drupal_static(__FUNCTION__); + } + $languages = &$drupal_static_fast['languages']; + + if (!isset($languages)) { + $languages = language_list('enabled'); + $languages = array_flip(array_keys($languages[1])); + } + // Language can be passed as an option, or we go for current URL language. if (!isset($options['language'])) { global $language_url; $options['language'] = $language_url; } + // We allow only enabled languages here. + elseif (!isset($languages[$options['language']->language])) { + unset($options['language']); + return; + } if (isset($options['language'])) { switch (variable_get('locale_language_negotiation_url_part', LOCALE_LANGUAGE_NEGOTIATION_URL_PREFIX)) { diff --git a/modules/locale/locale.test b/modules/locale/locale.test index 321be44d756a187bb516369f32eb1a89aa43a36c..949505ff27cbea164b14e23daac4f1df8e0965cb 100644 --- a/modules/locale/locale.test +++ b/modules/locale/locale.test @@ -1942,6 +1942,88 @@ class LocaleUILanguageNegotiationTest extends DrupalWebTestCase { } } +/** + * Test that URL rewriting works as expected. + */ +class LocaleUrlRewritingTest extends DrupalWebTestCase { + public static function getInfo() { + return array( + 'name' => 'URL rewriting', + 'description' => 'Test that URL rewriting works as expected.', + 'group' => 'Locale', + ); + } + + function setUp() { + parent::setUp('locale'); + + // Create and login user. + $this->web_user = $this->drupalCreateUser(array('administer languages', 'access administration pages')); + $this->drupalLogin($this->web_user); + + // Install French language. + $edit = array(); + $edit['langcode'] = 'fr'; + $this->drupalPost('admin/config/regional/language/add', $edit, t('Add language')); + + // Install Italian language. + $edit = array(); + $edit['langcode'] = 'it'; + $this->drupalPost('admin/config/regional/language/add', $edit, t('Add language')); + + // Disable Italian language. + $edit = array('enabled[it]' => FALSE); + $this->drupalPost('admin/config/regional/language', $edit, t('Save configuration')); + + // Enable URL language detection and selection. + $edit = array('language[enabled][locale-url]' => 1); + $this->drupalPost('admin/config/regional/language/configure', $edit, t('Save settings')); + + // Reset static caching. + drupal_static_reset('language_list'); + drupal_static_reset('locale_url_outbound_alter'); + drupal_static_reset('locale_language_url_rewrite_url'); + } + + /** + * Check that disabled or non-installed languages are not considered. + */ + function testUrlRewritingEdgeCases() { + // Check URL rewriting with a disabled language. + $languages = language_list(); + $this->checkUrl($languages['it'], t('Path language is ignored if language is disabled.'), t('URL language negotiation does not work with disabled languages')); + + // Check URL rewriting with a non-installed language. + $non_existing = language_default(); + $non_existing->language = $this->randomName(); + $non_existing->prefix = $this->randomName(); + $this->checkUrl($non_existing, t('Path language is ignored if language is not installed.'), t('URL language negotiation does not work with non-installed languages')); + } + + /** + * Check URL rewriting for the given language. + * + * The test is performed with a fixed URL (the default front page) to simply + * check that language prefixes are not added to it and that the prefixed URL + * is actually not working. + */ + private function checkUrl($language, $message1, $message2) { + $options = array('language' => $language); + $base_path = trim(base_path(), '/'); + $rewritten_path = trim(str_replace(array('?q=', $base_path), '', url('node', $options)), '/'); + $segments = explode('/', $rewritten_path, 2); + $prefix = $segments[0]; + $path = isset($segments[1]) ? $segments[1] : $prefix; + // If the rewritten URL has not a language prefix we pick the right one from + // the language object so we can always check the prefixed URL. + if ($this->assertNotEqual($language->prefix, $prefix, $message1)) { + $prefix = $language->prefix; + } + $this->drupalGet("$prefix/$path"); + $this->assertResponse(404, $message2); + } +} + /** * Functional test for multilingual fields. */