1 | <?php |
||||
2 | |||||
3 | namespace SilverStripe\CMS\Tests\Controllers; |
||||
4 | |||||
5 | use Page; |
||||
0 ignored issues
–
show
|
|||||
6 | use SilverStripe\CMS\Controllers\ContentController; |
||||
7 | use SilverStripe\CMS\Controllers\ModelAsController; |
||||
8 | use SilverStripe\CMS\Controllers\OldPageRedirector; |
||||
9 | use SilverStripe\CMS\Controllers\RootURLController; |
||||
10 | use SilverStripe\CMS\Model\SiteTree; |
||||
11 | use SilverStripe\Control\Controller; |
||||
12 | use SilverStripe\Control\Director; |
||||
13 | use SilverStripe\Core\Config\Config; |
||||
14 | use SilverStripe\Dev\FunctionalTest; |
||||
15 | use SilverStripe\Versioned\Versioned; |
||||
16 | use SilverStripe\View\Parsers\URLSegmentFilter; |
||||
17 | |||||
18 | class ModelAsControllerTest extends FunctionalTest |
||||
19 | { |
||||
20 | protected $usesDatabase = true; |
||||
21 | |||||
22 | protected $autoFollowRedirection = false; |
||||
23 | |||||
24 | protected static $required_extensions = [ |
||||
25 | ModelAsController::class => [ |
||||
26 | OldPageRedirector::class, |
||||
27 | ], |
||||
28 | ContentController::class => [ |
||||
29 | OldPageRedirector::class, |
||||
30 | ], |
||||
31 | ]; |
||||
32 | |||||
33 | /** |
||||
34 | * New tests require nested urls to be enabled, but the site might not |
||||
35 | * support nested URLs. |
||||
36 | * This setup will enable nested-urls for this test and resets the state |
||||
37 | * after the tests have been performed. |
||||
38 | */ |
||||
39 | protected function setUp() : void |
||||
40 | { |
||||
41 | parent::setUp(); |
||||
42 | Config::modify()->set(SiteTree::class, 'nested_urls', true); |
||||
43 | } |
||||
44 | |||||
45 | |||||
46 | protected function generateNestedPagesFixture() |
||||
47 | { |
||||
48 | $level1 = SiteTree::create(); |
||||
49 | $level1->Title = 'First Level'; |
||||
50 | $level1->URLSegment = 'level1'; |
||||
51 | $level1->write(); |
||||
52 | $level1->copyVersionToStage(Versioned::DRAFT, Versioned::LIVE); |
||||
53 | |||||
54 | $level1->URLSegment = 'newlevel1'; |
||||
55 | $level1->write(); |
||||
56 | $level1->copyVersionToStage(Versioned::DRAFT, Versioned::LIVE); |
||||
57 | |||||
58 | $level2 = SiteTree::create(); |
||||
59 | $level2->Title = 'Second Level'; |
||||
60 | $level2->URLSegment = 'level2'; |
||||
61 | $level2->ParentID = $level1->ID; |
||||
62 | $level2->write(); |
||||
63 | $level2->copyVersionToStage(Versioned::DRAFT, Versioned::LIVE); |
||||
64 | |||||
65 | $level2->URLSegment = 'newlevel2'; |
||||
66 | $level2->write(); |
||||
67 | $level2->copyVersionToStage(Versioned::DRAFT, Versioned::LIVE); |
||||
68 | |||||
69 | $level3 = SiteTree::create(); |
||||
70 | $level3->Title = "Level 3"; |
||||
71 | $level3->URLSegment = 'level3'; |
||||
72 | $level3->ParentID = $level2->ID; |
||||
73 | $level3->write(); |
||||
74 | $level3->copyVersionToStage('Stage', 'Live'); |
||||
75 | |||||
76 | $level3->URLSegment = 'newlevel3'; |
||||
77 | $level3->write(); |
||||
78 | $level3->copyVersionToStage('Stage', 'Live'); |
||||
79 | } |
||||
80 | |||||
81 | /** |
||||
82 | * We're building up a page hierarchy ("nested URLs") and rename |
||||
83 | * all the individual pages afterwards. The assumption is that |
||||
84 | * all pages will be found by their old segments. |
||||
85 | * |
||||
86 | * NOTE: This test requires nested_urls |
||||
87 | * |
||||
88 | * Original: level1/level2/level3 |
||||
89 | * Republished as: newlevel1/newlevel2/newlevel3 |
||||
90 | */ |
||||
91 | public function testRedirectsNestedRenamedPages() |
||||
92 | { |
||||
93 | $this->generateNestedPagesFixture(); |
||||
94 | |||||
95 | // check a first level URLSegment |
||||
96 | $response = $this->get('level1/action'); |
||||
97 | $this->assertEquals($response->getStatusCode(), 301); |
||||
98 | $this->assertEquals( |
||||
99 | Controller::join_links(Director::baseURL() . 'newlevel1/action'), |
||||
100 | $response->getHeader('Location') |
||||
101 | ); |
||||
102 | |||||
103 | // check second level URLSegment |
||||
104 | $response = $this->get('newlevel1/level2'); |
||||
105 | $this->assertEquals($response->getStatusCode(), 301); |
||||
106 | $this->assertEquals( |
||||
107 | Controller::join_links(Director::baseURL() . 'newlevel1/newlevel2/'), |
||||
108 | $response->getHeader('Location') |
||||
109 | ); |
||||
110 | |||||
111 | // check third level URLSegment |
||||
112 | $response = $this->get('newlevel1/newlevel2/level3'); |
||||
113 | $this->assertEquals($response->getStatusCode(), 301); |
||||
114 | $this->assertEquals( |
||||
115 | Controller::join_links(Director::baseURL() . 'newlevel1/newlevel2/newlevel3/'), |
||||
116 | $response->getHeader('Location') |
||||
117 | ); |
||||
118 | |||||
119 | $response = $this->get('newlevel1/newlevel2/level3'); |
||||
0 ignored issues
–
show
|
|||||
120 | } |
||||
121 | |||||
122 | /** |
||||
123 | * Test that the redirect works even with a lot of nested pages |
||||
124 | * Original: /oldurl/level2/level3/level4/level5 |
||||
125 | * New: /newurl/level2/level3/level4/level5 |
||||
126 | */ |
||||
127 | public function testHeavilyNestedRenamedRedirectedPages() |
||||
128 | { |
||||
129 | $page = SiteTree::create(); |
||||
130 | $page->Title = 'First Level'; |
||||
131 | $page->URLSegment = 'oldurl'; |
||||
132 | $page->write(); |
||||
133 | $page->copyVersionToStage(Versioned::DRAFT, Versioned::LIVE); |
||||
134 | |||||
135 | $page->URLSegment = 'newurl'; |
||||
136 | $page->write(); |
||||
137 | $page->copyVersionToStage(Versioned::DRAFT, Versioned::LIVE); |
||||
138 | |||||
139 | $page2 = SiteTree::create(); |
||||
140 | $page2->Title = 'Second Level Page'; |
||||
141 | $page2->URLSegment = 'level2'; |
||||
142 | $page2->ParentID = $page->ID; |
||||
143 | $page2->write(); |
||||
144 | $page2->copyVersionToStage(Versioned::DRAFT, Versioned::LIVE); |
||||
145 | |||||
146 | $page3 = SiteTree::create(); |
||||
147 | $page3->Title = 'Third Level Page'; |
||||
148 | $page3->URLSegment = 'level3'; |
||||
149 | $page3->ParentID = $page2->ID; |
||||
150 | $page3->write(); |
||||
151 | $page3->copyVersionToStage(Versioned::DRAFT, Versioned::LIVE); |
||||
152 | |||||
153 | $page4 = SiteTree::create(); |
||||
154 | $page4->Title = 'Fourth Level Page'; |
||||
155 | $page4->URLSegment = 'level4'; |
||||
156 | $page4->ParentID = $page3->ID; |
||||
157 | $page4->write(); |
||||
158 | $page4->copyVersionToStage(Versioned::DRAFT, Versioned::LIVE); |
||||
159 | |||||
160 | $page5 = SiteTree::create(); |
||||
161 | $page5->Title = 'Fifth Level Page'; |
||||
162 | $page5->URLSegment = 'level5'; |
||||
163 | $page5->ParentID = $page4->ID; |
||||
164 | $page5->write(); |
||||
165 | $page5->copyVersionToStage(Versioned::DRAFT, Versioned::LIVE); |
||||
166 | |||||
167 | // Test that the redirect still works fine when trying to access the most nested page |
||||
168 | $response = $this->get('oldurl/level2/level3/level4/level5/'); |
||||
169 | $this->assertEquals($response->getStatusCode(), 301); |
||||
170 | $this->assertEquals( |
||||
171 | Controller::join_links(Director::baseURL() . 'newurl/level2/level3/level4/level5/'), |
||||
172 | $response->getHeader('Location') |
||||
173 | ); |
||||
174 | } |
||||
175 | |||||
176 | |||||
177 | public function testRedirectionForPreNestedurlsBookmarks() |
||||
178 | { |
||||
179 | $this->generateNestedPagesFixture(); |
||||
180 | |||||
181 | // Up-to-date URLs will be redirected to the appropriate subdirectory |
||||
182 | $response = $this->get('newlevel3'); |
||||
183 | $this->assertEquals(301, $response->getStatusCode()); |
||||
184 | $this->assertEquals( |
||||
185 | Director::baseURL() . 'newlevel1/newlevel2/newlevel3/', |
||||
186 | $response->getHeader("Location") |
||||
187 | ); |
||||
188 | |||||
189 | // So will the legacy ones |
||||
190 | $response = $this->get('level3'); |
||||
191 | $this->assertEquals(301, $response->getStatusCode()); |
||||
192 | $this->assertEquals( |
||||
193 | Director::baseURL() . 'newlevel1/newlevel2/newlevel3/', |
||||
194 | $response->getHeader("Location") |
||||
195 | ); |
||||
196 | } |
||||
197 | |||||
198 | public function testDoesntRedirectToNestedChildrenOutsideOfOwnHierarchy() |
||||
199 | { |
||||
200 | $this->generateNestedPagesFixture(); |
||||
201 | |||||
202 | $otherParent = SiteTree::create([ |
||||
203 | 'URLSegment' => 'otherparent', |
||||
204 | ]); |
||||
205 | $otherParent->write(); |
||||
206 | $otherParent->copyVersionToStage(Versioned::DRAFT, Versioned::LIVE); |
||||
207 | |||||
208 | $response = $this->get('level1/otherparent'); |
||||
209 | $this->assertEquals($response->getStatusCode(), 301); |
||||
210 | |||||
211 | $response = $this->get('newlevel1/otherparent'); |
||||
212 | $this->assertEquals( |
||||
213 | $response->getStatusCode(), |
||||
214 | 404, |
||||
215 | 'Requesting an unrelated page on a renamed parent should be interpreted as a missing action, not a redirect' |
||||
216 | ); |
||||
217 | } |
||||
218 | |||||
219 | /** |
||||
220 | * |
||||
221 | * NOTE: This test requires nested_urls |
||||
222 | * |
||||
223 | */ |
||||
224 | public function testRedirectsNestedRenamedPagesWithGetParameters() |
||||
225 | { |
||||
226 | $this->generateNestedPagesFixture(); |
||||
227 | |||||
228 | // check third level URLSegment |
||||
229 | $response = $this->get('newlevel1/newlevel2/level3/?foo=bar&test=test'); |
||||
230 | $this->assertEquals($response->getStatusCode(), 301); |
||||
231 | $this->assertEquals( |
||||
232 | Controller::join_links(Director::baseURL() . 'newlevel1/newlevel2/newlevel3/', '?foo=bar&test=test'), |
||||
233 | $response->getHeader('Location') |
||||
234 | ); |
||||
235 | } |
||||
236 | |||||
237 | /** |
||||
238 | * |
||||
239 | * NOTE: This test requires nested_urls |
||||
240 | * |
||||
241 | */ |
||||
242 | public function testDoesntRedirectToNestedRenamedPageWhenNewExists() |
||||
243 | { |
||||
244 | $this->generateNestedPagesFixture(); |
||||
245 | |||||
246 | $otherLevel1 = SiteTree::create([ |
||||
247 | 'Title' => "Other Level 1", |
||||
248 | 'URLSegment' => 'level1', |
||||
249 | ]); |
||||
250 | $otherLevel1->write(); |
||||
251 | $otherLevel1->copyVersionToStage(Versioned::DRAFT, Versioned::LIVE); |
||||
252 | |||||
253 | $response = $this->get('level1'); |
||||
254 | $this->assertEquals( |
||||
255 | $response->getStatusCode(), |
||||
256 | 200 |
||||
257 | ); |
||||
258 | |||||
259 | $response = $this->get('level1/newlevel2'); |
||||
260 | $this->assertEquals( |
||||
261 | $response->getStatusCode(), |
||||
262 | 404, |
||||
263 | 'The old newlevel2/ URLSegment is checked as an action on the new page, which shouldnt exist.' |
||||
264 | ); |
||||
265 | } |
||||
266 | |||||
267 | /** |
||||
268 | * |
||||
269 | * NOTE: This test requires nested_urls |
||||
270 | * |
||||
271 | */ |
||||
272 | public function testFindOldPage() |
||||
273 | { |
||||
274 | $page = SiteTree::create(); |
||||
275 | $page->Title = 'First Level'; |
||||
276 | $page->URLSegment = 'oldurl'; |
||||
277 | $page->write(); |
||||
278 | $page->copyVersionToStage(Versioned::DRAFT, Versioned::LIVE); |
||||
279 | |||||
280 | $page->URLSegment = 'newurl'; |
||||
281 | $page->write(); |
||||
282 | $page->copyVersionToStage(Versioned::DRAFT, Versioned::LIVE); |
||||
283 | |||||
284 | $url = OldPageRedirector::find_old_page('oldurl'); |
||||
0 ignored issues
–
show
'oldurl' of type string is incompatible with the type array expected by parameter $params of SilverStripe\CMS\Control...rector::find_old_page() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
285 | $matchedPage = SiteTree::get_by_link($url); |
||||
0 ignored issues
–
show
It seems like
$url can also be of type false ; however, parameter $link of SilverStripe\CMS\Model\SiteTree::get_by_link() does only seem to accept string , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
286 | $this->assertEquals('First Level', $matchedPage->Title); |
||||
287 | |||||
288 | $page2 = SiteTree::create(); |
||||
289 | $page2->Title = 'Second Level Page'; |
||||
290 | $page2->URLSegment = 'oldpage2'; |
||||
291 | $page2->ParentID = $page->ID; |
||||
292 | $page2->write(); |
||||
293 | $page2->copyVersionToStage(Versioned::DRAFT, Versioned::LIVE); |
||||
294 | |||||
295 | $page2->URLSegment = 'newpage2'; |
||||
296 | $page2->write(); |
||||
297 | $page2->copyVersionToStage(Versioned::DRAFT, Versioned::LIVE); |
||||
298 | |||||
299 | $url = OldPageRedirector::find_old_page('oldpage2', $page2->ParentID); |
||||
300 | $matchedPage = SiteTree::get_by_link($url); |
||||
301 | $this->assertEquals('Second Level Page', $matchedPage->Title); |
||||
302 | |||||
303 | $url = OldPageRedirector::find_old_page('oldpage2', $page2->ID); |
||||
304 | $matchedPage = SiteTree::get_by_link($url); |
||||
305 | $this->assertEquals(false, $matchedPage); |
||||
306 | } |
||||
307 | |||||
308 | /** |
||||
309 | * go to a page that's been published but is child of an unpublished page |
||||
310 | * |
||||
311 | * NOTE: This test requires nested_urls |
||||
312 | */ |
||||
313 | public function testChildOfDraft() |
||||
314 | { |
||||
315 | RootURLController::reset(); |
||||
316 | Config::modify()->set(SiteTree::class, 'nested_urls', true); |
||||
317 | |||||
318 | $draft = SiteTree::create(); |
||||
319 | $draft->Title = 'Root Leve Draft Page'; |
||||
320 | $draft->URLSegment = 'root'; |
||||
321 | $draft->write(); |
||||
322 | |||||
323 | $published = SiteTree::create(); |
||||
324 | $published->Title = 'Published Page Under Draft Page'; |
||||
325 | $published->URLSegment = 'sub-root'; |
||||
326 | $published->write(); |
||||
327 | $published->copyVersionToStage(Versioned::DRAFT, Versioned::LIVE); |
||||
328 | $response = $this->get('root/sub-root'); |
||||
329 | |||||
330 | $this->assertEquals( |
||||
331 | $response->getStatusCode(), |
||||
332 | 404, |
||||
333 | 'The page should not be found since its parent has not been published, in this case ' . |
||||
334 | 'http://<yousitename>/root/sub-root or http://<yousitename>/sub-root' |
||||
335 | ); |
||||
336 | } |
||||
337 | |||||
338 | public function testAllowMultibyte() |
||||
339 | { |
||||
340 | Config::modify()->set(URLSegmentFilter::class, 'default_allow_multibyte', true); |
||||
341 | |||||
342 | $parent = new Page(); |
||||
343 | $parent->Title = 'Multibyte test'; |
||||
344 | $parent->URLSegment = 'بلاگ'; |
||||
345 | $parent->write(); |
||||
346 | $parent->copyVersionToStage(Versioned::DRAFT, Versioned::LIVE); |
||||
347 | |||||
348 | $child = new Page(); |
||||
349 | $child->Title = 'Multibyte test'; |
||||
350 | $child->URLSegment = 'فضة'; |
||||
351 | $child->ParentID = $parent->ID; |
||||
352 | $child->write(); |
||||
353 | $child->copyVersionToStage(Versioned::DRAFT, Versioned::LIVE); |
||||
354 | |||||
355 | // Emulate browser behaviour around multibyte URL encodings |
||||
356 | $response = $this->get(rawurlencode('بلاگ')); |
||||
357 | $this->assertEquals( |
||||
358 | $response->getStatusCode(), |
||||
359 | 200, |
||||
360 | 'Routes toplevel paths' |
||||
361 | ); |
||||
362 | |||||
363 | $response = $this->get(join('/', [rawurlencode('بلاگ'), rawurlencode('فضة')])); |
||||
364 | $this->assertEquals( |
||||
365 | $response->getStatusCode(), |
||||
366 | 200, |
||||
367 | 'Routes nested paths' |
||||
368 | ); |
||||
369 | } |
||||
370 | } |
||||
371 |
The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g.
excluded_paths: ["lib/*"]
, you can move it to the dependency path list as follows:For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths