Passed
Push — master ( 7115d0...94e88b )
by Robbie
05:00
created

testTwoPagesWithSameURLOnDifferentSubsites()   B

Complexity

Conditions 1
Paths 1

Size

Total Lines 26
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

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