FIX: restore spam, rss, delete, approve and ham controller actions on the front end.

This commit is contained in:
Will Rossiter 2012-07-22 13:30:33 +12:00
parent 41f3c61718
commit 95667fdf41
5 changed files with 303 additions and 88 deletions

View File

@ -66,7 +66,16 @@ class Commenting {
Object::remove_extension($class, 'CommentsExtension');
}
/**
* Returns whether a given class name has commenting enabled
*
* @return bool
*/
public static function has_commenting($class) {
return (isset(self::$enabled_classes[$class]));
}
/**
* Sets a value for a class of a given config setting. Passing 'all' as the class
* sets it for everything

View File

@ -6,8 +6,12 @@
class CommentingController extends Controller {
static $allowed_actions = array(
public static $allowed_actions = array(
'delete',
'spam',
'ham',
'approve',
'rss',
'CommentsForm',
'doPostComment'
);
@ -42,38 +46,194 @@ class CommentingController extends Controller {
/**
* Workaround for generating the link to this controller
*
* @return string
*/
public function Link($action = "") {
return __CLASS__ .'/'. $action;
public function Link($action = "", $id = '', $other = '') {
return Controller::join_links(__CLASS__ , $action, $id, $other);
}
/**
* Performs the delete task for deleting {@link Comment}.
* Return an RSS feed of comments for a given set of comments or all
* comments on the website.
*
* /delete/$ID deletes the $ID comment
* To maintain backwards compatibility with 2.4 this supports mapping
* of PageComment/rss?pageid= as well as the new RSS format for comments
* of CommentingController/rss/{classname}/{id}
*
* @return RSS
*/
public function delete() {
public function rss() {
$link = $this->Link('rss');
$class = $this->urlParams['ID'];
$id = $this->urlParams['OtherID'];
if(isset($_GET['pageid'])) {
$id = Convert::raw2sql($_GET['pageid']);
$comments = Comment::get()->where(sprintf(
"BaseClass = 'SiteTree' AND ParentID = '%s'", $id
));
$link = $this->Link('rss', 'SiteTree', $id);
} else if($class && $id) {
if(Commenting::has_commenting($class)) {
$comments = Comment::get()->where(sprintf(
"BaseClass = '%s' AND ParentID = '%s'",
Convert::raw2sql($class),
Convert::raw2sql($id)
));
$link = $this->Link('rss', Convert::raw2xml($class), (int) $id);
} else {
return $this->httpError(404);
}
} else if($class) {
if(Commenting::has_commenting($class)) {
$comments = Comment::get()->where(sprintf(
"BaseClass = '%s'", Convert::raw2sql($class)
));
} else {
return $this->httpError(404);
}
} else {
$comments = Comment::get();
}
$title = _t('CommentingController.RSSTITLE', "Comments RSS Feed");
$feed = new RSSFeed($comments, $link, $title, $link, 'Title', 'Comment', 'AuthorName');
$feed->outputToBrowser();
}
/**
* Deletes a given {@link Comment} via the URL.
*
* @param SS_HTTPRequest
*/
public function delete($request) {
if(!$this->checkSecurityToken($request)) {
return $this->httpError(400);
}
if(($comment = $this->getComment()) && $comment->canDelete()) {
$comment->delete();
return ($this->request->isAjax()) ? true : $this->redirectBack();
}
return $this->httpError(404);
}
/**
* Marks a given {@link Comment} as spam. Removes the comment from display
*
* @param SS_HTTPRequest
*/
public function spam() {
if(!$this->checkSecurityToken($request)) {
return $this->httpError(400);
}
$comment = $this->getComment();
if(($comment = $this->getComment()) && $comment->canEdit()) {
$comment->IsSpam = true;
$comment->Moderated = true;
$comment->write();
return ($this->request->isAjax()) ? true : $this->redirectBack();
}
return $this->httpError(404);
}
/**
* Marks a given {@link Comment} as ham (not spam).
*
* @param SS_HTTPRequest
*/
public function ham($request) {
if(!$this->checkSecurityToken($request)) {
return $this->httpError(400);
}
$comment = $this->getComment();
if(($comment = $this->getComment()) && $comment->canEdit()) {
$comment->IsSpam = false;
$comment->Moderated = true;
$comment->write();
return ($this->request->isAjax()) ? true : $this->redirectBack();
}
return $this->httpError(404);
}
/**
* Marks a given {@link Comment} as approved.
*
* @param SS_HTTPRequest
*/
public function approve($request) {
if(!$this->checkSecurityToken($request)) {
return $this->httpError(400);
}
$comment = $this->getComment();
if(($comment = $this->getComment()) && $comment->canEdit()) {
$comment->IsSpam = false;
$comment->Moderated = true;
$comment->write();
return ($this->request->isAjax()) ? true : $this->redirectBack();
}
return $this->httpError(404);
}
/**
* Returns the comment referenced in the URL (by ID).
*
* @return Comment|false
*/
public function getComment() {
$id = isset($this->urlParams['ID']) ? $this->urlParams['ID'] : false;
if($id) {
$comment = DataObject::get_by_id('Comment', $id);
if($comment && $comment->canDelete()) {
$comment->delete();
return ($this->request->isAjax()) ? true : $this->redirectBack();
if($comment) {
return $comment;
}
}
return ($this->request->isAjax()) ? false : $this->httpError('404');
return false;
}
/**
* Checks the security token given with the URL to prevent CSRF attacks
* against administrators allowing users to hijack comment moderation.
*
* @param SS_HTTPRequest
*
* @return boolean
*/
public function checkSecurityToken($req) {
$token = SecurityToken::inst();
return $token->checkRequest($req);
}
/**
* Post a comment form
*
* @return Form
*/
function CommentsForm() {
public function CommentsForm() {
$member = Member::currentUser();
$fields = new FieldList(
@ -143,6 +303,10 @@ class CommentingController extends Controller {
"Comment" => Cookie::get('CommentsForm_Comment')
));
}
if($member) {
$form->loadDataFrom($member);
}
// hook to allow further extensions to alter the comments form
$this->extend('alterCommentForm', $form);
@ -156,7 +320,7 @@ class CommentingController extends Controller {
* @param array $data
* @param Form $form
*/
function doPostComment($data, $form) {
public function doPostComment($data, $form) {
$class = (isset($data['BaseClass'])) ? $data['BaseClass'] : $this->getBaseClass();
// if no class then we cannot work out what controller or model they

View File

@ -7,7 +7,7 @@
*/
class Comment extends DataObject {
static $db = array(
public static $db = array(
"Name" => "Varchar(200)",
"Comment" => "Text",
"Email" => "Varchar(200)",
@ -15,27 +15,29 @@ class Comment extends DataObject {
"BaseClass" => "Varchar(200)",
"Moderated" => "Boolean",
"IsSpam" => "Boolean",
'NeedsModeration' => 'Boolean',
"ParentID" => "Int"
);
static $has_one = array(
"Parent" => "DataObject",
public static $has_one = array(
"Author" => "Member"
);
static $has_many = array();
public static $default_sort = "Created DESC";
static $many_many = array();
public static $has_many = array();
static $defaults = array(
public static $many_many = array();
public static $defaults = array(
"Moderated" => true
);
static $casting = array(
"RSSTitle" => "Varchar",
public static $casting = array(
'AuthorName' => 'Varchar',
'RSSName' => 'Varchar'
);
static $searchable_fields = array(
public static $searchable_fields = array(
'Name',
'Email',
'Comment',
@ -43,12 +45,13 @@ class Comment extends DataObject {
'BaseClass',
);
static $summary_fields = array(
public static $summary_fields = array(
'Name' => 'Submitted By',
'Email' => 'Email',
'Comment' => 'Comment',
'Created' => 'Date Posted',
'ParentTitle' => 'Parent',
'IsSpam' => 'Is Spam'
);
@ -87,7 +90,7 @@ class Comment extends DataObject {
* @return string link to this comment.
*/
public function Link($action = "") {
return $this->Parent()->Link($action) . '#' . $this->Permalink();
return $this->getParent()->Link($action) . '#' . $this->Permalink();
}
/**
@ -103,9 +106,11 @@ class Comment extends DataObject {
}
/**
* @param boolean $includerelations a boolean value to indicate if the labels returned include relation fields
* Translate the form field labels for the CMS administration
*
* @param boolean $includerelations
*/
function fieldLabels($includerelations = true) {
public function fieldLabels($includerelations = true) {
$labels = parent::fieldLabels($includerelations);
$labels['Name'] = _t('Comment.NAME', 'Author Name');
$labels['Comment'] = _t('Comment.COMMENT', 'Comment');
@ -132,8 +137,9 @@ class Comment extends DataObject {
*
* @return string
*/
function getParentTitle(){
public function getParentTitle(){
$parent = $this->getParent();
return ($parent->Title) ? $parent->Title : $parent->ClassName . " #" . $parent->ID;
}
@ -142,20 +148,18 @@ class Comment extends DataObject {
*
* @return Boolean
*/
function canCreate($member = null) {
public function canCreate($member = null) {
return false;
}
/**
* 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}.
* Checks for association with a page, and {@link SiteTree->ProvidePermission}
* flag being set to true.
*
* @param Member $member
* @return Boolean
*/
function canView($member = null) {
public function canView($member = null) {
if(!$member) $member = Member::currentUser();
// Standard mechanism for accepting permission changes from decorators
@ -170,13 +174,13 @@ class Comment extends DataObject {
}
/**
* Checks for "CMS_ACCESS_CommentAdmin" permission codes
* and {@link canView()}.
* Checks for "CMS_ACCESS_CommentAdmin" permission codes and
* {@link canView()}.
*
* @param Member $member
* @return Boolean
*/
function canEdit($member = null) {
public function canEdit($member = null) {
if(!$member) $member = Member::currentUser();
// Standard mechanism for accepting permission changes from decorators
@ -189,13 +193,13 @@ class Comment extends DataObject {
}
/**
* Checks for "CMS_ACCESS_CommentAdmin" permission codes
* and {@link canEdit()}.
* Checks for "CMS_ACCESS_CommentAdmin" permission codes and
* {@link canEdit()}.
*
* @param Member $member
* @return Boolean
*/
function canDelete($member = null) {
public function canDelete($member = null) {
if(!$member) $member = Member::currentUser();
// Standard mechanism for accepting permission changes from decorators
@ -204,40 +208,76 @@ class Comment extends DataObject {
return $this->canEdit($member);
}
/************************************ Review the following */
function getRSSName() {
/**
* Return the authors name for the comment
*
* @return string
*/
public function getAuthorName() {
if($this->Name) {
return $this->Name;
} elseif($this->Author()) {
} else if($this->Author()) {
return $this->Author()->getName();
}
}
function DeleteLink() {
return ($this->canDelete()) ? "PageComment_Controller/deletecomment/$this->ID" : false;
/**
* @return string
*/
public function DeleteLink() {
if($this->canDelete()) {
$token = SecurityToken::inst();
return DBField::create_field("Varchar", $token->addToUrl(sprintf(
"CommentingController/delete/%s", (int) $this->ID
)));
}
}
function CommentTextWithLinks() {
$pattern = '|([a-zA-Z]+://)([a-zA-Z0-9?&%.;:/=+_-]*)|is';
$replace = '<a rel="nofollow" href="$1$2">$1$2</a>';
return preg_replace($pattern, $replace, $this->Comment);
/**
* @return string
*/
public function SpamLink() {
if($this->canEdit() && !$this->IsSpam) {
$token = SecurityToken::inst();
return DBField::create_field("Varchar", $token->addToUrl(sprintf(
"CommentingController/spam/%s", (int) $this->ID
)));
}
}
function SpamLink() {
return ($this->canEdit() && !$this->IsSpam) ? "PageComment_Controller/reportspam/$this->ID" : false;
/**
* @return string
*/
public function HamLink() {
if($this->canEdit() && $this->IsSpam) {
$token = SecurityToken::inst();
return DBField::create_field("Varchar", $token->addToUrl(sprintf(
"CommentingController/ham/%s", (int) $this->ID
)));
}
}
function HamLink() {
return ($this->canEdit() && $this->IsSpam) ? "PageComment_Controller/reportham/$this->ID" : false;
/**
* @return string
*/
public function ApproveLink() {
if($this->canEdit() && !$this->Moderated) {
$token = SecurityToken::inst();
return DBField::create_field("Varchar", $token->addToUrl(sprintf(
"CommentingController/approve/%s", (int) $this->ID
)));
}
}
function ApproveLink() {
return ($this->canEdit() && $this->NeedsModeration) ? "PageComment_Controller/approve/$this->ID" : false;
}
function SpamClass() {
/**
* @return string
*/
public function SpamClass() {
if($this->getField('IsSpam')) {
return 'spam';
} else if($this->getField('NeedsModeration')) {
@ -247,12 +287,18 @@ class Comment extends DataObject {
}
}
function RSSTitle() {
return sprintf(
_t('PageComment.COMMENTBY', "Comment by '%s' on %s", PR_MEDIUM, 'Name, Page Title'),
Convert::raw2xml($this->getRSSName()),
$this->Parent()->Title
);
/**
* @return string
*/
public function getTitle() {
$title = sprintf(_t('Comment.COMMENTBY', "Comment by '%s'", 'Name'), $this->getAuthorName());
if($parent = $this->getParent()) {
if($parent->Title) {
$title .= sprintf(" %s %s", _t('Comment.ON', 'on'), $parent->Title);
}
}
return $title;
}
}

View File

@ -15,7 +15,7 @@ class CommentsExtension extends DataExtension {
*
* @return array
*/
function extraStatics($class = null, $extension = null) {
public function extraStatics($class = null, $extension = null) {
$fields = array();
$relationships = array(
@ -99,9 +99,7 @@ class CommentsExtension extends DataExtension {
// do not include the comments on pages which don't have id's such as security pages
if($this->owner->ID < 0) return false;
$controller = new CommentingController();
// tad bit messy but needed to ensure all data is available
$controller = new CommentingController();
$controller->setOwnerRecord($this->owner);
$controller->setBaseClass($this->ownerBaseClass);
$controller->setOwnerController(Controller::curr());
@ -114,6 +112,8 @@ class CommentsExtension extends DataExtension {
'CommentHolderID' => Commenting::get_config_value($this->ownerBaseClass, 'comments_holder_id'),
'PostingRequiresPermission' => Commenting::get_config_value($this->ownerBaseClass, 'required_permission'),
'CanPost' => Commenting::can_member_post($this->ownerBaseClass),
'RssLink' => "CommentingController/rss",
'RssLinkPage' => "CommentingController/rss/". $this->ownerBaseClass . '/'.$this->owner->ID,
'CommentsEnabled' => $enabled,
'AddCommentForm' => $form,
'Comments' => $this->Comments()
@ -134,7 +134,7 @@ class CommentsExtension extends DataExtension {
/**
* @deprecated 1.0 Please use {@link CommentsExtension->CommentsForm()}
*/
function PageComments() {
public function PageComments() {
// This method is very commonly used, don't throw a warning just yet
//user_error('$PageComments is deprecated. Please use $CommentsForm', E_USER_WARNING);

View File

@ -1,32 +1,28 @@
<p class="comment" id="$Permalink">
<% if bbCodeEnabled %>
$ParsedBBCode
<% else %>
$Comment.XML
<% end_if %>
</p>
<div class="comment" id="$Permalink">
<p>$Comment.XML</p>
</div>
<p class="info">
<% if $URL %>
<% _t('PBY','Posted by') %> <a href="$URL.URL" rel="nofollow">$Name.XML</a>, $Created.Nice ($Created.Ago)
<% _t('PBY','Posted by') %> <a href="$URL.URL" rel="nofollow">$AuthorName.XML</a>, $Created.Nice ($Created.Ago)
<% else %>
<% _t('PBY','Posted by') %> $Name.XML, $Created.Nice ($Created.Ago)
<% _t('PBY','Posted by') %> $AuthorName.XML, $Created.Nice ($Created.Ago)
<% end_if %>
</p>
<% if ApproveLink || SpamLink || HamLink || DeleteLink %>
<% if $ApproveLink || $SpamLink || $HamLink || $DeleteLink %>
<ul class="action-links">
<% if ApproveLink %>
<li><a href="$ApproveLink" class="approve"><% _t('APPROVE', 'approve this comment') %></a></li>
<li><a href="$ApproveLink.ATT" class="approve"><% _t('APPROVE', 'approve this comment') %></a></li>
<% end_if %>
<% if SpamLink %>
<li><a href="$SpamLink" class="spam"><% _t('ISSPAM','this comment is spam') %></a></li>
<li><a href="$SpamLink.ATT" class="spam"><% _t('ISSPAM','this comment is spam') %></a></li>
<% end_if %>
<% if HamLink %>
<li><a href="$HamLink" class="ham"><% _t('ISNTSPAM','this comment is not spam') %></a></li>
<li><a href="$HamLink.ATT" class="ham"><% _t('ISNTSPAM','this comment is not spam') %></a></li>
<% end_if %>
<% if DeleteLink %>
<li class="last"><a href="$DeleteLink" class="delete"><% _t('REMCOM','remove this comment') %></a></li>
<li class="last"><a href="$DeleteLink.ATT" class="delete"><% _t('REMCOM','remove this comment') %></a></li>
<% end_if %>
</ul>
<% end_if %>