Security update for Core, with self-updated composer
[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   /**
65    * Constructs a PathProcessorLanguage object.
66    *
67    * @param \Drupal\Core\Config\ConfigFactoryInterface $config
68    *   A config factory object for retrieving configuration settings.
69    * @param \Drupal\language\ConfigurableLanguageManagerInterface $language_manager
70    *   The configurable language manager.
71    * @param \Drupal\language\LanguageNegotiatorInterface $negotiator
72    *   The language negotiator.
73    * @param \Drupal\Core\Session\AccountInterface $current_user
74    *   The current active user.
75    * @param \Drupal\language\EventSubscriber\ConfigSubscriber $config_subscriber
76    *   The language configuration event subscriber.
77    */
78   public function __construct(ConfigFactoryInterface $config, ConfigurableLanguageManagerInterface $language_manager, LanguageNegotiatorInterface $negotiator, AccountInterface $current_user, ConfigSubscriber $config_subscriber) {
79     $this->config = $config;
80     $this->languageManager = $language_manager;
81     $this->negotiator = $negotiator;
82     $this->negotiator->setCurrentUser($current_user);
83     $this->configSubscriber = $config_subscriber;
84   }
85
86   /**
87    * {@inheritdoc}
88    */
89   public function processInbound($path, Request $request) {
90     if (!empty($path)) {
91       $scope = 'inbound';
92       if (!isset($this->processors[$scope])) {
93         $this->initProcessors($scope);
94       }
95       foreach ($this->processors[$scope] as $instance) {
96         $path = $instance->processInbound($path, $request);
97       }
98     }
99     return $path;
100   }
101
102   /**
103    * {@inheritdoc}
104    */
105   public function processOutbound($path, &$options = [], Request $request = NULL, BubbleableMetadata $bubbleable_metadata = NULL) {
106     if (!isset($this->multilingual)) {
107       $this->multilingual = $this->languageManager->isMultilingual();
108     }
109     if ($this->multilingual) {
110       $this->negotiator->reset();
111       $scope = 'outbound';
112       if (!isset($this->processors[$scope])) {
113         $this->initProcessors($scope);
114       }
115       foreach ($this->processors[$scope] as $instance) {
116         $path = $instance->processOutbound($path, $options, $request, $bubbleable_metadata);
117       }
118       // No language dependent path allowed in this mode.
119       if (empty($this->processors[$scope])) {
120         unset($options['language']);
121       }
122     }
123     return $path;
124   }
125
126   /**
127    * Initializes the local cache for language path processors.
128    *
129    * @param string $scope
130    *   The scope of the processors: "inbound" or "outbound".
131    */
132   protected function initProcessors($scope) {
133     $interface = '\Drupal\Core\PathProcessor\\' . Unicode::ucfirst($scope) . 'PathProcessorInterface';
134     $this->processors[$scope] = [];
135     $weights = [];
136     foreach ($this->languageManager->getLanguageTypes() as $type) {
137       foreach ($this->negotiator->getNegotiationMethods($type) as $method_id => $method) {
138         if (!isset($this->processors[$scope][$method_id])) {
139           $reflector = new \ReflectionClass($method['class']);
140           if ($reflector->implementsInterface($interface)) {
141             $this->processors[$scope][$method_id] = $this->negotiator->getNegotiationMethodInstance($method_id);
142             $weights[$method_id] = $method['weight'];
143           }
144         }
145       }
146     }
147
148     // Sort the processors list, so that their functions are called in the
149     // order specified by the weight of the methods.
150     uksort($this->processors[$scope], function ($method_id_a, $method_id_b) use ($weights) {
151       $a_weight = $weights[$method_id_a];
152       $b_weight = $weights[$method_id_b];
153
154       if ($a_weight == $b_weight) {
155         return 0;
156       }
157
158       return ($a_weight < $b_weight) ? -1 : 1;
159     });
160   }
161
162   /**
163    * Initializes the injected event subscriber with the language path processor.
164    *
165    * The language path processor service is registered only on multilingual
166    * site configuration, thus we inject it in the event subscriber only when
167    * it is initialized.
168    */
169   public function initConfigSubscriber() {
170     $this->configSubscriber->setPathProcessorLanguage($this);
171   }
172
173   /**
174    * Resets the collected processors instances.
175    */
176   public function reset() {
177     $this->processors = [];
178   }
179
180 }