Commit 16caf92d authored by catch's avatar catch

Issue #1833010 by Gábor Hojtsy: Fixed Admin user language preference WSOD if...

Issue #1833010 by Gábor Hojtsy: Fixed Admin user language preference WSOD if ahead of path prefixes.
parent 2ecdf8ce
...@@ -7,12 +7,14 @@ ...@@ -7,12 +7,14 @@
namespace Drupal\user\Plugin\LanguageNegotiation; namespace Drupal\user\Plugin\LanguageNegotiation;
use Drupal\Core\PathProcessor\PathProcessorManager;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface; use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\Core\Routing\AdminContext; use Drupal\Core\Routing\AdminContext;
use Drupal\language\LanguageNegotiationMethodBase; use Drupal\language\LanguageNegotiationMethodBase;
use Symfony\Cmf\Component\Routing\RouteObjectInterface; use Symfony\Cmf\Component\Routing\RouteObjectInterface;
use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Exception\ResourceNotFoundException;
use Symfony\Component\Routing\Matcher\UrlMatcherInterface; use Symfony\Component\Routing\Matcher\UrlMatcherInterface;
/** /**
...@@ -50,6 +52,13 @@ class LanguageNegotiationUserAdmin extends LanguageNegotiationMethodBase impleme ...@@ -50,6 +52,13 @@ class LanguageNegotiationUserAdmin extends LanguageNegotiationMethodBase impleme
*/ */
protected $router; protected $router;
/**
* The path processor manager.
*
* @var \Drupal\Core\PathProcessor\PathProcessorManager
*/
protected $pathProcessorManager;
/** /**
* Constructs a new LanguageNegotiationUserAdmin instance. * Constructs a new LanguageNegotiationUserAdmin instance.
* *
...@@ -57,10 +66,13 @@ class LanguageNegotiationUserAdmin extends LanguageNegotiationMethodBase impleme ...@@ -57,10 +66,13 @@ class LanguageNegotiationUserAdmin extends LanguageNegotiationMethodBase impleme
* The admin context. * The admin context.
* @param \Symfony\Component\Routing\Matcher\UrlMatcherInterface $router * @param \Symfony\Component\Routing\Matcher\UrlMatcherInterface $router
* The router. * The router.
* @param \Drupal\Core\PathProcessor\PathProcessorManager $path_processor_manager
* The path processor manager.
*/ */
public function __construct(AdminContext $admin_context, UrlMatcherInterface $router) { public function __construct(AdminContext $admin_context, UrlMatcherInterface $router, PathProcessorManager $path_processor_manager) {
$this->adminContext = $admin_context; $this->adminContext = $admin_context;
$this->router = $router; $this->router = $router;
$this->pathProcessorManager = $path_processor_manager;
} }
/** /**
...@@ -69,7 +81,8 @@ public function __construct(AdminContext $admin_context, UrlMatcherInterface $ro ...@@ -69,7 +81,8 @@ public function __construct(AdminContext $admin_context, UrlMatcherInterface $ro
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
return new static( return new static(
$container->get('router.admin_context'), $container->get('router.admin_context'),
$container->get('router') $container->get('router'),
$container->get('path_processor_manager')
); );
} }
...@@ -105,10 +118,20 @@ public function getLangcode(Request $request = NULL) { ...@@ -105,10 +118,20 @@ public function getLangcode(Request $request = NULL) {
public function isAdminPath(Request $request) { public function isAdminPath(Request $request) {
$result = FALSE; $result = FALSE;
if ($request && $this->adminContext) { if ($request && $this->adminContext) {
// If called from an event subscriber, the request may not the route info // If called from an event subscriber, the request may not have the route
// yet, so use the router to look up the path first. // object yet (it is still being built), so use the router to look up
// based on the path.
if (!$route_object = $request->attributes->get(RouteObjectInterface::ROUTE_OBJECT)) { if (!$route_object = $request->attributes->get(RouteObjectInterface::ROUTE_OBJECT)) {
$attributes = $this->router->match('/' . urldecode(trim($request->getPathInfo(), '/'))); try {
// Process the path as an inbound path. This will remove any language
// prefixes and other path components that inbound processing would
// clear out, so we can attempt to load the route clearly.
$path = $this->pathProcessorManager->processInbound(urldecode(trim($request->getPathInfo(), '/')), $request);
$attributes = $this->router->match('/' . $path);
}
catch (ResourceNotFoundException $e) {
return FALSE;
}
$route_object = $attributes[RouteObjectInterface::ROUTE_OBJECT]; $route_object = $attributes[RouteObjectInterface::ROUTE_OBJECT];
} }
$result = $this->adminContext->isAdminRoute($route_object); $result = $this->adminContext->isAdminRoute($route_object);
......
...@@ -36,7 +36,7 @@ class UserAdminLanguageTest extends WebTestBase { ...@@ -36,7 +36,7 @@ class UserAdminLanguageTest extends WebTestBase {
* *
* @var array * @var array
*/ */
public static $modules = array('user', 'language'); public static $modules = array('user', 'language', 'language_test');
public function setUp() { public function setUp() {
parent::setUp(); parent::setUp();
...@@ -105,17 +105,60 @@ function testUserAdminLanguageConfigurationAvailableIfAdminLanguageNegotiationIs ...@@ -105,17 +105,60 @@ function testUserAdminLanguageConfigurationAvailableIfAdminLanguageNegotiationIs
$this->assertNoFieldByXPath($this->constructFieldXpath('id', 'edit-preferred-admin-langcode'), NULL, 'Administration pages language selector not available for regular user.'); $this->assertNoFieldByXPath($this->constructFieldXpath('id', 'edit-preferred-admin-langcode'), NULL, 'Administration pages language selector not available for regular user.');
} }
/**
* Tests the actual language negotiation.
*/
function testActualNegotiation() {
$this->drupalLogin($this->adminUser);
$this->addCustomLanguage();
$this->setLanguageNegotiation();
// Even though we have admin language negotiation, so long as the user has
// no preference set, negotiation will fall back further.
$path = 'user/' . $this->adminUser->id() . '/edit';
$this->drupalGet($path);
$this->assertText('Language negotiation method: language-default');
// Set a preferred language code for the user.
$path = 'user/' . $this->adminUser->id() . '/edit';
$edit = array();
$edit['preferred_admin_langcode'] = 'xx';
$this->drupalPostForm($path, $edit, t('Save'));
// Test negotiation with the URL method first. The admin method will only
// be used if the URL method did not match.
$path = 'user/' . $this->adminUser->id() . '/edit';
$this->drupalGet($path);
$this->assertText('Language negotiation method: language-user-admin');
$path = 'xx/user/' . $this->adminUser->id() . '/edit';
$this->drupalGet($path);
$this->assertText('Language negotiation method: language-url');
// Test negotiation with the admin language method first. The admin method
// will be used at all times.
$this->setLanguageNegotiation(TRUE);
$path = 'user/' . $this->adminUser->id() . '/edit';
$this->drupalGet($path);
$this->assertText('Language negotiation method: language-user-admin');
$path = 'xx/user/' . $this->adminUser->id() . '/edit';
$this->drupalGet($path);
$this->assertText('Language negotiation method: language-user-admin');
}
/** /**
* Sets the User interface negotiation detection method. * Sets the User interface negotiation detection method.
* *
* @param bool $admin_first
* Whether the admin negotiation should be first.
*
* Enables the "Account preference for administration pages" language * Enables the "Account preference for administration pages" language
* detection method for the User interface language negotiation type. * detection method for the User interface language negotiation type.
*/ */
function setLanguageNegotiation() { function setLanguageNegotiation($admin_first = FALSE) {
$edit = array( $edit = array(
'language_interface[enabled][language-user-admin]' => TRUE, 'language_interface[enabled][language-user-admin]' => TRUE,
'language_interface[enabled][language-url]' => TRUE, 'language_interface[enabled][language-url]' => TRUE,
'language_interface[weight][language-user-admin]' => -8, 'language_interface[weight][language-user-admin]' => ($admin_first ? -12 : -8),
'language_interface[weight][language-url]' => -10, 'language_interface[weight][language-url]' => -10,
); );
$this->drupalPostForm('admin/config/regional/language/detection', $edit, t('Save settings')); $this->drupalPostForm('admin/config/regional/language/detection', $edit, t('Save settings'));
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment