Completed
Push — master ( 82c4a1...4bf0a8 )
by Robbie
10:38
created

src/Extensions/CommentsExtension.php (16 issues)

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\Comments\Extensions;
4
5
use SilverStripe\CMS\Model\SiteTree;
6
use SilverStripe\Comments\Admin\CommentsGridField;
7
use SilverStripe\Comments\Admin\CommentsGridFieldConfig;
8
use SilverStripe\Comments\Controllers\CommentingController;
9
use SilverStripe\Comments\Model\Comment;
10
use SilverStripe\Control\Controller;
11
use SilverStripe\Control\Director;
12
use SilverStripe\Control\Session;
13
use SilverStripe\Core\Config\Config;
14
use SilverStripe\Core\Manifest\ModuleLoader;
15
use SilverStripe\Dev\Deprecation;
16
use SilverStripe\Forms\CheckboxField;
17
use SilverStripe\Forms\DropdownField;
18
use SilverStripe\Forms\FieldGroup;
19
use SilverStripe\Forms\FieldList;
20
use SilverStripe\Forms\Tab;
21
use SilverStripe\Forms\TabSet;
22
use SilverStripe\ORM\DataExtension;
23
use SilverStripe\ORM\PaginatedList;
24
use SilverStripe\Security\Member;
25
use SilverStripe\Security\Permission;
26
use SilverStripe\View\Requirements;
27
28
/**
29
 * Extension to {@link DataObject} to enable tracking comments.
30
 *
31
 * @package comments
32
 */
