1 | <?php |
||||
2 | |||||
3 | namespace SilverStripe\CMS\Tests\Model; |
||||
4 | |||||
5 | use LogicException; |
||||
6 | use Page; |
||||
0 ignored issues
–
show
|
|||||
7 | use ReflectionMethod; |
||||
8 | use SilverStripe\CMS\Model\RedirectorPage; |
||||
9 | use SilverStripe\CMS\Model\SiteTree; |
||||
10 | use SilverStripe\CMS\Model\VirtualPage; |
||||
11 | use SilverStripe\Control\ContentNegotiator; |
||||
12 | use SilverStripe\Control\Controller; |
||||
13 | use SilverStripe\Control\Director; |
||||
14 | use SilverStripe\Core\Config\Config; |
||||
15 | use SilverStripe\Core\Injector\Injector; |
||||
16 | use SilverStripe\Core\Manifest\ManifestFileFinder; |
||||
17 | use SilverStripe\Dev\SapphireTest; |
||||
18 | use SilverStripe\i18n\i18n; |
||||
19 | use SilverStripe\ORM\DataObject; |
||||
20 | use SilverStripe\ORM\DB; |
||||
21 | use SilverStripe\ORM\FieldType\DBDatetime; |
||||
22 | use SilverStripe\ORM\ValidationException; |
||||
23 | use SilverStripe\Security\Group; |
||||
24 | use SilverStripe\Security\InheritedPermissions; |
||||
25 | use SilverStripe\Security\Member; |
||||
26 | use SilverStripe\Security\Permission; |
||||
27 | use SilverStripe\Security\Security; |
||||
28 | use SilverStripe\SiteConfig\SiteConfig; |
||||
29 | use SilverStripe\Subsites\Extensions\SiteTreeSubsites; |
||||
0 ignored issues
–
show
The type
SilverStripe\Subsites\Extensions\SiteTreeSubsites was not found. Maybe you did not declare it correctly or list all dependencies?
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. filter:
dependency_paths: ["lib/*"]
For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths ![]() |
|||||
30 | use SilverStripe\Versioned\Versioned; |
||||
31 | use SilverStripe\View\Parsers\Diff; |
||||
32 | use SilverStripe\View\Parsers\ShortcodeParser; |
||||
33 | use SilverStripe\View\Parsers\URLSegmentFilter; |
||||
34 | use TractorCow\Fluent\Extension\FluentSiteTreeExtension; |
||||
0 ignored issues
–
show
The type
TractorCow\Fluent\Extens...FluentSiteTreeExtension was not found. Maybe you did not declare it correctly or list all dependencies?
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. filter:
dependency_paths: ["lib/*"]
For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths ![]() |
|||||
35 | use const ASSETS_DIR; |
||||
36 | |||||
37 | class SiteTreeTest extends SapphireTest |
||||
38 | { |
||||
39 | protected static $fixture_file = 'SiteTreeTest.yml'; |
||||
40 | |||||
41 | protected static $illegal_extensions = [ |
||||
42 | SiteTree::class => [ |
||||
43 | SiteTreeSubsites::class, |
||||
44 | FluentSiteTreeExtension::class, |
||||
45 | ], |
||||
46 | ]; |
||||
47 | |||||
48 | protected static $extra_dataobjects = [ |
||||
49 | SiteTreeTest_ClassA::class, |
||||
50 | SiteTreeTest_ClassB::class, |
||||
51 | SiteTreeTest_ClassC::class, |
||||
52 | SiteTreeTest_ClassD::class, |
||||
53 | SiteTreeTest_ClassCext::class, |
||||
54 | SiteTreeTest_NotRoot::class, |
||||
55 | SiteTreeTest_StageStatusInherit::class, |
||||
56 | SiteTreeTest_DataObject::class, |
||||
57 | ]; |
||||
58 | |||||
59 | public function reservedSegmentsProvider() |
||||
60 | { |
||||
61 | return [ |
||||
62 | // segments reserved by rules |
||||
63 | ['Admin', 'admin-2'], |
||||
64 | ['Dev', 'dev-2'], |
||||
65 | ['Robots in disguise', 'robots-in-disguise'], |
||||
66 | // segments reserved by folder name |
||||
67 | [ASSETS_DIR, ASSETS_DIR . '-2'], |
||||
68 | ['notafoldername', 'notafoldername'], |
||||
69 | ]; |
||||
70 | } |
||||
71 | |||||
72 | public function testCreateDefaultpages() |
||||
73 | { |
||||
74 | $remove = SiteTree::get(); |
||||
75 | if ($remove) { |
||||
0 ignored issues
–
show
|
|||||
76 | foreach ($remove as $page) { |
||||
77 | $page->delete(); |
||||
78 | } |
||||
79 | } |
||||
80 | // Make sure the table is empty |
||||
81 | $this->assertEquals(DB::query('SELECT COUNT("ID") FROM "SiteTree"')->value(), 0); |
||||
82 | |||||
83 | // Disable the creation |
||||
84 | SiteTree::config()->create_default_pages = false; |
||||
85 | singleton(SiteTree::class)->requireDefaultRecords(); |
||||
86 | |||||
87 | // The table should still be empty |
||||
88 | $this->assertEquals(DB::query('SELECT COUNT("ID") FROM "SiteTree"')->value(), 0); |
||||
89 | |||||
90 | // Enable the creation |
||||
91 | SiteTree::config()->create_default_pages = true; |
||||
92 | singleton(SiteTree::class)->requireDefaultRecords(); |
||||
93 | |||||
94 | // The table should now have three rows (home, about-us, contact-us) |
||||
95 | $this->assertEquals(DB::query('SELECT COUNT("ID") FROM "SiteTree"')->value(), 3); |
||||
96 | } |
||||
97 | |||||
98 | /** |
||||
99 | * Test generation of the URLSegment values. |
||||
100 | * - Turns things into lowercase-hyphen-format |
||||
101 | * - Generates from Title by default, unless URLSegment is explicitly set |
||||
102 | * - Resolves duplicates by appending a number |
||||
103 | * - renames classes with a class name conflict |
||||
104 | */ |
||||
105 | public function testURLGeneration() |
||||
106 | { |
||||
107 | $expectedURLs = [ |
||||
108 | 'home' => 'home', |
||||
109 | 'staff' => 'my-staff', |
||||
110 | 'about' => 'about-us', |
||||
111 | 'staffduplicate' => 'my-staff-2', |
||||
112 | 'product1' => '1-1-test-product', |
||||
113 | 'product2' => 'another-product', |
||||
114 | 'product3' => 'another-product-2', |
||||
115 | 'product4' => 'another-product-3', |
||||
116 | 'object' => 'object', |
||||
117 | 'controller' => 'controller', |
||||
118 | 'numericonly' => '1930', |
||||
119 | ]; |
||||
120 | |||||
121 | foreach ($expectedURLs as $fixture => $urlSegment) { |
||||
122 | $obj = $this->objFromFixture(SiteTree::class, $fixture); |
||||
123 | $this->assertEquals($urlSegment, $obj->URLSegment); |
||||
124 | } |
||||
125 | } |
||||
126 | |||||
127 | /** |
||||
128 | * Check if reserved URL's are properly appended with a number at top level |
||||
129 | * @dataProvider reservedSegmentsProvider |
||||
130 | */ |
||||
131 | public function testDisallowedURLGeneration($title, $urlSegment) |
||||
132 | { |
||||
133 | $page = SiteTree::create(['Title' => $title]); |
||||
134 | $id = $page->write(); |
||||
135 | $page = SiteTree::get()->byID($id); |
||||
136 | $this->assertEquals($urlSegment, $page->URLSegment); |
||||
137 | } |
||||
138 | |||||
139 | /** |
||||
140 | * Check if reserved URL's are not appended with a number on a child page |
||||
141 | * It's okay to have a URL like domain.com/my-page/admin as it won't interfere with domain.com/admin |
||||
142 | * @dataProvider reservedSegmentsProvider |
||||
143 | */ |
||||
144 | public function testDisallowedChildURLGeneration($title, $urlSegment) |
||||
145 | { |
||||
146 | Config::modify()->set(SiteTree::class, 'nested_urls', true); |
||||
147 | // Using the same dataprovider, strip out the -2 from the admin and dev segment |
||||
148 | $urlSegment = str_replace('-2', '', $urlSegment); |
||||
149 | $page = SiteTree::create(['Title' => $title, 'ParentID' => 1]); |
||||
150 | $id = $page->write(); |
||||
151 | $page = SiteTree::get()->byID($id); |
||||
152 | $this->assertEquals($urlSegment, $page->URLSegment); |
||||
153 | } |
||||
154 | |||||
155 | /** |
||||
156 | * Check that explicitly setting a URL segment to the resources dir will rename it to have a -2 suffix |
||||
157 | */ |
||||
158 | public function testExplicitlyUsingResourcesDirForURLSegment() |
||||
159 | { |
||||
160 | $page = SiteTree::create(['URLSegment' => ManifestFileFinder::RESOURCES_DIR]); |
||||
0 ignored issues
–
show
The constant
SilverStripe\Core\Manife...leFinder::RESOURCES_DIR has been deprecated: 4.4.0:5.0.0 Use global `RESOURCES_DIR` instead.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This class constant 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 constant will be removed from the class and what other constant to use instead. ![]() |
|||||
161 | $id = $page->write(); |
||||
162 | $page = SiteTree::get()->byID($id); |
||||
163 | $this->assertSame(ManifestFileFinder::RESOURCES_DIR . '-2', $page->URLSegment); |
||||
0 ignored issues
–
show
The constant
SilverStripe\Core\Manife...leFinder::RESOURCES_DIR has been deprecated: 4.4.0:5.0.0 Use global `RESOURCES_DIR` instead.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This class constant 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 constant will be removed from the class and what other constant to use instead. ![]() |
|||||
164 | } |
||||
165 | |||||
166 | /** |
||||
167 | * For legacy resources dir values ("resources"), check that URLSegments get a -2 appended |
||||
168 | */ |
||||
169 | public function testLegacyResourcesDirValuesHaveIncrementedValueAppended() |
||||
170 | { |
||||
171 | if (ManifestFileFinder::RESOURCES_DIR !== 'resources') { |
||||
0 ignored issues
–
show
The constant
SilverStripe\Core\Manife...leFinder::RESOURCES_DIR has been deprecated: 4.4.0:5.0.0 Use global `RESOURCES_DIR` instead.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This class constant 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 constant will be removed from the class and what other constant to use instead. ![]() |
|||||
172 | $this->markTestSkipped('This legacy test requires RESOURCES_DIR to be "resources"'); |
||||
173 | } |
||||
174 | |||||
175 | $page = SiteTree::create(['Title' => 'Resources']); |
||||
176 | $id = $page->write(); |
||||
177 | $page = SiteTree::get()->byID($id); |
||||
178 | $this->assertSame('resources-2', $page->URLSegment); |
||||
179 | } |
||||
180 | |||||
181 | /** |
||||
182 | * For new/configured resources dir values ("_resources"), check that URLSegments have the leading underscore |
||||
183 | * removed |
||||
184 | */ |
||||
185 | public function testDefaultResourcesDirHasLeadingUnderscoreRemovedAndResourcesIsUsed() |
||||
186 | { |
||||
187 | if (ManifestFileFinder::RESOURCES_DIR === 'resources') { |
||||
0 ignored issues
–
show
The constant
SilverStripe\Core\Manife...leFinder::RESOURCES_DIR has been deprecated: 4.4.0:5.0.0 Use global `RESOURCES_DIR` instead.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This class constant 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 constant will be removed from the class and what other constant to use instead. ![]() |
|||||
188 | $this->markTestSkipped('This test requires RESOURCES_DIR to be something other than "resources"'); |
||||
189 | } |
||||
190 | |||||
191 | $page = SiteTree::create(['Title' => '_Resources']); |
||||
192 | $id = $page->write(); |
||||
193 | $page = SiteTree::get()->byID($id); |
||||
194 | $this->assertSame('resources', $page->URLSegment); |
||||
195 | } |
||||
196 | |||||
197 | /** |
||||
198 | * Test that publication copies data to SiteTree_Live |
||||
199 | */ |
||||
200 | public function testPublishCopiesToLiveTable() |
||||
201 | { |
||||
202 | $obj = $this->objFromFixture(SiteTree::class, 'about'); |
||||
203 | $obj->copyVersionToStage(Versioned::DRAFT, Versioned::LIVE); |
||||
204 | |||||
205 | $createdID = DB::query( |
||||
206 | "SELECT \"ID\" FROM \"SiteTree_Live\" WHERE \"URLSegment\" = '$obj->URLSegment'" |
||||
207 | )->value(); |
||||
208 | $this->assertEquals($obj->ID, $createdID); |
||||
209 | } |
||||
210 | |||||
211 | /** |
||||
212 | * Test that field which are set and then cleared are also transferred to the published site. |
||||
213 | */ |
||||
214 | public function testPublishDeletedFields() |
||||
215 | { |
||||
216 | $this->logInWithPermission('ADMIN'); |
||||
217 | |||||
218 | $obj = $this->objFromFixture(SiteTree::class, 'about'); |
||||
219 | $obj->Title = "asdfasdf"; |
||||
220 | $obj->write(); |
||||
221 | $this->assertTrue($obj->publishRecursive()); |
||||
222 | |||||
223 | $this->assertEquals( |
||||
224 | 'asdfasdf', |
||||
225 | DB::query("SELECT \"Title\" FROM \"SiteTree_Live\" WHERE \"ID\" = '$obj->ID'")->value() |
||||
226 | ); |
||||
227 | |||||
228 | $obj->Title = null; |
||||
229 | $obj->write(); |
||||
230 | $this->assertTrue($obj->publishRecursive()); |
||||
231 | |||||
232 | $this->assertNotNull(DB::query("SELECT \"Title\" FROM \"SiteTree_Live\" WHERE \"ID\" = '$obj->ID'")->value()); |
||||
233 | } |
||||
234 | |||||
235 | public function testParentNodeCachedInMemory() |
||||
236 | { |
||||
237 | $parent = SiteTree::create(); |
||||
238 | $parent->Title = 'Section Title'; |
||||
239 | $child = SiteTree::create(); |
||||
240 | $child->Title = 'Page Title'; |
||||
241 | $child->setParent($parent); |
||||
242 | |||||
243 | $this->assertInstanceOf(SiteTree::class, $child->Parent); |
||||
244 | $this->assertEquals("Section Title", $child->Parent->Title); |
||||
245 | } |
||||
246 | |||||
247 | public function testParentModelReturnType() |
||||
248 | { |
||||
249 | $parent = new SiteTreeTest_PageNode(); |
||||
250 | $child = new SiteTreeTest_PageNode(); |
||||
251 | |||||
252 | $child->setParent($parent); |
||||
253 | $this->assertInstanceOf(SiteTreeTest_PageNode::class, $child->Parent); |
||||
0 ignored issues
–
show
The property
Parent does not exist on SilverStripe\CMS\Tests\Model\SiteTreeTest_PageNode . Since you implemented __get , consider adding a @property annotation.
![]() |
|||||
254 | } |
||||
255 | |||||
256 | /** |
||||
257 | * Confirm that DataObject::get_one() gets records from SiteTree_Live |
||||
258 | */ |
||||
259 | public function testGetOneFromLive() |
||||
260 | { |
||||
261 | $s = SiteTree::create(); |
||||
262 | $s->Title = "V1"; |
||||
263 | $s->URLSegment = "get-one-test-page"; |
||||
264 | $s->write(); |
||||
265 | $s->copyVersionToStage(Versioned::DRAFT, Versioned::LIVE); |
||||
266 | $s->Title = "V2"; |
||||
267 | $s->write(); |
||||
268 | |||||
269 | $oldMode = Versioned::get_reading_mode(); |
||||
270 | Versioned::set_stage(Versioned::LIVE); |
||||
271 | |||||
272 | $checkSiteTree = DataObject::get_one(SiteTree::class, [ |
||||
273 | '"SiteTree"."URLSegment"' => 'get-one-test-page', |
||||
274 | ]); |
||||
275 | $this->assertEquals("V1", $checkSiteTree->Title); |
||||
276 | |||||
277 | Versioned::set_reading_mode($oldMode); |
||||
278 | } |
||||
279 | |||||
280 | public function testChidrenOfRootAreTopLevelPages() |
||||
281 | { |
||||
282 | $pages = SiteTree::get(); |
||||
283 | foreach ($pages as $page) { |
||||
284 | $page->copyVersionToStage(Versioned::DRAFT, Versioned::LIVE); |
||||
285 | } |
||||
286 | unset($pages); |
||||
287 | |||||
288 | /* If we create a new SiteTree object with ID = 0 */ |
||||
289 | $obj = SiteTree::create(); |
||||
290 | /* Then its children should be the top-level pages */ |
||||
291 | $stageChildren = $obj->stageChildren()->map('ID', 'Title'); |
||||
292 | $liveChildren = $obj->liveChildren()->map('ID', 'Title'); |
||||
293 | $allChildren = $obj->AllChildrenIncludingDeleted()->map('ID', 'Title'); |
||||
294 | |||||
295 | $this->assertContains('Home', $stageChildren); |
||||
296 | $this->assertContains('Products', $stageChildren); |
||||
297 | $this->assertNotContains('Staff', $stageChildren); |
||||
298 | |||||
299 | $this->assertContains('Home', $liveChildren); |
||||
300 | $this->assertContains('Products', $liveChildren); |
||||
301 | $this->assertNotContains('Staff', $liveChildren); |
||||
302 | |||||
303 | $this->assertContains('Home', $allChildren); |
||||
304 | $this->assertContains('Products', $allChildren); |
||||
305 | $this->assertNotContains('Staff', $allChildren); |
||||
306 | } |
||||
307 | |||||
308 | public function testCanSaveBlankToHasOneRelations() |
||||
309 | { |
||||
310 | /* DataObject::write() should save to a has_one relationship if you set a field called (relname)ID */ |
||||
311 | $page = SiteTree::create(); |
||||
312 | $parentID = $this->idFromFixture(SiteTree::class, 'home'); |
||||
313 | $page->ParentID = $parentID; |
||||
314 | $page->write(); |
||||
315 | $this->assertEquals( |
||||
316 | $parentID, |
||||
317 | DB::query("SELECT \"ParentID\" FROM \"SiteTree\" WHERE \"ID\" = $page->ID")->value() |
||||
318 | ); |
||||
319 | |||||
320 | /* You should then be able to save a null/0/'' value to the relation */ |
||||
321 | $page->ParentID = null; |
||||
322 | $page->write(); |
||||
323 | $this->assertEquals(0, DB::query("SELECT \"ParentID\" FROM \"SiteTree\" WHERE \"ID\" = $page->ID")->value()); |
||||
324 | } |
||||
325 | |||||
326 | public function testStageStates() |
||||
327 | { |
||||
328 | // newly created page |
||||
329 | $createdPage = SiteTree::create(); |
||||
330 | $createdPage->write(); |
||||
331 | $this->assertTrue($createdPage->isOnDraft()); |
||||
332 | $this->assertFalse($createdPage->isPublished()); |
||||
333 | $this->assertTrue($createdPage->isOnDraftOnly()); |
||||
334 | $this->assertTrue($createdPage->isModifiedOnDraft()); |
||||
335 | |||||
336 | // published page |
||||
337 | $publishedPage = SiteTree::create(); |
||||
338 | $publishedPage->write(); |
||||
339 | $publishedPage->copyVersionToStage('Stage', 'Live'); |
||||
340 | $this->assertTrue($publishedPage->isOnDraft()); |
||||
341 | $this->assertTrue($publishedPage->isPublished()); |
||||
342 | $this->assertFalse($publishedPage->isOnDraftOnly()); |
||||
343 | $this->assertFalse($publishedPage->isOnLiveOnly()); |
||||
344 | $this->assertFalse($publishedPage->isModifiedOnDraft()); |
||||
345 | |||||
346 | // published page, deleted from stage |
||||
347 | $deletedFromDraftPage = SiteTree::create(); |
||||
348 | $deletedFromDraftPage->write(); |
||||
349 | $deletedFromDraftPage->copyVersionToStage('Stage', 'Live'); |
||||
350 | $deletedFromDraftPage->deleteFromStage('Stage'); |
||||
351 | $this->assertFalse($deletedFromDraftPage->isArchived()); |
||||
352 | $this->assertFalse($deletedFromDraftPage->isOnDraft()); |
||||
353 | $this->assertTrue($deletedFromDraftPage->isPublished()); |
||||
354 | $this->assertFalse($deletedFromDraftPage->isOnDraftOnly()); |
||||
355 | $this->assertTrue($deletedFromDraftPage->isOnLiveOnly()); |
||||
356 | $this->assertFalse($deletedFromDraftPage->isModifiedOnDraft()); |
||||
357 | |||||
358 | // published page, deleted from live |
||||
359 | $deletedFromLivePage = SiteTree::create(); |
||||
360 | $deletedFromLivePage->write(); |
||||
361 | $deletedFromLivePage->copyVersionToStage('Stage', 'Live'); |
||||
362 | $deletedFromLivePage->deleteFromStage('Live'); |
||||
363 | $this->assertFalse($deletedFromLivePage->isArchived()); |
||||
364 | $this->assertTrue($deletedFromLivePage->isOnDraft()); |
||||
365 | $this->assertFalse($deletedFromLivePage->isPublished()); |
||||
366 | $this->assertTrue($deletedFromLivePage->isOnDraftOnly()); |
||||
367 | $this->assertFalse($deletedFromLivePage->isOnLiveOnly()); |
||||
368 | $this->assertTrue($deletedFromLivePage->isModifiedOnDraft()); |
||||
369 | |||||
370 | // published page, deleted from both stages |
||||
371 | $deletedFromAllStagesPage = SiteTree::create(); |
||||
372 | $deletedFromAllStagesPage->write(); |
||||
373 | $deletedFromAllStagesPage->copyVersionToStage('Stage', 'Live'); |
||||
374 | $deletedFromAllStagesPage->deleteFromStage('Stage'); |
||||
375 | $deletedFromAllStagesPage->deleteFromStage('Live'); |
||||
376 | $this->assertTrue($deletedFromAllStagesPage->isArchived()); |
||||
377 | $this->assertFalse($deletedFromAllStagesPage->isOnDraft()); |
||||
378 | $this->assertFalse($deletedFromAllStagesPage->isPublished()); |
||||
379 | $this->assertFalse($deletedFromAllStagesPage->isOnDraftOnly()); |
||||
380 | $this->assertFalse($deletedFromAllStagesPage->isOnLiveOnly()); |
||||
381 | $this->assertFalse($deletedFromAllStagesPage->isModifiedOnDraft()); |
||||
382 | |||||
383 | // published page, modified |
||||
384 | $modifiedOnDraftPage = SiteTree::create(); |
||||
385 | $modifiedOnDraftPage->write(); |
||||
386 | $modifiedOnDraftPage->copyVersionToStage('Stage', 'Live'); |
||||
387 | $modifiedOnDraftPage->Content = 'modified'; |
||||
388 | $modifiedOnDraftPage->write(); |
||||
389 | $this->assertFalse($modifiedOnDraftPage->isArchived()); |
||||
390 | $this->assertTrue($modifiedOnDraftPage->isOnDraft()); |
||||
391 | $this->assertTrue($modifiedOnDraftPage->isPublished()); |
||||
392 | $this->assertFalse($modifiedOnDraftPage->isOnDraftOnly()); |
||||
393 | $this->assertFalse($modifiedOnDraftPage->isOnLiveOnly()); |
||||
394 | $this->assertTrue($modifiedOnDraftPage->isModifiedOnDraft()); |
||||
395 | } |
||||
396 | |||||
397 | /** |
||||
398 | * Test that a page can be completely deleted and restored to the stage site |
||||
399 | */ |
||||
400 | public function testRestoreToStage() |
||||
401 | { |
||||
402 | $page = $this->objFromFixture(SiteTree::class, 'about'); |
||||
403 | $pageID = $page->ID; |
||||
404 | $page->delete(); |
||||
405 | $this->assertTrue(!DataObject::get_by_id(SiteTree::class, $pageID)); |
||||
406 | |||||
407 | $deletedPage = Versioned::get_latest_version(SiteTree::class, $pageID); |
||||
408 | $resultPage = $deletedPage->doRestoreToStage(); |
||||
409 | |||||
410 | $requeriedPage = DataObject::get_by_id(SiteTree::class, $pageID); |
||||
411 | |||||
412 | $this->assertEquals($pageID, $resultPage->ID); |
||||
413 | $this->assertEquals($pageID, $requeriedPage->ID); |
||||
414 | $this->assertEquals('About Us', $requeriedPage->Title); |
||||
415 | $this->assertInstanceOf(SiteTree::class, $requeriedPage); |
||||
416 | |||||
417 | |||||
418 | $page2 = $this->objFromFixture(SiteTree::class, 'products'); |
||||
419 | $page2ID = $page2->ID; |
||||
420 | $page2->doUnpublish(); |
||||
421 | $page2->delete(); |
||||
422 | |||||
423 | // Check that if we restore while on the live site that the content still gets pushed to |
||||
424 | // stage |
||||
425 | Versioned::set_stage(Versioned::LIVE); |
||||
426 | $deletedPage = Versioned::get_latest_version(SiteTree::class, $page2ID); |
||||
427 | $deletedPage->doRestoreToStage(); |
||||
428 | $this->assertFalse( |
||||
429 | (bool)Versioned::get_one_by_stage(SiteTree::class, Versioned::LIVE, "\"SiteTree\".\"ID\" = " . $page2ID) |
||||
430 | ); |
||||
431 | |||||
432 | Versioned::set_stage(Versioned::DRAFT); |
||||
433 | $requeriedPage = DataObject::get_by_id(SiteTree::class, $page2ID); |
||||
434 | $this->assertEquals('Products', $requeriedPage->Title); |
||||
435 | $this->assertInstanceOf(SiteTree::class, $requeriedPage); |
||||
436 | } |
||||
437 | |||||
438 | public function testNoCascadingDeleteWithoutID() |
||||
439 | { |
||||
440 | Config::inst()->update('SiteTree', 'enforce_strict_hierarchy', true); |
||||
0 ignored issues
–
show
The method
update() does not exist on SilverStripe\Config\Coll...nfigCollectionInterface . It seems like you code against a sub-type of said class. However, the method does not exist in SilverStripe\Config\Coll...nfigCollectionInterface . Are you sure you never get one of those?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
441 | $count = SiteTree::get()->count(); |
||||
442 | $this->assertNotEmpty($count); |
||||
443 | $obj = SiteTree::create(); |
||||
444 | $this->assertFalse($obj->exists()); |
||||
445 | $fail = true; |
||||
446 | try { |
||||
447 | $obj->delete(); |
||||
448 | } catch (LogicException $e) { |
||||
449 | $fail = false; |
||||
450 | } |
||||
451 | if ($fail) { |
||||
452 | $this->fail('Failed to throw delete exception'); |
||||
453 | } |
||||
454 | $this->assertCount($count, SiteTree::get()); |
||||
455 | } |
||||
456 | |||||
457 | public function testGetByLink() |
||||
458 | { |
||||
459 | $home = $this->objFromFixture(SiteTree::class, 'home'); |
||||
460 | $about = $this->objFromFixture(SiteTree::class, 'about'); |
||||
461 | $staff = $this->objFromFixture(SiteTree::class, 'staff'); |
||||
462 | $product = $this->objFromFixture(SiteTree::class, 'product1'); |
||||
463 | |||||
464 | SiteTree::config()->nested_urls = false; |
||||
465 | |||||
466 | $this->assertEquals($home->ID, SiteTree::get_by_link('/', false)->ID); |
||||
467 | $this->assertEquals($home->ID, SiteTree::get_by_link('/home/', false)->ID); |
||||
468 | $this->assertEquals($about->ID, SiteTree::get_by_link($about->Link(), false)->ID); |
||||
469 | $this->assertEquals($staff->ID, SiteTree::get_by_link($staff->Link(), false)->ID); |
||||
470 | $this->assertEquals($product->ID, SiteTree::get_by_link($product->Link(), false)->ID); |
||||
471 | |||||
472 | Config::modify()->set(SiteTree::class, 'nested_urls', true); |
||||
473 | |||||
474 | $this->assertEquals($home->ID, SiteTree::get_by_link('/', false)->ID); |
||||
475 | $this->assertEquals($home->ID, SiteTree::get_by_link('/home/', false)->ID); |
||||
476 | $this->assertEquals($about->ID, SiteTree::get_by_link($about->Link(), false)->ID); |
||||
477 | $this->assertEquals($staff->ID, SiteTree::get_by_link($staff->Link(), false)->ID); |
||||
478 | $this->assertEquals($product->ID, SiteTree::get_by_link($product->Link(), false)->ID); |
||||
479 | |||||
480 | $this->assertEquals( |
||||
481 | $staff->ID, |
||||
482 | SiteTree::get_by_link('/my-staff/', false)->ID, |
||||
483 | 'Assert a unique URLSegment can be used for b/c.' |
||||
484 | ); |
||||
485 | } |
||||
486 | |||||
487 | public function testRelativeLink() |
||||
488 | { |
||||
489 | $about = $this->objFromFixture(SiteTree::class, 'about'); |
||||
490 | $staff = $this->objFromFixture(SiteTree::class, 'staff'); |
||||
491 | |||||
492 | Config::modify()->set(SiteTree::class, 'nested_urls', true); |
||||
493 | |||||
494 | $this->assertEquals( |
||||
495 | 'about-us/', |
||||
496 | $about->RelativeLink(), |
||||
497 | 'Matches URLSegment on top level without parameters' |
||||
498 | ); |
||||
499 | $this->assertEquals( |
||||
500 | 'about-us/my-staff/', |
||||
501 | $staff->RelativeLink(), |
||||
502 | 'Matches URLSegment plus parent on second level without parameters' |
||||
503 | ); |
||||
504 | $this->assertEquals( |
||||
505 | 'about-us/edit', |
||||
506 | $about->RelativeLink('edit'), |
||||
507 | 'Matches URLSegment plus parameter on top level' |
||||
508 | ); |
||||
509 | $this->assertEquals( |
||||
510 | 'about-us/tom&jerry', |
||||
511 | $about->RelativeLink('tom&jerry'), |
||||
512 | 'Doesnt url encode parameter' |
||||
513 | ); |
||||
514 | } |
||||
515 | |||||
516 | public function testPageLevel() |
||||
517 | { |
||||
518 | $about = $this->objFromFixture(SiteTree::class, 'about'); |
||||
519 | $staff = $this->objFromFixture(SiteTree::class, 'staff'); |
||||
520 | $this->assertEquals(1, $about->getPageLevel()); |
||||
521 | $this->assertEquals(2, $staff->getPageLevel()); |
||||
522 | } |
||||
523 | |||||
524 | public function testAbsoluteLiveLink() |
||||
525 | { |
||||
526 | $parent = $this->objFromFixture(SiteTree::class, 'about'); |
||||
527 | $child = $this->objFromFixture(SiteTree::class, 'staff'); |
||||
528 | |||||
529 | Config::modify()->set(SiteTree::class, 'nested_urls', true); |
||||
530 | |||||
531 | $child->copyVersionToStage(Versioned::DRAFT, Versioned::LIVE); |
||||
532 | $parent->URLSegment = 'changed-on-live'; |
||||
533 | $parent->write(); |
||||
534 | $parent->copyVersionToStage(Versioned::DRAFT, Versioned::LIVE); |
||||
535 | $parent->URLSegment = 'changed-on-draft'; |
||||
536 | $parent->write(); |
||||
537 | |||||
538 | $this->assertStringEndsWith('changed-on-live/my-staff/', $child->getAbsoluteLiveLink(false)); |
||||
539 | $this->assertStringEndsWith('changed-on-live/my-staff/?stage=Live', $child->getAbsoluteLiveLink()); |
||||
540 | } |
||||
541 | |||||
542 | public function testDuplicateChildrenRetainSort() |
||||
543 | { |
||||
544 | $parent = SiteTree::create(); |
||||
545 | $parent->Title = 'Parent'; |
||||
546 | $parent->write(); |
||||
547 | |||||
548 | $child1 = SiteTree::create(); |
||||
549 | $child1->ParentID = $parent->ID; |
||||
550 | $child1->Title = 'Child 1'; |
||||
551 | $child1->Sort = 2; |
||||
552 | $child1->write(); |
||||
553 | |||||
554 | $child2 = SiteTree::create(); |
||||
555 | $child2->ParentID = $parent->ID; |
||||
556 | $child2->Title = 'Child 2'; |
||||
557 | $child2->Sort = 1; |
||||
558 | $child2->write(); |
||||
559 | |||||
560 | $duplicateParent = $parent->duplicateWithChildren(); |
||||
561 | $duplicateChildren = $duplicateParent->AllChildren()->toArray(); |
||||
562 | $this->assertCount(2, $duplicateChildren); |
||||
563 | |||||
564 | $duplicateChild2 = array_shift($duplicateChildren); |
||||
565 | $duplicateChild1 = array_shift($duplicateChildren); |
||||
566 | |||||
567 | |||||
568 | $this->assertEquals('Child 1', $duplicateChild1->Title); |
||||
569 | $this->assertEquals('Child 2', $duplicateChild2->Title); |
||||
570 | |||||
571 | // assertGreaterThan works by having the LOWER value first |
||||
572 | $this->assertGreaterThan($duplicateChild2->Sort, $duplicateChild1->Sort); |
||||
573 | } |
||||
574 | |||||
575 | public function testDeleteFromStageOperatesRecursively() |
||||
576 | { |
||||
577 | Config::modify()->set(SiteTree::class, 'enforce_strict_hierarchy', false); |
||||
578 | $pageAbout = $this->objFromFixture(SiteTree::class, 'about'); |
||||
579 | $pageStaff = $this->objFromFixture(SiteTree::class, 'staff'); |
||||
580 | $pageStaffDuplicate = $this->objFromFixture(SiteTree::class, 'staffduplicate'); |
||||
581 | |||||
582 | $pageAbout->delete(); |
||||
583 | |||||
584 | $this->assertNull(DataObject::get_by_id(SiteTree::class, $pageAbout->ID)); |
||||
585 | $this->assertTrue(DataObject::get_by_id(SiteTree::class, $pageStaff->ID) instanceof SiteTree); |
||||
586 | $this->assertTrue(DataObject::get_by_id(SiteTree::class, $pageStaffDuplicate->ID) instanceof SiteTree); |
||||
587 | Config::modify()->set(SiteTree::class, 'enforce_strict_hierarchy', true); |
||||
588 | } |
||||
589 | |||||
590 | public function testDeleteFromStageOperatesRecursivelyStrict() |
||||
591 | { |
||||
592 | Config::modify()->set(SiteTree::class, 'enforce_strict_hierarchy', true); |
||||
593 | $pageAbout = $this->objFromFixture(SiteTree::class, 'about'); |
||||
594 | $pageStaff = $this->objFromFixture(SiteTree::class, 'staff'); |
||||
595 | $pageStaffDuplicate = $this->objFromFixture(SiteTree::class, 'staffduplicate'); |
||||
596 | |||||
597 | $pageAbout->delete(); |
||||
598 | |||||
599 | $this->assertNull(DataObject::get_by_id(SiteTree::class, $pageAbout->ID)); |
||||
600 | $this->assertNull(DataObject::get_by_id(SiteTree::class, $pageStaff->ID)); |
||||
601 | $this->assertNull(DataObject::get_by_id(SiteTree::class, $pageStaffDuplicate->ID)); |
||||
602 | } |
||||
603 | |||||
604 | public function testDuplicate() |
||||
605 | { |
||||
606 | $pageAbout = $this->objFromFixture(SiteTree::class, 'about'); |
||||
607 | $dupe = $pageAbout->duplicate(); |
||||
608 | $this->assertEquals($pageAbout->Title, $dupe->Title); |
||||
609 | $this->assertNotEquals($pageAbout->URLSegment, $dupe->URLSegment); |
||||
610 | $this->assertNotEquals($pageAbout->Sort, $dupe->Sort); |
||||
611 | } |
||||
612 | |||||
613 | public function testDeleteFromLiveOperatesRecursively() |
||||
614 | { |
||||
615 | Config::modify()->set(SiteTree::class, 'enforce_strict_hierarchy', false); |
||||
616 | $this->logInWithPermission('ADMIN'); |
||||
617 | |||||
618 | $pageAbout = $this->objFromFixture(SiteTree::class, 'about'); |
||||
619 | $pageAbout->publishRecursive(); |
||||
620 | $pageStaff = $this->objFromFixture(SiteTree::class, 'staff'); |
||||
621 | $pageStaff->publishRecursive(); |
||||
622 | $pageStaffDuplicate = $this->objFromFixture(SiteTree::class, 'staffduplicate'); |
||||
623 | $pageStaffDuplicate->publishRecursive(); |
||||
624 | |||||
625 | $parentPage = $this->objFromFixture(SiteTree::class, 'about'); |
||||
626 | |||||
627 | $parentPage->doUnpublish(); |
||||
628 | |||||
629 | Versioned::set_stage(Versioned::LIVE); |
||||
630 | |||||
631 | $this->assertNull(DataObject::get_by_id(SiteTree::class, $pageAbout->ID)); |
||||
632 | $this->assertTrue(DataObject::get_by_id(SiteTree::class, $pageStaff->ID) instanceof SiteTree); |
||||
633 | $this->assertTrue(DataObject::get_by_id(SiteTree::class, $pageStaffDuplicate->ID) instanceof SiteTree); |
||||
634 | Versioned::set_stage(Versioned::DRAFT); |
||||
635 | Config::modify()->set(SiteTree::class, 'enforce_strict_hierarchy', true); |
||||
636 | } |
||||
637 | |||||
638 | public function testUnpublishDoesNotDeleteChildrenWithLooseHierachyOn() |
||||
639 | { |
||||
640 | Config::modify()->set(SiteTree::class, 'enforce_strict_hierarchy', false); |
||||
641 | $this->logInWithPermission('ADMIN'); |
||||
642 | |||||
643 | $pageAbout = $this->objFromFixture(SiteTree::class, 'about'); |
||||
644 | $pageAbout->publishRecursive(); |
||||
645 | $pageStaff = $this->objFromFixture(SiteTree::class, 'staff'); |
||||
646 | $pageStaff->publishRecursive(); |
||||
647 | $pageStaffDuplicate = $this->objFromFixture(SiteTree::class, 'staffduplicate'); |
||||
648 | $pageStaffDuplicate->publishRecursive(); |
||||
649 | |||||
650 | $parentPage = $this->objFromFixture(SiteTree::class, 'about'); |
||||
651 | $parentPage->doUnpublish(); |
||||
652 | |||||
653 | Versioned::set_stage(Versioned::LIVE); |
||||
654 | $this->assertNull(DataObject::get_by_id(SiteTree::class, $pageAbout->ID)); |
||||
655 | $this->assertTrue(DataObject::get_by_id(SiteTree::class, $pageStaff->ID) instanceof SiteTree); |
||||
656 | $this->assertTrue(DataObject::get_by_id(SiteTree::class, $pageStaffDuplicate->ID) instanceof SiteTree); |
||||
657 | Versioned::set_stage(Versioned::DRAFT); |
||||
658 | Config::modify()->set(SiteTree::class, 'enforce_strict_hierarchy', true); |
||||
659 | } |
||||
660 | |||||
661 | public function testDeleteFromLiveOperatesRecursivelyStrict() |
||||
662 | { |
||||
663 | Config::inst()->update(SiteTree::class, 'enforce_strict_hierarchy', true); |
||||
664 | $this->logInWithPermission('ADMIN'); |
||||
665 | |||||
666 | $pageAbout = $this->objFromFixture(SiteTree::class, 'about'); |
||||
667 | $pageAbout->publishRecursive(); |
||||
668 | $pageStaff = $this->objFromFixture(SiteTree::class, 'staff'); |
||||
669 | $pageStaff->publishRecursive(); |
||||
670 | $pageStaffDuplicate = $this->objFromFixture(SiteTree::class, 'staffduplicate'); |
||||
671 | $pageStaffDuplicate->publishRecursive(); |
||||
672 | |||||
673 | $parentPage = $this->objFromFixture(SiteTree::class, 'about'); |
||||
674 | $parentPage->doUnpublish(); |
||||
675 | |||||
676 | Versioned::set_stage(Versioned::LIVE); |
||||
677 | $this->assertNull(DataObject::get_by_id(SiteTree::class, $pageAbout->ID)); |
||||
678 | $this->assertNull(DataObject::get_by_id(SiteTree::class, $pageStaff->ID)); |
||||
679 | $this->assertNull(DataObject::get_by_id(SiteTree::class, $pageStaffDuplicate->ID)); |
||||
680 | Versioned::set_stage(Versioned::DRAFT); |
||||
681 | } |
||||
682 | |||||
683 | /** |
||||
684 | * Simple test to confirm that querying from a particular archive date doesn't throw |
||||
685 | * an error |
||||
686 | */ |
||||
687 | public function testReadArchiveDate() |
||||
688 | { |
||||
689 | DBDatetime::set_mock_now('2009-07-02 14:05:07'); |
||||
690 | $oldPage = SiteTree::create(); |
||||
691 | $oldPage->Title = 'A really old page'; |
||||
692 | $oldPage->write(); |
||||
693 | DBDatetime::clear_mock_now(); |
||||
694 | |||||
695 | $date = '2009-07-02 14:05:07'; |
||||
696 | Versioned::reading_archived_date($date); |
||||
697 | $result = SiteTree::get()->where([ |
||||
698 | '"SiteTree"."ParentID"' => 0 |
||||
699 | ]); |
||||
700 | $this->assertCount(1, $result, '"A really old page" should be returned'); |
||||
701 | } |
||||
702 | |||||
703 | public function testEditPermissions() |
||||
704 | { |
||||
705 | $editor = $this->objFromFixture(Member::class, "editor"); |
||||
706 | |||||
707 | $home = $this->objFromFixture(SiteTree::class, "home"); |
||||
708 | $staff = $this->objFromFixture(SiteTree::class, "staff"); |
||||
709 | $products = $this->objFromFixture(SiteTree::class, "products"); |
||||
710 | $product1 = $this->objFromFixture(SiteTree::class, "product1"); |
||||
711 | $product4 = $this->objFromFixture(SiteTree::class, "product4"); |
||||
712 | |||||
713 | // Test logged out users cannot edit |
||||
714 | $this->logOut(); |
||||
715 | $this->assertFalse($staff->canEdit()); |
||||
716 | |||||
717 | // Can't edit a page that is locked to admins |
||||
718 | $this->assertFalse($home->canEdit($editor)); |
||||
719 | |||||
720 | // Can edit a page that is locked to editors |
||||
721 | $this->assertTrue($products->canEdit($editor)); |
||||
722 | |||||
723 | // Can edit a child of that page that inherits |
||||
724 | $this->assertTrue($product1->canEdit($editor)); |
||||
725 | |||||
726 | // Can't edit a child of that page that has its permissions overridden |
||||
727 | $this->assertFalse($product4->canEdit($editor)); |
||||
728 | } |
||||
729 | |||||
730 | public function testCanEditWithAccessToAllSections() |
||||
731 | { |
||||
732 | $page = SiteTree::create(); |
||||
733 | $page->write(); |
||||
734 | $allSectionMember = $this->objFromFixture(Member::class, 'allsections'); |
||||
735 | $securityAdminMember = $this->objFromFixture(Member::class, 'securityadmin'); |
||||
736 | |||||
737 | $this->assertTrue($page->canEdit($allSectionMember)); |
||||
738 | $this->assertFalse($page->canEdit($securityAdminMember)); |
||||
739 | } |
||||
740 | |||||
741 | public function testCreatePermissions() |
||||
742 | { |
||||
743 | // Test logged out users cannot create |
||||
744 | $this->logOut(); |
||||
745 | $this->assertFalse(singleton(SiteTree::class)->canCreate()); |
||||
746 | |||||
747 | // Login with another permission |
||||
748 | $this->logInWithPermission('DUMMY'); |
||||
749 | $this->assertFalse(singleton(SiteTree::class)->canCreate()); |
||||
750 | |||||
751 | // Login with basic CMS permission |
||||
752 | $perms = SiteConfig::config()->required_permission; |
||||
753 | $this->logInWithPermission(reset($perms)); |
||||
754 | $this->assertTrue(singleton(SiteTree::class)->canCreate()); |
||||
755 | |||||
756 | // Test creation underneath a parent which this user doesn't have access to |
||||
757 | $parent = $this->objFromFixture(SiteTree::class, 'about'); |
||||
758 | $this->assertFalse(singleton(SiteTree::class)->canCreate(null, ['Parent' => $parent])); |
||||
759 | |||||
760 | // Test creation underneath a parent which doesn't allow a certain child |
||||
761 | $parentB = new SiteTreeTest_ClassB(); |
||||
762 | $parentB->Title = 'Only Allows SiteTreeTest_ClassC'; |
||||
763 | $parentB->write(); |
||||
764 | $this->assertTrue(singleton(SiteTreeTest_ClassA::class)->canCreate(null)); |
||||
765 | $this->assertFalse(singleton(SiteTreeTest_ClassA::class)->canCreate(null, ['Parent' => $parentB])); |
||||
766 | $this->assertTrue(singleton(SiteTreeTest_ClassC::class)->canCreate(null, ['Parent' => $parentB])); |
||||
767 | |||||
768 | // Test creation underneath a parent which doesn't exist in the database. This should |
||||
769 | // fall back to checking whether the user can create pages at the root of the site |
||||
770 | $this->assertTrue(singleton(SiteTree::class)->canCreate(null, ['Parent' => singleton(SiteTree::class)])); |
||||
771 | |||||
772 | //Test we don't check for allowedChildren on parent context if it's not SiteTree instance |
||||
773 | $this->assertTrue( |
||||
774 | singleton(SiteTree::class)->canCreate( |
||||
775 | null, |
||||
776 | ['Parent' => $this->objFromFixture(SiteTreeTest_DataObject::class, 'relations')] |
||||
777 | ) |
||||
778 | ); |
||||
779 | } |
||||
780 | |||||
781 | public function testEditPermissionsOnDraftVsLive() |
||||
782 | { |
||||
783 | // Create an inherit-permission page |
||||
784 | $page = SiteTree::create(); |
||||
785 | $page->write(); |
||||
786 | $page->CanEditType = "Inherit"; |
||||
787 | $page->publishRecursive(); |
||||
788 | $pageID = $page->ID; |
||||
0 ignored issues
–
show
|
|||||
789 | |||||
790 | // Lock down the site config |
||||
791 | $sc = $page->SiteConfig; |
||||
792 | $sc->CanEditType = 'OnlyTheseUsers'; |
||||
793 | $sc->EditorGroups()->add($this->idFromFixture(Group::class, 'admins')); |
||||
794 | $sc->write(); |
||||
795 | |||||
796 | // Confirm that Member.editor can't edit the page |
||||
797 | $member = $this->objFromFixture(Member::class, 'editor'); |
||||
798 | Security::setCurrentUser($member); |
||||
799 | $this->assertFalse($page->canEdit()); |
||||
800 | |||||
801 | // Change the page to be editable by Group.editors, but do not publish |
||||
802 | $admin = $this->objFromFixture(Member::class, 'admin'); |
||||
803 | Security::setCurrentUser($admin); |
||||
804 | $page->CanEditType = 'OnlyTheseUsers'; |
||||
805 | $page->EditorGroups()->add($this->idFromFixture(Group::class, 'editors')); |
||||
806 | $page->write(); |
||||
807 | |||||
808 | // Clear permission cache |
||||
809 | /** @var InheritedPermissions $checker */ |
||||
810 | $checker = SiteTree::getPermissionChecker(); |
||||
811 | $checker->clearCache(); |
||||
812 | |||||
813 | // Confirm that Member.editor can now edit the page |
||||
814 | $member = $this->objFromFixture(Member::class, 'editor'); |
||||
815 | Security::setCurrentUser($member); |
||||
816 | $this->assertTrue($page->canEdit()); |
||||
817 | |||||
818 | // Publish the changes to the page |
||||
819 | $admin = $this->objFromFixture(Member::class, 'admin'); |
||||
820 | Security::setCurrentUser($admin); |
||||
821 | $page->publishRecursive(); |
||||
822 | |||||
823 | // Confirm that Member.editor can still edit the page |
||||
824 | $member = $this->objFromFixture(Member::class, 'editor'); |
||||
825 | Security::setCurrentUser($member); |
||||
826 | $this->assertTrue($page->canEdit()); |
||||
827 | } |
||||
828 | |||||
829 | public function testCompareVersions() |
||||
830 | { |
||||
831 | // Necessary to avoid |
||||
832 | $oldCleanerClass = Diff::$html_cleaner_class; |
||||
833 | Diff::$html_cleaner_class = SiteTreeTest_NullHtmlCleaner::class; |
||||
834 | |||||
835 | $page = SiteTree::create(); |
||||
836 | $page->write(); |
||||
837 | $this->assertEquals(1, $page->Version); |
||||
838 | |||||
839 | // Use inline element to avoid double wrapping applied to |
||||
840 | // blocklevel elements depending on HTMLCleaner implementation: |
||||
841 | // <ins><p> gets converted to <ins><p><inst> |
||||
842 | $page->Content = "<span>This is a test</span>"; |
||||
843 | $page->write(); |
||||
844 | $this->assertEquals(2, $page->Version); |
||||
845 | |||||
846 | $diff = $page->compareVersions(1, 2); |
||||
847 | |||||
848 | $processedContent = trim($diff->Content); |
||||
849 | $processedContent = preg_replace('/\s*</', '<', $processedContent); |
||||
850 | $processedContent = preg_replace('/>\s*/', '>', $processedContent); |
||||
851 | $this->assertEquals("<ins><span>This is a test</span></ins>", $processedContent); |
||||
852 | |||||
853 | Diff::$html_cleaner_class = $oldCleanerClass; |
||||
854 | } |
||||
855 | |||||
856 | public function testAuthorIDAndPublisherIDFilledOutOnPublish() |
||||
857 | { |
||||
858 | // Ensure that we have a member ID who is doing all this work |
||||
859 | $member = $this->objFromFixture(Member::class, "admin"); |
||||
860 | $this->logInAs($member); |
||||
861 | |||||
862 | // Write the page |
||||
863 | $about = $this->objFromFixture(SiteTree::class, 'about'); |
||||
864 | $about->Title = "Another title"; |
||||
865 | $about->write(); |
||||
866 | |||||
867 | // Check the version created |
||||
868 | $savedVersion = DB::prepared_query( |
||||
0 ignored issues
–
show
The function
SilverStripe\ORM\Connect\Query::first() has been deprecated: Use record() instead
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This function has been deprecated. The supplier of the function has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead. ![]() |
|||||
869 | "SELECT \"AuthorID\", \"PublisherID\" FROM \"SiteTree_Versions\" |
||||
870 | WHERE \"RecordID\" = ? ORDER BY \"Version\" DESC", |
||||
871 | [$about->ID] |
||||
872 | )->first(); |
||||
873 | $this->assertEquals($member->ID, $savedVersion['AuthorID']); |
||||
874 | $this->assertEquals(0, $savedVersion['PublisherID']); |
||||
875 | |||||
876 | // Publish the page |
||||
877 | $about->publishRecursive(); |
||||
878 | $publishedVersion = DB::prepared_query( |
||||
0 ignored issues
–
show
The function
SilverStripe\ORM\Connect\Query::first() has been deprecated: Use record() instead
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This function has been deprecated. The supplier of the function has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead. ![]() |
|||||
879 | "SELECT \"AuthorID\", \"PublisherID\" FROM \"SiteTree_Versions\" |
||||
880 | WHERE \"RecordID\" = ? ORDER BY \"Version\" DESC", |
||||
881 | [$about->ID] |
||||
882 | )->first(); |
||||
883 | |||||
884 | // Check the version created |
||||
885 | $this->assertEquals($member->ID, $publishedVersion['AuthorID']); |
||||
886 | $this->assertEquals($member->ID, $publishedVersion['PublisherID']); |
||||
887 | } |
||||
888 | |||||
889 | public function testLinkShortcodeHandler() |
||||
890 | { |
||||
891 | $aboutPage = $this->objFromFixture(SiteTree::class, 'about'); |
||||
892 | $redirectPage = $this->objFromFixture(RedirectorPage::class, 'external'); |
||||
893 | |||||
894 | $parser = new ShortcodeParser(); |
||||
895 | $parser->register('sitetree_link', [SiteTree::class, 'link_shortcode_handler']); |
||||
896 | |||||
897 | $aboutShortcode = sprintf('[sitetree_link,id=%d]', $aboutPage->ID); |
||||
898 | $aboutEnclosed = sprintf('[sitetree_link,id=%d]Example Content[/sitetree_link]', $aboutPage->ID); |
||||
899 | |||||
900 | $aboutShortcodeExpected = $aboutPage->Link(); |
||||
901 | $aboutEnclosedExpected = sprintf('<a href="%s">Example Content</a>', $aboutPage->Link()); |
||||
902 | |||||
903 | $this->assertEquals( |
||||
904 | $aboutShortcodeExpected, |
||||
905 | $parser->parse($aboutShortcode), |
||||
906 | 'Test that simple linking works.' |
||||
907 | ); |
||||
908 | $this->assertEquals( |
||||
909 | $aboutEnclosedExpected, |
||||
910 | $parser->parse($aboutEnclosed), |
||||
911 | 'Test enclosed content is linked.' |
||||
912 | ); |
||||
913 | |||||
914 | $aboutPage->delete(); |
||||
915 | |||||
916 | $this->assertEquals( |
||||
917 | $aboutShortcodeExpected, |
||||
918 | $parser->parse($aboutShortcode), |
||||
919 | 'Test that deleted pages still link.' |
||||
920 | ); |
||||
921 | $this->assertEquals($aboutEnclosedExpected, $parser->parse($aboutEnclosed)); |
||||
922 | |||||
923 | $aboutShortcode = '[sitetree_link,id="-1"]'; |
||||
924 | $aboutEnclosed = '[sitetree_link,id="-1"]Example Content[/sitetree_link]'; |
||||
925 | |||||
926 | $this->assertEquals('', $parser->parse($aboutShortcode), 'Test empty result if no suitable matches.'); |
||||
927 | $this->assertEquals('', $parser->parse($aboutEnclosed)); |
||||
928 | |||||
929 | $redirectShortcode = sprintf('[sitetree_link,id=%d]', $redirectPage->ID); |
||||
930 | $redirectEnclosed = sprintf('[sitetree_link,id=%d]Example Content[/sitetree_link]', $redirectPage->ID); |
||||
931 | $redirectExpected = 'http://www.google.com?a&b'; |
||||
932 | |||||
933 | $this->assertEquals($redirectExpected, $parser->parse($redirectShortcode)); |
||||
934 | $this->assertEquals( |
||||
935 | sprintf('<a href="%s">Example Content</a>', $redirectExpected), |
||||
936 | $parser->parse($redirectEnclosed) |
||||
937 | ); |
||||
938 | |||||
939 | $this->assertEquals('', $parser->parse('[sitetree_link]'), 'Test that invalid ID attributes are not parsed.'); |
||||
940 | $this->assertEquals('', $parser->parse('[sitetree_link,id="text"]')); |
||||
941 | $this->assertEquals('', $parser->parse('[sitetree_link]Example Content[/sitetree_link]')); |
||||
942 | } |
||||
943 | |||||
944 | public function testIsCurrent() |
||||
945 | { |
||||
946 | $aboutPage = $this->objFromFixture(SiteTree::class, 'about'); |
||||
947 | $productPage = $this->objFromFixture(SiteTree::class, 'products'); |
||||
948 | |||||
949 | Director::set_current_page($aboutPage); |
||||
950 | $this->assertTrue($aboutPage->isCurrent(), 'Assert that basic isCurrent checks works.'); |
||||
951 | $this->assertFalse($productPage->isCurrent()); |
||||
952 | |||||
953 | $this->assertTrue( |
||||
954 | DataObject::get_one(SiteTree::class, [ |
||||
955 | '"SiteTree"."Title"' => 'About Us', |
||||
956 | ])->isCurrent(), |
||||
957 | 'Assert that isCurrent works on another instance with the same ID.' |
||||
958 | ); |
||||
959 | |||||
960 | Director::set_current_page($newPage = SiteTree::create()); |
||||
961 | $this->assertTrue($newPage->isCurrent(), 'Assert that isCurrent works on unsaved pages.'); |
||||
962 | } |
||||
963 | |||||
964 | public function testIsSection() |
||||
965 | { |
||||
966 | $about = $this->objFromFixture(SiteTree::class, 'about'); |
||||
967 | $staff = $this->objFromFixture(SiteTree::class, 'staff'); |
||||
968 | $ceo = $this->objFromFixture(SiteTree::class, 'ceo'); |
||||
969 | |||||
970 | Director::set_current_page($about); |
||||
971 | $this->assertTrue($about->isSection()); |
||||
972 | $this->assertFalse($staff->isSection()); |
||||
973 | $this->assertFalse($ceo->isSection()); |
||||
974 | |||||
975 | Director::set_current_page($staff); |
||||
976 | $this->assertTrue($about->isSection()); |
||||
977 | $this->assertTrue($staff->isSection()); |
||||
978 | $this->assertFalse($ceo->isSection()); |
||||
979 | |||||
980 | Director::set_current_page($ceo); |
||||
981 | $this->assertTrue($about->isSection()); |
||||
982 | $this->assertTrue($staff->isSection()); |
||||
983 | $this->assertTrue($ceo->isSection()); |
||||
984 | } |
||||
985 | |||||
986 | public function testURLSegmentReserved() |
||||
987 | { |
||||
988 | $siteTree = SiteTree::create(['URLSegment' => 'admin']); |
||||
989 | $segment = $siteTree->validURLSegment(); |
||||
990 | |||||
991 | $this->assertFalse($segment); |
||||
992 | } |
||||
993 | |||||
994 | public function testURLSegmentAutoUpdate() |
||||
995 | { |
||||
996 | $sitetree = SiteTree::create(); |
||||
997 | $sitetree->Title = _t( |
||||
998 | 'SilverStripe\\CMS\\Controllers\\CMSMain.NEWPAGE', |
||||
999 | 'New {pagetype}', |
||||
1000 | ['pagetype' => $sitetree->i18n_singular_name()] |
||||
1001 | ); |
||||
1002 | $sitetree->write(); |
||||
1003 | $this->assertEquals( |
||||
1004 | 'new-page', |
||||
1005 | $sitetree->URLSegment, |
||||
1006 | 'Sets based on default title on first save' |
||||
1007 | ); |
||||
1008 | |||||
1009 | $sitetree->Title = 'Changed'; |
||||
1010 | $sitetree->write(); |
||||
1011 | $this->assertEquals( |
||||
1012 | 'changed', |
||||
1013 | $sitetree->URLSegment, |
||||
1014 | 'Auto-updates when set to default title' |
||||
1015 | ); |
||||
1016 | |||||
1017 | $sitetree->Title = 'Changed again'; |
||||
1018 | $sitetree->write(); |
||||
1019 | $this->assertEquals( |
||||
1020 | 'changed', |
||||
1021 | $sitetree->URLSegment, |
||||
1022 | 'Does not auto-update once title has been changed' |
||||
1023 | ); |
||||
1024 | } |
||||
1025 | |||||
1026 | public function testURLSegmentAutoUpdateLocalized() |
||||
1027 | { |
||||
1028 | $oldLocale = i18n::get_locale(); |
||||
1029 | i18n::set_locale('de_DE'); |
||||
1030 | |||||
1031 | $sitetree = SiteTree::create(); |
||||
1032 | $sitetree->Title = _t( |
||||
1033 | 'SilverStripe\\CMS\\Controllers\\CMSMain.NEWPAGE', |
||||
1034 | 'New {pagetype}', |
||||
1035 | ['pagetype' => $sitetree->i18n_singular_name()] |
||||
1036 | ); |
||||
1037 | $sitetree->write(); |
||||
1038 | $this->assertEquals( |
||||
1039 | 'neue-seite', |
||||
1040 | $sitetree->URLSegment, |
||||
1041 | 'Sets based on default title on first save' |
||||
1042 | ); |
||||
1043 | |||||
1044 | $sitetree->Title = 'Changed'; |
||||
1045 | $sitetree->write(); |
||||
1046 | $this->assertEquals( |
||||
1047 | 'changed', |
||||
1048 | $sitetree->URLSegment, |
||||
1049 | 'Auto-updates when set to default title' |
||||
1050 | ); |
||||
1051 | |||||
1052 | $sitetree->Title = 'Changed again'; |
||||
1053 | $sitetree->write(); |
||||
1054 | $this->assertEquals( |
||||
1055 | 'changed', |
||||
1056 | $sitetree->URLSegment, |
||||
1057 | 'Does not auto-update once title has been changed' |
||||
1058 | ); |
||||
1059 | |||||
1060 | i18n::set_locale($oldLocale); |
||||
1061 | } |
||||
1062 | |||||
1063 | /** |
||||
1064 | * @covers \SilverStripe\CMS\Model\SiteTree::validURLSegment |
||||
1065 | */ |
||||
1066 | public function testValidURLSegmentURLSegmentConflicts() |
||||
1067 | { |
||||
1068 | $sitetree = SiteTree::create(); |
||||
1069 | SiteTree::config()->nested_urls = false; |
||||
1070 | |||||
1071 | $sitetree->URLSegment = 'home'; |
||||
1072 | $this->assertFalse($sitetree->validURLSegment(), 'URLSegment conflicts are recognised'); |
||||
1073 | $sitetree->URLSegment = 'home-noconflict'; |
||||
1074 | $this->assertTrue($sitetree->validURLSegment()); |
||||
1075 | |||||
1076 | $sitetree->ParentID = $this->idFromFixture(SiteTree::class, 'about'); |
||||
1077 | $sitetree->URLSegment = 'home'; |
||||
1078 | $this->assertFalse($sitetree->validURLSegment(), 'Conflicts are still recognised with a ParentID value'); |
||||
1079 | |||||
1080 | Config::modify()->set(SiteTree::class, 'nested_urls', true); |
||||
1081 | |||||
1082 | $sitetree->ParentID = 0; |
||||
1083 | $sitetree->URLSegment = 'home'; |
||||
1084 | $this->assertFalse($sitetree->validURLSegment(), 'URLSegment conflicts are recognised'); |
||||
1085 | |||||
1086 | $sitetree->ParentID = $this->idFromFixture(SiteTree::class, 'about'); |
||||
1087 | $this->assertTrue($sitetree->validURLSegment(), 'URLSegments can be the same across levels'); |
||||
1088 | |||||
1089 | $sitetree->URLSegment = 'my-staff'; |
||||
1090 | $this->assertFalse($sitetree->validURLSegment(), 'Nested URLSegment conflicts are recognised'); |
||||
1091 | $sitetree->URLSegment = 'my-staff-noconflict'; |
||||
1092 | $this->assertTrue($sitetree->validURLSegment()); |
||||
1093 | } |
||||
1094 | |||||
1095 | /** |
||||
1096 | * @covers \SilverStripe\CMS\Model\SiteTree::validURLSegment |
||||
1097 | */ |
||||
1098 | public function testValidURLSegmentClassNameConflicts() |
||||
1099 | { |
||||
1100 | $sitetree = SiteTree::create(); |
||||
1101 | $sitetree->URLSegment = Controller::class; |
||||
1102 | |||||
1103 | $this->assertTrue($sitetree->validURLSegment(), 'Class names are no longer conflicts'); |
||||
1104 | } |
||||
1105 | |||||
1106 | /** |
||||
1107 | * @covers \SilverStripe\CMS\Model\SiteTree::validURLSegment |
||||
1108 | */ |
||||
1109 | public function testValidURLSegmentControllerConflicts() |
||||
1110 | { |
||||
1111 | Config::modify()->set(SiteTree::class, 'nested_urls', true); |
||||
1112 | |||||
1113 | $sitetree = SiteTree::create(); |
||||
1114 | $sitetree->ParentID = $this->idFromFixture(SiteTreeTest_Conflicted::class, 'parent'); |
||||
1115 | |||||
1116 | $sitetree->URLSegment = 'index'; |
||||
1117 | $this->assertFalse($sitetree->validURLSegment(), 'index is not a valid URLSegment'); |
||||
1118 | |||||
1119 | $sitetree->URLSegment = 'conflicted-action'; |
||||
1120 | $this->assertFalse($sitetree->validURLSegment(), 'allowed_actions conflicts are recognised'); |
||||
1121 | |||||
1122 | $sitetree->URLSegment = 'conflicted-template'; |
||||
1123 | $this->assertFalse($sitetree->validURLSegment(), 'Action-specific template conflicts are recognised'); |
||||
1124 | |||||
1125 | $sitetree->URLSegment = 'valid'; |
||||
1126 | $this->assertTrue($sitetree->validURLSegment(), 'Valid URLSegment values are allowed'); |
||||
1127 | } |
||||
1128 | |||||
1129 | public function testURLSegmentPrioritizesExtensionVotes() |
||||
1130 | { |
||||
1131 | $sitetree = SiteTree::create(); |
||||
1132 | $sitetree->URLSegment = 'unique-segment'; |
||||
1133 | $this->assertTrue($sitetree->validURLSegment()); |
||||
1134 | |||||
1135 | SiteTree::add_extension(SiteTreeTest_Extension::class); |
||||
1136 | $sitetree = SiteTree::create(); |
||||
1137 | $sitetree->URLSegment = 'unique-segment'; |
||||
1138 | $this->assertFalse($sitetree->validURLSegment()); |
||||
1139 | SiteTree::remove_extension(SiteTreeTest_Extension::class); |
||||
1140 | } |
||||
1141 | |||||
1142 | public function testURLSegmentMultiByte() |
||||
1143 | { |
||||
1144 | URLSegmentFilter::config()->set('default_allow_multibyte', true); |
||||
1145 | $sitetree = SiteTree::create(); |
||||
1146 | $sitetree->write(); |
||||
1147 | |||||
1148 | $sitetree->URLSegment = 'brötchen'; |
||||
1149 | $sitetree->write(); |
||||
1150 | $sitetree = DataObject::get_by_id(SiteTree::class, $sitetree->ID, false); |
||||
1151 | $this->assertEquals($sitetree->URLSegment, rawurlencode('brötchen')); |
||||
1152 | |||||
1153 | $sitetree->copyVersionToStage(Versioned::DRAFT, Versioned::LIVE); |
||||
1154 | $sitetree = DataObject::get_by_id(SiteTree::class, $sitetree->ID, false); |
||||
1155 | $this->assertEquals($sitetree->URLSegment, rawurlencode('brötchen')); |
||||
1156 | $sitetreeLive = Versioned::get_one_by_stage( |
||||
1157 | SiteTree::class, |
||||
1158 | Versioned::LIVE, |
||||
1159 | '"SiteTree"."ID" = ' . $sitetree->ID, |
||||
1160 | false |
||||
1161 | ); |
||||
1162 | $this->assertEquals($sitetreeLive->URLSegment, rawurlencode('brötchen')); |
||||
1163 | } |
||||
1164 | |||||
1165 | public function testVersionsAreCreated() |
||||
1166 | { |
||||
1167 | $p = SiteTree::create(); |
||||
1168 | $p->Content = "one"; |
||||
1169 | $p->write(); |
||||
1170 | $this->assertEquals(1, $p->Version); |
||||
1171 | |||||
1172 | // No changes don't bump version |
||||
1173 | $p->write(); |
||||
1174 | $this->assertEquals(1, $p->Version); |
||||
1175 | |||||
1176 | $p->Content = "two"; |
||||
1177 | $p->write(); |
||||
1178 | $this->assertEquals(2, $p->Version); |
||||
1179 | |||||
1180 | // Only change meta-data don't bump version |
||||
1181 | $p->HasBrokenLink = true; |
||||
1182 | $p->write(); |
||||
1183 | $p->HasBrokenLink = false; |
||||
1184 | $p->write(); |
||||
1185 | $this->assertEquals(2, $p->Version); |
||||
1186 | |||||
1187 | $p->Content = "three"; |
||||
1188 | $p->write(); |
||||
1189 | $this->assertEquals(3, $p->Version); |
||||
1190 | } |
||||
1191 | |||||
1192 | public function testPageTypeClasses() |
||||
1193 | { |
||||
1194 | $classes = SiteTree::page_type_classes(); |
||||
1195 | $this->assertNotContains(SiteTree::class, $classes, 'Page types do not include base class'); |
||||
1196 | $this->assertContains('Page', $classes, 'Page types do contain subclasses'); |
||||
1197 | |||||
1198 | // Testing what happens in an incorrect config value is set - hide_ancestor should be a string |
||||
1199 | Config::modify()->set(SiteTreeTest_ClassA::class, 'hide_ancestor', true); |
||||
1200 | $newClasses = SiteTree::page_type_classes(); |
||||
1201 | $this->assertEquals( |
||||
1202 | $classes, |
||||
1203 | $newClasses, |
||||
1204 | 'Setting hide_ancestor to a boolean (incorrect) value caused a page class to be hidden' |
||||
1205 | ); |
||||
1206 | } |
||||
1207 | |||||
1208 | /** |
||||
1209 | * Tests that core subclasses of SiteTree are included in allowedChildren() by default, but not instances of |
||||
1210 | * HiddenClass |
||||
1211 | */ |
||||
1212 | public function testAllowedChildrenContainsCoreSubclassesButNotHiddenClass() |
||||
1213 | { |
||||
1214 | $page = SiteTree::create(); |
||||
1215 | $allowedChildren = $page->allowedChildren(); |
||||
1216 | |||||
1217 | $this->assertContains( |
||||
1218 | VirtualPage::class, |
||||
1219 | $allowedChildren, |
||||
1220 | 'Includes core subclasses by default' |
||||
1221 | ); |
||||
1222 | |||||
1223 | $this->assertNotContains( |
||||
1224 | SiteTreeTest_ClassE::class, |
||||
1225 | $allowedChildren, |
||||
1226 | 'HiddenClass instances should not be returned' |
||||
1227 | ); |
||||
1228 | } |
||||
1229 | |||||
1230 | /** |
||||
1231 | * Tests that various types of SiteTree classes will or will not be returned from the allowedChildren method |
||||
1232 | * @dataProvider allowedChildrenProvider |
||||
1233 | * @param string $className |
||||
1234 | * @param array $expected |
||||
1235 | * @param string $assertionMessage |
||||
1236 | */ |
||||
1237 | public function testAllowedChildren($className, $expected, $assertionMessage) |
||||
1238 | { |
||||
1239 | $class = new $className(); |
||||
1240 | $this->assertEquals($expected, $class->allowedChildren(), $assertionMessage); |
||||
1241 | } |
||||
1242 | |||||
1243 | /** |
||||
1244 | * @return array |
||||
1245 | */ |
||||
1246 | public function allowedChildrenProvider() |
||||
1247 | { |
||||
1248 | return [ |
||||
1249 | [ |
||||
1250 | // Class name |
||||
1251 | SiteTreeTest_ClassA::class, |
||||
1252 | // Expected |
||||
1253 | [ SiteTreeTest_ClassB::class ], |
||||
1254 | // Assertion message |
||||
1255 | 'Direct setting of allowed children', |
||||
1256 | ], |
||||
1257 | [ |
||||
1258 | SiteTreeTest_ClassB::class, |
||||
1259 | [ SiteTreeTest_ClassC::class, SiteTreeTest_ClassCext::class ], |
||||
1260 | 'Includes subclasses', |
||||
1261 | ], |
||||
1262 | [ |
||||
1263 | SiteTreeTest_ClassC::class, |
||||
1264 | [], |
||||
1265 | 'Null setting', |
||||
1266 | ], |
||||
1267 | [ |
||||
1268 | SiteTreeTest_ClassD::class, |
||||
1269 | [SiteTreeTest_ClassC::class], |
||||
1270 | 'Excludes subclasses if class is prefixed by an asterisk', |
||||
1271 | ], |
||||
1272 | ]; |
||||
1273 | } |
||||
1274 | |||||
1275 | public function testAllowedChildrenValidation() |
||||
1276 | { |
||||
1277 | $page = SiteTree::create(); |
||||
1278 | $page->write(); |
||||
1279 | $classA = new SiteTreeTest_ClassA(); |
||||
1280 | $classA->write(); |
||||
1281 | $classB = new SiteTreeTest_ClassB(); |
||||
1282 | $classB->write(); |
||||
1283 | $classC = new SiteTreeTest_ClassC(); |
||||
1284 | $classC->write(); |
||||
1285 | $classD = new SiteTreeTest_ClassD(); |
||||
1286 | $classD->write(); |
||||
1287 | $classCext = new SiteTreeTest_ClassCext(); |
||||
1288 | $classCext->write(); |
||||
1289 | |||||
1290 | $classB->ParentID = $page->ID; |
||||
0 ignored issues
–
show
|
|||||
1291 | $valid = $classB->doValidate(); |
||||
1292 | $this->assertTrue($valid->isValid(), "Does allow children on unrestricted parent"); |
||||
1293 | |||||
1294 | $classB->ParentID = $classA->ID; |
||||
1295 | $valid = $classB->doValidate(); |
||||
1296 | $this->assertTrue($valid->isValid(), "Does allow child specifically allowed by parent"); |
||||
1297 | |||||
1298 | $classC->ParentID = $classA->ID; |
||||
1299 | $valid = $classC->doValidate(); |
||||
1300 | $this->assertFalse($valid->isValid(), "Doesnt allow child on parents specifically restricting children"); |
||||
1301 | |||||
1302 | $classB->ParentID = $classC->ID; |
||||
1303 | $valid = $classB->doValidate(); |
||||
1304 | $this->assertFalse($valid->isValid(), "Doesnt allow child on parents disallowing all children"); |
||||
1305 | |||||
1306 | $classB->ParentID = $classCext->ID; |
||||
1307 | $valid = $classB->doValidate(); |
||||
1308 | $this->assertTrue($valid->isValid(), "Extensions of allowed classes are incorrectly reported as invalid"); |
||||
1309 | |||||
1310 | $classCext->ParentID = $classD->ID; |
||||
1311 | $valid = $classCext->doValidate(); |
||||
1312 | $this->assertFalse( |
||||
1313 | $valid->isValid(), |
||||
1314 | "Doesnt allow child where only parent class is allowed on parent node, and asterisk prefixing is used" |
||||
1315 | ); |
||||
1316 | } |
||||
1317 | |||||
1318 | public function testClassDropdown() |
||||
1319 | { |
||||
1320 | $sitetree = SiteTree::create(); |
||||
1321 | $method = new ReflectionMethod($sitetree, 'getClassDropdown'); |
||||
1322 | $method->setAccessible(true); |
||||
1323 | |||||
1324 | Security::setCurrentUser(null); |
||||
1325 | $this->assertArrayNotHasKey(SiteTreeTest_ClassA::class, $method->invoke($sitetree)); |
||||
1326 | |||||
1327 | $this->loginWithPermission('ADMIN'); |
||||
1328 | $this->assertArrayHasKey(SiteTreeTest_ClassA::class, $method->invoke($sitetree)); |
||||
1329 | |||||
1330 | $this->loginWithPermission('CMS_ACCESS_CMSMain'); |
||||
1331 | $this->assertArrayHasKey(SiteTreeTest_ClassA::class, $method->invoke($sitetree)); |
||||
1332 | |||||
1333 | Security::setCurrentUser(null); |
||||
1334 | } |
||||
1335 | |||||
1336 | public function testCanBeRoot() |
||||
1337 | { |
||||
1338 | $page = SiteTree::create(); |
||||
1339 | $page->ParentID = 0; |
||||
1340 | $page->write(); |
||||
1341 | |||||
1342 | $notRootPage = new SiteTreeTest_NotRoot(); |
||||
1343 | $notRootPage->ParentID = 0; |
||||
0 ignored issues
–
show
|
|||||
1344 | $isDetected = false; |
||||
1345 | try { |
||||
1346 | $notRootPage->write(); |
||||
1347 | } catch (ValidationException $e) { |
||||
1348 | $this->assertStringContainsString('is not allowed on the root level', $e->getMessage()); |
||||
1349 | $isDetected = true; |
||||
1350 | } |
||||
1351 | |||||
1352 | if (!$isDetected) { |
||||
1353 | $this->fail('Fails validation with $can_be_root=false'); |
||||
1354 | } |
||||
1355 | } |
||||
1356 | |||||
1357 | public function testModifyStatusFlagByInheritance() |
||||
1358 | { |
||||
1359 | $node = new SiteTreeTest_StageStatusInherit(); |
||||
1360 | $treeTitle = $node->getTreeTitle(); |
||||
1361 | $this->assertStringContainsString('InheritedTitle', $treeTitle); |
||||
1362 | $this->assertStringContainsString('inherited-class', $treeTitle); |
||||
1363 | } |
||||
1364 | |||||
1365 | public function testMenuTitleIsUnsetWhenEqualsTitle() |
||||
1366 | { |
||||
1367 | $page = SiteTree::create(); |
||||
1368 | $page->Title = 'orig'; |
||||
1369 | $page->MenuTitle = 'orig'; |
||||
1370 | $page->write(); |
||||
1371 | |||||
1372 | // change menu title |
||||
1373 | $page->MenuTitle = 'changed'; |
||||
1374 | $page->write(); |
||||
1375 | $page = SiteTree::get()->byID($page->ID); |
||||
1376 | $this->assertEquals('changed', $page->getField('MenuTitle')); |
||||
1377 | |||||
1378 | // change menu title back |
||||
1379 | $page->MenuTitle = 'orig'; |
||||
1380 | $page->write(); |
||||
1381 | $page = SiteTree::get()->byID($page->ID); |
||||
1382 | $this->assertEquals(null, $page->getField('MenuTitle')); |
||||
1383 | } |
||||
1384 | |||||
1385 | public function testMetaTagGeneratorDisabling() |
||||
1386 | { |
||||
1387 | $generator = Config::inst()->get(SiteTree::class, 'meta_generator'); |
||||
0 ignored issues
–
show
|
|||||
1388 | |||||
1389 | // Stub to ensure customisations don't affect the test |
||||
1390 | Config::modify()->set(SiteTree::class, 'meta_generator', 'SilverStripe - https://www.silverstripe.org'); |
||||
1391 | |||||
1392 | $page = new SiteTreeTest_PageNode(); |
||||
1393 | |||||
1394 | $meta = $page->MetaTags(); |
||||
1395 | $this->assertStringContainsString('meta name="generator"', $meta, 'Should include generator tag'); |
||||
1396 | $this->assertStringContainsString( |
||||
1397 | 'content="SilverStripe - https://www.silverstripe.org', |
||||
1398 | $meta, |
||||
1399 | 'Should contain default meta generator info' |
||||
1400 | ); |
||||
1401 | |||||
1402 | // test proper escaping of quotes in attribute value |
||||
1403 | Config::modify()->set(SiteTree::class, 'meta_generator', 'Generator with "quotes" in it'); |
||||
1404 | $meta = $page->MetaTags(); |
||||
1405 | $this->assertStringContainsString( |
||||
1406 | 'content="Generator with "quotes" in it', |
||||
1407 | $meta, |
||||
1408 | 'test proper escaping of values from Config' |
||||
1409 | ); |
||||
1410 | |||||
1411 | // test empty generator - no tag should appear at all |
||||
1412 | Config::modify()->set(SiteTree::class, 'meta_generator', ''); |
||||
1413 | $meta = $page->MetaTags(); |
||||
1414 | $this->assertStringNotContainsString( |
||||
1415 | 'meta name="generator"', |
||||
1416 | $meta, |
||||
1417 | 'test blank value means no tag generated' |
||||
1418 | ); |
||||
1419 | } |
||||
1420 | |||||
1421 | |||||
1422 | public function testGetBreadcrumbItems() |
||||
1423 | { |
||||
1424 | $page = $this->objFromFixture(SiteTree::class, "breadcrumbs"); |
||||
1425 | $this->assertEquals(1, $page->getBreadcrumbItems()->count(), "Only display current page."); |
||||
1426 | |||||
1427 | // Test breadcrumb order |
||||
1428 | $page = $this->objFromFixture(SiteTree::class, "breadcrumbs5"); |
||||
1429 | $breadcrumbs = $page->getBreadcrumbItems(); |
||||
1430 | $this->assertEquals($breadcrumbs->count(), 5, "Display all breadcrumbs"); |
||||
1431 | $this->assertEquals($breadcrumbs->first()->Title, "Breadcrumbs", "Breadcrumbs should be the first item."); |
||||
1432 | $this->assertEquals($breadcrumbs->last()->Title, "Breadcrumbs 5", "Breadcrumbs 5 should be last item."); |
||||
1433 | |||||
1434 | // Test breadcrumb max depth |
||||
1435 | $breadcrumbs = $page->getBreadcrumbItems(2); |
||||
1436 | $this->assertEquals($breadcrumbs->count(), 2, "Max depth should limit the breadcrumbs to 2 items."); |
||||
1437 | $this->assertEquals($breadcrumbs->first()->Title, "Breadcrumbs 4", "First item should be Breadrcumbs 4."); |
||||
1438 | $this->assertEquals($breadcrumbs->last()->Title, "Breadcrumbs 5", "Breadcrumbs 5 should be last."); |
||||
1439 | } |
||||
1440 | |||||
1441 | /** |
||||
1442 | * Tests SiteTree::MetaTags |
||||
1443 | * Note that this test makes no assumption on the closing of tags (other than <title></title>) |
||||
1444 | */ |
||||
1445 | public function testMetaTags() |
||||
1446 | { |
||||
1447 | $this->logInWithPermission('ADMIN'); |
||||
1448 | $page = $this->objFromFixture(SiteTree::class, 'metapage'); |
||||
1449 | |||||
1450 | // Test with title |
||||
1451 | $meta = $page->MetaTags(); |
||||
1452 | $charset = Config::inst()->get(ContentNegotiator::class, 'encoding'); |
||||
1453 | $this->assertStringContainsString('<meta http-equiv="Content-Type" content="text/html; charset=' . $charset . '"', $meta); |
||||
1454 | $this->assertStringContainsString('<meta name="description" content="The <br /> and <br> tags"', $meta); |
||||
1455 | $this->assertStringContainsString('<link rel="canonical" href="http://www.mysite.com/html-and-xml"', $meta); |
||||
1456 | $this->assertStringContainsString('<meta name="x-page-id" content="' . $page->ID . '"', $meta); |
||||
1457 | $this->assertStringContainsString('<meta name="x-cms-edit-link" content="' . $page->CMSEditLink() . '"', $meta); |
||||
1458 | $this->assertStringContainsString('<title>HTML & XML</title>', $meta); |
||||
1459 | |||||
1460 | // Test without title |
||||
1461 | $meta = $page->MetaTags(false); |
||||
1462 | $this->assertStringNotContainsString('<title>', $meta); |
||||
1463 | |||||
1464 | $meta = $page->MetaTags('false'); |
||||
1465 | $this->assertStringNotContainsString('<title>', $meta); |
||||
1466 | } |
||||
1467 | |||||
1468 | public function testMetaComponents() |
||||
1469 | { |
||||
1470 | $this->logInWithPermission('ADMIN'); |
||||
1471 | /** @var SiteTree $page */ |
||||
1472 | $page = $this->objFromFixture(SiteTree::class, 'metapage'); |
||||
1473 | |||||
1474 | $charset = Config::inst()->get(ContentNegotiator::class, 'encoding'); |
||||
1475 | |||||
1476 | $expected = [ |
||||
1477 | 'title' => [ |
||||
1478 | 'tag' => 'title', |
||||
1479 | 'content' => "HTML & XML", |
||||
1480 | ], |
||||
1481 | 'generator' => [ |
||||
1482 | 'attributes' => [ |
||||
1483 | 'name' => 'generator', |
||||
1484 | 'content' => Config::inst()->get(SiteTree::class, 'meta_generator') |
||||
1485 | ], |
||||
1486 | ], |
||||
1487 | 'contentType' => [ |
||||
1488 | 'attributes' => [ |
||||
1489 | 'http-equiv' => 'Content-Type', |
||||
1490 | 'content' => "text/html; charset=$charset", |
||||
1491 | ], |
||||
1492 | ], |
||||
1493 | 'description' => [ |
||||
1494 | 'attributes' => [ |
||||
1495 | 'name' => 'description', |
||||
1496 | 'content' => 'The <br /> and <br> tags' |
||||
1497 | ] |
||||
1498 | ], |
||||
1499 | 'pageId' => [ |
||||
1500 | 'attributes' => [ |
||||
1501 | 'name' => 'x-page-id', |
||||
1502 | 'content' => $page->ID |
||||
1503 | ], |
||||
1504 | ], |
||||
1505 | 'cmsEditLink' => [ |
||||
1506 | 'attributes' => [ |
||||
1507 | 'name' => 'x-cms-edit-link', |
||||
1508 | 'content' => $page->CMSEditLink() |
||||
1509 | ] |
||||
1510 | ] |
||||
1511 | ]; |
||||
1512 | |||||
1513 | $this->assertEquals($expected, $page->MetaComponents()); |
||||
1514 | } |
||||
1515 | |||||
1516 | /** |
||||
1517 | * Test that orphaned pages are handled correctly |
||||
1518 | */ |
||||
1519 | public function testOrphanedPages() |
||||
1520 | { |
||||
1521 | $origStage = Versioned::get_reading_mode(); |
||||
1522 | |||||
1523 | // Setup user who can view draft content, but lacks cms permission. |
||||
1524 | // To users such as this, orphaned pages should be inaccessible. canView for these pages is only |
||||
1525 | // necessary for admin / cms users, who require this permission to edit / rearrange these pages. |
||||
1526 | $permission = new Permission(); |
||||
1527 | $permission->Code = 'VIEW_DRAFT_CONTENT'; |
||||
1528 | $group = new Group(['Title' => 'Staging Users']); |
||||
1529 | $group->write(); |
||||
1530 | $group->Permissions()->add($permission); |
||||
1531 | $member = new Member(); |
||||
1532 | $member->Email = '[email protected]'; |
||||
1533 | $member->write(); |
||||
1534 | $member->Groups()->add($group); |
||||
1535 | |||||
1536 | // both pages are viewable in stage |
||||
1537 | Versioned::set_stage(Versioned::DRAFT); |
||||
1538 | $about = $this->objFromFixture(SiteTree::class, 'about'); |
||||
1539 | $staff = $this->objFromFixture(SiteTree::class, 'staff'); |
||||
1540 | $this->assertFalse($about->isOrphaned()); |
||||
1541 | $this->assertFalse($staff->isOrphaned()); |
||||
1542 | $this->assertTrue($about->canView($member)); |
||||
1543 | $this->assertTrue($staff->canView($member)); |
||||
1544 | |||||
1545 | // Publishing only the child page to live should orphan the live record, but not the staging one |
||||
1546 | $staff->copyVersionToStage(Versioned::DRAFT, Versioned::LIVE); |
||||
1547 | $this->assertFalse($staff->isOrphaned()); |
||||
1548 | $this->assertTrue($staff->canView($member)); |
||||
1549 | Versioned::set_stage(Versioned::LIVE); |
||||
1550 | $staff = $this->objFromFixture(SiteTree::class, 'staff'); // Live copy of page |
||||
1551 | $this->assertTrue($staff->isOrphaned()); // because parent isn't published |
||||
1552 | $this->assertFalse($staff->canView($member)); |
||||
1553 | |||||
1554 | // Publishing the parent page should restore visibility |
||||
1555 | Versioned::set_stage(Versioned::DRAFT); |
||||
1556 | $about = $this->objFromFixture(SiteTree::class, 'about'); |
||||
1557 | $about->copyVersionToStage(Versioned::DRAFT, Versioned::LIVE); |
||||
1558 | Versioned::set_stage(Versioned::LIVE); |
||||
1559 | $staff = $this->objFromFixture(SiteTree::class, 'staff'); |
||||
1560 | $this->assertFalse($staff->isOrphaned()); |
||||
1561 | $this->assertTrue($staff->canView($member)); |
||||
1562 | |||||
1563 | // Removing staging page should not prevent live page being visible |
||||
1564 | $about->deleteFromStage('Stage'); |
||||
1565 | $staff->deleteFromStage('Stage'); |
||||
1566 | $staff = $this->objFromFixture(SiteTree::class, 'staff'); |
||||
1567 | $this->assertFalse($staff->isOrphaned()); |
||||
1568 | $this->assertTrue($staff->canView($member)); |
||||
1569 | |||||
1570 | // Cleanup |
||||
1571 | Versioned::set_reading_mode($origStage); |
||||
1572 | } |
||||
1573 | |||||
1574 | /** |
||||
1575 | * Test archived page behaviour |
||||
1576 | */ |
||||
1577 | public function testArchivedPages() |
||||
1578 | { |
||||
1579 | $this->logInWithPermission('ADMIN'); |
||||
1580 | |||||
1581 | /** @var SiteTree $page */ |
||||
1582 | $page = $this->objFromFixture(SiteTree::class, 'home'); |
||||
1583 | $this->assertTrue($page->canAddChildren()); |
||||
1584 | $this->assertTrue($page->isOnDraft()); |
||||
1585 | $this->assertFalse($page->isPublished()); |
||||
1586 | |||||
1587 | // Publish |
||||
1588 | $page->publishRecursive(); |
||||
1589 | $this->assertTrue($page->canAddChildren()); |
||||
1590 | $this->assertTrue($page->isOnDraft()); |
||||
1591 | $this->assertTrue($page->isPublished()); |
||||
1592 | |||||
1593 | // Archive |
||||
1594 | $page->doArchive(); |
||||
1595 | $this->assertFalse($page->canAddChildren()); |
||||
1596 | $this->assertFalse($page->isOnDraft()); |
||||
1597 | $this->assertTrue($page->isArchived()); |
||||
1598 | $this->assertFalse($page->isPublished()); |
||||
1599 | } |
||||
1600 | |||||
1601 | public function testCanNot() |
||||
1602 | { |
||||
1603 | // Test that |
||||
1604 | $this->logInWithPermission('ADMIN'); |
||||
1605 | $page = new SiteTreeTest_AdminDenied(); |
||||
1606 | $this->assertFalse($page->canCreate()); |
||||
1607 | $this->assertFalse($page->canEdit()); |
||||
1608 | $this->assertFalse($page->canDelete()); |
||||
1609 | $this->assertFalse($page->canAddChildren()); |
||||
1610 | $this->assertFalse($page->canView()); |
||||
1611 | } |
||||
1612 | |||||
1613 | public function testCanPublish() |
||||
1614 | { |
||||
1615 | $page = new SiteTreeTest_ClassD(); |
||||
1616 | $this->logOut(); |
||||
1617 | |||||
1618 | // Test that false overrides any can_publish = true |
||||
1619 | SiteTreeTest_ExtensionA::$can_publish = true; |
||||
1620 | SiteTreeTest_ExtensionB::$can_publish = false; |
||||
1621 | $this->assertFalse($page->canPublish()); |
||||
1622 | SiteTreeTest_ExtensionA::$can_publish = false; |
||||
1623 | SiteTreeTest_ExtensionB::$can_publish = true; |
||||
1624 | $this->assertFalse($page->canPublish()); |
||||
1625 | |||||
1626 | // Test null extensions fall back to canEdit() |
||||
1627 | SiteTreeTest_ExtensionA::$can_publish = null; |
||||
1628 | SiteTreeTest_ExtensionB::$can_publish = null; |
||||
1629 | $page->canEditValue = true; |
||||
1630 | $this->assertTrue($page->canPublish()); |
||||
1631 | $page->canEditValue = false; |
||||
1632 | $this->assertFalse($page->canPublish()); |
||||
1633 | } |
||||
1634 | |||||
1635 | /** |
||||
1636 | * Test url rewriting extensions |
||||
1637 | */ |
||||
1638 | public function testLinkExtension() |
||||
1639 | { |
||||
1640 | Director::config()->set('alternate_base_url', 'http://www.baseurl.com'); |
||||
1641 | $page = new SiteTreeTest_ClassD(); |
||||
1642 | $page->URLSegment = 'classd'; |
||||
1643 | $page->write(); |
||||
1644 | $this->assertEquals( |
||||
1645 | 'http://www.updatedhost.com/classd/myaction?extra=1', |
||||
1646 | $page->Link('myaction') |
||||
1647 | ); |
||||
1648 | $this->assertEquals( |
||||
1649 | 'http://www.updatedhost.com/classd/myaction?extra=1', |
||||
1650 | $page->AbsoluteLink('myaction') |
||||
1651 | ); |
||||
1652 | $this->assertEquals( |
||||
1653 | 'classd/myaction', |
||||
1654 | $page->RelativeLink('myaction') |
||||
1655 | ); |
||||
1656 | } |
||||
1657 | |||||
1658 | /** |
||||
1659 | * Test that the controller name for a SiteTree instance can be gathered by appending "Controller" to the SiteTree |
||||
1660 | * class name in a PSR-2 compliant manner. |
||||
1661 | */ |
||||
1662 | public function testGetControllerName() |
||||
1663 | { |
||||
1664 | $class = Page::create(); |
||||
1665 | $this->assertSame('PageController', $class->getControllerName()); |
||||
1666 | } |
||||
1667 | |||||
1668 | /** |
||||
1669 | * Test that the controller name for a SiteTree instance can be gathered when set directly via config var |
||||
1670 | */ |
||||
1671 | public function testGetControllerNameFromConfig() |
||||
1672 | { |
||||
1673 | Config::inst()->update(Page::class, 'controller_name', 'This\\Is\\A\\New\\Controller'); |
||||
1674 | $class = new Page(); |
||||
1675 | $this->assertSame('This\\Is\\A\\New\\Controller', $class->getControllerName()); |
||||
1676 | } |
||||
1677 | |||||
1678 | /** |
||||
1679 | * Test that underscored class names (legacy) are still supported (deprecation notice is issued though). |
||||
1680 | */ |
||||
1681 | public function testGetControllerNameWithUnderscoresIsSupported() |
||||
1682 | { |
||||
1683 | $class = new SiteTreeTest_LegacyControllerName(); |
||||
1684 | $this->assertEquals(SiteTreeTest_LegacyControllerName_Controller::class, $class->getControllerName()); |
||||
1685 | } |
||||
1686 | |||||
1687 | public function testTreeTitleCache() |
||||
1688 | { |
||||
1689 | $siteTree = SiteTree::create(); |
||||
1690 | $user = $this->objFromFixture(Member::class, 'allsections'); |
||||
1691 | Security::setCurrentUser($user); |
||||
1692 | $pageClass = array_values(SiteTree::page_type_classes())[0]; |
||||
1693 | |||||
1694 | $mockPageMissesCache = $this->getMockBuilder($pageClass) |
||||
0 ignored issues
–
show
The function
PHPUnit\Framework\MockOb...ckBuilder::setMethods() has been deprecated: https://github.com/sebastianbergmann/phpunit/pull/3687
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This function has been deprecated. The supplier of the function has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead. ![]() |
|||||
1695 | ->setMethods(['canCreate']) |
||||
1696 | ->getMock(); |
||||
1697 | $mockPageMissesCache |
||||
1698 | ->expects($this->exactly(3)) |
||||
1699 | ->method('canCreate'); |
||||
1700 | |||||
1701 | $mockPageHitsCache = $this->getMockBuilder($pageClass) |
||||
0 ignored issues
–
show
The function
PHPUnit\Framework\MockOb...ckBuilder::setMethods() has been deprecated: https://github.com/sebastianbergmann/phpunit/pull/3687
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This function has been deprecated. The supplier of the function has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead. ![]() |
|||||
1702 | ->setMethods(['canCreate']) |
||||
1703 | ->getMock(); |
||||
1704 | $mockPageHitsCache |
||||
1705 | ->expects($this->never()) |
||||
1706 | ->method('canCreate'); |
||||
1707 | |||||
1708 | // Initially, cache misses (1) |
||||
1709 | Injector::inst()->registerService($mockPageMissesCache, $pageClass); |
||||
1710 | $title = $siteTree->getTreeTitle(); |
||||
1711 | $this->assertNotNull($title); |
||||
1712 | |||||
1713 | // Now it hits |
||||
1714 | Injector::inst()->registerService($mockPageHitsCache, $pageClass); |
||||
1715 | $title = $siteTree->getTreeTitle(); |
||||
1716 | $this->assertNotNull($title); |
||||
1717 | |||||
1718 | |||||
1719 | // Mutating member record invalidates cache. Misses (2) |
||||
1720 | $user->FirstName = 'changed'; |
||||
1721 | $user->write(); |
||||
1722 | Injector::inst()->registerService($mockPageMissesCache, $pageClass); |
||||
1723 | $title = $siteTree->getTreeTitle(); |
||||
1724 | $this->assertNotNull($title); |
||||
1725 | |||||
1726 | // Now it hits again |
||||
1727 | Injector::inst()->registerService($mockPageHitsCache, $pageClass); |
||||
1728 | $title = $siteTree->getTreeTitle(); |
||||
1729 | $this->assertNotNull($title); |
||||
1730 | |||||
1731 | // Different user. Misses. (3) |
||||
1732 | $user = $this->objFromFixture(Member::class, 'editor'); |
||||
1733 | Security::setCurrentUser($user); |
||||
1734 | Injector::inst()->registerService($mockPageMissesCache, $pageClass); |
||||
1735 | $title = $siteTree->getTreeTitle(); |
||||
1736 | $this->assertNotNull($title); |
||||
1737 | } |
||||
1738 | |||||
1739 | public function testDependentPagesOnUnsavedRecord() |
||||
1740 | { |
||||
1741 | $record = new SiteTree(); |
||||
1742 | $pages = $record->DependentPages(); |
||||
1743 | $this->assertCount(0, $pages, 'Unsaved pages should have no dependent pages'); |
||||
1744 | } |
||||
1745 | } |
||||
1746 |
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