Completed
Push — master ( a62ce1...6c1e6a )
by Daniel
13s
created

BlogTest::testFilteredCategoriesArchive()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 17
Code Lines 10

Duplication

Lines 17
Ratio 100 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 17
loc 17
rs 9.4285
cc 1
eloc 10
nc 1
nop 0
1
<?php
2
3
namespace SilverStripe\Blog\Tests;
4
5
use SilverStripe\Blog\Model\Blog;
6
use SilverStripe\Blog\Model\BlogController;
7
use SilverStripe\Blog\Model\BlogPost;
8
use SilverStripe\CMS\Controllers\ContentController;
9
use SilverStripe\Control\Controller;
10
use SilverStripe\Control\Director;
11
use SilverStripe\Control\HTTPRequest;
12
use SilverStripe\Control\Session;
13
use SilverStripe\Core\Config\Config;
14
use SilverStripe\Dev\SapphireTest;
15
use SilverStripe\ORM\DataModel;
16
use SilverStripe\ORM\FieldType\DBDatetime;
17
use SilverStripe\ORM\SS_List;
18
use SilverStripe\Security\Member;
19
20
/**
21
 * @mixin PHPUnit_Framework_TestCase
22
 */
23
class BlogTest extends SapphireTest
24
{
25
    /**
26
     * @var string
27
     */
28
    protected static $fixture_file = 'blog.yml';
29
30
    /**
31
     * {@inheritdoc}
32
     */
33
    public function setUp()
34
    {
35
        parent::setUp();
36
37
        Config::nest();
38
        DBDatetime::set_mock_now('2013-10-10 20:00:00');
39
40
        /**
41
         * @var Blog $blog
42
         */
43
        $blog = $this->objFromFixture(Blog::class, 'FirstBlog');
44
45
        $blog->publish('Stage', 'Live');
46
    }
47
48
    /**
49
     * {@inheritdoc}
50
     */
51
    public function tearDown()
52
    {
53
        DBDatetime::clear_mock_now();
54
        Config::unnest();
55
56
        parent::tearDown();
57
    }
58
59
    public function testGetExcludedSiteTreeClassNames()
60
    {
61
        $member = Member::currentUser();
0 ignored issues
show
Deprecated Code introduced by
The method SilverStripe\Security\Member::currentUser() has been deprecated with message: 5.0.0 use Security::getCurrentUser()

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
62
63
        if ($member) {
64
            $member->logout();
0 ignored issues
show
Deprecated Code introduced by
The method SilverStripe\Security\Member::logOut() has been deprecated with message: Use Security::setCurrentUser(null) or an IdentityStore
Logs this member out.

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
65
        }
66
67
        /**
68
         * @var Blog $blog
69
         */
70
        $blog = $this->objFromFixture(Blog::class, 'FirstBlog');
71
72
        Config::inst()->update(BlogPost::class, 'show_in_sitetree', true);
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface SilverStripe\Config\Coll...nfigCollectionInterface as the method update() does only exist in the following implementations of said interface: SilverStripe\Config\Coll...\MemoryConfigCollection.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
73
        $classes = $blog->getExcludedSiteTreeClassNames();
74
75
        $this->assertNotContains(BlogPost::class, $classes, 'BlogPost class should be hidden.');
76
77
        Config::inst()->update(BlogPost::class, 'show_in_sitetree', false);
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface SilverStripe\Config\Coll...nfigCollectionInterface as the method update() does only exist in the following implementations of said interface: SilverStripe\Config\Coll...\MemoryConfigCollection.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
78
        $classes = $blog->getExcludedSiteTreeClassNames();
79
80
        $this->assertContains(BlogPost::class, $classes, 'BlogPost class should be hidden.');
81
    }
82
83
    public function testGetArchivedBlogPosts()
84
    {
85
        $member = Member::currentUser();
0 ignored issues
show
Deprecated Code introduced by
The method SilverStripe\Security\Member::currentUser() has been deprecated with message: 5.0.0 use Security::getCurrentUser()

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
86
87
        if ($member) {
88
            $member->logout();
0 ignored issues
show
Deprecated Code introduced by
The method SilverStripe\Security\Member::logOut() has been deprecated with message: Use Security::setCurrentUser(null) or an IdentityStore
Logs this member out.

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
89
        }
90
91
        /**
92
         * @var Blog $blog
93
         */
94
        $blog = $this->objFromFixture(Blog::class, 'FirstBlog');
95
96
        $archive = $blog->getArchivedBlogPosts(2013);
97
98
        $this->assertEquals(2, $archive->count(), 'Incorrect Yearly Archive count for 2013');
99
        $this->assertEquals('First Post', $archive->first()->Title, 'Incorrect First Blog post');
100
        $this->assertEquals('Second Post', $archive->last()->Title, 'Incorrect Last Blog post');
101
102
        $archive = $blog->getArchivedBlogPosts(2013, 10);
103
104
        $this->assertEquals(1, $archive->count(), 'Incorrect monthly archive count.');
105
106
        $archive = $blog->getArchivedBlogPosts(2013, 10, 01);
107
108
        $this->assertEquals(1, $archive->count(), 'Incorrect daily archive count.');
109
    }
110
111
    public function testArchiveLinks()
112
    {
113
        /**
114
         * @var Blog $blog
115
         */
116
        $blog = $this->objFromFixture(Blog::class, 'FirstBlog');
117
118
        $link = Controller::join_links($blog->Link('archive'), '2013', '10', '01');
119
120
        $this->assertEquals(200, $this->getStatusOf($link), 'HTTP Status should be 200');
121
122
        $link = Controller::join_links($blog->Link('archive'), '2013', '10');
123
124
        $this->assertEquals(200, $this->getStatusOf($link), 'HTTP Status should be 200');
125
126
        $link = Controller::join_links($blog->Link('archive'), '2013');
127
128
        $this->assertEquals(200, $this->getStatusOf($link), 'HTTP Status should be 200');
129
130
        $link = Controller::join_links($blog->Link('archive'), '2011', '10', '01');
131
132
        $this->assertEquals(200, $this->getStatusOf($link), 'HTTP Status should be 200');
133
134
        $link = Controller::join_links($blog->Link('archive'));
135
        $this->assertEquals(200, $this->getStatusOf($link), 'HTTP Status should be 200');
136
137
        $link = Controller::join_links($blog->Link('archive'), 'invalid-year');
138
139
        $this->assertEquals(404, $this->getStatusOf($link), 'HTTP Status should be 404');
140
141
        $link = Controller::join_links($blog->Link('archive'), '2013', '99');
142
143
        $this->assertEquals(404, $this->getStatusOf($link), 'HTTP Status should be 404');
144
145
        $link = Controller::join_links($blog->Link('archive'), '2013', '10', '99');
146
147
        $this->assertEquals(404, $this->getStatusOf($link), 'HTTP Status should be 404');
148
    }
149
150
    /*
151
     * Test archive year
152
     */
153
    public function testArchiveYear()
154
    {
155
        $blog = $this->objFromFixture(Blog::class, 'FirstBlog');
156
        $controller = new BlogController($blog);
157
        $this->requestURL($controller, 'first-post/archive/');
158
        $this->assertEquals(2013, $controller->getArchiveYear(), 'getArchiveYear should return 2013');
159
    }
160
161
    /**
162
     * @param string $link
163
     *
164
     * @return int
165
     */
166
    protected function getStatusOf($link)
167
    {
168
        return Director::test($link)->getStatusCode();
169
    }
170
171
    public function testRoles()
172
    {
173
        /**
174
         * @var Blog $firstBlog
175
         */
176
        $firstBlog = $this->objFromFixture(Blog::class, 'FirstBlog');
177
178
        /**
179
         * @var Blog $fourthBlog
180
         */
181
        $fourthBlog = $this->objFromFixture(Blog::class, 'FourthBlog');
182
183
        /**
184
         * @var BlogPost $postA
185
         */
186
        $postA = $this->objFromFixture(BlogPost::class, 'PostA');
187
188
        /**
189
         * @var BlogPost $postB
190
         */
191
        $postB = $this->objFromFixture(BlogPost::class, 'PostB');
192
193
        /**
194
         * @var BlogPost $postC
195
         */
196
        $postC = $this->objFromFixture(BlogPost::class, 'PostC');
197
198
        /**
199
         * @var Member $editor
200
         */
201
        $editor = $this->objFromFixture(Member::class, 'BlogEditor');
202
203
        /**
204
         * @var Member $writer
205
         */
206
        $writer = $this->objFromFixture(Member::class, 'Writer');
207
208
        /**
209
         * @var Member $contributor
210
         */
211
        $contributor = $this->objFromFixture(Member::class, 'Contributor');
212
213
        /**
214
         * @var Member $visitor
215
         */
216
        $visitor = $this->objFromFixture(Member::class, 'Visitor');
217
218
        $this->assertEquals('Editor', $fourthBlog->RoleOf($editor));
219
        $this->assertEquals('Contributor', $fourthBlog->RoleOf($contributor));
220
        $this->assertEquals('Writer', $fourthBlog->RoleOf($writer));
221
        $this->assertEmpty($fourthBlog->RoleOf($visitor));
222
        $this->assertEquals('Author', $postA->RoleOf($writer));
223
        $this->assertEquals('Author', $postA->RoleOf($contributor));
224
        $this->assertEquals('Editor', $postA->RoleOf($editor));
225
        $this->assertEmpty($postA->RoleOf($visitor));
226
227
        // Test RoleOf with string values given
228
        $this->assertEquals('Editor', $fourthBlog->RoleOf((string)(int)$editor->ID));
229
        $this->assertEquals('Contributor', $fourthBlog->RoleOf((string)(int)$contributor->ID));
230
        $this->assertEquals('Writer', $fourthBlog->RoleOf((string)(int)$writer->ID));
231
        $this->assertEmpty($fourthBlog->RoleOf((string)(int)$visitor->ID));
232
        $this->assertEquals('Author', $postA->RoleOf((string)(int)$writer->ID));
233
        $this->assertEquals('Author', $postA->RoleOf((string)(int)$contributor->ID));
234
        $this->assertEquals('Editor', $postA->RoleOf((string)(int)$editor->ID));
235
        $this->assertEmpty($postA->RoleOf((string)(int)$visitor->ID));
236
237
        // Test RoleOf with int values given
238
        $this->assertEquals('Editor', $fourthBlog->RoleOf((int)$editor->ID));
239
        $this->assertEquals('Contributor', $fourthBlog->RoleOf((int)$contributor->ID));
240
        $this->assertEquals('Writer', $fourthBlog->RoleOf((int)$writer->ID));
241
        $this->assertEmpty($fourthBlog->RoleOf((int)$visitor->ID));
242
        $this->assertEquals('Author', $postA->RoleOf((int)$writer->ID));
243
        $this->assertEquals('Author', $postA->RoleOf((int)$contributor->ID));
244
        $this->assertEquals('Editor', $postA->RoleOf((int)$editor->ID));
245
        $this->assertEmpty($postA->RoleOf((int)$visitor->ID));
246
247
        $this->assertTrue($fourthBlog->canEdit($editor));
248
        $this->assertFalse($firstBlog->canEdit($editor));
249
        $this->assertTrue($fourthBlog->canAddChildren($editor));
250
        $this->assertFalse($firstBlog->canAddChildren($editor));
251
        $this->assertTrue($postA->canEdit($editor));
252
        $this->assertTrue($postB->canEdit($editor));
253
        $this->assertTrue($postC->canEdit($editor));
254
        $this->assertTrue($postA->canPublish($editor));
255
        $this->assertTrue($postB->canPublish($editor));
256
        $this->assertTrue($postC->canPublish($editor));
257
258
        $this->assertFalse($fourthBlog->canEdit($writer));
259
        $this->assertFalse($firstBlog->canEdit($writer));
260
        $this->assertTrue($fourthBlog->canAddChildren($writer));
261
        $this->assertFalse($firstBlog->canAddChildren($writer));
262
        $this->assertTrue($postA->canEdit($writer));
263
        $this->assertFalse($postB->canEdit($writer));
264
        $this->assertTrue($postC->canEdit($writer));
265
        $this->assertTrue($postA->canPublish($writer));
266
        $this->assertFalse($postB->canPublish($writer));
267
        $this->assertTrue($postC->canPublish($writer));
268
269
        $this->assertFalse($fourthBlog->canEdit($contributor));
270
        $this->assertFalse($firstBlog->canEdit($contributor));
271
        $this->assertTrue($fourthBlog->canAddChildren($contributor));
272
        $this->assertFalse($firstBlog->canAddChildren($contributor));
273
        $this->assertTrue($postA->canEdit($contributor));
274
        $this->assertFalse($postB->canEdit($contributor));
275
        $this->assertTrue($postC->canEdit($contributor));
276
        $this->assertFalse($postA->canPublish($contributor));
277
        $this->assertFalse($postB->canPublish($contributor));
278
        $this->assertFalse($postC->canPublish($contributor));
279
280
        $this->assertFalse($fourthBlog->canEdit($visitor));
281
        $this->assertFalse($firstBlog->canEdit($visitor));
282
        $this->assertFalse($fourthBlog->canAddChildren($visitor));
283
        $this->assertFalse($firstBlog->canAddChildren($visitor));
284
        $this->assertFalse($postA->canEdit($visitor));
285
        $this->assertFalse($postB->canEdit($visitor));
286
        $this->assertFalse($postC->canEdit($visitor));
287
        $this->assertFalse($postA->canPublish($visitor));
288
        $this->assertFalse($postB->canPublish($visitor));
289
        $this->assertFalse($postC->canPublish($visitor));
290
    }
291
292 View Code Duplication
    public function testFilteredCategoriesRoot()
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...
293
    {
294
        $blog = $this->objFromFixture(Blog::class, 'FirstBlog');
295
        $controller = new BlogController($blog);
296
        $this->requestURL($controller, 'first-post');
297
        $this->assertIDsEquals(
298
            $blog->AllChildren()->column('ID'),
299
            $controller->PaginatedList()->column('ID')
300
        );
301
    }
302
303 View Code Duplication
    public function testFilteredCategoriesRSS()
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...
304
    {
305
        $blog = $this->objFromFixture(Blog::class, 'FirstBlog');
306
        $controller = new BlogController($blog);
307
        $this->requestURL($controller, 'first-post/rss');
308
        $this->assertIDsEquals(
309
            $blog->AllChildren()->column('ID'),
310
            $controller->PaginatedList()->column('ID')
311
        );
312
    }
313
314 View Code Duplication
    public function testFilteredCategoriesTags()
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...
315
    {
316
        $blog = $this->objFromFixture(Blog::class, 'FirstBlog');
317
        $controller = new BlogController($blog);
318
319
        // Posts
320
        $firstPostID = $this->idFromFixture(BlogPost::class, 'FirstBlogPost');
321
        $firstFuturePostID = $this->idFromFixture(BlogPost::class, 'FirstFutureBlogPost');
322
        $secondFuturePostID = $this->idFromFixture(BlogPost::class, 'SecondFutureBlogPost');
323
324
        // Request first tag
325
        $this->requestURL($controller, 'first-post/tag/first-tag');
326
        $this->assertIDsEquals(
327
            array($firstPostID, $firstFuturePostID, $secondFuturePostID),
328
            $controller->PaginatedList()
329
        );
330
    }
331
332 View Code Duplication
    public function testFilteredCategoriesArchive()
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...
333
    {
334
        $blog = $this->objFromFixture(Blog::class, 'FirstBlog');
335
        $controller = new BlogController($blog);
336
337
        // Posts
338
        $firstPostID = $this->idFromFixture(BlogPost::class, 'FirstBlogPost');
339
        $secondPostID = $this->idFromFixture(BlogPost::class, 'SecondBlogPost');
340
        $secondFuturePostID = $this->idFromFixture(BlogPost::class, 'SecondFutureBlogPost');
341
342
        // Request 2013 posts
343
        $this->requestURL($controller, 'first-post/archive/2013');
344
        $this->assertIDsEquals(
345
            array($firstPostID, $secondPostID, $secondFuturePostID),
346
            $controller->PaginatedList()
347
        );
348
    }
349
350
    /**
351
     * Mock a request against a given controller
352
     *
353
     * @param ContentController $controller
354
     * @param string $url
355
     */
356
    protected function requestURL(ContentController $controller, $url)
357
    {
358
        $request = new HTTPRequest('get', $url);
359
        $request->match('$URLSegment//$Action/$ID/$OtherID');
360
        $request->shift();
361
        $session = new Session(null);
362
        $session->start($request);
363
        $request->setSession($session);
364
        $controller->doInit();
365
        $controller->handleRequest($request);
366
        $session->clearAll();
367
        $session->destroy();
368
    }
369
370
    /**
371
     * Assert these id lists match
372
     *
373
     * @param array|SS_List $left
374
     * @param array|SS_List $right
375
     */
376
    protected function assertIDsEquals($left, $right)
377
    {
378
        if ($left instanceof SS_List) {
379
            $left = $left->column('ID');
380
        }
381
        if ($right instanceof SS_List) {
382
            $right = $right->column('ID');
383
        }
384
        asort($left);
385
        asort($right);
386
        $this->assertEquals(array_values($left), array_values($right));
387
    }
388
}
389