33
class CommentsExtension extends DataExtension
34
{
35
    /**
36
     * Default configuration values
37
     *
38
     * enabled:                     Allows commenting to be disabled even if the extension is present
39
     * enabled_cms:                 Allows commenting to be enabled or disabled via the CMS
40
     * require_login:               Boolean, whether a user needs to login (required for required_permission)
41
     * require_login_cms:           Allows require_login to be set via the CMS
42
     * required_permission:         Permission (or array of permissions) required to comment
43
     * include_js:                  Enhance operation by ajax behaviour on moderation links (required for use_preview)
44
     * use_gravatar:                Set to true to show gravatar icons
45
     * gravatar_default:            Theme for 'not found' gravatar {@see http://gravatar.com/site/implement/images}
46
     * gravatar_rating:             Gravatar rating (same as the standard default)
47
     * show_comments_when_disabled: Show older comments when commenting has been disabled.
48
     * order_comments_by:           Default sort order.
49
     * order_replies_by:            Sort order for replies.
50
     * comments_holder_id:          ID for the comments holder
51
     * comment_permalink_prefix:    ID prefix for each comment
52
     * require_moderation:          Require moderation for all comments
53
     * require_moderation_cms:      Ignore other comment moderation config settings and set via CMS
54
     * frontend_moderation:         Display unmoderated comments in the frontend, if the user can moderate them.
55
     * frontend_spam:               Display spam comments in the frontend, if the user can moderate them.
56
     * html_allowed:                Allow for sanitized HTML in comments
57
     * use_preview:                 Preview formatted comment (when allowing HTML)
58
     * nested_comments:             Enable nested comments
59
     * nested_depth:                Max depth of nested comments in levels (where root is 1 depth) 0 means no limit.
60
     *
61
     * @var array
62
     *
63
     * @config
64
     */
65
    private static $comments = [
0 ignored issues
show
The property $comments 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...
66
        'enabled' => true,
67
        'enabled_cms' => false,
68
        'require_login' => false,
69
        'require_login_cms' => false,
70
        'required_permission' => false,
71
        'include_js' => true,
72
        'use_gravatar' => false,
73
        'gravatar_size' => 80,
74
        'gravatar_default' => 'identicon',
75
        'gravatar_rating' => 'g',
76
        'show_comments_when_disabled' => false,
77
        'order_comments_by' => '"Created" DESC',
78
        'order_replies_by' => false,
79
        'comments_per_page' => 10,
80
        'comments_holder_id' => 'comments-holder',
81
        'comment_permalink_prefix' => 'comment-',
82
        'require_moderation' => false,
83
        'require_moderation_nonmembers' => false,
84
        'require_moderation_cms' => false,
85
        'frontend_moderation' => false,
86
        'frontend_spam' => false,
87
        'html_allowed' => false,
88
        'html_allowed_elements' => ['a', 'img', 'i', 'b'],
89
        'use_preview' => false,
90
        'nested_comments' => false,
91
        'nested_depth' => 2,
92
    ];
93
94
    /**
95
     * @var array
96
     */
97
    private static $db = [
0 ignored issues
show
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...
98
        'ProvideComments' => 'Boolean',
99
        'ModerationRequired' => 'Enum(\'None,Required,NonMembersOnly\',\'None\')',
100
        'CommentsRequireLogin' => 'Boolean',
101
    ];
102
103
    /**
104
     * {@inheritDoc}
105
     */
106
    private static $has_many = [
0 ignored issues
show
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...
107
        'Commments' => Comment::class . '.Parent'
108
    ];
109
110
    /**
111
     * CMS configurable options should default to the config values, but respect
112
     * default values specified by the object
113
     */
114
    public function populateDefaults()
115
    {
116
        $defaults = $this->owner->config()->get('defaults');
117
118
        // Set if comments should be enabled by default
119
        if (isset($defaults['ProvideComments'])) {
120
            $this->owner->ProvideComments = $defaults['ProvideComments'];
121
        } else {
122
            $this->owner->ProvideComments = $this->owner->getCommentsOption('enabled') ? 1 : 0;
123
        }
124
125
        // If moderation options should be configurable via the CMS then
126
        if (isset($defaults['ModerationRequired'])) {
127
            $this->owner->ModerationRequired = $defaults['ModerationRequired'];
128
        } elseif ($this->owner->getCommentsOption('require_moderation')) {
129
            $this->owner->ModerationRequired = 'Required';
130
        } elseif ($this->owner->getCommentsOption('require_moderation_nonmembers')) {
131
            $this->owner->ModerationRequired = 'NonMembersOnly';
132
        } else {
133
            $this->owner->ModerationRequired = 'None';
134
        }
135
136
        // Set login required
137
        if (isset($defaults['CommentsRequireLogin'])) {
138
            $this->owner->CommentsRequireLogin = $defaults['CommentsRequireLogin'];
139
        } else {
140
            $this->owner->CommentsRequireLogin = $this->owner->getCommentsOption('require_login') ? 1 : 0;
141
        }
142
    }
143
144
145
    /**
146
     * If this extension is applied to a {@link SiteTree} record then
147
     * append a Provide Comments checkbox to allow authors to trigger
148
     * whether or not to display comments
149
     *
150
     * @todo Allow customization of other {@link Commenting} configuration
151
     *
152
     * @param FieldList $fields
153
     */
154
    public function updateSettingsFields(FieldList $fields)
155
    {
156
        $options = FieldGroup::create()->setTitle(_t(__CLASS__ . '.COMMENTOPTIONS', 'Comments'));
157
158
        // Check if enabled setting should be cms configurable
159
        if ($this->owner->getCommentsOption('enabled_cms')) {
160
            $options->push(new CheckboxField('ProvideComments', _t('SilverStripe\\Comments\\Model\\Comment.ALLOWCOMMENTS', 'Allow Comments')));
161
        }
162
163
        // Check if we should require users to login to comment
164
        if ($this->owner->getCommentsOption('require_login_cms')) {
165
            $options->push(
166
                new CheckboxField(
167
                    'CommentsRequireLogin',
168
                    _t('Comments.COMMENTSREQUIRELOGIN', 'Require login to comment')
169
                )
170
            );
171
        }
172
173
        if ($options->FieldList()->count()) {
174
            if ($fields->hasTabSet()) {
175
                $fields->addFieldsToTab('Root.Settings', $options);
0 ignored issues
show
$options is of type object<SilverStripe\Forms\FieldGroup>, but the function expects a array.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
176
            } else {
177
                $fields->push($options);
178
            }
179
        }
180
181
        // Check if moderation should be enabled via cms configurable
182
        if ($this->owner->getCommentsOption('require_moderation_cms')) {
183
            $moderationField = new DropdownField('ModerationRequired', _t(__CLASS__ . '.COMMENTMODERATION', 'Comment Moderation'), array(
184
                'None' => _t(__CLASS__ . '.MODERATIONREQUIRED_NONE', 'No moderation required'),
185
                'Required' => _t(__CLASS__ . '.MODERATIONREQUIRED_REQUIRED', 'Moderate all comments'),
186
                'NonMembersOnly' => _t(
187
                    'SilverStripe\\Comments\\Extensions\\CommentsExtension.MODERATIONREQUIRED_NONMEMBERSONLY',
188
                    'Only moderate non-members'
189
                ),
190
            ));
191
            if ($fields->hasTabSet()) {
192
                $fields->addFieldsToTab('Root.Settings', $moderationField);
0 ignored issues
show
$moderationField is of type object<SilverStripe\Forms\DropdownField>, but the function expects a array.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
193
            } else {
194
                $fields->push($moderationField);
195
            }
196
        }
197
    }
198
199
    /**
200
     * Get comment moderation rules for this parent
201
     *
202
     * None:           No moderation required
203
     * Required:       All comments
204
     * NonMembersOnly: Only anonymous users
205
     *
206
     * @return string
207
     */
208
    public function getModerationRequired()
209
    {
210
        if ($this->owner->getCommentsOption('require_moderation_cms')) {
211
            return $this->owner->getField('ModerationRequired');
212
        } elseif ($this->owner->getCommentsOption('require_moderation')) {
213
            return 'Required';
214
        } elseif ($this->owner->getCommentsOption('require_moderation_nonmembers')) {
215
            return 'NonMembersOnly';
216
        } else {
217
            return 'None';
218
        }
219
    }
220
221
    /**
222
     * Determine if users must be logged in to post comments
223
     *
224
     * @return boolean
225
     */
226
    public function getCommentsRequireLogin()
227
    {
228
        if ($this->owner->getCommentsOption('require_login_cms')) {
229
            return (bool) $this->owner->getField('CommentsRequireLogin');
230
        } else {
231
            return (bool) $this->owner->getCommentsOption('require_login');
232
        }
233
    }
234
235
    /**
236
     * Returns the RelationList of all comments against this object. Can be used as a data source
237
     * for a gridfield with write access.
238
     *
239
     * @return DataList
240
     */
241 View Code Duplication
    public function AllComments()
0 ignored issues
show
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...
242
    {
243
        $order = $this->owner->getCommentsOption('order_comments_by');
244
        $comments = Comment::get()
245
            ->filter('ParentID', $this->owner->ID)
246
            ->sort($order);
247
        $this->owner->extend('updateAllComments', $comments);
248
        return $comments;
249
    }
250
251
    /**
252
     * Returns all comments against this object, with with spam and unmoderated items excluded, for use in the frontend
253
     *
254
     * @return DataList
255
     */
256
    public function AllVisibleComments()
257
    {
258
        $list = $this->AllComments();
259
260
        // Filter spam comments for non-administrators if configured
261
        $showSpam = $this->owner->getCommentsOption('frontend_spam') && $this->owner->canModerateComments();
262
263
        if (!$showSpam) {
264
            $list = $list->filter('IsSpam', 0);
265
        }
266
267
        // Filter un-moderated comments for non-administrators if moderation is enabled
268
        $showUnmoderated = ($this->owner->ModerationRequired === 'None')
269
            || ($this->owner->getCommentsOption('frontend_moderation') && $this->owner->canModerateComments());
270
        if (!$showUnmoderated) {
271
            $list = $list->filter('Moderated', 1);
272
        }
273
274
        $this->owner->extend('updateAllVisibleComments', $list);
275
        return $list;
276
    }
277
278
    /**
279
     * Returns the root level comments, with spam and unmoderated items excluded, for use in the frontend
280
     *
281
     * @return DataList
282
     */
283 View Code Duplication
    public function Comments()
0 ignored issues
show
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...
284
    {
285
        $list = $this->AllVisibleComments();
286
287
        // If nesting comments, only show root level
288
        if ($this->owner->getCommentsOption('nested_comments')) {
289
            $list = $list->filter('ParentCommentID', 0);
290
        }
291
292
        $this->owner->extend('updateComments', $list);
293
        return $list;
294
    }
295
296
    /**
297
     * Returns a paged list of the root level comments, with spam and unmoderated items excluded,
298
     * for use in the frontend
299
     *
300
     * @return PaginatedList
301
     */
302 View Code Duplication
    public function PagedComments()
0 ignored issues
show
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...
303
    {
304
        $list = $this->Comments();
305
306
        // Add pagination
307
        $list = new PaginatedList($list, Controller::curr()->getRequest());
0 ignored issues
show
\SilverStripe\Control\Co...r::curr()->getRequest() is of type object<SilverStripe\Control\HTTPRequest>, but the function expects a array.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
308
        $list->setPaginationGetVar('commentsstart' . $this->owner->ID);
309
        $list->setPageLength($this->owner->getCommentsOption('comments_per_page'));
310
311
        $this->owner->extend('updatePagedComments', $list);
312
        return $list;
313
    }
314
315
    /**
316
     * Determine if comments are enabled for this instance
317
     *
318
     * @return boolean
319
     */
320
    public function getCommentsEnabled()
321
    {
322
        // Don't display comments form for pseudo-pages (such as the login form)
323
        if (!$this->owner->exists()) {
324
            return false;
325
        }
326
327
        // Determine which flag should be used to determine if this is enabled
328
        if ($this->owner->getCommentsOption('enabled_cms')) {
329
            return (bool) $this->owner->ProvideComments;
330
        }
331
332
        return (bool) $this->owner->getCommentsOption('enabled');
333
    }
334
335
    /**
336
     * Get the HTML ID for the comment holder in the template
337
     *
338
     * @return string
339
     */
340
    public function getCommentHolderID()
341
    {
342
        return $this->owner->getCommentsOption('comments_holder_id');
343
    }
344
345
    /**
346
     * Permission codes required in order to post (or empty if none required)
347
     *
348
     * @return string|array Permission or list of permissions, if required
349
     */
350
    public function getPostingRequiredPermission()
351
    {
352
        return $this->owner->getCommentsOption('required_permission');
353
    }
354
355
    /**
356
     * Determine if a user can post comments on this item
357
     *
358
     * @param Member $member Member to check
0 ignored issues
show
Should the type for parameter $member not be Member|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
359
     *
360
     * @return boolean
361
     */
362
    public function canPostComment($member = null)
363
    {
364
        // Deny if not enabled for this object
365
        if (!$this->owner->CommentsEnabled) {
366
            return false;
367
        }
368
369
        if (!$this->owner->canView($member)) {
370
            // deny if current user cannot view the underlying record.
371
            return false;
372
        }
373
374
        // Check if member is required
375
        $requireLogin = $this->owner->CommentsRequireLogin;
376
        if (!$requireLogin) {
377
            return true;
378
        }
379
380
        // Check member is logged in
381
        $member = $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...
382
        if (!$member) {
383
            return false;
384
        }
385
386
        // If member required check permissions
387
        $requiredPermission = $this->owner->PostingRequiredPermission;
388
        if ($requiredPermission && !Permission::checkMember($member, $requiredPermission)) {
0 ignored issues
show
This if statement, and the following return statement can be replaced with return !($requiredPermis... $requiredPermission));.
Loading history...
389
            return false;
390
        }
391
392
        return true;
393
    }
