diff --git a/code/sitefeatures/PageComment.php b/code/sitefeatures/PageComment.php index ead42075..a10444b3 100755 --- a/code/sitefeatures/PageComment.php +++ b/code/sitefeatures/PageComment.php @@ -60,7 +60,7 @@ class PageComment extends DataObject { } function DeleteLink() { - return (Permission::check('CMS_ACCESS_CMSMain')) ? "PageComment_Controller/deletecomment/$this->ID" : false; + return ($this->canDelete()) ? "PageComment_Controller/deletecomment/$this->ID" : false; } function CommentTextWithLinks() { @@ -70,15 +70,15 @@ class PageComment extends DataObject { } function SpamLink() { - return (Permission::check('CMS_ACCESS_CMSMain') && !$this->IsSpam) ? "PageComment_Controller/reportspam/$this->ID" : false; + return ($this->canEdit() && !$this->IsSpam) ? "PageComment_Controller/reportspam/$this->ID" : false; } function HamLink() { - return (Permission::check('CMS_ACCESS_CMSMain') && $this->IsSpam) ? "PageComment_Controller/reportham/$this->ID" : false; + return ($this->canEdit() && $this->IsSpam) ? "PageComment_Controller/reportham/$this->ID" : false; } function ApproveLink() { - return (Permission::check('CMS_ACCESS_CMSMain') && $this->NeedsModeration) ? "PageComment_Controller/approve/$this->ID" : false; + return ($this->canEdit() && $this->NeedsModeration) ? "PageComment_Controller/approve/$this->ID" : false; } function SpamClass() { @@ -156,6 +156,77 @@ class PageComment extends DataObject { } } } + + /** + * This always returns true, and should be handled by {@link PageCommentInterface->CanPostComment()}. + * + * @todo Integrate with PageCommentInterface::$comments_require_permission and $comments_require_login + * + * @param Member $member + * @return Boolean + */ + function canCreate($member = null) { + return true; + } + + /** + * Checks for association with a page, + * and {@link SiteTree->ProvidePermission} flag being set to TRUE. + * Note: There's an additional layer of permission control + * in {@link PageCommentInterface}. + * + * @param Member $member + * @return Boolean + */ + function canView($member = null) { + if(!$member) $member = Member::currentUser(); + + // Standard mechanism for accepting permission changes from decorators + $extended = $this->extendedCan('canView', $member); + if($extended !== null) return $extended; + + $page = $this->Parent(); + return ( + ($page && $page->ProvideComments) + || (bool)Permission::checkMember($member, 'CMS_ACCESS_CommentAdmin') + ); + } + + /** + * Checks for "CMS_ACCESS_CommentAdmin" permission codes + * and {@link canView()}. + * + * @param Member $member + * @return Boolean + */ + function canEdit($member = null) { + if(!$member) $member = Member::currentUser(); + + // Standard mechanism for accepting permission changes from decorators + $extended = $this->extendedCan('canEdit', $member); + if($extended !== null) return $extended; + + if(!$this->canView($member)) return false; + + return (bool)Permission::checkMember($member, 'CMS_ACCESS_CommentAdmin'); + } + + /** + * Checks for "CMS_ACCESS_CommentAdmin" permission codes + * and {@link canEdit()}. + * + * @param Member $member + * @return Boolean + */ + function canDelete($member = null) { + if(!$member) $member = Member::currentUser(); + + // Standard mechanism for accepting permission changes from decorators + $extended = $this->extendedCan('canDelete', $member); + if($extended !== null) return $extended; + + return $this->canEdit($member); + } } @@ -180,13 +251,11 @@ class PageComment_Controller extends Controller { * Deletes all comments on the page referenced by the url param pageid */ function deleteallcomments() { - if(Permission::check('CMS_ACCESS_CMSMain')) { - $pageId = $_REQUEST['pageid']; - if(preg_match('/^\d+$/', $pageId)) { - $comments = DataObject::get("PageComment", "\"ParentID\" = $pageId"); - if($comments) foreach($comments as $c) { - $c->delete(); - } + $pageId = $_REQUEST['pageid']; + if(preg_match('/^\d+$/', $pageId)) { + $comments = DataObject::get("PageComment", "\"ParentID\" = $pageId"); + if($comments) foreach($comments as $c) { + if($c->canDelete()) $c->delete(); } } @@ -198,11 +267,9 @@ class PageComment_Controller extends Controller { } function deletecomment() { - if(Permission::check('CMS_ACCESS_CMSMain')) { - $comment = DataObject::get_by_id("PageComment", $this->urlParams['ID']); - if($comment) { - $comment->delete(); - } + $comment = DataObject::get_by_id("PageComment", $this->urlParams['ID']); + if($comment && $comment->canDelete()) { + $comment->delete(); } if($this->isAjax()) { @@ -213,51 +280,45 @@ class PageComment_Controller extends Controller { } function approve() { - if(Permission::check('CMS_ACCESS_CMSMain')) { - $comment = DataObject::get_by_id("PageComment", $this->urlParams['ID']); + $comment = DataObject::get_by_id("PageComment", $this->urlParams['ID']); - if($comment) { - $comment->NeedsModeration = false; - $comment->write(); - - // @todo Report to spamprotecter this is true - - if($this->isAjax()) { - echo $comment->renderWith('PageCommentInterface_singlecomment'); - } else { - $this->redirectBack(); - } + if($comment && $comment->canEdit()) { + $comment->NeedsModeration = false; + $comment->write(); + + // @todo Report to spamprotecter this is true + + if($this->isAjax()) { + echo $comment->renderWith('PageCommentInterface_singlecomment'); + } else { + Director::redirectBack(); } } } function reportspam() { $comment = DataObject::get_by_id("PageComment", $this->urlParams['ID']); - if($comment) { - // check they have access - if(Permission::check('CMS_ACCESS_CMSMain')) { - - // if spam protection module exists - if(class_exists('SpamProtectorManager')) { - SpamProtectorManager::send_feedback($comment, 'spam'); - } - - // If Akismet is enabled - else if(SSAkismet::isEnabled()) { - try { - $akismet = new SSAkismet(); - $akismet->setCommentAuthor($comment->getField('Name')); - $akismet->setCommentContent($comment->getField('Comment')); - $akismet->submitSpam(); - } catch (Exception $e) { - // Akismet didn't work, most likely the service is down. - } - } - - $comment->IsSpam = true; - $comment->NeedsModeration = false; - $comment->write(); + if($comment && $comment->canEdit()) { + // if spam protection module exists + if(class_exists('SpamProtectorManager')) { + SpamProtectorManager::send_feedback($comment, 'spam'); } + + // If Akismet is enabled + else if(SSAkismet::isEnabled()) { + try { + $akismet = new SSAkismet(); + $akismet->setCommentAuthor($comment->getField('Name')); + $akismet->setCommentContent($comment->getField('Comment')); + $akismet->submitSpam(); + } catch (Exception $e) { + // Akismet didn't work, most likely the service is down. + } + } + + $comment->IsSpam = true; + $comment->NeedsModeration = false; + $comment->write(); } if($this->isAjax()) { if(SSAkismet::isEnabled() && SSAkismet::getSaveSpam()) { @@ -274,27 +335,24 @@ class PageComment_Controller extends Controller { */ function reportham() { $comment = DataObject::get_by_id("PageComment", $this->urlParams['ID']); - if($comment) { - if(Permission::check('CMS_ACCESS_CMSMain')) { - - // if spam protection module exists - if(class_exists('SpamProtectorManager')) { - SpamProtectorManager::send_feedback($comment, 'ham'); - } - - if(SSAkismet::isEnabled()) { - try { - $akismet = new SSAkismet(); - $akismet->setCommentAuthor($comment->getField('Name')); - $akismet->setCommentContent($comment->getField('Comment')); - $akismet->submitHam(); - } catch (Exception $e) { - // Akismet didn't work, most likely the service is down. - } - } - $comment->setField('IsSpam', false); - $comment->write(); + if($comment && $comment->canEdit()) { + // if spam protection module exists + if(class_exists('SpamProtectorManager')) { + SpamProtectorManager::send_feedback($comment, 'ham'); } + + if(SSAkismet::isEnabled()) { + try { + $akismet = new SSAkismet(); + $akismet->setCommentAuthor($comment->getField('Name')); + $akismet->setCommentContent($comment->getField('Comment')); + $akismet->submitHam(); + } catch (Exception $e) { + // Akismet didn't work, most likely the service is down. + } + } + $comment->setField('IsSpam', false); + $comment->write(); } if($this->isAjax()) { echo $comment->renderWith('PageCommentInterface_singlecomment'); @@ -305,4 +363,4 @@ class PageComment_Controller extends Controller { } -?> +?> \ No newline at end of file diff --git a/code/sitefeatures/PageCommentInterface.php b/code/sitefeatures/PageCommentInterface.php index 8d091acb..cacc6a8d 100755 --- a/code/sitefeatures/PageCommentInterface.php +++ b/code/sitefeatures/PageCommentInterface.php @@ -231,7 +231,7 @@ class PageCommentInterface extends RequestHandler { $limit['limit'] = PageComment::$comments_per_page; $spamfilter = isset($_GET['showspam']) ? '' : "AND \"IsSpam\" = 0"; - $unmoderatedfilter = Permission::check('ADMIN') ? '' : "AND \"NeedsModeration\" = 0"; + $unmoderatedfilter = Permission::check('CMS_ACCESS_CommentAdmin') ? '' : "AND \"NeedsModeration\" = 0"; $order = self::$order_comments_by; $comments = DataObject::get("PageComment", "\"ParentID\" = '" . Convert::raw2sql($this->page->ID) . "' $spamfilter $unmoderatedfilter", $order, "", $limit); @@ -254,7 +254,7 @@ class PageCommentInterface extends RequestHandler { * comments on a page referenced by the url param pageid */ function DeleteAllLink() { - if(Permission::check('CMS_ACCESS_CMSMain')) { + if(Permission::check('CMS_ACCESS_CommentAdmin')) { return Director::absoluteBaseURL() . "PageComment/deleteallcomments?pageid=" . $this->page->ID; } } diff --git a/tests/CommentAdminTest.php b/tests/CommentAdminTest.php index 9a3cfa92..9ec92e26 100644 --- a/tests/CommentAdminTest.php +++ b/tests/CommentAdminTest.php @@ -28,7 +28,7 @@ class CommentAdminTest extends FunctionalTest { function testdeletemarked(){ $comm = $this->objFromFixture('PageComment', 'Comment1'); $id = $comm->ID; - $this->logInWithPermission('ADMIN'); + $this->logInWithPermission('CMS_ACCESS_CommentAdmin'); $result = $this->get("admin/comments/EditForm/field/Comments/item/$id/delete"); $checkComm = DataObject::get_by_id('PageComment',$id); diff --git a/tests/PageCommentsTest.php b/tests/PageCommentsTest.php index 7d2f6b81..4510a31f 100644 --- a/tests/PageCommentsTest.php +++ b/tests/PageCommentsTest.php @@ -4,13 +4,64 @@ class PageCommentsTest extends FunctionalTest { static $fixture_file = 'cms/tests/PageCommentsTest.yml'; + function testCanView() { + $visitor = $this->objFromFixture('Member', 'visitor'); + $admin = $this->objFromFixture('Member', 'commentadmin'); + $comment = $this->objFromFixture('PageComment', 'firstComA'); + + $this->assertTrue($comment->canView($visitor), + 'Unauthenticated members can view comments associated to a page with ProvideComments=1' + ); + $this->assertTrue($comment->canView($admin), + 'Admins with CMS_ACCESS_CommentAdmin permissions can view comments associated to a page with ProvideComments=1' + ); + + $disabledComment = $this->objFromFixture('PageComment', 'disabledCom'); + + $this->assertFalse($disabledComment->canView($visitor), + 'Unauthenticated members can not view comments associated to a page with ProvideComments=0' + ); + $this->assertTrue($disabledComment->canView($admin), + 'Admins with CMS_ACCESS_CommentAdmin permissions can view comments associated to a page with ProvideComments=0' + ); + } + + function testCanEdit() { + $visitor = $this->objFromFixture('Member', 'visitor'); + $admin = $this->objFromFixture('Member', 'commentadmin'); + $comment = $this->objFromFixture('PageComment', 'firstComA'); + + $this->assertFalse($comment->canEdit($visitor)); + $this->assertTrue($comment->canEdit($admin)); + } + + function testCanDelete() { + $visitor = $this->objFromFixture('Member', 'visitor'); + $admin = $this->objFromFixture('Member', 'commentadmin'); + $comment = $this->objFromFixture('PageComment', 'firstComA'); + + $this->assertFalse($comment->canEdit($visitor)); + $this->assertTrue($comment->canEdit($admin)); + } + + function testDeleteComment() { + $firstPage = $this->objFromFixture('Page', 'first'); + $this->autoFollowRedirection = false; + $this->logInAs('commentadmin'); + + $firstComment = $this->objFromFixture('PageComment', 'firstComA'); + $firstCommentID = $firstComment->ID; + Director::test($firstPage->RelativeLink(), null, $this->session()); + Director::test('PageComment/deletecomment/'.$firstComment->ID, null, $this->session()); + + $this->assertFalse(DataObject::get_by_id('PageComment', $firstCommentID)); + } function testDeleteAllCommentsOnPage() { - - $second = $this->objFromFixture('Page', 'second'); $this->autoFollowRedirection = false; - $this->logInAs('admin'); + $this->logInAs('commentadmin'); + Director::test('second-page', null, $this->session()); Director::test('PageComment/deleteallcomments?pageid='.$second->ID, null, $this->session()); diff --git a/tests/PageCommentsTest.yml b/tests/PageCommentsTest.yml index b70d5c0f..5ec73a0e 100644 --- a/tests/PageCommentsTest.yml +++ b/tests/PageCommentsTest.yml @@ -1,27 +1,36 @@ Member: - admin: + commentadmin: FirstName: admin + visitor: + FirstName: visitor Group: - admin: + commentadmins: Title: Admin - Members: =>Member.admin + Members: =>Member.commentadmin Permission: admin: - Code: ADMIN - Group: =>Group.admin + Code: CMS_ACCESS_CommentAdmin + Group: =>Group.commentadmins Page: first: Title: First page URLSegment: first-page + ProvideComments: 1 second: Title: Second page URLSegment: second-page + ProvideComments: 1 third: Title: Third page URLSegment:third-page + ProvideComments: 1 + pageNoComments: + Title: No comments + URLSegment: no-comments + ProvideComments: 0 PageComment: firstComA: @@ -48,3 +57,6 @@ PageComment: ParentID: =>Page.third Name: TC Comment: textTC + disabledCom: + ParentID: =>Page.pageNoComments + Name: Disabled \ No newline at end of file