Completed
Push — master ( 0ebf95...33622c )
by Damian
12s
created

SubsiteTest::testAllSites()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 15
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 15
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 13
nc 1
nop 0
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\Model\SiteTree;
7
use SilverStripe\Control\Director;
8
use SilverStripe\Core\Config\Config;
9
use SilverStripe\ORM\DataObject;
10
use SilverStripe\Security\Member;
11
use SilverStripe\Subsites\Model\Subsite;
12
use SilverStripe\Subsites\Model\SubsiteDomain;
13
use SilverStripe\Subsites\State\SubsiteState;
14
use UnexpectedValueException;
15
16
class SubsiteTest extends BaseSubsiteTest
17
{
18
    protected static $fixture_file = 'SubsiteTest.yml';
19
20
    /**
21
     * Original value of {@see SubSite::$strict_subdomain_matching}
22
     *
23
     * @var bool
24
     */
25
    protected $origStrictSubdomainMatching = null;
26
27
    /**
28
     * Original value of $_REQUEST
29
     *
30
     * @var array
31
     */
32
    protected $origServer = [];
33
34
    protected function setUp()
35
    {
36
        parent::setUp();
37
38
        Config::modify()->set(Director::class, 'alternate_base_url', '/');
39
        $this->origStrictSubdomainMatching = Subsite::$strict_subdomain_matching;
40
        $this->origServer = $_SERVER;
41
        Subsite::$strict_subdomain_matching = false;
42
    }
43
44
    protected function tearDown()
45
    {
46
        $_SERVER = $this->origServer;
47
        Subsite::$strict_subdomain_matching = $this->origStrictSubdomainMatching;
48
49
        parent::tearDown();
50
    }
51
52
    /**
53
     * Create a new subsite from the template and verify that all the template's pages are copied
54
     */
55
    public function testSubsiteCreation()
56
    {
57
        Subsite::$write_hostmap = false;
58
59
        // Create the instance
60
        $template = $this->objFromFixture(Subsite::class, 'main');
61
62
        // Test that changeSubsite is working
63
        Subsite::changeSubsite($template->ID);
64
        $this->assertEquals($template->ID, SubsiteState::singleton()->getSubsiteId());
65
        $tmplStaff = $this->objFromFixture('Page', 'staff');
0 ignored issues
show
Unused Code introduced by
The assignment to $tmplStaff is dead and can be removed.
Loading history...
66
        $tmplHome = DataObject::get_one('Page', "\"URLSegment\" = 'home'");
0 ignored issues
show
Unused Code introduced by
The assignment to $tmplHome is dead and can be removed.
Loading history...
67
68
        // Publish all the pages in the template, testing that DataObject::get only returns pages from the chosen subsite
69
        $pages = DataObject::get(SiteTree::class);
70
        $totalPages = $pages->count();
0 ignored issues
show
Unused Code introduced by
The assignment to $totalPages is dead and can be removed.
Loading history...
71
        foreach ($pages as $page) {
72
            $this->assertEquals($template->ID, $page->SubsiteID);
73
            $page->copyVersionToStage('Stage', 'Live');
74
        }
75
76
        // Create a new site
77
        $subsite = $template->duplicate();
78
79
        // Check title
80
        $this->assertEquals($subsite->Title, $template->Title);
81
82
        // Another test that changeSubsite is working
83
        $subsite->activate();
84
85
        $siteHome = DataObject::get_one('Page', "\"URLSegment\" = 'home'");
86
        $this->assertNotEquals($siteHome, false, 'Home Page for subsite not found');
87
        $this->assertEquals(
88
            $subsite->ID,
89
            $siteHome->SubsiteID,
90
            'createInstance() copies existing pages retaining the same URLSegment'
91
        );
92
93
        Subsite::changeSubsite(0);
94
    }
95
96
    /**
97
     * Confirm that domain lookup is working
98
     */
99
    public function testDomainLookup()
100
    {
101
        // Clear existing fixtures
102
        foreach (DataObject::get(Subsite::class) as $subsite) {
103
            $subsite->delete();
104
        }
105
        foreach (DataObject::get(SubsiteDomain::class) as $domain) {
106
            $domain->delete();
107
        }
108
109
        // Much more expressive than YML in this case
110
        $subsite1 = $this->createSubsiteWithDomains([
111
            'one.example.org' => true,
112
            'one.*' => false,
113
        ]);
114
        $subsite2 = $this->createSubsiteWithDomains([
115
            'two.mysite.com' => true,
116
            '*.mysite.com' => false,
117
            'subdomain.onmultiplesubsites.com' => false,
118
        ]);
119
        $subsite3 = $this->createSubsiteWithDomains([
120
            'three.*' => true, // wildcards in primary domain are not recommended
121
            'subdomain.unique.com' => false,
122
            '*.onmultiplesubsites.com' => false,
123
        ]);
124
125
        $this->assertEquals(
126
            $subsite3->ID,
127
            Subsite::getSubsiteIDForDomain('subdomain.unique.com'),
128
            'Full unique match'
129
        );
130
131
        $this->assertEquals(
132
            $subsite1->ID,
133
            Subsite::getSubsiteIDForDomain('one.example.org'),
134
            'Full match, doesn\'t complain about multiple matches within a single subsite'
135
        );
136
137
        $failed = false;
138
        try {
139
            Subsite::getSubsiteIDForDomain('subdomain.onmultiplesubsites.com');
140
        } catch (UnexpectedValueException $e) {
141
            $failed = true;
142
        }
143
        $this->assertTrue(
144
            $failed,
145
            'Fails on multiple matches with wildcard vs. www across multiple subsites'
146
        );
147
148
        $this->assertEquals(
149
            $subsite1->ID,
150
            Subsite::getSubsiteIDForDomain('one.unique.com'),
151
            'Fuzzy match suffixed with wildcard (rule "one.*")'
152
        );
153
154
        $this->assertEquals(
155
            $subsite2->ID,
156
            Subsite::getSubsiteIDForDomain('two.mysite.com'),
157
            'Matches correct subsite for rule'
158
        );
159
160
        $this->assertEquals(
161
            $subsite2->ID,
162
            Subsite::getSubsiteIDForDomain('other.mysite.com'),
163
            'Fuzzy match prefixed with wildcard (rule "*.mysite.com")'
164
        );
165
166
        $this->assertEquals(
167
            0,
168
            Subsite::getSubsiteIDForDomain('unknown.madeup.com'),
169
            "Doesn't match unknown subsite"
170
        );
171
    }
172
173
    public function testStrictSubdomainMatching()
174
    {
175
        // Clear existing fixtures
176
        foreach (DataObject::get(Subsite::class) as $subsite) {
177
            $subsite->delete();
178
        }
179
        foreach (DataObject::get(SubsiteDomain::class) as $domain) {
180
            $domain->delete();
181
        }
182
183
        // Much more expressive than YML in this case
184
        $subsite1 = $this->createSubsiteWithDomains([
185
            'example.org' => true,
186
            'example.com' => false,
187
            '*.wildcard.com' => false,
188
        ]);
189
        $subsite2 = $this->createSubsiteWithDomains([
190
            'www.example.org' => true,
191
            'www.wildcard.com' => false,
192
        ]);
193
194
        Subsite::$strict_subdomain_matching = false;
195
196
        $this->assertEquals(
197
            $subsite1->ID,
198
            Subsite::getSubsiteIDForDomain('example.org'),
199
            'Exact matches without strict checking when not using www prefix'
200
        );
201
        $this->assertEquals(
202
            $subsite1->ID,
203
            Subsite::getSubsiteIDForDomain('www.example.org'),
204
            'Matches without strict checking when using www prefix, still matching first domain regardless of www prefix  (falling back to subsite primary key ordering)'
205
        );
206
        $this->assertEquals(
207
            $subsite1->ID,
208
            Subsite::getSubsiteIDForDomain('www.example.com'),
209
            'Fuzzy matches without strict checking with www prefix'
210
        );
211
        $this->assertEquals(
212
            0,
213
            Subsite::getSubsiteIDForDomain('www.wildcard.com'),
214
            'Doesn\'t match www prefix without strict check, even if a wildcard subdomain is in place'
215
        );
216
217
        Subsite::$strict_subdomain_matching = true;
218
219
        $this->assertEquals(
220
            $subsite1->ID,
221
            Subsite::getSubsiteIDForDomain('example.org'),
222
            'Matches with strict checking when not using www prefix'
223
        );
224
        $this->assertEquals(
225
            $subsite2->ID, // not 1
226
            Subsite::getSubsiteIDForDomain('www.example.org'),
227
            'Matches with strict checking when using www prefix'
228
        );
229
        $this->assertEquals(
230
            0,
231
            Subsite::getSubsiteIDForDomain('www.example.com'),
232
            'Doesn\'t fuzzy match with strict checking when using www prefix'
233
        );
234
        $failed = false;
235
        try {
236
            Subsite::getSubsiteIDForDomain('www.wildcard.com');
237
        } catch (UnexpectedValueException $e) {
238
            $failed = true;
239
        }
240
        $this->assertTrue(
241
            $failed,
242
            'Fails on multiple matches with strict checking and wildcard vs. www'
243
        );
244
    }
245
246
    protected function createSubsiteWithDomains($domains)
247
    {
248
        $subsite = new Subsite([
249
            'Title' => 'My Subsite'
250
        ]);
251
        $subsite->write();
252
        foreach ($domains as $domainStr => $isPrimary) {
253
            $domain = new SubsiteDomain([
254
                'Domain' => $domainStr,
255
                'IsPrimary' => $isPrimary,
256
                'SubsiteID' => $subsite->ID
257
            ]);
258
            $domain->write();
259
        }
260
261
        return $subsite;
262
    }
263
264
    /**
265
     * Test the Subsite->domain() method
266
     */
267
    public function testDefaultDomain()
268
    {
269
        $this->assertEquals(
270
            'one.example.org',
271
            $this->objFromFixture(Subsite::class, 'domaintest1')->domain()
272
        );
273
274
        $this->assertEquals(
275
            'two.mysite.com',
276
            $this->objFromFixture(Subsite::class, 'domaintest2')->domain()
277
        );
278
279
        $_SERVER['HTTP_HOST'] = 'www.example.org';
280
        $this->assertEquals(
281
            'three.example.org',
282
            $this->objFromFixture(Subsite::class, 'domaintest3')->domain()
283
        );
284
285
        $_SERVER['HTTP_HOST'] = 'mysite.example.org';
286
        $this->assertEquals(
287
            'three.mysite.example.org',
288
            $this->objFromFixture(Subsite::class, 'domaintest3')->domain()
289
        );
290
291
        $this->assertEquals($_SERVER['HTTP_HOST'], singleton(Subsite::class)->PrimaryDomain);
292
        $this->assertEquals(
293
            'http://' . $_SERVER['HTTP_HOST'] . Director::baseURL(),
294
            singleton(Subsite::class)->absoluteBaseURL()
295
        );
296
    }
297
298
    /**
299
     * Tests that Subsite and SubsiteDomain both respect http protocol correctly
300
     */
301
    public function testDomainProtocol()
302
    {
303
        // domaintest2 has 'protocol'
304
        $subsite2 = $this->objFromFixture(Subsite::class, 'domaintest2');
305
        $domain2a = $this->objFromFixture(SubsiteDomain::class, 'dt2a');
306
        $domain2b = $this->objFromFixture(SubsiteDomain::class, 'dt2b');
307
308
        // domaintest4 is 'https' (primary only)
309
        $subsite4 = $this->objFromFixture(Subsite::class, 'domaintest4');
310
        $domain4a = $this->objFromFixture(SubsiteDomain::class, 'dt4a');
311
        $domain4b = $this->objFromFixture(SubsiteDomain::class, 'dt4b'); // secondary domain is http only though
312
313
        // domaintest5 is 'http'
314
        $subsite5 = $this->objFromFixture(Subsite::class, 'domaintest5');
315
        $domain5a = $this->objFromFixture(SubsiteDomain::class, 'dt5');
316
317
        // Check protocol when current protocol is http://
318
        Config::modify()->set(Director::class, 'alternate_base_url', 'http://www.mysite.com');
319
320
        $this->assertEquals('http://two.mysite.com/', $subsite2->absoluteBaseURL());
321
        $this->assertEquals('http://two.mysite.com/', $domain2a->absoluteBaseURL());
322
        $this->assertEquals('http://subsite.mysite.com/', $domain2b->absoluteBaseURL());
323
        $this->assertEquals('https://www.primary.com/', $subsite4->absoluteBaseURL());
324
        $this->assertEquals('https://www.primary.com/', $domain4a->absoluteBaseURL());
325
        $this->assertEquals('http://www.secondary.com/', $domain4b->absoluteBaseURL());
326
        $this->assertEquals('http://www.tertiary.com/', $subsite5->absoluteBaseURL());
327
        $this->assertEquals('http://www.tertiary.com/', $domain5a->absoluteBaseURL());
328
329
        // Check protocol when current protocol is https://
330
        Config::modify()->set(Director::class, 'alternate_base_url', 'https://www.mysite.com');
331
332
        $this->assertEquals('https://two.mysite.com/', $subsite2->absoluteBaseURL());
333
        $this->assertEquals('https://two.mysite.com/', $domain2a->absoluteBaseURL());
334
        $this->assertEquals('https://subsite.mysite.com/', $domain2b->absoluteBaseURL());
335
        $this->assertEquals('https://www.primary.com/', $subsite4->absoluteBaseURL());
336
        $this->assertEquals('https://www.primary.com/', $domain4a->absoluteBaseURL());
337
        $this->assertEquals('http://www.secondary.com/', $domain4b->absoluteBaseURL());
338
        $this->assertEquals('http://www.tertiary.com/', $subsite5->absoluteBaseURL());
339
        $this->assertEquals('http://www.tertiary.com/', $domain5a->absoluteBaseURL());
340
    }
341
342
    public function testAllSites()
343
    {
344
        $subsites = Subsite::all_sites();
345
        $this->assertDOSEquals([
0 ignored issues
show
Deprecated Code introduced by
The function SilverStripe\Dev\SapphireTest::assertDOSEquals() has been deprecated: 4.0.0:5.0.0 Use assertListEquals() instead ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

345
        /** @scrutinizer ignore-deprecated */ $this->assertDOSEquals([

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.

Loading history...
346
            ['Title' => 'Main site'],
347
            ['Title' => 'Template'],
348
            ['Title' => 'Subsite1 Template'],
349
            ['Title' => 'Subsite2 Template'],
350
            ['Title' => 'Test 1'],
351
            ['Title' => 'Test 2'],
352
            ['Title' => 'Test 3'],
353
            ['Title' => 'Test Non-SSL'],
354
            ['Title' => 'Test SSL'],
355
            ['Title' => 'Test Vagrant VM on port 8080']
356
        ], $subsites, 'Lists all subsites');
0 ignored issues
show
Unused Code introduced by
The call to SilverStripe\Dev\SapphireTest::assertDOSEquals() has too many arguments starting with 'Lists all subsites'. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

356
        $this->/** @scrutinizer ignore-call */ 
357
               assertDOSEquals([

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
357
    }
358
359
    public function testAllAccessibleSites()
360
    {
361
        $member = $this->objFromFixture(Member::class, 'subsite1member');
362
363
        $subsites = Subsite::all_accessible_sites(true, 'Main site', $member);
364
        $this->assertDOSEquals([
0 ignored issues
show
Deprecated Code introduced by
The function SilverStripe\Dev\SapphireTest::assertDOSEquals() has been deprecated: 4.0.0:5.0.0 Use assertListEquals() instead ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

364
        /** @scrutinizer ignore-deprecated */ $this->assertDOSEquals([

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.

Loading history...
365
            ['Title' => 'Subsite1 Template']
366
        ], $subsites, 'Lists member-accessible sites.');
0 ignored issues
show
Unused Code introduced by
The call to SilverStripe\Dev\SapphireTest::assertDOSEquals() has too many arguments starting with 'Lists member-accessible sites.'. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

366
        $this->/** @scrutinizer ignore-call */ 
367
               assertDOSEquals([

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
367
    }
368
369
    /**
370
     * Test Subsite::accessible_sites()
371
     */
372
    public function testAccessibleSites()
373
    {
374
        $member1Sites = Subsite::accessible_sites(
375
            'CMS_ACCESS_CMSMain',
376
            false,
377
            null,
378
            $this->objFromFixture(Member::class, 'subsite1member')
379
        );
380
        $member1SiteTitles = $member1Sites->column('Title');
381
        sort($member1SiteTitles);
382
        $this->assertEquals('Subsite1 Template', $member1SiteTitles[0], 'Member can get to a subsite via a group');
383
384
        $adminSites = Subsite::accessible_sites(
385
            'CMS_ACCESS_CMSMain',
386
            false,
387
            null,
388
            $this->objFromFixture(Member::class, 'admin')
389
        );
390
        $adminSiteTitles = $adminSites->column('Title');
391
        sort($adminSiteTitles);
392
        $this->assertEquals([
393
            'Subsite1 Template',
394
            'Subsite2 Template',
395
            'Template',
396
            'Test 1',
397
            'Test 2',
398
            'Test 3',
399
            'Test Non-SSL',
400
            'Test SSL',
401
            'Test Vagrant VM on port 8080'
402
        ], array_values($adminSiteTitles));
403
404
        $member2Sites = Subsite::accessible_sites(
405
            'CMS_ACCESS_CMSMain',
406
            false,
407
            null,
408
            $this->objFromFixture(Member::class, 'subsite1member2')
409
        );
410
        $member2SiteTitles = $member2Sites->column('Title');
411
        sort($member2SiteTitles);
412
        $this->assertEquals('Subsite1 Template', $member2SiteTitles[0], 'Member can get to subsite via a group role');
413
    }
414
415
    public function testhasMainSitePermission()
416
    {
417
        $admin = $this->objFromFixture(Member::class, 'admin');
418
        $subsite1member = $this->objFromFixture(Member::class, 'subsite1member');
419
        $subsite1admin = $this->objFromFixture(Member::class, 'subsite1admin');
420
        $allsubsitesauthor = $this->objFromFixture(Member::class, 'allsubsitesauthor');
421
422
        $this->assertTrue(
423
            Subsite::hasMainSitePermission($admin),
424
            'Default permissions granted for super-admin'
425
        );
426
        $this->assertTrue(
427
            Subsite::hasMainSitePermission($admin, ['ADMIN']),
428
            'ADMIN permissions granted for super-admin'
429
        );
430
        $this->assertFalse(
431
            Subsite::hasMainSitePermission($subsite1admin, ['ADMIN']),
432
            'ADMIN permissions (on main site) denied for subsite1 admin'
433
        );
434
        $this->assertFalse(
435
            Subsite::hasMainSitePermission($subsite1admin, ['CMS_ACCESS_CMSMain']),
436
            'CMS_ACCESS_CMSMain (on main site) denied for subsite1 admin'
437
        );
438
        $this->assertFalse(
439
            Subsite::hasMainSitePermission($allsubsitesauthor, ['ADMIN']),
440
            'ADMIN permissions (on main site) denied for CMS author with edit rights on all subsites'
441
        );
442
        $this->assertTrue(
443
            Subsite::hasMainSitePermission($allsubsitesauthor, ['CMS_ACCESS_CMSMain']),
444
            'CMS_ACCESS_CMSMain (on main site) granted for CMS author with edit rights on all subsites'
445
        );
446
        $this->assertFalse(
447
            Subsite::hasMainSitePermission($subsite1member, ['ADMIN']),
448
            'ADMIN (on main site) denied for subsite1 subsite1 cms author'
449
        );
450
        $this->assertFalse(
451
            Subsite::hasMainSitePermission($subsite1member, ['CMS_ACCESS_CMSMain']),
452
            'CMS_ACCESS_CMSMain (on main site) denied for subsite1 cms author'
453
        );
454
    }
455
456
    public function testDuplicateSubsite()
457
    {
458
        // get subsite1 & create page
459
        $subsite1 = $this->objFromFixture(Subsite::class, 'domaintest1');
460
        $subsite1->activate();
461
        $page1 = new Page();
462
        $page1->Title = 'MyAwesomePage';
463
        $page1->write();
464
        $page1->doPublish();
465
        $this->assertEquals($page1->SubsiteID, $subsite1->ID);
466
467
        // duplicate
468
        $subsite2 = $subsite1->duplicate();
469
        $subsite2->activate();
470
        // change content on dupe
471
        $page2 = DataObject::get_one('Page', "\"Title\" = 'MyAwesomePage'");
472
        $page2->Title = 'MyNewAwesomePage';
473
        $page2->write();
474
        $page2->doPublish();
475
476
        // check change & check change has not affected subiste1
477
        $subsite1->activate();
478
        $this->assertEquals('MyAwesomePage', DataObject::get_by_id('Page', $page1->ID)->Title);
479
        $subsite2->activate();
480
        $this->assertEquals('MyNewAwesomePage', DataObject::get_by_id('Page', $page2->ID)->Title);
481
    }
482
}
483