394
395
    /**
396
     * Determine if this member can moderate comments in the CMS
397
     *
398
     * @param Member $member
0 ignored issues
show
Should the type for parameter $member not be Member|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
399
     *
400
     * @return boolean
0 ignored issues
show
Should the return type not be boolean|string?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
401
     */
402
    public function canModerateComments($member = null)
403
    {
404
        // Deny if not enabled for this object
405
        if (!$this->owner->CommentsEnabled) {
406
            return false;
407
        }
408
409
        // Fallback to can-edit
410
        return $this->owner->canEdit($member);
411
    }
412
413
    /**
414
     * Gets the RSS link to all comments
415
     *
416
     * @return string
0 ignored issues
show
Should the return type not be string|false?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
417
     */
418
    public function getCommentRSSLink()
419
    {
420
        return Director::absoluteURL('comments/rss');
421
    }
422
423
    /**
424
     * Get the RSS link to all comments on this page
425
     *
426
     * @return string
427
     */
428
    public function getCommentRSSLinkPage()
429
    {
430
        return Controller::join_links(
431
            $this->getCommentRSSLink(),
432
            str_replace('\\', '-', $this->owner->baseClass()),
433
            $this->owner->ID
434
        );
435
    }
436
437
    /**
438
     * Comments interface for the front end. Includes the CommentAddForm and the composition
439
     * of the comments display.
440
     *
441
     * To customize the html see templates/CommentInterface.ss or extend this function with
442
     * your own extension.
443
     *
444
     * @todo Cleanup the passing of all this configuration based functionality
445
     *
446
     * @see  docs/en/Extending
447
     */
