Completed
Pull Request — master (#421)
by Robbie
13:34
created

Blog   F

Complexity

Total Complexity 57

Size/Duplication

Total Lines 642
Duplicated Lines 8.72 %

Coupling/Cohesion

Components 1
Dependencies 19

Importance

Changes 0
Metric Value
wmc 57
lcom 1
cbo 19
dl 56
loc 642
rs 2.2727
c 0
b 0
f 0

23 Methods

Rating   Name   Duplication   Size   Complexity  
A getCMSFields() 0 52 2
A canEdit() 0 10 2
A getMember() 12 12 3
A isEditor() 0 7 1
A isMemberOf() 12 12 4
B RoleOf() 0 24 6
A isWriter() 0 7 1
A isContributor() 0 7 1
A canAddChildren() 0 10 4
B getSettingsFields() 0 72 4
A getCandidateUsers() 0 12 2
A canEditEditors() 0 12 2
A canEditWriters() 16 16 3
A canEditContributors() 16 16 3
B getArchivedBlogPosts() 0 35 4
A getBlogPosts() 0 8 1
A ProfileLink() 0 10 2
A getLumberjackTitle() 0 4 1
A getLumberjackGridFieldConfig() 0 4 1
A providePermissions() 0 17 1
A onBeforeWrite() 0 5 1
B assignGroup() 0 19 6
A getUserGroup() 0 23 2

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like Blog often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Blog, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace SilverStripe\Blog\Model;
4
5
use Page;
6
use PageController;
7
use SilverStripe\Blog\Admin\GridFieldCategorisationConfig;
8
use SilverStripe\Blog\Forms\GridField\GridFieldConfig_BlogPost;
9
use SilverStripe\Blog\Model\BlogCategory;
10
use SilverStripe\Blog\Model\BlogFilter;
11
use SilverStripe\Blog\Model\BlogPost;
12
use SilverStripe\Blog\Model\BlogTag;
13
use SilverStripe\CMS\Controllers\RootURLController;
14
use SilverStripe\Control\Controller;
15
use SilverStripe\Control\RSS\RSSFeed;
16
use SilverStripe\Core\Convert;
17
use SilverStripe\Forms\GridField\GridField;
18
use SilverStripe\Forms\ListboxField;
19
use SilverStripe\Forms\NumericField;
20
use SilverStripe\ORM\ArrayList;
21
use SilverStripe\ORM\DataObject;
22
use SilverStripe\ORM\DB;
23
use SilverStripe\ORM\FieldType\DBDatetime;
24
use SilverStripe\ORM\PaginatedList;
25
use SilverStripe\ORM\UnsavedRelationList;
26
use SilverStripe\Security\Group;
27
use SilverStripe\Security\Member;
28
use SilverStripe\Security\Permission;
29
use SilverStripe\Security\PermissionProvider;
30
use SilverStripe\View\Requirements;
31
32
/**
33
 * Blog Holder
34
 *
35
 * @package silverstripe
36
 * @subpackage blog
37
 *
38
 * @method HasManyList Tags() List of tags in this blog
39
 * @method HasManyList Categories() List of categories in this blog
40
 * @method ManyManyList Editors() List of editors
41
 * @method ManyManyList Writers() List of writers
42
 * @method ManyManyList Contributors() List of contributors
43
 */
44
class Blog extends Page implements PermissionProvider
45
{
46
    /**
47
     * Permission for user management.
48
     *
49
     * @var string
50
     */
51
    const MANAGE_USERS = 'BLOG_MANAGE_USERS';
52
53
    /**
54
     * If true, users assigned as editor, writer, or contributor will be automatically granted
55
     * CMS_ACCESS_CMSMain permission. If false, only users with this permission already may be
56
     * assigned.
57
     *
58
     * @config
59
     *
60
     * @var boolean
61
     */
62
    private static $grant_user_access = true;
0 ignored issues
show
Unused Code introduced by
The property $grant_user_access is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
63
64
    /**
65
     * Permission to either require, or grant to users assigned to work on this blog.
66
     *
67
     * @config
68
     *
69
     * @var string
70
     */
71
    private static $grant_user_permission = 'CMS_ACCESS_CMSMain';
0 ignored issues
show
Unused Code introduced by
The property $grant_user_permission is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
72
73
    /**
74
     * Group code to assign newly granted users to.
75
     *
76
     * @config
77
     *
78
     * @var string
79
     */
80
    private static $grant_user_group = 'blog-users';
0 ignored issues
show
Unused Code introduced by
The property $grant_user_group is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
81
82
    /**
83
     * {@inheritDoc}
84
     * @var string
85
     */
86
    private static $table_name = 'Blog';
0 ignored issues
show
Unused Code introduced by
The property $table_name is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
87
88
    /**
89
     * @var array
90
     */
91
    private static $db = array(
0 ignored issues
show
Unused Code introduced by
The property $db is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
92
        'PostsPerPage' => 'Int',
93
    );
94
95
    /**
96
     * @var array
97
     */
98
    private static $has_many = array(
0 ignored issues
show
Unused Code introduced by
The property $has_many is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
99
        'Tags' => BlogTag::class,
100
        'Categories' => BlogCategory::class,
101
    );
102
103
    /**
104
     * @var array
105
     */
106
    private static $many_many = array(
0 ignored issues
show
Unused Code introduced by
The property $many_many is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
107
        'Editors' => Member::class,
108
        'Writers' => Member::class,
109
        'Contributors' => Member::class,
110
    );
111
112
    /**
113
     * @var array
114
     */
115
    private static $allowed_children = array(
0 ignored issues
show
Unused Code introduced by
The property $allowed_children is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
116
        BlogPost::class,
117
    );
118
119
    /**
120
     * @var array
121
     */
122
    private static $extensions = array(
0 ignored issues
show
Unused Code introduced by
The property $extensions is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
123
        BlogFilter::class,
124
    );
125
126
    /**
127
     * @var array
128
     */
129
    private static $defaults = array(
0 ignored issues
show
Unused Code introduced by
The property $defaults is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
130
        'ProvideComments' => false,
131
        'PostsPerPage'    => 10
132
    );
133
134
    /**
135
     * @var string
136
     */
137
    private static $description = 'Adds a blog to your website.';
0 ignored issues
show
Unused Code introduced by
The property $description is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
138
139
    private static $icon = 'blog/images/site-tree-icon.png';
0 ignored issues
show
Unused Code introduced by
The property $icon is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
140
141
    /**
142
     * {@inheritdoc}
143
     */
144
    public function getCMSFields()
145
    {
146
        Requirements::css(BLOGGER_DIR . '/css/cms.css');
147
        Requirements::javascript(BLOGGER_DIR . '/js/cms.js');
148
149
        $this->beforeUpdateCMSFields(function ($fields) {
150
            if (!$this->canEdit()) {
151
                return;
152
            }
153
154
            $categories = GridField::create(
155
                'Categories',
156
                _t('Blog.Categories', 'Categories'),
157
                $this->Categories(),
158
                GridFieldCategorisationConfig::create(
159
                    15,
160
                    $this->Categories()->sort('Title'),
161
                    BlogCategory::class,
162
                    'Categories',
163
                    'BlogPosts'
164
                )
165
            );
166
167
            $tags = GridField::create(
168
                'Tags',
169
                _t('Blog.Tags', 'Tags'),
170
                $this->Tags(),
171
                GridFieldCategorisationConfig::create(
172
                    15,
173
                    $this->Tags()->sort('Title'),
174
                    BlogTag::class,
175
                    'Tags',
176
                    'BlogPosts'
177
                )
178
            );
179
180
            /**
181
             * @var FieldList $fields
182
             */
183
            $fields->addFieldsToTab(
184
                'Root.Categorisation',
185
                array(
186
                    $categories,
187
                    $tags
188
                )
189
            );
190
191
            $fields->findOrMakeTab('Root.Categorisation')->addExtraClass('blog-cms-categorisation');
192
        });
193
194
        return parent::getCMSFields();
195
    }
196
197
    /**
198
     * {@inheritdoc}
199
     */
200
    public function canEdit($member = null)
201
    {
202
        $member = $this->getMember($member);
203
204
        if ($this->isEditor($member)) {
205
            return true;
206
        }
207
208
        return parent::canEdit($member);
209
    }
210
211
    /**
212
     * @param null|int|Member $member
213
     *
214
     * @return null|Member
215
     */
216 View Code Duplication
    protected function getMember($member = null)
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...
217
    {
218
        if (!$member) {
219
            $member = Member::currentUser();
220
        }
221
222
        if (is_numeric($member)) {
223
            $member = Member::get()->byID($member);
224
        }
225
226
        return $member;
227
    }
228
229
    /**
230
     * Check if this member is an editor of the blog.
231
     *
232
     * @param Member $member
233
     *
234
     * @return bool
235
     */
236
    public function isEditor($member)
237
    {
238
        $isEditor = $this->isMemberOf($member, $this->Editors());
239
        $this->extend('updateIsEditor', $isEditor, $member);
240
241
        return $isEditor;
242
    }
243
244
    /**
245
     * Determine if the given member belongs to the given relation.
246
     *
247
     * @param Member $member
248
     * @param DataList $relation
249
     *
250
     * @return bool
251
     */
252 View Code Duplication
    protected function isMemberOf($member, $relation)
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...
253
    {
254
        if (!$member || !$member->exists()) {
255
            return false;
256
        }
257
258
        if ($relation instanceof UnsavedRelationList) {
259
            return in_array($member->ID, $relation->getIDList());
260
        }
261
262
        return $relation->byID($member->ID) !== null;
263
    }
264
265
    /**
266
     * Determine the role of the given member.
267
     *
268
     * Call be called via template to determine the current user.
269
     *
270
     * @example "Hello $RoleOf($CurrentMember.ID)"
271
     *
272
     * @param int|Member $member
273
     *
274
     * @return null|string
275
     */
276
    public function RoleOf($member)
277
    {
278
        if (is_numeric($member)) {
279
            $member = Member::get()->byId($member);
280
        }
281
282
        if (!$member) {
283
            return null;
284
        }
285
286
        if ($this->isEditor($member)) {
287
            return _t('Blog.EDITOR', 'Editor');
288
        }
289
290
        if ($this->isWriter($member)) {
291
            return _t('Blog.WRITER', 'Writer');
292
        }
293
294
        if ($this->isContributor($member)) {
295
            return _t('Blog.CONTRIBUTOR', 'Contributor');
296
        }
297
298
        return null;
299
    }
300
301
    /**
302
     * Check if this member is a writer of the blog.
303
     *
304
     * @param Member $member
305
     *
306
     * @return bool
307
     */
308
    public function isWriter($member)
309
    {
310
        $isWriter = $this->isMemberOf($member, $this->Writers());
311
        $this->extend('updateIsWriter', $isWriter, $member);
312
313
        return $isWriter;
314
    }
315
316
    /**
317
     * Check if this member is a contributor of the blog.
318
     *
319
     * @param Member $member
320
     *
321
     * @return bool
322
     */
323
    public function isContributor($member)
324
    {
325
        $isContributor = $this->isMemberOf($member, $this->Contributors());
326
        $this->extend('updateIsContributor', $isContributor, $member);
327
328
        return $isContributor;
329
    }
330
331
    /**
332
     * {@inheritdoc}
333
     */
334
    public function canAddChildren($member = null)
335
    {
336
        $member = $this->getMember($member);
337
338
        if ($this->isEditor($member) || $this->isWriter($member) || $this->isContributor($member)) {
339
            return true;
340
        }
341
342
        return parent::canAddChildren($member);
343
    }
344
345
    /**
346
     * {@inheritdoc}
347
     */
348
    public function getSettingsFields()
349
    {
350
        $fields = parent::getSettingsFields();
351
352
        $fields->addFieldToTab(
353
            'Root.Settings',
354
            NumericField::create('PostsPerPage', _t('Blog.PostsPerPage', 'Posts Per Page'))
355
        );
356
357
        $members = $this->getCandidateUsers()->map()->toArray();
358
359
        $editorField = ListboxField::create('Editors', 'Editors', $members)
360
            // ->setMultiple(true)
0 ignored issues
show
Unused Code Comprehensibility introduced by
67% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
361
            ->setRightTitle('<a class="toggle-description">help</a>')
362
            ->setDescription('
363
				An editor has control over specific Blogs, and all posts included within it. Short of being able to assign other editors to a blog, they are able to handle most changes to their assigned blog.<br />
364
				<br />
365
				Editors have these permissions:<br />
366
				<br />
367
				Update or publish any BlogPost in their Blog<br />
368
				Update or publish their Blog<br />
369
				Assign/unassign writers to their Blog<br />
370
				Assign/unassign contributors to their Blog<br />
371
				Assign/unassign any member as an author of a particular BlogPost
372
			');
373
374
        if (!$this->canEditEditors()) {
375
            $editorField = $editorField->performDisabledTransformation();
376
        }
377
378
        $writerField = ListboxField::create('Writers', 'Writers', $members)
379
            // ->setMultiple(true)
0 ignored issues
show
Unused Code Comprehensibility introduced by
67% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
380
            ->setRightTitle('<a class="toggle-description">help</a>')
381
            ->setDescription('
382
				A writer has full control over creating, editing and publishing BlogPosts they have authored or have been assigned to. Writers are unable to edit BlogPosts to which they are not assigned.<br />
383
				<br />
384
				Writers have these permissions:<br />
385
				<br />
386
				Update or publish any BlogPost they have authored or have been assigned to<br />
387
				Assign/unassign any member as an author of a particular BlogPost they have authored or have been assigned to
388
			');
389
390
        if (!$this->canEditWriters()) {
391
            $writerField = $writerField->performDisabledTransformation();
392
        }
393
394
        $contributorField = ListboxField::create('Contributors', 'Contributors', $members)
395
            // ->setMultiple(true)
0 ignored issues
show
Unused Code Comprehensibility introduced by
67% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
396
            ->setRightTitle('<a class="toggle-description">help</a>')
397
            ->setDescription('
398
				Contributors have the ability to create or edit BlogPosts, but are unable to publish without authorisation of an editor. They are also unable to assign other contributing authors to any of their BlogPosts.<br />
399
				<br />
400
				Contributors have these permissions:<br />
401
				<br />
402
				Update any BlogPost they have authored or have been assigned to
403
			');
404
405
        if (!$this->canEditContributors()) {
406
            $contributorField = $contributorField->performDisabledTransformation();
407
        }
408
409
        $fields->addFieldsToTab(
410
            'Root.Users',
411
            array(
412
                $editorField,
413
                $writerField,
414
                $contributorField
415
            )
416
        );
417
418
        return $fields;
419
    }
420
421
    /**
422
     * Gets the list of user candidates to be assigned to assist with this blog.
423
     *
424
     * @return SS_List
425
     */
426
    protected function getCandidateUsers()
427
    {
428
        if ($this->config()->grant_user_access) {
429
            $list = Member::get();
430
            $this->extend('updateCandidateUsers', $list);
431
            return $list;
432
        } else {
433
            return Permission::get_members_by_permission(
434
                $this->config()->grant_user_permission
435
            );
436
        }
437
    }
438
439
    /**
440
     * Determine if this user can edit the editors list.
441
     *
442
     * @param int|Member $member
443
     *
444
     * @return bool
445
     */
446
    public function canEditEditors($member = null)
447
    {
448
        $member = $this->getMember($member);
449
450
        $extended = $this->extendedCan('canEditEditors', $member);
451
452
        if ($extended !== null) {
453
            return $extended;
454
        }
455
456
        return Permission::checkMember($member, self::MANAGE_USERS);
0 ignored issues
show
Bug Compatibility introduced by
The expression \SilverStripe\Security\P...r, self::MANAGE_USERS); of type boolean|string adds the type string to the return on line 456 which is incompatible with the return type documented by SilverStripe\Blog\Model\Blog::canEditEditors of type boolean.
Loading history...
457
    }
458
459
    /**
460
     * Determine if this user can edit writers list.
461
     *
462
     * @param int|Member $member
463
     *
464
     * @return boolean
465
     */
466 View Code Duplication
    public function canEditWriters($member = null)
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...
467
    {
468
        $member = $this->getMember($member);
469
470
        $extended = $this->extendedCan('canEditWriters', $member);
471
472
        if ($extended !== null) {
473
            return $extended;
474
        }
475
476
        if ($this->isEditor($member)) {
477
            return true;
478
        }
479
480
        return Permission::checkMember($member, self::MANAGE_USERS);
0 ignored issues
show
Bug Compatibility introduced by
The expression \SilverStripe\Security\P...r, self::MANAGE_USERS); of type boolean|string adds the type string to the return on line 480 which is incompatible with the return type documented by SilverStripe\Blog\Model\Blog::canEditWriters of type boolean.
Loading history...
481
    }
482
483
    /**
484
     * Determines if this user can edit the contributors list.
485
     *
486
     * @param int|Member $member
487
     *
488
     * @return boolean
489
     */
490 View Code Duplication
    public function canEditContributors($member = null)
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...
491
    {
492
        $member = $this->getMember($member);
493
494
        $extended = $this->extendedCan('canEditContributors', $member);
495
496
        if ($extended !== null) {
497
            return $extended;
498
        }
499
500
        if ($this->isEditor($member)) {
501
            return true;
502
        }
503
504
        return Permission::checkMember($member, self::MANAGE_USERS);
0 ignored issues
show
Bug Compatibility introduced by
The expression \SilverStripe\Security\P...r, self::MANAGE_USERS); of type boolean|string adds the type string to the return on line 504 which is incompatible with the return type documented by SilverStripe\Blog\Model\Blog::canEditContributors of type boolean.
Loading history...
505
    }
506
507
    /**
508
     * Returns BlogPosts for a given date period.
509
     *
510
     * @param int $year
511
     * @param null|int $month
512
     * @param null|int $day
513
     *
514
     * @return DataList
515
     */
516
    public function getArchivedBlogPosts($year, $month = null, $day = null)
517
    {
518
        $query = $this->getBlogPosts()->dataQuery();
519
520
        $stage = $query->getQueryParam('Versioned.stage');
521
522
        if ($stage) {
523
            $stage = '_' . $stage;
524
        }
525
526
        $query->innerJoin(
527
            DataObject::getSchema()->tableName(BlogPost::class),
528
            sprintf('"SiteTree%s"."ID" = "BlogPost%s"."ID"', $stage, $stage)
529
        );
530
531
        $conn = DB::getConn();
0 ignored issues
show
Deprecated Code introduced by
The method SilverStripe\ORM\DB::getConn() has been deprecated with message: since version 4.0 Use DB::get_conn instead

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...
532
533
        // Filter by year
534
        $yearCond = $conn->formattedDatetimeClause('"BlogPost"."PublishDate"', '%Y');
535
        $query->where(sprintf('%s = \'%04d\'', $yearCond, Convert::raw2sql($year)));
536
537
        // Filter by month (if given)
538
        if ($month) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $month of type null|integer is loosely compared to true; this is ambiguous if the integer can be zero. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
539
            $monthCond = $conn->formattedDatetimeClause('"BlogPost"."PublishDate"', '%m');
540
            $query->where(sprintf('%s = \'%02d\'', $monthCond, Convert::raw2sql($month)));
541
542
            if ($day) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $day of type null|integer is loosely compared to true; this is ambiguous if the integer can be zero. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
543
                $dayCond = $conn->formattedDatetimeClause('"BlogPost"."PublishDate"', '%d');
544
                $query->where(sprintf('%s = \'%02d\'', $dayCond, Convert::raw2sql($day)));
545
            }
546
        }
547
548
549
        return $this->getBlogPosts()->setDataQuery($query);
550
    }
