Completed
Push — master ( 5cf2d8...46bcff )
by Damian
13s
created

tests/php/SubsiteTest.php (2 issues)

Labels
Severity

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
namespace SilverStripe\Subsites\Tests;
4
5
use Page;
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
14
class SubsiteTest extends BaseSubsiteTest
15
{
16
    protected static $fixture_file = 'SubsiteTest.yml';
17
18
    /**
19
     * Original value of {@see SubSite::$strict_subdomain_matching}
20
     *
21
     * @var bool
22
     */
23
    protected $origStrictSubdomainMatching = null;
24
25
    /**
26
     * Original value of $_REQUEST
27
     *
28
     * @var array
29
     */
30
    protected $origServer = [];
31
32
    protected function setUp()
33
    {
34
        parent::setUp();
35
36
        Config::modify()->set(Director::class, 'alternate_base_url', '/');
37
        $this->origStrictSubdomainMatching = Subsite::$strict_subdomain_matching;
38
        $this->origServer = $_SERVER;
39
        Subsite::$strict_subdomain_matching = false;
40
    }
41
42
    protected function tearDown()
43
    {
44
        $_SERVER = $this->origServer;
45
        Subsite::$strict_subdomain_matching = $this->origStrictSubdomainMatching;
46
47
        parent::tearDown();
48
    }
49
50
    /**
51
     * Create a new subsite from the template and verify that all the template's pages are copied
52
     */
53
    public function testSubsiteCreation()
54
    {
55
        Subsite::$write_hostmap = false;
56
57
        // Create the instance
58
        $template = $this->objFromFixture(Subsite::class, 'main');
59
60
        // Test that changeSubsite is working
61
        Subsite::changeSubsite($template->ID);
62
        $this->assertEquals($template->ID, Subsite::currentSubsiteID());
63
        $tmplStaff = $this->objFromFixture('Page', 'staff');
64
        $tmplHome = DataObject::get_one('Page', "\"URLSegment\" = 'home'");
65
66
        // Publish all the pages in the template, testing that DataObject::get only returns pages from the chosen subsite
67
        $pages = DataObject::get(SiteTree::class);
68
        $totalPages = $pages->count();
69
        foreach ($pages as $page) {
70
            $this->assertEquals($template->ID, $page->SubsiteID);
71
            $page->copyVersionToStage('Stage', 'Live');
72
        }
73
74
        // Create a new site
75
        $subsite = $template->duplicate();
76
77
        // Check title
78
        $this->assertEquals($subsite->Title, $template->Title);
79
80
        // Another test that changeSubsite is working
81
        $subsite->activate();
82
83
        $siteHome = DataObject::get_one('Page', "\"URLSegment\" = 'home'");
84
        $this->assertNotEquals($siteHome, false, 'Home Page for subsite not found');
85
        $this->assertEquals(
86
            $subsite->ID,
87
            $siteHome->SubsiteID,
88
            'createInstance() copies existing pages retaining the same URLSegment'
89
        );
90
91
        Subsite::changeSubsite(0);
92
    }
93
94
    /**
95
     * Confirm that domain lookup is working
96
     */
97
    public function testDomainLookup()
98
    {
99
        // Clear existing fixtures
100
        foreach (DataObject::get(Subsite::class) as $subsite) {
101
            $subsite->delete();
102
        }
103
        foreach (DataObject::get(SubsiteDomain::class) as $domain) {
104
            $domain->delete();
105
        }
106
107
        // Much more expressive than YML in this case
108
        $subsite1 = $this->createSubsiteWithDomains([
109
            'one.example.org' => true,
110
            'one.*' => false,
111
        ]);
112
        $subsite2 = $this->createSubsiteWithDomains([
113
            'two.mysite.com' => true,
114
            '*.mysite.com' => false,
115
            'subdomain.onmultiplesubsites.com' => false,
116
        ]);
117
        $subsite3 = $this->createSubsiteWithDomains([
118
            'three.*' => true, // wildcards in primary domain are not recommended
119
            'subdomain.unique.com' => false,
120
            '*.onmultiplesubsites.com' => false,
121
        ]);
122
123
        $this->assertEquals(
124
            $subsite3->ID,
125
            Subsite::getSubsiteIDForDomain('subdomain.unique.com'),
126
            'Full unique match'
127
        );
128
129
        $this->assertEquals(
130
            $subsite1->ID,
131
            Subsite::getSubsiteIDForDomain('one.example.org'),
132
            'Full match, doesn\'t complain about multiple matches within a single subsite'
133
        );
134
135
        $failed = false;
136
        try {
137
            Subsite::getSubsiteIDForDomain('subdomain.onmultiplesubsites.com');
138
        } catch (UnexpectedValueException $e) {
0 ignored issues
show
The class SilverStripe\Subsites\Te...nexpectedValueException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
139
            $failed = true;
140
        }
141
        $this->assertTrue(
142
            $failed,
143
            'Fails on multiple matches with wildcard vs. www across multiple subsites'
144
        );
145
146
        $this->assertEquals(
147
            $subsite1->ID,
148
            Subsite::getSubsiteIDForDomain('one.unique.com'),
149
            'Fuzzy match suffixed with wildcard (rule "one.*")'
150
        );
151
152
        $this->assertEquals(
153
            $subsite2->ID,
154
            Subsite::getSubsiteIDForDomain('two.mysite.com'),
155
            'Matches correct subsite for rule'
156
        );
157
158
        $this->assertEquals(
159
            $subsite2->ID,
160
            Subsite::getSubsiteIDForDomain('other.mysite.com'),
161
            'Fuzzy match prefixed with wildcard (rule "*.mysite.com")'
162
        );
163
164
        $this->assertEquals(
165
            0,
166
            Subsite::getSubsiteIDForDomain('unknown.madeup.com'),
167
            "Doesn't match unknown subsite"
168
        );
169
    }
170
171
    public function testStrictSubdomainMatching()
172
    {
173
        // Clear existing fixtures
174
        foreach (DataObject::get(Subsite::class) as $subsite) {
175
            $subsite->delete();
176
        }
177
        foreach (DataObject::get(SubsiteDomain::class) as $domain) {
178
            $domain->delete();
179
        }
180
181
        // Much more expressive than YML in this case
182
        $subsite1 = $this->createSubsiteWithDomains([
183
            'example.org' => true,
184
            'example.com' => false,
185
            '*.wildcard.com' => false,
186
        ]);
187
        $subsite2 = $this->createSubsiteWithDomains([
188
            'www.example.org' => true,
189
            'www.wildcard.com' => false,
190
        ]);
191
192
        Subsite::$strict_subdomain_matching = false;
193
194
        $this->assertEquals(
195
            $subsite1->ID,
196
            Subsite::getSubsiteIDForDomain('example.org'),
197
            'Exact matches without strict checking when not using www prefix'
198
        );
199
        $this->assertEquals(
200
            $subsite1->ID,
201
            Subsite::getSubsiteIDForDomain('www.example.org'),
202
            'Matches without strict checking when using www prefix, still matching first domain regardless of www prefix  (falling back to subsite primary key ordering)'
203
        );
204
        $this->assertEquals(
205
            $subsite1->ID,
206
            Subsite::getSubsiteIDForDomain('www.example.com'),
207
            'Fuzzy matches without strict checking with www prefix'
208
        );
209
        $this->assertEquals(
210
            0,
211
            Subsite::getSubsiteIDForDomain('www.wildcard.com'),
212
            'Doesn\'t match www prefix without strict check, even if a wildcard subdomain is in place'
213
        );
214
215
        Subsite::$strict_subdomain_matching = true;
216
217
        $this->assertEquals(
218
            $subsite1->ID,
219
            Subsite::getSubsiteIDForDomain('example.org'),
220
            'Matches with strict checking when not using www prefix'
221
        );
222
        $this->assertEquals(
223
            $subsite2->ID, // not 1
224
            Subsite::getSubsiteIDForDomain('www.example.org'),
225
            'Matches with strict checking when using www prefix'
226
        );
227
        $this->assertEquals(
228
            0,
229
            Subsite::getSubsiteIDForDomain('www.example.com'),
230
            'Doesn\'t fuzzy match with strict checking when using www prefix'
231
        );
232
        $failed = false;
233
        try {
234
            Subsite::getSubsiteIDForDomain('www.wildcard.com');
235
        } catch (UnexpectedValueException $e) {
0 ignored issues
show
The class SilverStripe\Subsites\Te...nexpectedValueException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
236
            $failed = true;
237
        }
238
        $this->assertTrue(
239
            $failed,
240
            'Fails on multiple matches with strict checking and wildcard vs. www'
241
        );
242
    }
243
244
    protected function createSubsiteWithDomains($domains)
245
    {
246
        $subsite = new Subsite([
247
            'Title' => 'My Subsite'
248
        ]);
249
        $subsite->write();
250
        foreach ($domains as $domainStr => $isPrimary) {
251
            $domain = new SubsiteDomain([
252
                'Domain' => $domainStr,
253
                'IsPrimary' => $isPrimary,
254
                'SubsiteID' => $subsite->ID
255
            ]);
256
            $domain->write();
257
        }
258
259
        return $subsite;
260
    }
261
262
    /**
263
     * Test the Subsite->domain() method
264
     */
265
    public function testDefaultDomain()
266
    {
267
        $this->assertEquals(
268
            'one.example.org',
269
            $this->objFromFixture(Subsite::class, 'domaintest1')->domain()
270
        );
271
272
        $this->assertEquals(
273
            'two.mysite.com',
274
            $this->objFromFixture(Subsite::class, 'domaintest2')->domain()
275
        );
276
277
        $_SERVER['HTTP_HOST'] = 'www.example.org';
278
        $this->assertEquals(
279
            'three.example.org',
280
            $this->objFromFixture(Subsite::class, 'domaintest3')->domain()
281
        );
282
283
        $_SERVER['HTTP_HOST'] = 'mysite.example.org';
284
        $this->assertEquals(
285
            'three.mysite.example.org',
286
            $this->objFromFixture(Subsite::class, 'domaintest3')->domain()
287
        );
288
289
        $this->assertEquals($_SERVER['HTTP_HOST'], singleton(Subsite::class)->PrimaryDomain);
290
        $this->assertEquals(
291
            'http://' . $_SERVER['HTTP_HOST'] . Director::baseURL(),
292
            singleton(Subsite::class)->absoluteBaseURL()
293
        );
294
    }
295
296
    /**
297
     * Tests that Subsite and SubsiteDomain both respect http protocol correctly
298
     */
299
    public function testDomainProtocol()
300
    {
301
        // domaintest2 has 'protocol'
302
        $subsite2 = $this->objFromFixture(Subsite::class, 'domaintest2');
303
        $domain2a = $this->objFromFixture(SubsiteDomain::class, 'dt2a');
304
        $domain2b = $this->objFromFixture(SubsiteDomain::class, 'dt2b');
305
306
        // domaintest4 is 'https' (primary only)
307
        $subsite4 = $this->objFromFixture(Subsite::class, 'domaintest4');
308
        $domain4a = $this->objFromFixture(SubsiteDomain::class, 'dt4a');
309
        $domain4b = $this->objFromFixture(SubsiteDomain::class, 'dt4b'); // secondary domain is http only though
310
311
        // domaintest5 is 'http'
312
        $subsite5 = $this->objFromFixture(Subsite::class, 'domaintest5');
313
        $domain5a = $this->objFromFixture(SubsiteDomain::class, 'dt5');
314
315
        // Check protocol when current protocol is http://
316
        $_SERVER['HTTP_HOST'] = 'www.mysite.com';
317
        $_SERVER['HTTPS'] = '';
318
319
        $this->assertEquals('http://two.mysite.com/', $subsite2->absoluteBaseURL());
320
        $this->assertEquals('http://two.mysite.com/', $domain2a->absoluteBaseURL());
321
        $this->assertEquals('http://subsite.mysite.com/', $domain2b->absoluteBaseURL());
322
        $this->assertEquals('https://www.primary.com/', $subsite4->absoluteBaseURL());
323
        $this->assertEquals('https://www.primary.com/', $domain4a->absoluteBaseURL());
324
        $this->assertEquals('http://www.secondary.com/', $domain4b->absoluteBaseURL());
325
        $this->assertEquals('http://www.tertiary.com/', $subsite5->absoluteBaseURL());
326
        $this->assertEquals('http://www.tertiary.com/', $domain5a->absoluteBaseURL());
327
328
        // Check protocol when current protocol is https://
329
        $_SERVER['HTTP_HOST'] = 'www.mysite.com';
330
        $_SERVER['HTTPS'] = 'ON';
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([
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
        ], $subsites, 'Lists all subsites');
356
    }
357
358
    public function testAllAccessibleSites()
359
    {
360
        $member = $this->objFromFixture(Member::class, 'subsite1member');
361
362
        $subsites = Subsite::all_accessible_sites(true, 'Main site', $member);
363
        $this->assertDOSEquals([
364
            ['Title' => 'Subsite1 Template']
365
        ], $subsites, 'Lists member-accessible sites.');
366
    }
367
368
    /**
369
     * Test Subsite::accessible_sites()
370
     */
371
    public function testAccessibleSites()
372
    {
373
        $member1Sites = Subsite::accessible_sites(
374
            'CMS_ACCESS_CMSMain',
375
            false,
376
            null,
377
            $this->objFromFixture(Member::class, 'subsite1member')
378
        );
379
        $member1SiteTitles = $member1Sites->column('Title');
380
        sort($member1SiteTitles);
381
        $this->assertEquals('Subsite1 Template', $member1SiteTitles[0], 'Member can get to a subsite via a group');
382
383
        $adminSites = Subsite::accessible_sites(
384
            'CMS_ACCESS_CMSMain',
385
            false,
386
            null,
387
            $this->objFromFixture(Member::class, 'admin')
388
        );
389
        $adminSiteTitles = $adminSites->column('Title');
390
        sort($adminSiteTitles);
391
        $this->assertEquals([
392
            'Subsite1 Template',
393
            'Subsite2 Template',
394
            'Template',
395
            'Test 1',
396
            'Test 2',
397
            'Test 3',
398
            'Test Non-SSL',
399
            'Test SSL'
400
        ], array_values($adminSiteTitles));
401
402
        $member2Sites = Subsite::accessible_sites(
403
            'CMS_ACCESS_CMSMain',
404
            false,
405
            null,
406
            $this->objFromFixture(Member::class, 'subsite1member2')
407
        );
408
        $member2SiteTitles = $member2Sites->column('Title');
409
        sort($member2SiteTitles);
410
        $this->assertEquals('Subsite1 Template', $member2SiteTitles[0], 'Member can get to subsite via a group role');
411
    }
412
413
    public function testhasMainSitePermission()
414
    {
415
        $admin = $this->objFromFixture(Member::class, 'admin');
416
        $subsite1member = $this->objFromFixture(Member::class, 'subsite1member');
417
        $subsite1admin = $this->objFromFixture(Member::class, 'subsite1admin');
418
        $allsubsitesauthor = $this->objFromFixture(Member::class, 'allsubsitesauthor');
419
420
        $this->assertTrue(
421
            Subsite::hasMainSitePermission($admin),
422
            'Default permissions granted for super-admin'
423
        );
424
        $this->assertTrue(
425
            Subsite::hasMainSitePermission($admin, ['ADMIN']),
426
            'ADMIN permissions granted for super-admin'
427
        );
428
        $this->assertFalse(
429
            Subsite::hasMainSitePermission($subsite1admin, ['ADMIN']),
430
            'ADMIN permissions (on main site) denied for subsite1 admin'
431
        );
432
        $this->assertFalse(
433
            Subsite::hasMainSitePermission($subsite1admin, ['CMS_ACCESS_CMSMain']),
434
            'CMS_ACCESS_CMSMain (on main site) denied for subsite1 admin'
435
        );
436
        $this->assertFalse(
437
            Subsite::hasMainSitePermission($allsubsitesauthor, ['ADMIN']),
438
            'ADMIN permissions (on main site) denied for CMS author with edit rights on all subsites'
439
        );
440
        $this->assertTrue(
441
            Subsite::hasMainSitePermission($allsubsitesauthor, ['CMS_ACCESS_CMSMain']),
442
            'CMS_ACCESS_CMSMain (on main site) granted for CMS author with edit rights on all subsites'
443
        );
444
        $this->assertFalse(
445
            Subsite::hasMainSitePermission($subsite1member, ['ADMIN']),
446
            'ADMIN (on main site) denied for subsite1 subsite1 cms author'
447
        );
448
        $this->assertFalse(
449
            Subsite::hasMainSitePermission($subsite1member, ['CMS_ACCESS_CMSMain']),
450
            'CMS_ACCESS_CMSMain (on main site) denied for subsite1 cms author'
451
        );
452
    }
453
454
    public function testDuplicateSubsite()
455
    {
456
        // get subsite1 & create page
457
        $subsite1 = $this->objFromFixture(Subsite::class, 'domaintest1');
458
        $subsite1->activate();
459
        $page1 = new Page();
460
        $page1->Title = 'MyAwesomePage';
461
        $page1->write();
462
        $page1->doPublish();
463
        $this->assertEquals($page1->SubsiteID, $subsite1->ID);
464
465
        // duplicate
466
        $subsite2 = $subsite1->duplicate();
467
        $subsite2->activate();
468
        // change content on dupe
469
        $page2 = DataObject::get_one('Page', "\"Title\" = 'MyAwesomePage'");
470
        $page2->Title = 'MyNewAwesomePage';
471
        $page2->write();
472
        $page2->doPublish();
473
474
        // check change & check change has not affected subiste1
475
        $subsite1->activate();
476
        $this->assertEquals('MyAwesomePage', DataObject::get_by_id('Page', $page1->ID)->Title);
477
        $subsite2->activate();
478
        $this->assertEquals('MyNewAwesomePage', DataObject::get_by_id('Page', $page2->ID)->Title);
479
    }
480
}
481