diff --git a/src/EventSubscriber/RouteNormalizerRequestSubscriber.php b/src/EventSubscriber/RouteNormalizerRequestSubscriber.php index 9814d4f..fcd211d 100644 --- a/src/EventSubscriber/RouteNormalizerRequestSubscriber.php +++ b/src/EventSubscriber/RouteNormalizerRequestSubscriber.php @@ -5,6 +5,7 @@ namespace Drupal\redirect\EventSubscriber; use Drupal\Core\Path\PathMatcherInterface; use Drupal\Core\Routing\RequestHelper; use Drupal\Core\Routing\UrlGeneratorInterface; +use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\KernelEvents; use Symfony\Component\HttpKernel\Event\GetResponseEvent; use Symfony\Component\EventDispatcher\EventSubscriberInterface; @@ -85,6 +86,13 @@ class RouteNormalizerRequestSubscriber implements EventSubscriberInterface { 'absolute' => TRUE, ]; $redirect_uri = $this->urlGenerator->generateFromRoute($route_name, [], $options); + + // Remove /index.php from redirect uri the hard way. + if (!RequestHelper::isCleanUrl($request)) { + // This needs to be fixed differently. + $redirect_uri = str_replace('/index.php', '', $redirect_uri); + } + $original_uri = $request->getSchemeAndHttpHost() . $request->getRequestUri(); if ($redirect_uri != $original_uri) { $response = new RedirectResponse($redirect_uri, 301); @@ -104,12 +112,15 @@ class RouteNormalizerRequestSubscriber implements EventSubscriberInterface { */ protected function shouldRedirect(GetResponseEvent $event) { if ($request = $event->getRequest()) { - $route = RouteMatch::createFromRequest($request)->getRouteObject(); + $routeMatch = RouteMatch::createFromRequest($request); + $routeName = $routeMatch->getRouteName(); + $route = $routeMatch->getRouteObject(); + return $this->routeNormalizerEnabled + && $routeName !== 'image.style_public' && $event->isMasterRequest() && ($request->isMethod('GET') || $request->isMethod('HEAD')) && !$request->query->has('destination') - && RequestHelper::isCleanUrl($request) && !$request->attributes->get('_disable_route_normalizer') && (!\Drupal::config('redirect.settings')->get('ignore_admin_path') || !\Drupal::service('router.admin_context')->isAdminRoute($route)); } diff --git a/src/Tests/GlobalRedirectTest.php b/src/Tests/GlobalRedirectTest.php index e375b4e..a122bbb 100644 --- a/src/Tests/GlobalRedirectTest.php +++ b/src/Tests/GlobalRedirectTest.php @@ -9,6 +9,7 @@ namespace Drupal\redirect\Tests; use Drupal\Component\Utility\SafeMarkup; use Drupal\Core\Language\Language; use Drupal\simpletest\WebTestBase; +use Drupal\language\Entity\ConfigurableLanguage; /** * Global redirect test cases. @@ -22,7 +23,16 @@ class GlobalRedirectTest extends WebTestBase { * * @var array */ - public static $modules = array('path', 'node', 'redirect', 'taxonomy', 'forum', 'views'); + public static $modules = [ + 'path', + 'node', + 'redirect', + 'taxonomy', + 'forum', + 'views', + 'language', + 'content_translation' + ]; /** * @var \Drupal\Core\Session\AccountInterface @@ -75,6 +85,12 @@ class GlobalRedirectTest extends WebTestBase { $this->adminUser = $this->drupalCreateUser([ 'administer site configuration', 'access administration pages', + 'administer languages', + 'administer content types', + 'administer content translation', + 'create page content', + 'edit own page content', + 'create content translations', ]); // Save the node. @@ -125,6 +141,9 @@ class GlobalRedirectTest extends WebTestBase { $this->assertRedirect('node/' . $this->node->id(), 'test-node'); $this->assertRedirect('Test-node', 'test-node'); + // Test redirects for non-clean urls. + $this->assertRedirect('index.php/node/' . $this->node->id(), 'test-node'); + $this->assertRedirect('index.php/test-node', 'test-node'); // Test deslashing. $this->assertRedirect('test-node/', 'test-node'); @@ -169,6 +188,41 @@ class GlobalRedirectTest extends WebTestBase { } /** + * Test that redirects work properly with content_translation enabled. + */ + public function testLanguageRedirects() { + $this->drupalLogin($this->adminUser); + + // Add a new language. + ConfigurableLanguage::createFromLangcode('es') + ->save(); + + // Enable URL language detection and selection. + $edit = ['language_interface[enabled][language-url]' => '1']; + $this->drupalPostForm('admin/config/regional/language/detection', $edit, t('Save settings')); + + // Set page content type to use multilingual support. + $edit = [ + 'language_configuration[language_alterable]' => TRUE, + 'language_configuration[content_translation]' => TRUE, + ]; + $this->drupalPostForm('admin/structure/types/manage/page', $edit, t('Save content type')); + $this->assertRaw(t('The content type %type has been updated.', array('%type' => 'Page')), 'Basic page content type has been updated.'); + + $spanish_node = $this->drupalCreateNode([ + 'type' => 'page', + 'title' => 'Spanish Test Page Node', + 'path' => ['alias' => '/spanish-test-node'], + 'langcode' => 'es', + ]); + + $this->drupalGet('es/node/' . $spanish_node->id() . '/edit'); + + // Test multilingual redirect. + $this->assertRedirect('es/node/' . $spanish_node->id(), 'es/spanish-test-node'); + } + + /** * Asserts the redirect from $path to the $expected_ending_url. * * @param string $path