9feae277c7f87c81ea026990f76885a12f03806e
[yaffs-website] / web / core / modules / language / src / HttpKernel / PathProcessorLanguage.php
1 <?php
2
3 namespace Drupal\language\HttpKernel;
4
5 use Drupal\Component\Utility\Unicode;
6 use Drupal\Core\Config\ConfigFactoryInterface;
7 use Drupal\Core\PathProcessor\InboundPathProcessorInterface;
8 use Drupal\Core\PathProcessor\OutboundPathProcessorInterface;
9 use Drupal\Core\Render\BubbleableMetadata;
10 use Drupal\language\ConfigurableLanguageManagerInterface;
11 use Drupal\language\EventSubscriber\ConfigSubscriber;
12 use Drupal\language\LanguageNegotiatorInterface;
13 use Symfony\Component\HttpFoundation\Request;
14 use Drupal\Core\Session\AccountInterface;
15
16 /**
17  * Processes the inbound path using path alias lookups.
18  */
19 class PathProcessorLanguage implements InboundPathProcessorInterface, OutboundPathProcessorInterface {
20
21   /**
22    * A config factory for retrieving required config settings.
23    *
24    * @var \Drupal\Core\Config\ConfigFactoryInterface
25    */
26   protected $config;
27
28   /**
29    * Language manager for retrieving the url language type.
30    *
31    * @var \Drupal\language\ConfigurableLanguageManagerInterface
32    */
33   protected $languageManager;
34
35   /**
36    * The language negotiator.
37    *
38    * @var \Drupal\language\LanguageNegotiatorInterface
39    */
40   protected $negotiator;
41
42   /**
43    * Local cache for language path processors.
44    *
45    * @var array
46    */
47   protected $processors;
48
49   /**
50    * Flag indicating whether the site is multilingual.
51    *
52    * @var bool
53    */
54   protected $multilingual;
55
56   /**
57    * The language configuration event subscriber.
58    *
59    * @var \Drupal\language\EventSubscriber\ConfigSubscriber
60    */
61   protected $configSubscriber;
62
63   /**
64    * Constructs a PathProcessorLanguage object.
65    *
66    * @param \Drupal\Core\Config\ConfigFactoryInterface $config
67    *   A config factory object for retrieving configuration settings.
68    * @param \Drupal\language\ConfigurableLanguageManagerInterface $language_manager
69    *   The configurable language manager.
70    * @param \Drupal\language\LanguageNegotiatorInterface $negotiator
71    *   The language negotiator.
72    * @param \Drupal\Core\Session\AccountInterface $current_user
73    *   The current active user.
74    * @param \Drupal\language\EventSubscriber\ConfigSubscriber $config_subscriber
75    *   The language configuration event subscriber.
76    */
77   public function __construct(ConfigFactoryInterface $config, ConfigurableLanguageManagerInterface $language_manager, LanguageNegotiatorInterface $negotiator, AccountInterface $current_user, ConfigSubscriber $config_subscriber) {
78     $this->config = $config;
79     $this->languageManager = $language_manager;
80     $this->negotiator = $negotiator;
81     $this->negotiator->setCurrentUser($current_user);
82     $this->configSubscriber = $config_subscriber;
83   }
84
85   /**
86    * {@inheritdoc}
87    */
88   public function processInbound($path, Request $request) {
89     if (!empty($path)) {
90       $scope = 'inbound';
91       if (!isset($this->processors[$scope])) {
92         $this->initProcessors($scope);
93       }
94       foreach ($this->processors[$scope] as $instance) {
95         $path = $instance->processInbound($path, $request);
96       }
97     }
98     return $path;
99   }
100
101   /**
102    * {@inheritdoc}
103    */
104   public function processOutbound($path, &$options = [], Request $request = NULL, BubbleableMetadata $bubbleable_metadata = NULL) {
105     if (!isset($this->multilingual)) {
106       $this->multilingual = $this->languageManager->isMultilingual();
107     }
108     if ($this->multilingual) {
109       $this->negotiator->reset();
110       $scope = 'outbound';
111       if (!isset($this->processors[$scope])) {
112         $this->initProcessors($scope);
113       }
114       foreach ($this->processors[$scope] as $instance) {
115         $path = $instance->processOutbound($path, $options, $request, $bubbleable_metadata);
116       }
117       // No language dependent path allowed in this mode.
118       if (empty($this->processors[$scope])) {
119         unset($options['language']);
120       }
121     }
122     return $path;
123   }
124
125   /**
126    * Initializes the local cache for language path processors.
127    *
128    * @param string $scope
129    *   The scope of the processors: "inbound" or "outbound".
130    */
131   protected function initProcessors($scope) {
132     $interface = '\Drupal\Core\PathProcessor\\' . Unicode::ucfirst($scope) . 'PathProcessorInterface';
133     $this->processors[$scope] = [];
134     $weights = [];
135     foreach ($this->languageManager->getLanguageTypes() as $type) {
136       foreach ($this->negotiator->getNegotiationMethods($type) as $method_id => $method) {
137         if (!isset($this->processors[$scope][$method_id])) {
138           $reflector = new \ReflectionClass($method['class']);
139           if ($reflector->implementsInterface($interface)) {
140             $this->processors[$scope][$method_id] = $this->negotiator->getNegotiationMethodInstance($method_id);
141             $weights[$method_id] = $method['weight'];
142           }
143         }
144       }
145     }
146
147     // Sort the processors list, so that their functions are called in the
148     // order specified by the weight of the methods.
149     uksort($this->processors[$scope], function ($method_id_a, $method_id_b) use ($weights) {
150       $a_weight = $weights[$method_id_a];
151       $b_weight = $weights[$method_id_b];
152
153       if ($a_weight == $b_weight) {
154         return 0;
155       }
156
157       return ($a_weight < $b_weight) ? -1 : 1;
158     });
159   }
160
161   /**
162    * Initializes the injected event subscriber with the language path processor.
163    *
164    * The language path processor service is registered only on multilingual
165    * site configuration, thus we inject it in the event subscriber only when
166    * it is initialized.
167    */
168   public function initConfigSubscriber() {
169     $this->configSubscriber->setPathProcessorLanguage($this);
170   }
171
172   /**
173    * Resets the collected processors instances.
174    */
175   public function reset() {
176     $this->processors = [];
177   }
178
179 }