551
552
    /**
553
     * Return blog posts.
554
     *
555
     * @return DataList of BlogPost objects
556
     */
557
    public function getBlogPosts()
558
    {
559
        $blogPosts = BlogPost::get()->filter('ParentID', $this->ID);
560
561
        $this->extend('updateGetBlogPosts', $blogPosts);
562
563
        return $blogPosts;
564
    }
565
566
    /**
567
     * Get a link to a Member profile.
568
     *
569
     * @param string $urlSegment
570
     *
571
     * @return string
572
     */
573
    public function ProfileLink($urlSegment)
574
    {
575
        $baseLink = $this->Link();
576
        if ($baseLink === '/') {
577
            // Handle homepage blogs
578
            $baseLink = RootURLController::get_homepage_link();
579
        }
580
581
        return Controller::join_links($baseLink, 'profile', $urlSegment);
582
    }
583
584
    /**
585
     * This sets the title for our gridfield.
586
     *
587
     * @return string
588
     */
589
    public function getLumberjackTitle()
590
    {
591
        return _t('Blog.LumberjackTitle', 'Blog Posts');
592
    }
593
594
    /**
595
     * This overwrites lumberjacks default gridfield config.
596
     *
597
     * @return GridFieldConfig
598
     */
599
    public function getLumberjackGridFieldConfig()
