3 namespace Drupal\Tests\Core\PathProcessor;
5 use Drupal\Core\Language\Language;
6 use Drupal\Core\Language\LanguageInterface;
7 use Drupal\Core\PathProcessor\PathProcessorAlias;
8 use Drupal\Core\PathProcessor\PathProcessorDecode;
9 use Drupal\Core\PathProcessor\PathProcessorFront;
10 use Drupal\Core\PathProcessor\PathProcessorManager;
11 use Drupal\language\HttpKernel\PathProcessorLanguage;
12 use Drupal\language\Plugin\LanguageNegotiation\LanguageNegotiationUrl;
13 use Symfony\Component\HttpFoundation\Request;
15 use Drupal\Tests\UnitTestCase;
18 * Tests processing of the inbound path.
20 * @group PathProcessor
22 class PathProcessorTest extends UnitTestCase {
25 * Configuration for the languageManager stub.
27 * @var \Drupal\Core\Language\LanguageInterface[]
32 * The language manager stub used to construct a PathProcessorLanguage object.
34 * @var \Drupal\language\ConfigurableLanguageManagerInterface|\PHPUnit_Framework_MockObject_MockBuilder
36 protected $languageManager;
38 protected function setUp() {
40 // Set up some languages to be used by the language-based path processor.
42 foreach (['en', 'fr'] as $langcode) {
43 $language = new Language(['id' => $langcode]);
44 $languages[$langcode] = $language;
46 $this->languages = $languages;
48 // Create a stub configuration.
49 $language_prefixes = array_keys($this->languages);
52 'prefixes' => array_combine($language_prefixes, $language_prefixes)
56 // Create a URL-based language negotiation method definition.
57 $method_definitions = [
58 LanguageNegotiationUrl::METHOD_ID => [
59 'class' => '\Drupal\language\Plugin\LanguageNegotiation\LanguageNegotiationUrl',
64 // Create a URL-based language negotiation method.
65 $method_instance = new LanguageNegotiationUrl($config);
67 // Create a language manager stub.
68 $language_manager = $this->getMockBuilder('Drupal\language\ConfigurableLanguageManagerInterface')
70 $language_manager->expects($this->any())
71 ->method('getCurrentLanguage')
72 ->will($this->returnValue($languages['en']));
73 $language_manager->expects($this->any())
74 ->method('getLanguages')
75 ->will($this->returnValue($this->languages));
76 $language_manager->expects($this->any())
77 ->method('getLanguageTypes')
78 ->will($this->returnValue([LanguageInterface::TYPE_INTERFACE]));
79 $language_manager->expects($this->any())
80 ->method('getNegotiationMethods')
81 ->will($this->returnValue($method_definitions));
82 $language_manager->expects($this->any())
83 ->method('getNegotiationMethodInstance')
84 ->will($this->returnValue($method_instance));
86 $method_instance->setLanguageManager($language_manager);
87 $this->languageManager = $language_manager;
91 * Tests resolving the inbound path to the system path.
93 public function testProcessInbound() {
95 // Create an alias manager stub.
96 $alias_manager = $this->getMockBuilder('Drupal\Core\Path\AliasManager')
97 ->disableOriginalConstructor()
101 // Set up one proper alias that can be resolved to a system path.
102 ['/foo', NULL, '/user/1'],
103 // Passing in anything else should return the same string.
104 ['/fr/foo', NULL, '/fr/foo'],
105 ['/fr', NULL, '/fr'],
106 ['/user/login', NULL, '/user/login'],
109 $alias_manager->expects($this->any())
110 ->method('getPathByAlias')
111 ->will($this->returnValueMap($system_path_map));
113 // Create a stub config factory with all config settings that will be checked
115 $config_factory_stub = $this->getConfigFactoryStub(
118 'page.front' => '/user/login'
120 'language.negotiation' => [
122 'prefixes' => ['fr' => 'fr'],
123 'source' => LanguageNegotiationUrl::CONFIG_PATH_PREFIX,
129 // Create a language negotiator stub.
130 $negotiator = $this->getMockBuilder('Drupal\language\LanguageNegotiatorInterface')
132 $negotiator->expects($this->any())
133 ->method('getNegotiationMethods')
134 ->will($this->returnValue([
135 LanguageNegotiationUrl::METHOD_ID => [
136 'class' => 'Drupal\language\Plugin\LanguageNegotiation\LanguageNegotiationUrl',
140 $method = new LanguageNegotiationUrl();
141 $method->setConfig($config_factory_stub);
142 $method->setLanguageManager($this->languageManager);
143 $negotiator->expects($this->any())
144 ->method('getNegotiationMethodInstance')
145 ->will($this->returnValue($method));
147 // Create a user stub.
148 $current_user = $this->getMockBuilder('Drupal\Core\Session\AccountInterface')
151 // Create a config event subscriber stub.
152 $config_subscriber = $this->getMockBuilder('Drupal\language\EventSubscriber\ConfigSubscriber')
153 ->disableOriginalConstructor()
156 // Create the processors.
157 $alias_processor = new PathProcessorAlias($alias_manager);
158 $decode_processor = new PathProcessorDecode();
159 $front_processor = new PathProcessorFront($config_factory_stub);
160 $language_processor = new PathProcessorLanguage($config_factory_stub, $this->languageManager, $negotiator, $current_user, $config_subscriber);
162 // First, test the processor manager with the processors in the incorrect
163 // order. The alias processor will run before the language processor, meaning
164 // aliases will not be found.
166 1000 => $alias_processor,
167 500 => $decode_processor,
168 300 => $front_processor,
169 200 => $language_processor,
172 // Create the processor manager and add the processors.
173 $processor_manager = new PathProcessorManager();
174 foreach ($priorities as $priority => $processor) {
175 $processor_manager->addInbound($processor, $priority);
178 // Test resolving the French homepage using the incorrect processor order.
180 $request = Request::create($test_path);
181 $processed = $processor_manager->processInbound($test_path, $request);
182 $this->assertEquals('/', $processed, 'Processing in the incorrect order fails to resolve the system path from the empty path');
184 // Test resolving an existing alias using the incorrect processor order.
185 $test_path = '/fr/foo';
186 $request = Request::create($test_path);
187 $processed = $processor_manager->processInbound($test_path, $request);
188 $this->assertEquals('/foo', $processed, 'Processing in the incorrect order fails to resolve the system path from an alias');
190 // Now create a new processor manager and add the processors, this time in
191 // the correct order.
192 $processor_manager = new PathProcessorManager();
194 1000 => $decode_processor,
195 500 => $language_processor,
196 300 => $front_processor,
197 200 => $alias_processor,
199 foreach ($priorities as $priority => $processor) {
200 $processor_manager->addInbound($processor, $priority);
203 // Test resolving the French homepage using the correct processor order.
205 $request = Request::create($test_path);
206 $processed = $processor_manager->processInbound($test_path, $request);
207 $this->assertEquals('/user/login', $processed, 'Processing in the correct order resolves the system path from the empty path.');
209 // Test resolving an existing alias using the correct processor order.
210 $test_path = '/fr/foo';
211 $request = Request::create($test_path);
212 $processed = $processor_manager->processInbound($test_path, $request);
213 $this->assertEquals('/user/1', $processed, 'Processing in the correct order resolves the system path from an alias.');