Passed
Pull Request — master (#326)
by Robbie
04:32
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 9.4285
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\Model\SiteTree;
9
use SilverStripe\Control\Director;
10
use SilverStripe\Core\Config\Config;
11
use SilverStripe\Core\Convert;
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
25
class SiteTreeSubsitesTest extends BaseSubsiteTest
26
{
27
    protected static $fixture_file = 'SubsiteTest.yml';
28
29
    protected static $extra_dataobjects = [
30
        TestClassA::class,
31
        TestClassB::class,
32
        TestErrorPage::class
33
    ];
34
35
    protected static $illegal_extensions = [
36
        SiteTree::class => ['Translatable'] // @todo implement Translatable namespace
37
    ];
38
39
    public function testPagesInDifferentSubsitesCanShareURLSegment()
40
    {
41
        $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...
42
        $subsite1 = $this->objFromFixture(Subsite::class, 'subsite1');
43
44
        $pageMain = new SiteTree();
45
        $pageMain->URLSegment = 'testpage';
46
        $pageMain->write();
47
        $pageMain->copyVersionToStage('Stage', 'Live');
48
49
        $pageMainOther = new SiteTree();
50
        $pageMainOther->URLSegment = 'testpage';
51
        $pageMainOther->write();
52
        $pageMainOther->copyVersionToStage('Stage', 'Live');
53
54
        $this->assertNotEquals(
55
            $pageMain->URLSegment,
56
            $pageMainOther->URLSegment,
57
            'Pages in same subsite cant share the same URL'
58
        );
59
60
        Subsite::changeSubsite($subsite1->ID);
61
62
        $pageSubsite1 = new SiteTree();
63
        $pageSubsite1->URLSegment = 'testpage';
64
        $pageSubsite1->write();
65
        $pageSubsite1->copyVersionToStage('Stage', 'Live');
66
67
        $this->assertEquals(
68
            $pageMain->URLSegment,
69
            $pageSubsite1->URLSegment,
70
            'Pages in different subsites can share the same URL'
71
        );
72
    }
73
74
    public function testBasicSanity()
75
    {
76
        $this->assertInstanceOf(SiteConfig::class, singleton(SiteTree::class)->getSiteConfig());
77
        // The following assert is breaking in Translatable.
78
        $this->assertInstanceOf(FieldList::class, singleton(SiteTree::class)->getCMSFields());
79
        $this->assertInstanceOf(FieldList::class, singleton(SubsitesVirtualPage::class)->getCMSFields());
80
        $this->assertTrue(is_array(singleton(SiteTreeSubsites::class)->extraStatics()));
81
    }
82
83
    public function errorPageLocationsProvider()
84
    {
85
        return [
86
            ['domaintest1', '/error-500-one.example.org.html'],
87
            ['domaintestVagrant', '/error-500-localhost8080.html']
88
        ];
89
    }
90
91
    /**
92
     * @dataProvider errorPageLocationsProvider
93
     */
94
    public function testErrorPageLocations($subsiteFixtureName, $expectedFilename)
95
    {
96
        $static_path = Config::inst()->get(ErrorPage::class, 'static_filepath');
97
98
        $subsite = $this->objFromFixture(Subsite::class, $subsiteFixtureName);
99
        $expected_path = $static_path . $expectedFilename;
100
101
        Subsite::changeSubsite($subsite->ID);
102
        $path = TestErrorPage::get_error_filename_spy(500);
103
104
        $this->assertEquals($expected_path, $path);
105
    }
106
107
    public function testCanEditSiteTree()
108
    {
109
        $admin = $this->objFromFixture(Member::class, 'admin');
110
        $subsite1member = $this->objFromFixture(Member::class, 'subsite1member');
111
        $subsite2member = $this->objFromFixture(Member::class, 'subsite2member');
112
        $mainpage = $this->objFromFixture('Page', 'home');
113
        $subsite1page = $this->objFromFixture('Page', 'subsite1_home');
114
        $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...
115
        $subsite1 = $this->objFromFixture(Subsite::class, 'subsite1');
116
        $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...
117
118
        // Cant pass member as arguments to canEdit() because of GroupSubsites
119
        $this->logInAs($admin);
120
121
        $this->assertTrue(
122
            (bool)$subsite1page->canEdit(),
123
            'Administrators can edit all subsites'
124
        );
125
126
        // @todo: Workaround because GroupSubsites->augmentSQL() is relying on session state
127
        Subsite::changeSubsite($subsite1);
128
129
        $this->logInAs($subsite1member->ID);
130
        $this->assertTrue(
131
            (bool)$subsite1page->canEdit(),
132
            'Members can edit pages on a subsite if they are in a group belonging to this subsite'
133
        );
134
135
        $this->logInAs($subsite2member->ID);
136
        $this->assertFalse(
137
            (bool)$subsite1page->canEdit(),
138
            'Members cant edit pages on a subsite if they are not in a group belonging to this subsite'
139
        );
140
141
        // @todo: Workaround because GroupSubsites->augmentSQL() is relying on session state
142
        Subsite::changeSubsite(0);
143
        $this->assertFalse(
144
            $mainpage->canEdit(),
145
            'Members cant edit pages on the main site if they are not in a group allowing this'
146
        );
147
    }
148
149
    /**
150
     * Similar to {@link SubsitesVirtualPageTest->testSubsiteVirtualPageCanHaveSameUrlsegmentAsOtherSubsite()}.
151
     */
152
    public function testTwoPagesWithSameURLOnDifferentSubsites()
153
    {
154
        // Set up a couple of pages with the same URL on different subsites
155
        $s1 = $this->objFromFixture(Subsite::class, 'domaintest1');
156
        $s2 = $this->objFromFixture(Subsite::class, 'domaintest2');
157
158
        $p1 = new SiteTree();
159
        $p1->Title = $p1->URLSegment = 'test-page';
160
        $p1->SubsiteID = $s1->ID;
161
        $p1->write();
162
163
        $p2 = new SiteTree();
164
        $p2->Title = $p1->URLSegment = 'test-page';
165
        $p2->SubsiteID = $s2->ID;
166
        $p2->write();
167
168
        // Check that the URLs weren't modified in our set-up
169
        $this->assertEquals('test-page', $p1->URLSegment);
170
        $this->assertEquals('test-page', $p2->URLSegment);
171
172
        // Check that if we switch between the different subsites, we receive the correct pages
173
        Subsite::changeSubsite($s1);
174
        $this->assertEquals($p1->ID, SiteTree::get_by_link('test-page')->ID);
175
176
        Subsite::changeSubsite($s2);
177
        $this->assertEquals($p2->ID, SiteTree::get_by_link('test-page')->ID);
178
    }
179
180
    public function testPageTypesBlacklistInClassDropdown()
181
    {
182
        $this->logInAs('editor');
183
184
        $s1 = $this->objFromFixture(Subsite::class, 'domaintest1');
185
        $s2 = $this->objFromFixture(Subsite::class, 'domaintest2');
186
        $page = singleton(SiteTree::class);
187
188
        $s1->PageTypeBlacklist = implode(',', [TestClassA::class, ErrorPage::class]);
189
        $s1->write();
190
191
        Subsite::changeSubsite($s1);
192
        $settingsFields = $page->getSettingsFields()->dataFieldByName('ClassName')->getSource();
193
194
        $this->assertArrayNotHasKey(
195
            ErrorPage::class,
196
            $settingsFields
197
        );
198
        $this->assertArrayNotHasKey(
199
            TestClassA::class,
200
            $settingsFields
201
        );
202
        $this->assertArrayHasKey(
203
            TestClassB::class,
204
            $settingsFields
205
        );
206
207
        Subsite::changeSubsite($s2);
208
        $settingsFields = $page->getSettingsFields()->dataFieldByName('ClassName')->getSource();
209
        $this->assertArrayHasKey(
210
            ErrorPage::class,
211
            $settingsFields
212
        );
213
        $this->assertArrayHasKey(
214
            TestClassA::class,
215
            $settingsFields
216
        );
217
        $this->assertArrayHasKey(
218
            TestClassB::class,
219
            $settingsFields
220
        );
221
    }
222
223
    public function testCopyToSubsite()
224
    {
225
        // Remove baseurl if testing in subdir
226
        Config::modify()->set(Director::class, 'alternate_base_url', '/');
227
228
        /** @var Subsite $otherSubsite */
229
        $otherSubsite = $this->objFromFixture(Subsite::class, 'subsite1');
230
        $staffPage = $this->objFromFixture(Page::class, 'staff'); // nested page
231
        $contactPage = $this->objFromFixture(Page::class, 'contact'); // top level page
232
233
        $staffPage2 = $staffPage->duplicateToSubsite($otherSubsite->ID);
234
        $contactPage2 = $contactPage->duplicateToSubsite($otherSubsite->ID);
235
236
        $this->assertNotEquals($staffPage->ID, $staffPage2->ID);
237
        $this->assertNotEquals($staffPage->SubsiteID, $staffPage2->SubsiteID);
238
        $this->assertNotEquals($contactPage->ID, $contactPage2->ID);
239
        $this->assertNotEquals($contactPage->SubsiteID, $contactPage2->SubsiteID);
240
        $this->assertEmpty($staffPage2->ParentID);
241
        $this->assertEmpty($contactPage2->ParentID);
242
        $this->assertNotEmpty($staffPage->ParentID);
243
        $this->assertEmpty($contactPage->ParentID);
244
245
        // Staff is shifted to top level and given a unique url segment
246
        $domain = $otherSubsite->domain();
247
        $this->assertEquals('http://' . $domain . '/staff-2/', $staffPage2->AbsoluteLink());
248
        $this->assertEquals('http://' . $domain . '/contact-us-2/', $contactPage2->AbsoluteLink());
249
    }
250
251
    public function testPageTypesBlacklistInCMSMain()
252
    {
253
        $this->logInAs('editor');
254
255
        $cmsmain = new CMSMain();
256
257
        $s1 = $this->objFromFixture(Subsite::class, 'domaintest1');
258
        $s2 = $this->objFromFixture(Subsite::class, 'domaintest2');
259
260
        $s1->PageTypeBlacklist = implode(',', [TestClassA::class, ErrorPage::class]);
261
        $s1->write();
262
263
        Subsite::changeSubsite($s1);
264
        $hints = Convert::json2array($cmsmain->SiteTreeHints());
265
        $classes = $hints['Root']['disallowedChildren'];
266
        $this->assertContains(ErrorPage::class, $classes);
267
        $this->assertContains(TestClassA::class, $classes);
268
        $this->assertNotContains(TestClassB::class, $classes);
269
270
        Subsite::changeSubsite($s2);
271
        $hints = Convert::json2array($cmsmain->SiteTreeHints());
272
        $classes = $hints['Root']['disallowedChildren'];
273
        $this->assertNotContains(ErrorPage::class, $classes);
274
        $this->assertNotContains(TestClassA::class, $classes);
275
        $this->assertNotContains(TestClassB::class, $classes);
276
    }
277
278
    /**
279
     * Tests that url segments between subsites don't conflict, but do conflict within them
280
     */
281
    public function testValidateURLSegment()
282
    {
283
        $this->logInWithPermission('ADMIN');
284
        // Saving existing page in the same subsite doesn't change urls
285
        $mainHome = $this->objFromFixture(Page::class, 'home');
286
        $mainSubsiteID = $this->idFromFixture(Subsite::class, 'main');
287
        Subsite::changeSubsite($mainSubsiteID);
288
        $mainHome->Content = '<p>Some new content</p>';
289
        $mainHome->write();
290
        $this->assertEquals('home', $mainHome->URLSegment);
291
        $mainHome->doPublish();
292
        $mainHomeLive = Versioned::get_one_by_stage('Page', 'Live', sprintf('"SiteTree"."ID" = \'%d\'', $mainHome->ID));
293
        $this->assertEquals('home', $mainHomeLive->URLSegment);
294
295
        // Saving existing page in another subsite doesn't change urls
296
        Subsite::changeSubsite($mainSubsiteID);
297
        $subsite1Home = $this->objFromFixture('Page', 'subsite1_home');
298
        $subsite1Home->Content = '<p>In subsite 1</p>';
299
        $subsite1Home->write();
300
        $this->assertEquals('home', $subsite1Home->URLSegment);
301
        $subsite1Home->doPublish();
302
        $subsite1HomeLive = Versioned::get_one_by_stage(
303
            'Page',
304
            'Live',
305
            sprintf('"SiteTree"."ID" = \'%d\'', $subsite1Home->ID)
306
        );
307
        $this->assertEquals('home', $subsite1HomeLive->URLSegment);
308
309
        // Creating a new page in a subsite doesn't conflict with urls in other subsites
310
        $subsite1ID = $this->idFromFixture(Subsite::class, 'subsite1');
311
        Subsite::changeSubsite($subsite1ID);
312
        $subsite1NewPage = new Page();
313
        $subsite1NewPage->SubsiteID = $subsite1ID;
314
        $subsite1NewPage->Title = 'Important Page (Subsite 1)';
315
        $subsite1NewPage->URLSegment = 'important-page'; // Also exists in main subsite
316
        $subsite1NewPage->write();
317
        $this->assertEquals('important-page', $subsite1NewPage->URLSegment);
318
        $subsite1NewPage->doPublish();
319
        $subsite1NewPageLive = Versioned::get_one_by_stage(
320
            'Page',
321
            'Live',
322
            sprintf('"SiteTree"."ID" = \'%d\'', $subsite1NewPage->ID)
323
        );
324
        $this->assertEquals('important-page', $subsite1NewPageLive->URLSegment);
325
326
        // Creating a new page in a subsite DOES conflict with urls in the same subsite
327
        $subsite1NewPage2 = new Page();
328
        $subsite1NewPage2->SubsiteID = $subsite1ID;
329
        $subsite1NewPage2->Title = 'Important Page (Subsite 1)';
330
        $subsite1NewPage2->URLSegment = 'important-page'; // Also exists in main subsite
331
        $subsite1NewPage2->write();
332
        $this->assertEquals('important-page-2', $subsite1NewPage2->URLSegment);
333
        $subsite1NewPage2->doPublish();
334
        $subsite1NewPage2Live = Versioned::get_one_by_stage(
335
            'Page',
336
            'Live',
337
            sprintf('"SiteTree"."ID" = \'%d\'', $subsite1NewPage2->ID)
338
        );
339
        $this->assertEquals('important-page-2', $subsite1NewPage2Live->URLSegment);
340
341
        // Original page is left un-modified
342
        $mainSubsiteImportantPageID = $this->idFromFixture('Page', 'importantpage');
343
        $mainSubsiteImportantPage = Page::get()->byID($mainSubsiteImportantPageID);
344
        $this->assertEquals('important-page', $mainSubsiteImportantPage->URLSegment);
345
        $mainSubsiteImportantPage->Content = '<p>New Important Page Content</p>';
346
        $mainSubsiteImportantPage->write();
347
        $this->assertEquals('important-page', $mainSubsiteImportantPage->URLSegment);
348
    }
349
350 View Code Duplication
    public function testCopySubsiteWithChildren()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
351
    {
352
        $page = $this->objFromFixture('Page', 'about');
353
        $newSubsite = $this->objFromFixture(Subsite::class, 'subsite1');
354
355
        $moved = $page->duplicateToSubsite($newSubsite->ID, true);
356
        $this->assertEquals($moved->SubsiteID, $newSubsite->ID, 'Ensure returned records are on new subsite');
357
        $this->assertEquals(
358
            $moved->AllChildren()->count(),
359
            $page->AllChildren()->count(),
360
            'All pages are copied across'
361
        );
362
    }
363
364 View Code Duplication
    public function testCopySubsiteWithoutChildren()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
365
    {
366
        $page = $this->objFromFixture('Page', 'about');
367
        $newSubsite = $this->objFromFixture(Subsite::class, 'subsite2');
368
369
        $moved = $page->duplicateToSubsite($newSubsite->ID, false);
370
        $this->assertEquals($moved->SubsiteID, $newSubsite->ID, 'Ensure returned records are on new subsite');
371
        $this->assertEquals($moved->AllChildren()->count(), 0, 'All pages are copied across');
372
    }
373
374
    public function testIfSubsiteThemeIsSetToThemeList()
375
    {
376
        $defaultThemes = ['default'];
377
        SSViewer::set_themes($defaultThemes);
378
379
        $subsitePage = $this->objFromFixture(Page::class, 'home');
380
        Subsite::changeSubsite($subsitePage->SubsiteID);
381
        $controller = ModelAsController::controller_for($subsitePage);
382
        SiteTree::singleton()->extend('contentcontrollerInit', $controller);
383
384
        $this->assertEquals(
385
            SSViewer::get_themes(),
386
            $defaultThemes,
387
            'Themes should not be modified when Subsite has no theme defined'
388
        );
389
390
        $pageWithTheme = $this->objFromFixture(Page::class, 'subsite1_home');
391
        Subsite::changeSubsite($pageWithTheme->SubsiteID);
392
        $controller = ModelAsController::controller_for($pageWithTheme);
393
        SiteTree::singleton()->extend('contentcontrollerInit', $controller);
394
        $subsiteTheme = $pageWithTheme->Subsite()->Theme;
395
396
        $allThemes = SSViewer::get_themes();
397
398
        $this->assertContains(
399
            $subsiteTheme,
400
            $allThemes,
401
            'Themes should be modified when Subsite has theme defined'
402
        );
403
404
        $this->assertEquals(
405
            $subsiteTheme,
406
            array_shift($allThemes),
407
            'Subsite theme should be prepeded to theme list'
408
        );
409
    }
410
411
    public function provideAlternateAbsoluteLink()
412
    {
413
        return [
414
            ['home', null, 'http://localhost/'],
415
            ['home', 'myaction', 'http://localhost/home/myaction'],
416
            ['contact', null, 'http://localhost/contact-us/'],
417
            ['contact', 'myaction', 'http://localhost/contact-us/myaction'],
418
            ['subsite1_home', null, 'http://subsite1.localhost/'],
419
            ['subsite1_home', 'myaction', 'http://subsite1.localhost/home/myaction'],
420
            ['subsite1_contactus', null, 'http://subsite1.localhost/contact-us/'],
421
            ['subsite1_contactus', 'myaction', 'http://subsite1.localhost/contact-us/myaction']
422
        ];
423
    }
424
425
    /**
426
     * @dataProvider provideAlternateAbsoluteLink
427
     * @param name $pageFixtureName
0 ignored issues
show
Bug introduced by
The type SilverStripe\Subsites\Tests\name 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...
428
     * @param string|null $action
429
     * @param string $expectedAbsoluteLink
430
     */
431
    public function testAlternateAbsoluteLink($pageFixtureName, $action, $expectedAbsoluteLink)
432
    {
433
        /** @var Page $page */
434
        $page = $this->objFromFixture(Page::class, $pageFixtureName);
435
436
        $result = $page->AbsoluteLink($action);
437
438
        $this->assertEquals($expectedAbsoluteLink, $result);
439
    }
440
}
441