448
    public function CommentsForm()
449
    {
450
        // Check if enabled
451
        $enabled = $this->getCommentsEnabled();
452
        if ($enabled && $this->owner->getCommentsOption('include_js')) {
453
            $adminThirdPartyDir = ModuleLoader::getModule('silverstripe/admin')->getRelativePath() . '/thirdparty';
454
            Requirements::javascript($adminThirdPartyDir . '/jquery/jquery.js');
455
            Requirements::javascript($adminThirdPartyDir . '/jquery-entwine/dist/jquery.entwine-dist.js');
456
            Requirements::javascript($adminThirdPartyDir . '/jquery-form/jquery.form.js');
457
            Requirements::javascript('silverstripe/comments:thirdparty/jquery-validate/jquery.validate.min.js');
458
            Requirements::add_i18n_javascript('silverstripe/comments:javascript/lang');
459
            Requirements::javascript('silverstripe/comments:javascript/CommentsInterface.js');
460
        }
461
462
        $controller = CommentingController::create();
463
        $controller->setOwnerRecord($this->owner);
464
        $controller->setParentClass($this->owner->getClassName());
465
        $controller->setOwnerController(Controller::curr());
466
467
        $session = Controller::curr()->getRequest()->getSession();
468
        $moderatedSubmitted = $session->get('CommentsModerated');
469
        $session->clear('CommentsModerated');
470
471
        $form = ($enabled) ? $controller->CommentsForm() : false;
472
473
        // a little bit all over the show but to ensure a slightly easier upgrade for users
474
        // return back the same variables as previously done in comments
475
        return $this
476
            ->owner
477
            ->customise(array(
478
                'AddCommentForm' => $form,
479
                'ModeratedSubmitted' => $moderatedSubmitted,
480
            ))
481
            ->renderWith('CommentsInterface');
482
    }
