1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
/** |
4
|
|
|
* @copyright Copyright (C) eZ Systems AS. All rights reserved. |
5
|
|
|
* @license For full copyright and license information view LICENSE file distributed with this source code. |
6
|
|
|
*/ |
7
|
|
|
namespace eZ\Publish\Core\MVC\Symfony\SiteAccess\Tests; |
8
|
|
|
|
9
|
|
|
use eZ\Publish\Core\MVC\Exception\InvalidSiteAccessException; |
10
|
|
|
use eZ\Publish\Core\MVC\Symfony\SiteAccess; |
11
|
|
|
use eZ\Publish\Core\MVC\Symfony\SiteAccess\Router; |
12
|
|
|
use eZ\Publish\Core\MVC\Symfony\SiteAccess\MatcherBuilderInterface; |
13
|
|
|
use eZ\Publish\Core\MVC\Symfony\SiteAccess\Matcher; |
14
|
|
|
use eZ\Publish\Core\MVC\Symfony\Routing\SimplifiedRequest; |
15
|
|
|
use eZ\Publish\Core\MVC\Symfony\SiteAccess\VersatileMatcher; |
16
|
|
|
use Psr\Log\LoggerInterface; |
17
|
|
|
use Symfony\Component\HttpFoundation\Request; |
18
|
|
|
|
19
|
|
|
class RouterTest extends RouterBaseTest |
20
|
|
|
{ |
21
|
|
|
protected function tearDown(): void |
22
|
|
|
{ |
23
|
|
|
putenv('EZPUBLISH_SITEACCESS'); |
24
|
|
|
parent::tearDown(); |
25
|
|
|
} |
26
|
|
|
|
27
|
|
|
public function testConstructDebug() |
28
|
|
|
{ |
29
|
|
|
return $this->createRouter(true); |
30
|
|
|
} |
31
|
|
|
|
32
|
|
|
/** |
33
|
|
|
* @dataProvider matchProvider |
34
|
|
|
*/ |
35
|
|
|
public function testMatch(SimplifiedRequest $request, $siteAccess) |
36
|
|
|
{ |
37
|
|
|
$router = $this->createRouter(); |
38
|
|
|
$sa = $router->match($request); |
39
|
|
|
$this->assertInstanceOf(SiteAccess::class, $sa); |
40
|
|
|
$this->assertSame($siteAccess, $sa->name); |
41
|
|
|
// SiteAccess must be serializable as a whole. See https://jira.ez.no/browse/EZP-21613 |
42
|
|
|
$this->assertIsString(serialize($sa)); |
43
|
|
|
$router->setSiteAccess(); |
44
|
|
|
} |
45
|
|
|
|
46
|
|
View Code Duplication |
public function testMatchWithDevEnvFail() |
47
|
|
|
{ |
48
|
|
|
$router = $this->createRouter(true); |
49
|
|
|
putenv('EZPUBLISH_SITEACCESS=' . self::UNDEFINED_SA_NAME); |
50
|
|
|
|
51
|
|
|
$this->expectException(InvalidSiteAccessException::class); |
52
|
|
|
$this->expectExceptionMessageRegExp( |
|
|
|
|
53
|
|
|
'/^Invalid SiteAccess \'' . self::UNDEFINED_SA_NAME . '\', matched by .+\\. Valid SiteAccesses are/' |
54
|
|
|
); |
55
|
|
|
|
56
|
|
|
$router->match(new SimplifiedRequest()); |
57
|
|
|
} |
58
|
|
|
|
59
|
|
View Code Duplication |
public function testMatchWithProdEnvFail() |
60
|
|
|
{ |
61
|
|
|
$router = $this->createRouter(); |
62
|
|
|
putenv('EZPUBLISH_SITEACCESS=' . self::UNDEFINED_SA_NAME); |
63
|
|
|
|
64
|
|
|
$this->expectException(InvalidSiteAccessException::class); |
65
|
|
|
$this->expectExceptionMessageRegExp( |
|
|
|
|
66
|
|
|
'/^Invalid SiteAccess \'' . self::UNDEFINED_SA_NAME . '\', matched by .+\\.$/' |
67
|
|
|
); |
68
|
|
|
|
69
|
|
|
$router->match(new SimplifiedRequest()); |
70
|
|
|
} |
71
|
|
|
|
72
|
|
|
public function testMatchWithEnv() |
73
|
|
|
{ |
74
|
|
|
$router = $this->createRouter(); |
75
|
|
|
putenv('EZPUBLISH_SITEACCESS=' . self::ENV_SA_NAME); |
76
|
|
|
$sa = $router->match(new SimplifiedRequest()); |
77
|
|
|
$this->assertInstanceOf(SiteAccess::class, $sa); |
78
|
|
|
$this->assertSame(self::ENV_SA_NAME, $sa->name); |
79
|
|
|
$this->assertSame('env', $sa->matchingType); |
80
|
|
|
$router->setSiteAccess(); |
81
|
|
|
} |
82
|
|
|
|
83
|
|
|
public function testMatchWithRequestHeader(): void |
84
|
|
|
{ |
85
|
|
|
$router = $this->createRouter(); |
86
|
|
|
$request = Request::create('/foo/bar'); |
87
|
|
|
$request->headers->set('X-Siteaccess', self::HEADERBASED_SA_NAME); |
88
|
|
|
$sa = $router->match( |
89
|
|
|
new SimplifiedRequest( |
90
|
|
|
[ |
91
|
|
|
'headers' => $request->headers->all(), |
92
|
|
|
] |
93
|
|
|
) |
94
|
|
|
); |
95
|
|
|
$this->assertInstanceOf(SiteAccess::class, $sa); |
96
|
|
|
$this->assertSame(self::HEADERBASED_SA_NAME, $sa->name); |
97
|
|
|
$this->assertSame('header', $sa->matchingType); |
98
|
|
|
$router->setSiteAccess(); |
99
|
|
|
} |
100
|
|
|
|
101
|
|
|
public function matchProvider(): array |
102
|
|
|
{ |
103
|
|
|
return [ |
104
|
|
|
[SimplifiedRequest::fromUrl('http://example.com'), 'default_sa'], |
105
|
|
|
[SimplifiedRequest::fromUrl('https://example.com'), 'default_sa'], |
106
|
|
|
[SimplifiedRequest::fromUrl('http://example.com/'), 'default_sa'], |
107
|
|
|
[SimplifiedRequest::fromUrl('https://example.com/'), 'default_sa'], |
108
|
|
|
[SimplifiedRequest::fromUrl('http://example.com//'), 'default_sa'], |
109
|
|
|
[SimplifiedRequest::fromUrl('https://example.com//'), 'default_sa'], |
110
|
|
|
[SimplifiedRequest::fromUrl('http://example.com:8080/'), 'default_sa'], |
111
|
|
|
[SimplifiedRequest::fromUrl('http://example.com/first_siteaccess/'), 'default_sa'], |
112
|
|
|
[SimplifiedRequest::fromUrl('http://example.com/?first_siteaccess'), 'default_sa'], |
113
|
|
|
[SimplifiedRequest::fromUrl('http://example.com/?first_sa'), 'default_sa'], |
114
|
|
|
[SimplifiedRequest::fromUrl('http://example.com/first_salt'), 'default_sa'], |
115
|
|
|
[SimplifiedRequest::fromUrl('http://example.com/first_sa.foo'), 'default_sa'], |
116
|
|
|
[SimplifiedRequest::fromUrl('http://example.com/test'), 'default_sa'], |
117
|
|
|
[SimplifiedRequest::fromUrl('http://example.com/test/foo/'), 'default_sa'], |
118
|
|
|
[SimplifiedRequest::fromUrl('http://example.com/test/foo/bar/'), 'default_sa'], |
119
|
|
|
[SimplifiedRequest::fromUrl('http://example.com/test/foo/bar/first_sa'), 'default_sa'], |
120
|
|
|
[SimplifiedRequest::fromUrl('http://example.com/default_sa'), 'default_sa'], |
121
|
|
|
|
122
|
|
|
[SimplifiedRequest::fromUrl('http://example.com/first_sa'), 'first_sa'], |
123
|
|
|
[SimplifiedRequest::fromUrl('http://example.com/first_sa/'), 'first_sa'], |
124
|
|
|
[SimplifiedRequest::fromUrl('http://example.com/first_sa//'), 'first_sa'], |
125
|
|
|
// Double slashes shouldn't be considered as one |
126
|
|
|
[SimplifiedRequest::fromUrl('http://example.com//first_sa//'), 'default_sa'], |
127
|
|
|
[SimplifiedRequest::fromUrl('http://example.com/first_sa///test'), 'first_sa'], |
128
|
|
|
[SimplifiedRequest::fromUrl('http://example.com/first_sa/foo'), 'first_sa'], |
129
|
|
|
[SimplifiedRequest::fromUrl('http://example.com/first_sa/foo/bar'), 'first_sa'], |
130
|
|
|
[SimplifiedRequest::fromUrl('http://example.com:82/first_sa/'), 'first_sa'], |
131
|
|
|
[SimplifiedRequest::fromUrl('http://third_siteaccess/first_sa/'), 'first_sa'], |
132
|
|
|
[SimplifiedRequest::fromUrl('http://first_sa/'), 'first_sa'], |
133
|
|
|
[SimplifiedRequest::fromUrl('https://first_sa/'), 'first_sa'], |
134
|
|
|
[SimplifiedRequest::fromUrl('http://first_sa:81/'), 'first_sa'], |
135
|
|
|
[SimplifiedRequest::fromUrl('http://first_siteaccess/'), 'first_sa'], |
136
|
|
|
[SimplifiedRequest::fromUrl('http://first_siteaccess:82/'), 'first_sa'], |
137
|
|
|
[SimplifiedRequest::fromUrl('http://first_siteaccess:83/'), 'first_sa'], |
138
|
|
|
[SimplifiedRequest::fromUrl('http://first_siteaccess/foo/'), 'first_sa'], |
139
|
|
|
[SimplifiedRequest::fromUrl('http://first_siteaccess:82/foo/'), 'first_sa'], |
140
|
|
|
[SimplifiedRequest::fromUrl('http://first_siteaccess:83/foo/'), 'first_sa'], |
141
|
|
|
|
142
|
|
|
[SimplifiedRequest::fromUrl('http://example.com/second_sa'), 'second_sa'], |
143
|
|
|
[SimplifiedRequest::fromUrl('http://example.com/second_sa/'), 'second_sa'], |
144
|
|
|
[SimplifiedRequest::fromUrl('http://example.com/second_sa?param1=foo'), 'second_sa'], |
145
|
|
|
[SimplifiedRequest::fromUrl('http://example.com/second_sa/foo/'), 'second_sa'], |
146
|
|
|
[SimplifiedRequest::fromUrl('http://example.com:82/second_sa/'), 'second_sa'], |
147
|
|
|
[SimplifiedRequest::fromUrl('http://example.com:83/second_sa/'), 'second_sa'], |
148
|
|
|
[SimplifiedRequest::fromUrl('http://first_siteaccess:82/second_sa/'), 'second_sa'], |
149
|
|
|
[SimplifiedRequest::fromUrl('http://first_siteaccess:83/second_sa/'), 'second_sa'], |
150
|
|
|
|
151
|
|
|
[SimplifiedRequest::fromUrl('http://example.com:81/'), 'third_sa'], |
152
|
|
|
[SimplifiedRequest::fromUrl('https://example.com:81/'), 'third_sa'], |
153
|
|
|
[SimplifiedRequest::fromUrl('http://example.com:81/foo'), 'third_sa'], |
154
|
|
|
[SimplifiedRequest::fromUrl('http://example.com:81/foo/bar'), 'third_sa'], |
155
|
|
|
|
156
|
|
|
[SimplifiedRequest::fromUrl('http://example.com:82/'), 'fourth_sa'], |
157
|
|
|
[SimplifiedRequest::fromUrl('https://example.com:82/'), 'fourth_sa'], |
158
|
|
|
[SimplifiedRequest::fromUrl('https://example.com:82/foo'), 'fourth_sa'], |
159
|
|
|
|
160
|
|
|
[SimplifiedRequest::fromUrl('http://fr.ezpublish.dev/eng'), 'fr_eng'], |
161
|
|
|
[SimplifiedRequest::fromUrl('http://us.ezpublish.dev/fre'), 'fr_us'], |
162
|
|
|
]; |
163
|
|
|
} |
164
|
|
|
|
165
|
|
|
public function testMatchByNameInvalidSiteAccess() |
166
|
|
|
{ |
167
|
|
|
$this->expectException(\InvalidArgumentException::class); |
168
|
|
|
|
169
|
|
|
$matcherBuilder = $this->createMock(MatcherBuilderInterface::class); |
170
|
|
|
$logger = $this->createMock(LoggerInterface::class); |
171
|
|
|
$siteAccessProvider = $this->createMock(SiteAccess\SiteAccessProviderInterface::class); |
172
|
|
|
$siteAccessProvider |
|
|
|
|
173
|
|
|
->method('isDefined') |
174
|
|
|
->with('bar') |
175
|
|
|
->willReturn(false); |
176
|
|
|
$router = new Router($matcherBuilder, $logger, 'default_sa', [], $siteAccessProvider); |
177
|
|
|
$router->matchByName('bar'); |
178
|
|
|
} |
179
|
|
|
|
180
|
|
|
public function testMatchByName() |
181
|
|
|
{ |
182
|
|
|
$matcherBuilder = $this->createMock(MatcherBuilderInterface::class); |
183
|
|
|
$logger = $this->createMock(LoggerInterface::class); |
184
|
|
|
$matcherClass = 'Map\Host'; |
185
|
|
|
$matchedSiteAccess = 'foo'; |
186
|
|
|
$matcherConfig = [ |
187
|
|
|
'phoenix-rises.fm' => $matchedSiteAccess, |
188
|
|
|
]; |
189
|
|
|
$config = [ |
190
|
|
|
'Map\URI' => ['default' => 'default_sa'], |
191
|
|
|
$matcherClass => $matcherConfig, |
192
|
|
|
]; |
193
|
|
|
$siteAccessProvider = $this->createMock(SiteAccess\SiteAccessProviderInterface::class); |
194
|
|
|
$siteAccessProvider |
|
|
|
|
195
|
|
|
->method('isDefined') |
196
|
|
|
->willReturnMap([ |
197
|
|
|
[$matchedSiteAccess, true], |
198
|
|
|
['default_sa', true], |
199
|
|
|
]); |
200
|
|
|
$router = new Router($matcherBuilder, $logger, 'default_sa', $config, $siteAccessProvider); |
201
|
|
|
$matcherInitialSA = $this->createMock(SiteAccess\URILexer::class); |
202
|
|
|
$router->setSiteAccess(new SiteAccess('test', 'test', $matcherInitialSA)); |
203
|
|
|
$matcherInitialSA |
204
|
|
|
->expects($this->once()) |
205
|
|
|
->method('analyseURI'); |
206
|
|
|
|
207
|
|
|
$matcher = $this->createMock(VersatileMatcher::class); |
208
|
|
|
$matcherBuilder |
209
|
|
|
->expects($this->exactly(2)) |
210
|
|
|
->method('buildMatcher') |
211
|
|
|
->will( |
212
|
|
|
$this->onConsecutiveCalls( |
213
|
|
|
$this->createMock(Matcher::class), |
214
|
|
|
$matcher |
215
|
|
|
) |
216
|
|
|
); |
217
|
|
|
|
218
|
|
|
$reverseMatchedMatcher = $this->createMock(VersatileMatcher::class); |
219
|
|
|
$matcher |
220
|
|
|
->expects($this->once()) |
221
|
|
|
->method('reverseMatch') |
222
|
|
|
->with($matchedSiteAccess) |
223
|
|
|
->will($this->returnValue($reverseMatchedMatcher)); |
224
|
|
|
|
225
|
|
|
$siteAccess = $router->matchByName($matchedSiteAccess); |
226
|
|
|
$this->assertInstanceOf(SiteAccess::class, $siteAccess); |
227
|
|
|
$this->assertSame($reverseMatchedMatcher, $siteAccess->matcher); |
228
|
|
|
$this->assertSame($matchedSiteAccess, $siteAccess->name); |
229
|
|
|
} |
230
|
|
|
|
231
|
|
|
public function testMatchByNameNoVersatileMatcher() |
232
|
|
|
{ |
233
|
|
|
$matcherBuilder = $this->createMock(MatcherBuilderInterface::class); |
234
|
|
|
$logger = $this->createMock(LoggerInterface::class); |
235
|
|
|
$matcherClass = 'Map\Host'; |
236
|
|
|
$defaultSiteAccess = 'default_sa'; |
237
|
|
|
$matcherConfig = [ |
238
|
|
|
'phoenix-rises.fm' => 'foo', |
239
|
|
|
]; |
240
|
|
|
$config = [$matcherClass => $matcherConfig]; |
241
|
|
|
$siteAccessProvider = $this->createMock(SiteAccess\SiteAccessProviderInterface::class); |
242
|
|
|
$siteAccessProvider |
|
|
|
|
243
|
|
|
->method('isDefined') |
244
|
|
|
->willReturnMap([ |
245
|
|
|
[$defaultSiteAccess, true], |
246
|
|
|
['foo', true], |
247
|
|
|
]); |
248
|
|
|
$router = new Router($matcherBuilder, $logger, $defaultSiteAccess, $config, $siteAccessProvider); |
249
|
|
|
$router->setSiteAccess(new SiteAccess('test', 'test')); |
250
|
|
|
$request = $router->getRequest(); |
251
|
|
|
$matcherBuilder |
252
|
|
|
->expects($this->once()) |
253
|
|
|
->method('buildMatcher') |
254
|
|
|
->with($matcherClass, $matcherConfig, $request) |
255
|
|
|
->will($this->returnValue($this->createMock(Matcher::class))); |
256
|
|
|
|
257
|
|
|
$logger |
258
|
|
|
->expects($this->once()) |
259
|
|
|
->method('notice'); |
260
|
|
|
$this->assertEquals(new SiteAccess($defaultSiteAccess, 'default'), $router->matchByName($defaultSiteAccess)); |
261
|
|
|
} |
262
|
|
|
|
263
|
|
|
protected function createRouter($debug = false): Router |
264
|
|
|
{ |
265
|
|
|
return new Router( |
266
|
|
|
$this->matcherBuilder, |
267
|
|
|
$this->createMock(LoggerInterface::class), |
268
|
|
|
'default_sa', |
269
|
|
|
[ |
270
|
|
|
'Map\\URI' => [ |
271
|
|
|
'first_sa' => 'first_sa', |
272
|
|
|
'second_sa' => 'second_sa', |
273
|
|
|
], |
274
|
|
|
'Map\\Host' => [ |
275
|
|
|
'first_sa' => 'first_sa', |
276
|
|
|
'first_siteaccess' => 'first_sa', |
277
|
|
|
'third_siteaccess' => 'third_sa', |
278
|
|
|
], |
279
|
|
|
'Map\\Port' => [ |
280
|
|
|
81 => 'third_sa', |
281
|
|
|
82 => 'fourth_sa', |
282
|
|
|
83 => 'first_sa', |
283
|
|
|
85 => 'first_sa', |
284
|
|
|
], |
285
|
|
|
'Compound\\LogicalAnd' => [ |
286
|
|
|
[ |
287
|
|
|
'matchers' => [ |
288
|
|
|
'Map\\URI' => ['eng' => true], |
289
|
|
|
'Map\\Host' => ['fr.ezpublish.dev' => true], |
290
|
|
|
], |
291
|
|
|
'match' => 'fr_eng', |
292
|
|
|
], |
293
|
|
|
[ |
294
|
|
|
'matchers' => [ |
295
|
|
|
'Map\\URI' => ['fre' => true], |
296
|
|
|
'Map\\Host' => ['us.ezpublish.dev' => true], |
297
|
|
|
], |
298
|
|
|
'match' => 'fr_us', |
299
|
|
|
], |
300
|
|
|
], |
301
|
|
|
], |
302
|
|
|
$this->siteAccessProvider, |
303
|
|
|
null, |
304
|
|
|
$debug |
305
|
|
|
); |
306
|
|
|
} |
307
|
|
|
|
308
|
|
|
/** |
309
|
|
|
* @return \eZ\Publish\Core\MVC\Symfony\SiteAccess\Tests\SiteAccessSetting[] |
310
|
|
|
*/ |
311
|
|
|
public function getSiteAccessProviderSettings(): array |
312
|
|
|
{ |
313
|
|
|
return [ |
314
|
|
|
new SiteAccessSetting('first_sa', true), |
315
|
|
|
new SiteAccessSetting('second_sa', true), |
316
|
|
|
new SiteAccessSetting('third_sa', true), |
317
|
|
|
new SiteAccessSetting('fourth_sa', true), |
318
|
|
|
new SiteAccessSetting('fr_eng', true), |
319
|
|
|
new SiteAccessSetting('fr_us', true), |
320
|
|
|
new SiteAccessSetting(self::HEADERBASED_SA_NAME, true), |
321
|
|
|
new SiteAccessSetting(self::ENV_SA_NAME, true), |
322
|
|
|
new SiteAccessSetting(self::UNDEFINED_SA_NAME, false), |
323
|
|
|
]; |
324
|
|
|
} |
325
|
|
|
} |
326
|
|
|
|
This method has been deprecated. The supplier of the class has supplied an explanatory message.
The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.