Chris@0
|
1 <?php
|
Chris@0
|
2
|
Chris@0
|
3 namespace Drupal\user\Plugin\LanguageNegotiation;
|
Chris@0
|
4
|
Chris@0
|
5 use Drupal\Core\PathProcessor\PathProcessorManager;
|
Chris@0
|
6 use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
|
Chris@0
|
7 use Drupal\Core\Routing\AdminContext;
|
Chris@0
|
8 use Drupal\Core\Routing\StackedRouteMatchInterface;
|
Chris@0
|
9 use Drupal\language\LanguageNegotiationMethodBase;
|
Chris@0
|
10 use Symfony\Cmf\Component\Routing\RouteObjectInterface;
|
Chris@0
|
11 use Symfony\Component\DependencyInjection\ContainerInterface;
|
Chris@0
|
12 use Symfony\Component\HttpFoundation\Request;
|
Chris@0
|
13 use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
|
Chris@0
|
14 use Symfony\Component\Routing\Exception\ResourceNotFoundException;
|
Chris@0
|
15 use Symfony\Component\Routing\Matcher\UrlMatcherInterface;
|
Chris@0
|
16
|
Chris@0
|
17 /**
|
Chris@0
|
18 * Identifies admin language from the user preferences.
|
Chris@0
|
19 *
|
Chris@0
|
20 * @LanguageNegotiation(
|
Chris@0
|
21 * id = Drupal\user\Plugin\LanguageNegotiation\LanguageNegotiationUserAdmin::METHOD_ID,
|
Chris@0
|
22 * types = {Drupal\Core\Language\LanguageInterface::TYPE_INTERFACE},
|
Chris@0
|
23 * weight = -10,
|
Chris@0
|
24 * name = @Translation("Account administration pages"),
|
Chris@0
|
25 * description = @Translation("Account administration pages language setting.")
|
Chris@0
|
26 * )
|
Chris@0
|
27 */
|
Chris@0
|
28 class LanguageNegotiationUserAdmin extends LanguageNegotiationMethodBase implements ContainerFactoryPluginInterface {
|
Chris@0
|
29
|
Chris@0
|
30 /**
|
Chris@0
|
31 * The language negotiation method id.
|
Chris@0
|
32 */
|
Chris@0
|
33 const METHOD_ID = 'language-user-admin';
|
Chris@0
|
34
|
Chris@0
|
35 /**
|
Chris@0
|
36 * The admin context.
|
Chris@0
|
37 *
|
Chris@0
|
38 * @var \Drupal\Core\Routing\AdminContext
|
Chris@0
|
39 */
|
Chris@0
|
40 protected $adminContext;
|
Chris@0
|
41
|
Chris@0
|
42 /**
|
Chris@0
|
43 * The router.
|
Chris@0
|
44 *
|
Chris@0
|
45 * This is only used when called from an event subscriber, before the request
|
Chris@0
|
46 * has been populated with the route info.
|
Chris@0
|
47 *
|
Chris@0
|
48 * @var \Symfony\Component\Routing\Matcher\UrlMatcherInterface
|
Chris@0
|
49 */
|
Chris@0
|
50 protected $router;
|
Chris@0
|
51
|
Chris@0
|
52 /**
|
Chris@0
|
53 * The path processor manager.
|
Chris@0
|
54 *
|
Chris@0
|
55 * @var \Drupal\Core\PathProcessor\PathProcessorManager
|
Chris@0
|
56 */
|
Chris@0
|
57 protected $pathProcessorManager;
|
Chris@0
|
58
|
Chris@0
|
59 /**
|
Chris@0
|
60 * The stacked route match.
|
Chris@0
|
61 *
|
Chris@0
|
62 * @var \Drupal\Core\Routing\StackedRouteMatchInterface
|
Chris@0
|
63 */
|
Chris@0
|
64 protected $stackedRouteMatch;
|
Chris@0
|
65
|
Chris@0
|
66 /**
|
Chris@0
|
67 * Constructs a new LanguageNegotiationUserAdmin instance.
|
Chris@0
|
68 *
|
Chris@0
|
69 * @param \Drupal\Core\Routing\AdminContext $admin_context
|
Chris@0
|
70 * The admin context.
|
Chris@0
|
71 * @param \Symfony\Component\Routing\Matcher\UrlMatcherInterface $router
|
Chris@0
|
72 * The router.
|
Chris@0
|
73 * @param \Drupal\Core\PathProcessor\PathProcessorManager $path_processor_manager
|
Chris@0
|
74 * The path processor manager.
|
Chris@0
|
75 * @param \Drupal\Core\Routing\StackedRouteMatchInterface $stacked_route_match
|
Chris@0
|
76 * The stacked route match.
|
Chris@0
|
77 */
|
Chris@0
|
78 public function __construct(AdminContext $admin_context, UrlMatcherInterface $router, PathProcessorManager $path_processor_manager, StackedRouteMatchInterface $stacked_route_match) {
|
Chris@0
|
79 $this->adminContext = $admin_context;
|
Chris@0
|
80 $this->router = $router;
|
Chris@0
|
81 $this->pathProcessorManager = $path_processor_manager;
|
Chris@0
|
82 $this->stackedRouteMatch = $stacked_route_match;
|
Chris@0
|
83 }
|
Chris@0
|
84
|
Chris@0
|
85 /**
|
Chris@0
|
86 * {@inheritdoc}
|
Chris@0
|
87 */
|
Chris@0
|
88 public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
|
Chris@0
|
89 return new static(
|
Chris@0
|
90 $container->get('router.admin_context'),
|
Chris@0
|
91 $container->get('router'),
|
Chris@0
|
92 $container->get('path_processor_manager'),
|
Chris@0
|
93 $container->get('current_route_match')
|
Chris@0
|
94 );
|
Chris@0
|
95 }
|
Chris@0
|
96
|
Chris@0
|
97 /**
|
Chris@0
|
98 * {@inheritdoc}
|
Chris@0
|
99 */
|
Chris@0
|
100 public function getLangcode(Request $request = NULL) {
|
Chris@0
|
101 $langcode = NULL;
|
Chris@0
|
102
|
Chris@0
|
103 // User preference (only for administrators).
|
Chris@0
|
104 if ($this->currentUser->hasPermission('access administration pages') && ($preferred_admin_langcode = $this->currentUser->getPreferredAdminLangcode(FALSE)) && $this->isAdminPath($request)) {
|
Chris@0
|
105 $langcode = $preferred_admin_langcode;
|
Chris@0
|
106 }
|
Chris@0
|
107
|
Chris@0
|
108 // Not an admin, no admin language preference or not on an admin path.
|
Chris@0
|
109 return $langcode;
|
Chris@0
|
110 }
|
Chris@0
|
111
|
Chris@0
|
112 /**
|
Chris@0
|
113 * Checks whether the given path is an administrative one.
|
Chris@0
|
114 *
|
Chris@0
|
115 * @param \Symfony\Component\HttpFoundation\Request $request
|
Chris@0
|
116 * The request object.
|
Chris@0
|
117 *
|
Chris@0
|
118 * @return bool
|
Chris@0
|
119 * TRUE if the path is administrative, FALSE otherwise.
|
Chris@0
|
120 */
|
Chris@0
|
121 protected function isAdminPath(Request $request) {
|
Chris@0
|
122 $result = FALSE;
|
Chris@0
|
123 if ($request && $this->adminContext) {
|
Chris@0
|
124 // If called from an event subscriber, the request may not have the route
|
Chris@0
|
125 // object yet (it is still being built), so use the router to look up
|
Chris@0
|
126 // based on the path.
|
Chris@0
|
127 $route_match = $this->stackedRouteMatch->getRouteMatchFromRequest($request);
|
Chris@0
|
128 if ($route_match && !$route_object = $route_match->getRouteObject()) {
|
Chris@0
|
129 try {
|
Chris@17
|
130 // Some inbound path processors make changes to the request. Make a
|
Chris@17
|
131 // copy as we're not actually routing the request so we do not want to
|
Chris@17
|
132 // make changes.
|
Chris@17
|
133 $cloned_request = clone $request;
|
Chris@0
|
134 // Process the path as an inbound path. This will remove any language
|
Chris@0
|
135 // prefixes and other path components that inbound processing would
|
Chris@0
|
136 // clear out, so we can attempt to load the route clearly.
|
Chris@17
|
137 $path = $this->pathProcessorManager->processInbound(urldecode(rtrim($cloned_request->getPathInfo(), '/')), $cloned_request);
|
Chris@0
|
138 $attributes = $this->router->match($path);
|
Chris@0
|
139 }
|
Chris@0
|
140 catch (ResourceNotFoundException $e) {
|
Chris@0
|
141 return FALSE;
|
Chris@0
|
142 }
|
Chris@0
|
143 catch (AccessDeniedHttpException $e) {
|
Chris@0
|
144 return FALSE;
|
Chris@0
|
145 }
|
Chris@0
|
146 $route_object = $attributes[RouteObjectInterface::ROUTE_OBJECT];
|
Chris@0
|
147 }
|
Chris@0
|
148 $result = $this->adminContext->isAdminRoute($route_object);
|
Chris@0
|
149 }
|
Chris@0
|
150 return $result;
|
Chris@0
|
151 }
|
Chris@0
|
152
|
Chris@0
|
153 }
|