483
484
    /**
485
     * Returns whether this extension instance is attached to a {@link SiteTree} object
486
     *
487
     * @return bool
488
     */
489
    public function attachedToSiteTree()
490
    {
491
        $class = $this->owner->baseClass();
492
493
        return (is_subclass_of($class, SiteTree::class)) || ($class == SiteTree::class);
494
    }
495
496
    /**
497
     * Get the commenting option for this object.
498
     *
499
     * This can be overridden in any instance or extension to customise the
500
     * option available.
501
     *
502
     * @param string $key
503
     *
504
     * @return mixed Result if the setting is available, or null otherwise
505
     */
506
    public function getCommentsOption($key)
507
    {
508
        $settings = $this->getCommentsOptions();
509
        $value = null;
510
511
        if (isset($settings[$key])) {
512
            $value = $settings[$key];
513
        }
514
515
        // To allow other extensions to customise this option
516
        if ($this->owner) {
517
            $this->owner->extend('updateCommentsOption', $key, $value);
518
        }
519
520
        return $value;
521
    }
522
523
    /**
524
     * @return array
525
     */
526
    public function getCommentsOptions()
527
    {
528
        $settings = [];
0 ignored issues
show
$settings is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
529
530
        if ($this->owner) {
531
            $settings = $this->owner->config()->get('comments');
532
        } else {
533
            $settings = Config::inst()->get(__CLASS__, 'comments');
534
        }
535
536
        return $settings;
537
    }