600
    {
601
        return GridFieldConfig_BlogPost::create();
602
    }
603
604
    /**
605
     * {@inheritdoc}
606
     */
607
    public function providePermissions()
608
    {
609
        return array(
610
            Blog::MANAGE_USERS => array(
611
                'name' => _t(
612
                    'Blog.PERMISSION_MANAGE_USERS_DESCRIPTION',
613
                    'Manage users for individual blogs'
614
                ),
615
                'help' => _t(
616
                    'Blog.PERMISSION_MANAGE_USERS_HELP',
617
                    'Allow assignment of Editors, Writers, or Contributors to blogs'
618
                ),
619
                'category' => _t('Blog.PERMISSIONS_CATEGORY', 'Blog permissions'),
620
                'sort' => 100
621
            )
622
        );
623
    }
624
625
    /**
626
     * {@inheritdoc}
627
     */
628
    protected function onBeforeWrite()
629
    {
630
        parent::onBeforeWrite();
631
        $this->assignGroup();
632
    }
633
634
    /**
635
     * Assign users as necessary to the blog group.
636
     */
637
    protected function assignGroup()
638
    {
639
        if (!$this->config()->grant_user_access) {
640
            return;
641
        }
642
643
        $group = $this->getUserGroup();
644
645
        // Must check if the method exists or else an error occurs when changing page type
646
        if ($this->hasMethod('Editors')) {
647
            foreach (array($this->Editors(), $this->Writers(), $this->Contributors()) as $levels) {
648
                foreach ($levels as $user) {
649
                    if (!$user->inGroup($group)) {
650
                        $user->Groups()->add($group);
651
                    }
652
                }
653
            }
654
        }
655
    }
656
657
    /**
658
     * Gets or creates the group used to assign CMS access.
659
     *
660
     * @return Group
661
     */
662
    protected function getUserGroup()
663
    {
664
        $code = $this->config()->grant_user_group;
665
666
        $group = Group::get()->filter('Code', $code)->first();
667
668
        if ($group) {
669
            return $group;
670
        }
671
672
        $group = Group::create();
673
        $group->Title = 'Blog users';
674
        $group->Code = $code;
675
676
        $group->write();
677
678
        $permission = Permission::create();
679
        $permission->Code = $this->config()->grant_user_permission;
680
681
        $group->Permissions()->add($permission);
682
683
        return $group;
684
    }
685
}
686