Passed
Push — master ( 483a86...be3bca )
by Robbie
05:54 queued 10s
created

SiteTreeSubsitesTest::testBasicSanity()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 4
c 1
b 0
f 0
nc 1
nop 0
dl 0
loc 7
rs 10
1
<?php
2
3
namespace SilverStripe\Subsites\Tests;
4
5
use Page;
0 ignored issues
show
Bug introduced by
The type Page 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. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
6
use SilverStripe\CMS\Controllers\CMSMain;
7
use SilverStripe\CMS\Controllers\ModelAsController;
8
use SilverStripe\CMS\Forms\SiteTreeURLSegmentField;
9
use SilverStripe\CMS\Model\SiteTree;
10
use SilverStripe\Control\Director;
11
use SilverStripe\Core\Config\Config;
12
use SilverStripe\ErrorPage\ErrorPage;
13
use SilverStripe\Forms\FieldList;
14
use SilverStripe\Security\Member;
15
use SilverStripe\SiteConfig\SiteConfig;
16
use SilverStripe\Subsites\Extensions\SiteTreeSubsites;
17
use SilverStripe\Subsites\Model\Subsite;
18
use SilverStripe\Subsites\Pages\SubsitesVirtualPage;
19
use SilverStripe\Subsites\Tests\SiteTreeSubsitesTest\TestClassA;
20
use SilverStripe\Subsites\Tests\SiteTreeSubsitesTest\TestClassB;
21
use SilverStripe\Subsites\Tests\SiteTreeSubsitesTest\TestErrorPage;
22
use SilverStripe\Versioned\Versioned;
23
use SilverStripe\View\SSViewer;
24
use TractorCow\Fluent\Extension\FluentSiteTreeExtension;
0 ignored issues
show
Bug introduced by
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. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
25
26
class SiteTreeSubsitesTest extends BaseSubsiteTest
27
{
28
    protected static $fixture_file = 'SubsiteTest.yml';
29
30
    protected static $extra_dataobjects = [
31
        TestClassA::class,
32
        TestClassB::class,
33
        TestErrorPage::class
34
    ];
35
36
    protected static $illegal_extensions = [
37
        SiteTree::class => [
38
            FluentSiteTreeExtension::class,
39
        ],
40
    ];
41
42
    protected function setUp()
43
    {
44
        // We have our own home page fixtures, prevent the default one being created in this test suite.
45
        Config::modify()->set(SiteTree::class, 'create_default_pages', false);
46
47
        parent::setUp();
48
    }
49
50
    public function testPagesInDifferentSubsitesCanShareURLSegment()
51
    {
52
        $subsiteMain = $this->objFromFixture(Subsite::class, 'main');
0 ignored issues
show
Unused Code introduced by
The assignment to $subsiteMain is dead and can be removed.
Loading history...
53
        $subsite1 = $this->objFromFixture(Subsite::class, 'subsite1');
54
55
        $pageMain = new SiteTree();
56
        $pageMain->URLSegment = 'testpage';
57
        $pageMain->write();
58
        $pageMain->copyVersionToStage('Stage', 'Live');
59
60
        $pageMainOther = new SiteTree();
61
        $pageMainOther->URLSegment = 'testpage';
62
        $pageMainOther->write();
63
        $pageMainOther->copyVersionToStage('Stage', 'Live');
64
65
        $this->assertNotEquals(
66
            $pageMain->URLSegment,
67
            $pageMainOther->URLSegment,
68
            'Pages in same subsite cant share the same URL'
69
        );
70
71
        Subsite::changeSubsite($subsite1->ID);
72
73
        $pageSubsite1 = new SiteTree();
74
        $pageSubsite1->URLSegment = 'testpage';
75
        $pageSubsite1->write();
76
        $pageSubsite1->copyVersionToStage('Stage', 'Live');
77
78
        $this->assertEquals(
79
            $pageMain->URLSegment,
80
            $pageSubsite1->URLSegment,
81
            'Pages in different subsites can share the same URL'
82
        );
83
    }
84
85
    public function testBasicSanity()
86
    {
87
        $this->assertInstanceOf(SiteConfig::class, singleton(SiteTree::class)->getSiteConfig());
88
        // The following assert is breaking in Translatable.
89
        $this->assertInstanceOf(FieldList::class, singleton(SiteTree::class)->getCMSFields());
90
        $this->assertInstanceOf(FieldList::class, singleton(SubsitesVirtualPage::class)->getCMSFields());
91
        $this->assertTrue(is_array(singleton(SiteTreeSubsites::class)->extraStatics()));
92
    }
93
94
    public function errorPageLocationsProvider()
95
    {
96
        return [
97
            ['domaintest1', '/error-500-one.example.org.html'],
98
            ['domaintestVagrant', '/error-500-localhost8080.html']
99
        ];
100
    }
101
102
    /**
103
     * @dataProvider errorPageLocationsProvider
104
     */
105
    public function testErrorPageLocations($subsiteFixtureName, $expectedFilename)
106
    {
107
        $static_path = Config::inst()->get(ErrorPage::class, 'static_filepath');
108
109
        $subsite = $this->objFromFixture(Subsite::class, $subsiteFixtureName);
110
        $expected_path = $static_path . $expectedFilename;
111
112
        Subsite::changeSubsite($subsite->ID);
113
        $path = TestErrorPage::get_error_filename_spy(500);
114
115
        $this->assertEquals($expected_path, $path);
116
    }
117
118
    public function testCanEditSiteTree()
119
    {
120
        $admin = $this->objFromFixture(Member::class, 'admin');
121
        $subsite1member = $this->objFromFixture(Member::class, 'subsite1member');
122
        $subsite2member = $this->objFromFixture(Member::class, 'subsite2member');
123
        $mainpage = $this->objFromFixture('Page', 'home');
124
        $subsite1page = $this->objFromFixture('Page', 'subsite1_home');
125
        $subsite2page = $this->objFromFixture('Page', 'subsite2_home');
0 ignored issues
show
Unused Code introduced by
The assignment to $subsite2page is dead and can be removed.
Loading history...
126
        $subsite1 = $this->objFromFixture(Subsite::class, 'subsite1');
127
        $subsite2 = $this->objFromFixture(Subsite::class, 'subsite2');
0 ignored issues
show
Unused Code introduced by
The assignment to $subsite2 is dead and can be removed.
Loading history...
128
129
        // Cant pass member as arguments to canEdit() because of GroupSubsites
130
        $this->logInAs($admin);
131
132
        $this->assertTrue(
133
            (bool)$subsite1page->canEdit(),
134
            'Administrators can edit all subsites'
135
        );
136
137
        // @todo: Workaround because GroupSubsites->augmentSQL() is relying on session state
138
        Subsite::changeSubsite($subsite1);
139
140
        $this->logInAs($subsite1member->ID);
141
        $this->assertTrue(
142
            (bool)$subsite1page->canEdit(),
143
            'Members can edit pages on a subsite if they are in a group belonging to this subsite'
144
        );
145
146
        $this->logInAs($subsite2member->ID);
147
        $this->assertFalse(
148
            (bool)$subsite1page->canEdit(),
149
            'Members cant edit pages on a subsite if they are not in a group belonging to this subsite'
150
        );
151
152
        // @todo: Workaround because GroupSubsites->augmentSQL() is relying on session state
153
        Subsite::changeSubsite(0);
154
        $this->assertFalse(
155
            $mainpage->canEdit(),
156
            'Members cant edit pages on the main site if they are not in a group allowing this'
157
        );
158
    }
159
160
    /**
161
     * Similar to {@link SubsitesVirtualPageTest->testSubsiteVirtualPageCanHaveSameUrlsegmentAsOtherSubsite()}.
162
     */
163
    public function testTwoPagesWithSameURLOnDifferentSubsites()
164
    {
165
        // Set up a couple of pages with the same URL on different subsites
166
        $s1 = $this->objFromFixture(Subsite::class, 'domaintest1');
167
        $s2 = $this->objFromFixture(Subsite::class, 'domaintest2');
168
169
        $p1 = new SiteTree();
170
        $p1->Title = $p1->URLSegment = 'test-page';
171
        $p1->SubsiteID = $s1->ID;
172
        $p1->write();
173
174
        $p2 = new SiteTree();
175
        $p2->Title = $p1->URLSegment = 'test-page';
176
        $p2->SubsiteID = $s2->ID;
177
        $p2->write();
178
179
        // Check that the URLs weren't modified in our set-up
180
        $this->assertEquals('test-page', $p1->URLSegment);
181
        $this->assertEquals('test-page', $p2->URLSegment);
182
183
        // Check that if we switch between the different subsites, we receive the correct pages
184
        Subsite::changeSubsite($s1);
185
        $this->assertEquals($p1->ID, SiteTree::get_by_link('test-page')->ID);
186
187
        Subsite::changeSubsite($s2);
188
        $this->assertEquals($p2->ID, SiteTree::get_by_link('test-page')->ID);
189
    }
190
191
    public function testPageTypesBlacklistInClassDropdown()
192
    {
193
        $this->logInAs('editor');
194
195
        $s1 = $this->objFromFixture(Subsite::class, 'domaintest1');
196
        $s2 = $this->objFromFixture(Subsite::class, 'domaintest2');
197
        $page = singleton(SiteTree::class);
198
199
        $s1->PageTypeBlacklist = json_encode([TestClassA::class, ErrorPage::class]);
200
        $s1->write();
201
202
        Subsite::changeSubsite($s1);
203
        $settingsFields = $page->getSettingsFields()->dataFieldByName('ClassName')->getSource();
204
205
        $this->assertArrayNotHasKey(
206
            ErrorPage::class,
207
            $settingsFields
208
        );
209
        $this->assertArrayNotHasKey(
210
            TestClassA::class,
211
            $settingsFields
212
        );
213
        $this->assertArrayHasKey(
214
            TestClassB::class,
215
            $settingsFields
216
        );
217
218
        Subsite::changeSubsite($s2);
219
        $settingsFields = $page->getSettingsFields()->dataFieldByName('ClassName')->getSource();
220
        $this->assertArrayHasKey(
221
            ErrorPage::class,
222
            $settingsFields
223
        );
224
        $this->assertArrayHasKey(
225
            TestClassA::class,
226
            $settingsFields
227
        );
228
        $this->assertArrayHasKey(
229
            TestClassB::class,
230
            $settingsFields
231
        );
232
    }
233
234
    public function testCopyToSubsite()
235
    {
236
        // Remove baseurl if testing in subdir
237
        Config::modify()->set(Director::class, 'alternate_base_url', '/');
238
239
        /** @var Subsite $otherSubsite */
240
        $otherSubsite = $this->objFromFixture(Subsite::class, 'subsite1');
241
        $staffPage = $this->objFromFixture(Page::class, 'staff'); // nested page
242
        $contactPage = $this->objFromFixture(Page::class, 'contact'); // top level page
243
244
        $staffPage2 = $staffPage->duplicateToSubsite($otherSubsite->ID);
245
        $contactPage2 = $contactPage->duplicateToSubsite($otherSubsite->ID);
246
247
        $this->assertNotEquals($staffPage->ID, $staffPage2->ID);
248
        $this->assertNotEquals($staffPage->SubsiteID, $staffPage2->SubsiteID);
249
        $this->assertNotEquals($contactPage->ID, $contactPage2->ID);
250
        $this->assertNotEquals($contactPage->SubsiteID, $contactPage2->SubsiteID);
251
        $this->assertEmpty($staffPage2->ParentID);
252
        $this->assertEmpty($contactPage2->ParentID);
253
        $this->assertNotEmpty($staffPage->ParentID);
254
        $this->assertEmpty($contactPage->ParentID);
255
256
        // Staff is shifted to top level and given a unique url segment
257
        $domain = $otherSubsite->domain();
258
        $this->assertEquals('http://' . $domain . '/staff-2/', $staffPage2->AbsoluteLink());
259
        $this->assertEquals('http://' . $domain . '/contact-us-2/', $contactPage2->AbsoluteLink());
260
    }
261
262
    public function testPageTypesBlacklistInCMSMain()
263
    {
264
        $this->logInAs('editor');
265
266
        $s1 = $this->objFromFixture(Subsite::class, 'domaintest1');
267
        $s2 = $this->objFromFixture(Subsite::class, 'domaintest2');
268
269
        $s1->PageTypeBlacklist = json_encode([TestClassA::class, ErrorPage::class]);
270
        $s1->write();
271
272
        Subsite::changeSubsite($s1);
273
        $cmsmain = CMSMain::create();
274
        $hints = json_decode($cmsmain->SiteTreeHints(), true);
275
        $classes = $hints['Root']['disallowedChildren'];
276
        $this->assertContains(ErrorPage::class, $classes);
277
        $this->assertContains(TestClassA::class, $classes);
278
        $this->assertNotContains(TestClassB::class, $classes);
279
280
        Subsite::changeSubsite($s2);
281
        // SS 4.1 and above
282
        if ($cmsmain->hasMethod('getHintsCache')) {
283
            $cmsmain->getHintsCache()->clear();
284
        }
285
        $hints = json_decode($cmsmain->SiteTreeHints(), true);
286
287
        $classes = $hints['Root']['disallowedChildren'];
288
        $this->assertNotContains(ErrorPage::class, $classes);
289
        $this->assertNotContains(TestClassA::class, $classes);
290
        $this->assertNotContains(TestClassB::class, $classes);
291
    }
292
293
    /**
294
     * Tests that url segments between subsites don't conflict, but do conflict within them
295
     */
296
    public function testValidateURLSegment()
297
    {
298
        $this->logInWithPermission('ADMIN');
299
        // Saving existing page in the same subsite doesn't change urls
300
        $mainHome = $this->objFromFixture(Page::class, 'home');
301
        $mainSubsiteID = $this->idFromFixture(Subsite::class, 'main');
302
        Subsite::changeSubsite($mainSubsiteID);
303
        $mainHome->Content = '<p>Some new content</p>';
304
        $mainHome->write();
305
        $this->assertEquals('home', $mainHome->URLSegment);
306
        $mainHome->publishRecursive();
307
        $mainHomeLive = Versioned::get_one_by_stage('Page', 'Live', sprintf('"SiteTree"."ID" = \'%d\'', $mainHome->ID));
308
        $this->assertEquals('home', $mainHomeLive->URLSegment);
309
310
        // Saving existing page in another subsite doesn't change urls
311
        Subsite::changeSubsite($mainSubsiteID);
312
        $subsite1Home = $this->objFromFixture('Page', 'subsite1_home');
313
        $subsite1Home->Content = '<p>In subsite 1</p>';
314
        $subsite1Home->write();
315
        $this->assertEquals('home', $subsite1Home->URLSegment);
316
        $subsite1Home->publishRecursive();
317
        $subsite1HomeLive = Versioned::get_one_by_stage(
318
            'Page',
319
            'Live',
320
            sprintf('"SiteTree"."ID" = \'%d\'', $subsite1Home->ID)
321
        );
322
        $this->assertEquals('home', $subsite1HomeLive->URLSegment);
323
324
        // Creating a new page in a subsite doesn't conflict with urls in other subsites
325
        $subsite1ID = $this->idFromFixture(Subsite::class, 'subsite1');
326
        Subsite::changeSubsite($subsite1ID);
327
        $subsite1NewPage = new Page();
328
        $subsite1NewPage->SubsiteID = $subsite1ID;
329
        $subsite1NewPage->Title = 'Important Page (Subsite 1)';
330
        $subsite1NewPage->URLSegment = 'important-page'; // Also exists in main subsite
331
        $subsite1NewPage->write();
332
        $this->assertEquals('important-page', $subsite1NewPage->URLSegment);
333
        $subsite1NewPage->publishRecursive();
334
        $subsite1NewPageLive = Versioned::get_one_by_stage(
335
            'Page',
336
            'Live',
337
            sprintf('"SiteTree"."ID" = \'%d\'', $subsite1NewPage->ID)
338
        );
339
        $this->assertEquals('important-page', $subsite1NewPageLive->URLSegment);
340
341
        // Creating a new page in a subsite DOES conflict with urls in the same subsite
342
        $subsite1NewPage2 = new Page();
343
        $subsite1NewPage2->SubsiteID = $subsite1ID;
344
        $subsite1NewPage2->Title = 'Important Page (Subsite 1)';
345
        $subsite1NewPage2->URLSegment = 'important-page'; // Also exists in main subsite
346
        $subsite1NewPage2->write();
347
        $this->assertEquals('important-page-2', $subsite1NewPage2->URLSegment);
348
        $subsite1NewPage2->publishRecursive();
349
        $subsite1NewPage2Live = Versioned::get_one_by_stage(
350
            'Page',
351
            'Live',
352
            sprintf('"SiteTree"."ID" = \'%d\'', $subsite1NewPage2->ID)
353
        );
354
        $this->assertEquals('important-page-2', $subsite1NewPage2Live->URLSegment);
355
356
        // Original page is left un-modified
357
        $mainSubsiteImportantPageID = $this->idFromFixture('Page', 'importantpage');
358
        $mainSubsiteImportantPage = Page::get()->byID($mainSubsiteImportantPageID);
359
        $this->assertEquals('important-page', $mainSubsiteImportantPage->URLSegment);
360
        $mainSubsiteImportantPage->Content = '<p>New Important Page Content</p>';
361
        $mainSubsiteImportantPage->write();
362
        $this->assertEquals('important-page', $mainSubsiteImportantPage->URLSegment);
363
    }
364
365
    /**
366
     * @param bool $withChildren
367
     * @param int $expectedChildren
368
     * @dataProvider duplicateToSubsiteProvider
369
     */
370
    public function testDuplicateToSubsite($withChildren, $expectedChildren)
371
    {
372
        /** @var SiteTree $page */
373
        $page = $this->objFromFixture(Page::class, 'about');
374
        /** @var Subsite $newSubsite */
375
        $newSubsite = $this->objFromFixture(Subsite::class, 'subsite1');
376
377
        /** @var SiteTree $duplicatedPage */
378
        $duplicatedPage = $page->duplicateToSubsite($newSubsite->ID, $withChildren);
379
        $this->assertInstanceOf(SiteTree::class, $duplicatedPage, 'A new page is returned');
380
381
        $this->assertEquals($newSubsite->ID, $duplicatedPage->SubsiteID, 'Ensure returned records are on new subsite');
382
383
        $this->assertCount(1, $page->AllChildren());
384
        $this->assertCount(
385
            $expectedChildren,
386
            $duplicatedPage->AllChildren(),
387
            'Duplicated page also duplicates children'
388
        );
389
    }
390
391
    /**
392
     * @return array[]
393
     */
394
    public function duplicateToSubsiteProvider()
395
    {
396
        return [
397
            [true, 1],
398
            [false, 0],
399
        ];
400
    }
401
402
    public function testIfSubsiteThemeIsSetToThemeList()
403
    {
404
        $defaultThemes = ['default'];
405
        SSViewer::set_themes($defaultThemes);
406
407
        $subsitePage = $this->objFromFixture(Page::class, 'home');
408
        Subsite::changeSubsite($subsitePage->SubsiteID);
409
        $controller = ModelAsController::controller_for($subsitePage);
410
        SiteTree::singleton()->extend('contentcontrollerInit', $controller);
411
412
        $this->assertEquals(
413
            SSViewer::get_themes(),
414
            $defaultThemes,
415
            'Themes should not be modified when Subsite has no theme defined'
416
        );
417
418
        $pageWithTheme = $this->objFromFixture(Page::class, 'subsite1_home');
419
        Subsite::changeSubsite($pageWithTheme->SubsiteID);
420
        $controller = ModelAsController::controller_for($pageWithTheme);
421
        SiteTree::singleton()->extend('contentcontrollerInit', $controller);
422
        $subsiteTheme = $pageWithTheme->Subsite()->Theme;
423
424
        $allThemes = SSViewer::get_themes();
425
426
        $this->assertContains(
427
            $subsiteTheme,
428
            $allThemes,
429
            'Themes should be modified when Subsite has theme defined'
430
        );
431
432
        $this->assertEquals(
433
            $subsiteTheme,
434
            array_shift($allThemes),
435
            'Subsite theme should be prepeded to theme list'
436
        );
437
    }
438
439
    public function provideAlternateAbsoluteLink()
440
    {
441
        return [
442
            ['home', null, 'http://localhost/'],
443
            ['home', 'myaction', 'http://localhost/home/myaction'],
444
            ['contact', null, 'http://localhost/contact-us/'],
445
            ['contact', 'myaction', 'http://localhost/contact-us/myaction'],
446
            ['subsite1_home', null, 'http://subsite1.localhost/'],
447
            ['subsite1_home', 'myaction', 'http://subsite1.localhost/home/myaction'],
448
            ['subsite1_contactus', null, 'http://subsite1.localhost/contact-us/'],
449
            ['subsite1_contactus', 'myaction', 'http://subsite1.localhost/contact-us/myaction']
450
        ];
451
    }
452
453
    /**
454
     * @dataProvider provideAlternateAbsoluteLink
455
     * @param string $pageFixtureName
456
     * @param string|null $action
457
     * @param string $expectedAbsoluteLink
458
     */
459
    public function testAlternateAbsoluteLink($pageFixtureName, $action, $expectedAbsoluteLink)
460
    {
461
        // Setting a control value, in case base url is set for the installation under test
462
        Config::modify()->set(Director::class, 'alternate_base_url', 'http://localhost/');
463
464
        /** @var Page $page */
465
        $page = $this->objFromFixture(Page::class, $pageFixtureName);
466
467
        $result = $page->AbsoluteLink($action);
468
469
        $this->assertEquals($expectedAbsoluteLink, $result);
470
    }
471
472
    public function testURLSegmentBaseIsSetToSubsiteBaseURL()
473
    {
474
        // This subsite has a domain with 'one.example.org' as the primary domain
475
        /** @var Subsite $subsite */
476
        $subsite = $this->objFromFixture(Subsite::class, 'domaintest1');
477
        Subsite::changeSubsite($subsite);
478
479
        $page = new SiteTree();
480
        $page->SubsiteID = $subsite->ID;
481
        $page->write();
482
        $fields = $page->getCMSFields();
483
484
        /** @var SiteTreeURLSegmentField $urlSegmentField */
485
        $urlSegmentField = $fields->dataFieldByName('URLSegment');
486
        $this->assertInstanceOf(SiteTreeURLSegmentField::class, $urlSegmentField);
487
488
        $this->assertSame('http://one.example.org/', $urlSegmentField->getURLPrefix());
489
    }
490
}
491