538
539
    /**
540
     * Add moderation functions to the current fieldlist
541
     *
542
     * @param FieldList $fields
543
     */
544
    protected function updateModerationFields(FieldList $fields)
545
    {
546
        Requirements::css('silverstripe/comments:css/cms.css');
547
548
        $newComments = $this->owner->AllComments()->filter('Moderated', 0);
549
550
        $newGrid = new CommentsGridField(
551
            'NewComments',
552
            _t('CommentsAdmin.NewComments', 'New'),
553
            $newComments,
554
            CommentsGridFieldConfig::create()
555
        );
556
557
        $approvedComments = $this->owner->AllComments()->filter('Moderated', 1)->filter('IsSpam', 0);
558
559
        $approvedGrid = new CommentsGridField(
560
            'ApprovedComments',
561
            _t('CommentsAdmin.Comments', 'Approved'),
562
            $approvedComments,
563
            CommentsGridFieldConfig::create()
564
        );
565
566
        $spamComments = $this->owner->AllComments()->filter('Moderated', 1)->filter('IsSpam', 1);
567
568
        $spamGrid = new CommentsGridField(
569
            'SpamComments',
570
            _t('CommentsAdmin.SpamComments', 'Spam'),
571
            $spamComments,
572
            CommentsGridFieldConfig::create()
573
        );
574
575
        $newCount = '(' . count($newComments) . ')';
576
        $approvedCount = '(' . count($approvedComments) . ')';
577
        $spamCount = '(' . count($spamComments) . ')';
578
579
        if ($fields->hasTabSet()) {
580
            $tabs = new TabSet(
581
                'Comments',
582
                new Tab(
583
                    'CommentsNewCommentsTab',
584
                    _t('SilverStripe\\Comments\\Admin\\CommentAdmin.NewComments', 'New') . ' ' . $newCount,
585
                    $newGrid
586
                ),
587
                new Tab(
588
                    'CommentsCommentsTab',
589
                    _t('SilverStripe\\Comments\\Admin\\CommentAdmin.Comments', 'Approved') . ' ' . $approvedCount,
590
                    $approvedGrid
591
                ),
592
                new Tab(
593
                    'CommentsSpamCommentsTab',
594
                    _t('SilverStripe\\Comments\\Admin\\CommentAdmin.SpamComments', 'Spam') . ' ' . $spamCount,
595
                    $spamGrid
596
                )
597
            );
598
            $tabs->setTitle(_t(__CLASS__ . '.COMMENTSTABSET', 'Comments'));
599
600
            $fields->addFieldToTab('Root', $tabs);
601
        } else {
602
            $fields->push($newGrid);
603
            $fields->push($approvedGrid);
604
            $fields->push($spamGrid);
605
        }
606
    }
607
608
    public function updateCMSFields(FieldList $fields)
609
    {
610
        // Disable moderation if not permitted
611
        if ($this->owner->canModerateComments()) {
612
            $this->updateModerationFields($fields);
613
        }
614
615
        // If this isn't a page we should merge the settings into the CMS fields
616
        if (!$this->attachedToSiteTree()) {
617
            $this->updateSettingsFields($fields);
618
        }
619
    }
620
}
621