diff --git a/code/Commenting.php b/code/Commenting.php
index f81dd25..b4ec5c9 100644
--- a/code/Commenting.php
+++ b/code/Commenting.php
@@ -1,58 +1,60 @@
update($class, 'extensions', array('CommentsExtension'));
- // Check if settings must be customised
- if($settings === false) return;
- if(!is_array($settings)) {
- throw new InvalidArgumentException('$settings needs to be an array or null');
+ if($settings === false) {
+ return;
}
+
+ if(!is_array($settings)) {
+ throw new InvalidArgumentException(
+ '$settings needs to be an array or null'
+ );
+ }
+
Config::inst()->update($class, 'comments', $settings);
}
/**
- * Removes commenting from a {@link DataObject}. Does not remove existing comments
- * but does remove the extension.
+ * Removes commenting from a {@link DataObject}. Does not remove existing comments but does
+ * remove the extension.
*
* @deprecated since version 2.0
*
- * @param string $class Class to remove {@link CommentsExtension} from
+ * @param string $class
*/
public static function remove($class) {
Deprecation::notice('2.0', 'Using Commenting::remove is deprecated. Please use the config API instead');
+
$class::remove_extension('CommentsExtension');
}
/**
- * Returns whether a given class name has commenting enabled
+ * Returns whether a given class name has commenting enabled.
*
* @deprecated since version 2.0
*
@@ -60,87 +62,99 @@ class Commenting {
*/
public static function has_commenting($class) {
Deprecation::notice('2.0', 'Using Commenting::has_commenting is deprecated. Please use the config API instead');
+
return $class::has_extension('CommentsExtension');
}
/**
- * Sets a value for a class of a given config setting. Passing 'all' as the class
- * sets it for everything
- *
- * @deprecated since version 2.0
- *
- * @param string $class Class to set the value on. Passing 'all' will set it to all
- * active mappings
- * @param string $key setting to change
- * @param mixed $value value of the setting
- */
- public static function set_config_value($class, $key, $value = false) {
- Deprecation::notice('2.0', 'Commenting::set_config_value is deprecated. Use the config api instead');
- if($class === "all") $class = 'CommentsExtension';
- Config::inst()->update($class, 'comments', array($key => $value));
- }
-
- /**
- * Returns a given config value for a commenting class
- *
- * @deprecated since version 2.0
- *
- * @param string $class
- * @param string $key config value to return
- *
- * @throws Exception
- * @return mixed
- */
- public static function get_config_value($class, $key) {
- Deprecation::notice(
- '2.0',
- 'Using Commenting::get_config_value is deprecated. Please use $parent->getCommentsOption() or '
- . 'CommentingController::getOption() instead'
- );
-
- // Get settings
- if(!$class) {
- $class = 'CommentsExtension';
- } elseif(!$class::has_extension('CommentsExtension')) {
- throw new InvalidArgumentException("$class does not have commenting enabled");
- }
- return singleton($class)->getCommentsOption($key);
- }
-
- /**
- * Determines whether a config value on the commenting extension
- * matches a given value.
+ * Sets a value for a class of a given config setting. Passing 'all' as the class sets it for
+ * everything.
*
* @deprecated since version 2.0
*
* @param string $class
* @param string $key
- * @param string $value Expected value
- * @return boolean
+ * @param mixed $value
*/
- public static function config_value_equals($class, $key, $value) {
- $check = self::get_config_value($class, $key);
- if($check && ($check == $value)) return true;
+ public static function set_config_value($class, $key, $value = false) {
+ Deprecation::notice('2.0', 'Commenting::set_config_value is deprecated. Use the config api instead');
+
+ if($class === "all") {
+ $class = 'CommentsExtension';
+ }
+
+ Config::inst()->update($class, 'comments', array($key => $value));
}
/**
- * Return whether a user can post on a given commenting instance
+ * Returns a given config value for a commenting class.
*
* @deprecated since version 2.0
- *
+ *
* @param string $class
- * @return boolean true
+ * @param string $key config value to return
+ *
+ * @return mixed
+ *
+ * @throws InvalidArgumentException
+ */
+ public static function get_config_value($class, $key) {
+ Deprecation::notice('2.0', 'Using Commenting::get_config_value is deprecated. Please use $parent->getCommentsOption() or CommentingController::getOption() instead');
+
+ if(!$class) {
+ $class = 'CommentsExtension';
+ } elseif(!$class::has_extension('CommentsExtension')) {
+ throw new InvalidArgumentException(
+ sprintf('%s does not have commenting enabled', $class)
+ );
+ }
+
+ return singleton($class)->getCommentsOption($key);
+ }
+
+ /**
+ * Determines whether a config value on the commenting extension matches a given value.
+ *
+ * @deprecated since version 2.0
+ *
+ * @param string $class
+ * @param string $key
+ * @param string $value
+ *
+ * @return bool
+ */
+ public static function config_value_equals($class, $key, $value) {
+ $check = self::get_config_value($class, $key);
+
+ if($check && ($check == $value)) {
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Return whether a user can post on a given commenting instance.
+ *
+ * @deprecated since version 2.0
+ *
+ * @param string $class
+ *
+ * @return bool
*/
public static function can_member_post($class) {
- Deprecation::notice('2.0', 'Use $instance->canPostComment() directly instead');
+ Deprecation::notice('2.0', 'Use $instance->canPostComment() directly instead');
+
$member = Member::currentUser();
- // Check permission
$permission = self::get_config_value($class, 'required_permission');
- if($permission && !Permission::check($permission)) return false;
- // Check login required
+ if($permission && !Permission::check($permission)) {
+ return false;
+ }
+
$requireLogin = self::get_config_value($class, 'require_login');
+
return !$requireLogin || $member;
}
}
diff --git a/code/admin/CommentAdmin.php b/code/admin/CommentAdmin.php
index 36538ed..788811a 100644
--- a/code/admin/CommentAdmin.php
+++ b/code/admin/CommentAdmin.php
@@ -1,18 +1,29 @@
array(
- 'name' => _t('CommentAdmin.ADMIN_PERMISSION', "Access to 'Comments' section"),
- 'category' => _t('Permission.CMS_ACCESS_CATEGORY', 'CMS Access')
- )
+ 'CMS_ACCESS_CommentAdmin' => array(
+ 'name' => _t('CommentAdmin.ADMIN_PERMISSION', 'Access to \'Comments\' section'),
+ 'category' => _t('Permission.CMS_ACCESS_CATEGORY', 'CMS Access'),
+ ),
);
}
/**
- * @return Form
+ * {@inheritdoc}
*/
public function getEditForm($id = null, $fields = null) {
- if(!$id) $id = $this->currentPageID();
+ if(!$id) {
+ $id = $this->currentPageID();
+ }
- $form = parent::getEditForm($id);
$record = $this->getRecord($id);
if($record && !$record->canView()) {
@@ -48,61 +63,82 @@ class CommentAdmin extends LeftAndMain implements PermissionProvider {
$commentsConfig = CommentsGridFieldConfig::create();
- $newComments = Comment::get()->filter('Moderated', 0);
+ $newComments = Comment::get()
+ ->filter('Moderated', 0);
- $newGrid = new CommentsGridField(
+ $newCommentsGrid = new CommentsGridField(
'NewComments',
_t('CommentsAdmin.NewComments', 'New'),
$newComments,
$commentsConfig
);
- $approvedComments = Comment::get()->filter('Moderated', 1)->filter('IsSpam', 0);
+ $newCommentsCountLabel = sprintf('(%s)', count($newComments));
- $approvedGrid = new CommentsGridField(
+ $approvedComments = Comment::get()
+ ->filter('Moderated', 1)
+ ->filter('IsSpam', 0);
+
+ $approvedCommentsGrid = new CommentsGridField(
'ApprovedComments',
_t('CommentsAdmin.ApprovedComments', 'Approved'),
$approvedComments,
$commentsConfig
);
- $spamComments = Comment::get()->filter('Moderated', 1)->filter('IsSpam', 1);
+ $approvedCommentsCountLabel = sprintf('(%s)', count($approvedComments));
- $spamGrid = new CommentsGridField(
+ $spamComments = Comment::get()
+ ->filter('Moderated', 1)
+ ->filter('IsSpam', 1);
+
+ $spamCommentsGrid = new CommentsGridField(
'SpamComments',
_t('CommentsAdmin.SpamComments', 'Spam'),
$spamComments,
$commentsConfig
);
- $newCount = '(' . count($newComments) . ')';
- $approvedCount = '(' . count($approvedComments) . ')';
- $spamCount = '(' . count($spamComments) . ')';
+ $spamCommentsCountLabel = sprintf('(%s)', count($spamComments));
- $fields = new FieldList(
- $root = new TabSet(
- 'Root',
- new Tab('NewComments', _t('CommentAdmin.NewComments', 'New') . ' ' . $newCount,
- $newGrid
+ $tabSet = new TabSet(
+ 'Root',
+ new Tab(
+ 'NewComments',
+ sprintf(
+ '%s %s',
+ _t('CommentAdmin.NewComments', 'New'),
+ $newCommentsCountLabel
),
- new Tab('ApprovedComments', _t('CommentAdmin.ApprovedComments', 'Approved') . ' ' . $approvedCount,
- $approvedGrid
+ $newCommentsGrid
+ ),
+ new Tab(
+ 'ApprovedComments',
+ sprintf(
+ '%s %s',
+ _t('CommentAdmin.ApprovedComments', 'Approved'),
+ $approvedCommentsCountLabel
),
- new Tab('SpamComments', _t('CommentAdmin.SpamComments', 'Spam') . ' ' . $spamCount,
- $spamGrid
- )
+ $approvedCommentsGrid
+ ),
+ new Tab(
+ 'SpamComments',
+ sprintf(
+ '%s %s',
+ _t('CommentAdmin.SpamComments', 'Spam'),
+ $spamCommentsCountLabel
+ ),
+ $spamCommentsGrid
)
);
- $root->setTemplate('CMSTabSet');
-
- $actions = new FieldList();
+ $tabSet->setTemplate('CMSTabSet');
$form = new Form(
$this,
'EditForm',
- $fields,
- $actions
+ new FieldList($tabSet),
+ new FieldList()
);
$form->addExtraClass('cms-edit-form');
diff --git a/code/admin/CommentsGridField.php b/code/admin/CommentsGridField.php
index b434820..88b72a4 100644
--- a/code/admin/CommentsGridField.php
+++ b/code/admin/CommentsGridField.php
@@ -3,6 +3,8 @@
class CommentsGridField extends GridField {
/**
* {@inheritdoc}
+ *
+ * @param Comment $record
*/
protected function newRow($total, $index, $record, $attributes, $content) {
if(!isset($attributes['class'])) {
diff --git a/code/admin/CommentsGridFieldAction.php b/code/admin/CommentsGridFieldAction.php
index bb1fc30..0626c78 100644
--- a/code/admin/CommentsGridFieldAction.php
+++ b/code/admin/CommentsGridFieldAction.php
@@ -14,7 +14,9 @@ class CommentsGridFieldAction implements GridField_ColumnProvider, GridField_Act
* {@inheritdoc}
*/
public function getColumnAttributes($gridField, $record, $columnName) {
- return array('class' => 'col-buttons');
+ return array(
+ 'class' => 'col-buttons',
+ );
}
/**
@@ -22,24 +24,34 @@ class CommentsGridFieldAction implements GridField_ColumnProvider, GridField_Act
*/
public function getColumnMetadata($gridField, $columnName) {
if($columnName == 'Actions') {
- return array('title' => '');
+ return array(
+ 'title' => '',
+ );
}
+
+ return array();
}
/**
* {@inheritdoc}
*/
public function getColumnsHandled($gridField) {
- return array('Actions');
+ return array(
+ 'Actions',
+ );
}
/**
* {@inheritdoc}
+ *
+ * @param Comment $record
*/
public function getColumnContent($gridField, $record, $columnName) {
- if(!$record->canEdit()) return;
+ if(!$record->canEdit()) {
+ return '';
+ }
- $field = "";
+ $field = '';
if(!$record->IsSpam || !$record->Moderated) {
$field .= GridField_FormAction::create(
@@ -47,7 +59,9 @@ class CommentsGridFieldAction implements GridField_ColumnProvider, GridField_Act
'CustomAction' . $record->ID,
'Spam',
'spam',
- array('RecordID' => $record->ID)
+ array(
+ 'RecordID' => $record->ID,
+ )
)->Field();
}
@@ -57,7 +71,9 @@ class CommentsGridFieldAction implements GridField_ColumnProvider, GridField_Act
'CustomAction' . $record->ID,
'Approve',
'approve',
- array('RecordID' => $record->ID)
+ array(
+ 'RecordID' => $record->ID,
+ )
)->Field();
}
@@ -68,7 +84,10 @@ class CommentsGridFieldAction implements GridField_ColumnProvider, GridField_Act
* {@inheritdoc}
*/
public function getActions($gridField) {
- return array('spam', 'approve');
+ return array(
+ 'spam',
+ 'approve',
+ );
}
/**
@@ -76,25 +95,37 @@ class CommentsGridFieldAction implements GridField_ColumnProvider, GridField_Act
*/
public function handleAction(GridField $gridField, $actionName, $arguments, $data) {
if($actionName == 'spam') {
- $comment = Comment::get()->byID($arguments["RecordID"]);
+ /**
+ * @var Comment $comment
+ */
+ $comment = Comment::get()
+ ->byID($arguments["RecordID"]);
+
$comment->markSpam();
- // output a success message to the user
- Controller::curr()->getResponse()->setStatusCode(
- 200,
- 'Comment marked as spam.'
- );
+ Controller::curr()
+ ->getResponse()
+ ->setStatusCode(
+ 200,
+ 'Comment marked as spam.'
+ );
}
if($actionName == 'approve') {
- $comment = Comment::get()->byID($arguments["RecordID"]);
+ /**
+ * @var Comment $comment
+ */
+ $comment = Comment::get()
+ ->byID($arguments["RecordID"]);
+
$comment->markApproved();
- // output a success message to the user
- Controller::curr()->getResponse()->setStatusCode(
- 200,
- 'Comment approved.'
- );
+ Controller::curr()
+ ->getResponse()
+ ->setStatusCode(
+ 200,
+ 'Comment approved.'
+ );
}
}
-}
\ No newline at end of file
+}
diff --git a/code/admin/CommentsGridFieldBulkAction.php b/code/admin/CommentsGridFieldBulkAction.php
index 138ff70..e78f4ff 100644
--- a/code/admin/CommentsGridFieldBulkAction.php
+++ b/code/admin/CommentsGridFieldBulkAction.php
@@ -8,57 +8,83 @@ class CommentsGridFieldBulkAction extends GridFieldBulkActionHandler {
}
/**
- * A {@link GridFieldBulkActionHandler} for bulk marking comments as spam
+ * A {@link GridFieldBulkActionHandler} for bulk marking comments as spam.
*
* @package comments
*/
class CommentsGridFieldBulkAction_Handlers extends CommentsGridFieldBulkAction {
-
+ /**
+ * @var array
+ */
private static $allowed_actions = array(
'spam',
'approve',
);
+ /**
+ * @var array
+ */
private static $url_handlers = array(
'spam' => 'spam',
'approve' => 'approve',
);
+ /**
+ * @param SS_HTTPRequest $request
+ *
+ * @return SS_HTTPResponse
+ */
public function spam(SS_HTTPRequest $request) {
$ids = array();
foreach($this->getRecords() as $record) {
- array_push($ids, $record->ID);
+ /**
+ * @var Comment $record
+ */
$record->markSpam();
+
+ array_push($ids, $record->ID);
}
- $response = new SS_HTTPResponse(Convert::raw2json(array(
- 'done' => true,
- 'records' => $ids
- )));
+ $response = new SS_HTTPResponse(
+ Convert::raw2json(array(
+ 'done' => true,
+ 'records' => $ids,
+ ))
+ );
$response->addHeader('Content-Type', 'text/json');
return $response;
}
-
+ /**
+ * @param SS_HTTPRequest $request
+ *
+ * @return SS_HTTPResponse
+ */
public function approve(SS_HTTPRequest $request) {
$ids = array();
foreach($this->getRecords() as $record) {
- array_push($ids, $record->ID);
+ /**
+ * @var Comment $record
+ */
$record->markApproved();
+
+ array_push($ids, $record->ID);
}
- $response = new SS_HTTPResponse(Convert::raw2json(array(
- 'done' => true,
- 'records' => $ids
- )));
+ $response = new SS_HTTPResponse(
+ Convert::raw2json(array(
+ 'done' => true,
+ 'records' => $ids,
+ ))
+ );
$response->addHeader('Content-Type', 'text/json');
return $response;
}
-}
\ No newline at end of file
+}
diff --git a/code/admin/CommentsGridFieldConfig.php b/code/admin/CommentsGridFieldConfig.php
index bc01dd4..6cadca9 100644
--- a/code/admin/CommentsGridFieldConfig.php
+++ b/code/admin/CommentsGridFieldConfig.php
@@ -1,17 +1,24 @@
addComponent(new GridFieldExportButton());
-
$this->addComponent(new CommentsGridFieldAction());
- // Format column
+ /**
+ * @var GridFieldDataColumns $columns
+ */
$columns = $this->getComponentByType('GridFieldDataColumns');
+
$columns->setFieldFormatting(array(
- 'ParentTitle' => function($value, &$item) {
+ 'ParentTitle' => function ($value, &$item) {
return sprintf(
'%s',
Convert::raw2att($item->Link()),
@@ -20,24 +27,27 @@ class CommentsGridFieldConfig extends GridFieldConfig_RecordEditor {
}
));
- // Add bulk option
$manager = new GridFieldBulkManager();
$manager->addBulkAction(
- 'spam', 'Spam', 'CommentsGridFieldBulkAction_Handlers',
+ 'spam',
+ 'Spam',
+ 'CommentsGridFieldBulkAction_Handlers',
array(
'isAjax' => true,
'icon' => 'cross',
- 'isDestructive' => false
+ 'isDestructive' => false,
)
);
$manager->addBulkAction(
- 'approve', 'Approve', 'CommentsGridFieldBulkAction_Handlers',
+ 'approve',
+ 'Approve',
+ 'CommentsGridFieldBulkAction_Handlers',
array(
'isAjax' => true,
'icon' => 'cross',
- 'isDestructive' => false
+ 'isDestructive' => false,
)
);
@@ -46,4 +56,4 @@ class CommentsGridFieldConfig extends GridFieldConfig_RecordEditor {
$this->addComponent($manager);
}
-}
\ No newline at end of file
+}
diff --git a/code/controllers/CommentingController.php b/code/controllers/CommentingController.php
index ca1bf3a..fab454f 100644
--- a/code/controllers/CommentingController.php
+++ b/code/controllers/CommentingController.php
@@ -3,9 +3,10 @@
/**
* @package comments
*/
-
class CommentingController extends Controller {
-
+ /**
+ * @var array
+ */
private static $allowed_actions = array(
'delete',
'spam',
@@ -15,55 +16,59 @@ class CommentingController extends Controller {
'CommentsForm',
'reply',
'doPostComment',
- 'doPreviewComment'
+ 'doPreviewComment',
);
+ /**
+ * @var array
+ */
private static $url_handlers = array(
'reply/$ParentCommentID//$ID/$OtherID' => 'reply',
);
/**
- * Fields required for this form
+ * Fields required for this form.
+ *
+ * @config
*
* @var array
- * @config
*/
private static $required_fields = array(
'Name',
'Email',
- 'Comment'
+ 'Comment',
);
/**
- * Base class this commenting form is for
+ * Base class this commenting form is for.
*
* @var string
*/
- private $baseClass = "";
+ private $baseClass = '';
/**
- * The record this commenting form is for
- *
- * @var DataObject
+ * The record this commenting form is for.
+ *
+ * @var null|DataObject
*/
private $ownerRecord = null;
/**
- * Parent controller record
+ * Parent controller record.
*
- * @var Controller
+ * @var null|Controller
*/
private $ownerController = null;
/**
- * Backup url to return to
+ * Backup url to return to.
*
- * @var string
+ * @var null|string
*/
protected $fallbackReturnURL = null;
/**
- * Set the base class to use
+ * Set the base class to use.
*
* @param string $class
*/
@@ -72,7 +77,7 @@ class CommentingController extends Controller {
}
/**
- * Get the base class used
+ * Get the base class used.
*
* @return string
*/
@@ -81,7 +86,7 @@ class CommentingController extends Controller {
}
/**
- * Set the record this controller is working on
+ * Set the record this controller is working on.
*
* @param DataObject $record
*/
@@ -90,16 +95,16 @@ class CommentingController extends Controller {
}
/**
- * Get the record
+ * Get the record.
*
- * @return DataObject
+ * @return null|DataObject
*/
public function getOwnerRecord() {
return $this->ownerRecord;
}
/**
- * Set the parent controller
+ * Set the parent controller.
*
* @param Controller $controller
*/
@@ -108,46 +113,42 @@ class CommentingController extends Controller {
}
/**
- * Get the parent controller
+ * Get the parent controller.
*
- * @return Controller
+ * @return null|Controller
*/
public function getOwnerController() {
return $this->ownerController;
}
/**
- * Get the commenting option for the current state
+ * Get the commenting option for the current state.
*
* @param string $key
- * @return mixed Result if the setting is available, or null otherwise
+ *
+ * @return mixed
*/
public function getOption($key) {
- // If possible use the current record
if($record = $this->getOwnerRecord()) {
return $record->getCommentsOption($key);
}
-
- // Otherwise a singleton of that record
+
if($class = $this->getBaseClass()) {
return singleton($class)->getCommentsOption($key);
}
- // Otherwise just use the default options
return singleton('CommentsExtension')->getCommentsOption($key);
}
-
+
/**
- * Workaround for generating the link to this controller
- *
- * @return string
+ * {@inheritdoc}
*/
public function Link($action = '', $id = '', $other = '') {
- return Controller::join_links(Director::baseURL(), __CLASS__ , $action, $id, $other);
+ return Controller::join_links(Director::baseURL(), __CLASS__, $action, $id, $other);
}
-
+
/**
- * Outputs the RSS feed of comments
+ * Outputs the RSS feed of comments.
*
* @return HTMLText
*/
@@ -156,12 +157,11 @@ class CommentingController extends Controller {
}
/**
- * Return an RSSFeed of comments for a given set of comments or all
- * comments on the website.
+ * Return an RSSFeed of comments for a given set of comments or all comments on the website.
*
- * 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}
+ * 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}
*
* @param SS_HTTPRequest
*
@@ -172,26 +172,26 @@ class CommentingController extends Controller {
$class = $request->param('ID');
$id = $request->param('OtherID');
- // Support old pageid param
if(!$id && !$class && ($id = $request->getVar('pageid'))) {
$class = 'SiteTree';
}
- $comments = Comment::get()->filter(array(
- 'Moderated' => 1,
- 'IsSpam' => 0,
- ));
+ $comments = Comment::get()
+ ->filter(array(
+ 'Moderated' => 1,
+ 'IsSpam' => 0,
+ ));
- // Check if class filter
if($class) {
if(!is_subclass_of($class, 'DataObject') || !$class::has_extension('CommentsExtension')) {
return $this->httpError(404);
}
+
$this->setBaseClass($class);
+
$comments = $comments->filter('BaseClass', $class);
$link = Controller::join_links($link, $class);
- // Check if id filter
if($id) {
$comments = $comments->filter('ParentID', $id);
$link = Controller::join_links($link, $id);
@@ -199,17 +199,22 @@ class CommentingController extends Controller {
}
}
- $title = _t('CommentingController.RSSTITLE', "Comments RSS Feed");
+ $title = _t('CommentingController.RSSTITLE', 'Comments RSS Feed');
$comments = new PaginatedList($comments, $request);
- $comments->setPageLength($this->getOption('comments_per_page'));
+
+ $comments->setPageLength(
+ $this->getOption('comments_per_page')
+ );
return new RSSFeed(
- $comments,
- $link,
- $title,
- $link,
- 'Title', 'EscapedComment', 'AuthorName'
+ $comments,
+ $link,
+ $title,
+ $link,
+ 'Title',
+ 'EscapedComment',
+ 'AuthorName'
);
}
@@ -218,35 +223,53 @@ class CommentingController extends Controller {
*/
public function delete() {
$comment = $this->getComment();
- if(!$comment) return $this->httpError(404);
+
+ if(!$comment) {
+ $this->httpError(404);
+ }
+
if(!$comment->canDelete()) {
return Security::permissionFailure($this, 'You do not have permission to delete this comment');
}
- if(!$comment->getSecurityToken()->checkRequest($this->request)) return $this->httpError(400);
+
+ if(!$comment->getSecurityToken()->checkRequest($this->request)) {
+ $this->httpError(400);
+ }
$comment->delete();
- return $this->request->isAjax()
- ? true
- : $this->redirectBack();
+ if($this->request->isAjax()) {
+ return true;
+ }
+
+ return $this->redirectBack();
}
/**
- * Marks a given {@link Comment} as spam. Removes the comment from display
+ * Marks a given {@link Comment} as spam. Removes the comment from display.
*/
public function spam() {
$comment = $this->getComment();
- if(!$comment) return $this->httpError(404);
+
+ if(!$comment) {
+ $this->httpError(404);
+ }
+
if(!$comment->canEdit()) {
return Security::permissionFailure($this, 'You do not have permission to edit this comment');
}
- if(!$comment->getSecurityToken()->checkRequest($this->request)) return $this->httpError(400);
-
+
+ if(!$comment->getSecurityToken()->checkRequest($this->request)) {
+ $this->httpError(400);
+ }
+
$comment->markSpam();
- return $this->request->isAjax()
- ? $comment->renderWith('CommentsInterface_singlecomment')
- : $this->redirectBack();
+ if($this->request->isAjax()) {
+ return true;
+ }
+
+ return $this->redirectBack();
}
/**
@@ -254,17 +277,26 @@ class CommentingController extends Controller {
*/
public function ham() {
$comment = $this->getComment();
- if(!$comment) return $this->httpError(404);
+
+ if(!$comment) {
+ $this->httpError(404);
+ }
+
if(!$comment->canEdit()) {
return Security::permissionFailure($this, 'You do not have permission to edit this comment');
}
- if(!$comment->getSecurityToken()->checkRequest($this->request)) return $this->httpError(400);
+
+ if(!$comment->getSecurityToken()->checkRequest($this->request)) {
+ $this->httpError(400);
+ }
$comment->markApproved();
- return $this->request->isAjax()
- ? $comment->renderWith('CommentsInterface_singlecomment')
- : $this->redirectBack();
+ if($this->request->isAjax()) {
+ return true;
+ }
+
+ return $this->redirectBack();
}
/**
@@ -272,33 +304,42 @@ class CommentingController extends Controller {
*/
public function approve() {
$comment = $this->getComment();
- if(!$comment) return $this->httpError(404);
+
+ if(!$comment) {
+ $this->httpError(404);
+ }
+
if(!$comment->canEdit()) {
return Security::permissionFailure($this, 'You do not have permission to approve this comment');
}
- if(!$comment->getSecurityToken()->checkRequest($this->request)) return $this->httpError(400);
+
+ if(!$comment->getSecurityToken()->checkRequest($this->request)) {
+ $this->httpError(400);
+ }
$comment->markApproved();
- return $this->request->isAjax()
- ? $comment->renderWith('CommentsInterface_singlecomment')
- : $this->redirectBack();
+ if($this->request->isAjax()) {
+ return true;
+ }
+
+ return $this->redirectBack();
}
-
+
/**
- * Returns the comment referenced in the URL (by ID). Permission checking
- * should be done in the callee.
+ * Returns the comment referenced in the URL. Permission checking should be done in the callee.
*
- * @return Comment|false
+ * @return bool|Comment
*/
public function getComment() {
- $id = isset($this->urlParams['ID']) ? $this->urlParams['ID'] : false;
+ if(isset($this->urlParams['ID'])) {
+ $id = $this->urlParams['ID'];
- if($id) {
$comment = DataObject::get_by_id('Comment', $id);
if($comment) {
$this->fallbackReturnURL = $comment->Link();
+
return $comment;
}
}
@@ -307,216 +348,201 @@ class CommentingController extends Controller {
}
/**
- * Create a reply form for a specified comment
+ * Create a reply form for a specified comment.
*
* @param Comment $comment
+ *
+ * @return Form
*/
public function ReplyForm($comment) {
- // Enables multiple forms with different names to use the same handler
$form = $this->CommentsForm();
- $form->setName('ReplyForm_'.$comment->ID);
+ $form->setName('ReplyForm_' . $comment->ID);
$form->addExtraClass('reply-form');
- // Load parent into reply form
$form->loadDataFrom(array(
- 'ParentCommentID' => $comment->ID
+ 'ParentCommentID' => $comment->ID,
));
- // Customise action
- $form->setFormAction($this->Link('reply', $comment->ID));
-
+ $form->setFormAction(
+ $this->Link('reply', $comment->ID)
+ );
+
$this->extend('updateReplyForm', $form);
+
return $form;
}
-
/**
* Request handler for reply form.
- * This method will disambiguate multiple reply forms in the same method
+ *
+ * This method will disambiguate multiple reply forms in the same method.
*
* @param SS_HTTPRequest $request
+ *
+ * @return null|Form
*/
public function reply(SS_HTTPRequest $request) {
- // Extract parent comment from reply and build this way
if($parentID = $request->param('ParentCommentID')) {
+ /**
+ * @var null|Comment $comment
+ */
$comment = DataObject::get_by_id('Comment', $parentID, true);
+
if($comment) {
return $this->ReplyForm($comment);
}
}
- return $this->httpError(404);
+
+ $this->httpError(404);
+
+ return null;
}
/**
- * Post a comment form
+ * Post a comment form.
*
* @return Form
*/
public function CommentsForm() {
$usePreview = $this->getOption('use_preview');
- $nameRequired = _t('CommentInterface.YOURNAME_MESSAGE_REQUIRED', 'Please enter your name');
- $emailRequired = _t('CommentInterface.EMAILADDRESS_MESSAGE_REQUIRED', 'Please enter your email address');
- $emailInvalid = _t('CommentInterface.EMAILADDRESS_MESSAGE_EMAIL', 'Please enter a valid email address');
- $urlInvalid = _t('CommentInterface.COMMENT_MESSAGE_URL', 'Please enter a valid URL');
- $commentRequired = _t('CommentInterface.COMMENT_MESSAGE_REQUIRED', 'Please enter your comment');
-
$fields = new FieldList(
$dataFields = new CompositeField(
- // Name
- TextField::create("Name", _t('CommentInterface.YOURNAME', 'Your name'))
- ->setCustomValidationMessage($nameRequired)
- ->setAttribute('data-msg-required', $nameRequired),
-
- // Email
- EmailField::create(
- "Email",
- _t('CommentingController.EMAILADDRESS', "Your email address (will not be published)")
- )
- ->setCustomValidationMessage($emailRequired)
- ->setAttribute('data-msg-required', $emailRequired)
- ->setAttribute('data-msg-email', $emailInvalid)
- ->setAttribute('data-rule-email', true),
-
- // Url
- TextField::create("URL", _t('CommentingController.WEBSITEURL', "Your website URL"))
- ->setAttribute('data-msg-url', $urlInvalid)
- ->setAttribute('data-rule-url', true),
-
- // Comment
- TextareaField::create("Comment", _t('CommentingController.COMMENTS', "Comments"))
- ->setCustomValidationMessage($commentRequired)
- ->setAttribute('data-msg-required', $commentRequired)
+ $this->getNameField(),
+ $this->getEmailField(),
+ $this->getURLField(),
+ $this->getCommentField()
),
- HiddenField::create("ParentID"),
- HiddenField::create("ReturnURL"),
- HiddenField::create("ParentCommentID"),
- HiddenField::create("BaseClass")
+ HiddenField::create('ParentID'),
+ HiddenField::create('ReturnURL'),
+ HiddenField::create('ParentCommentID'),
+ HiddenField::create('BaseClass')
);
- // Preview formatted comment. Makes most sense when shortcodes or
- // limited HTML is allowed. Populated by JS/Ajax.
if($usePreview) {
$fields->insertAfter(
- ReadonlyField::create('PreviewComment', _t('CommentInterface.PREVIEWLABEL', 'Preview'))
- ->setAttribute('style', 'display: none'), // enable through JS
+ $this->getPreviewCommentField(),
'Comment'
);
}
-
+
$dataFields->addExtraClass('data-fields');
- // save actions
$actions = new FieldList(
- new FormAction("doPostComment", _t('CommentInterface.POST', 'Post'))
+ new FormAction(
+ 'doPostComment',
+ _t('CommentInterface.POST', 'Post')
+ )
);
+
if($usePreview) {
$actions->push(
- FormAction::create('doPreviewComment', _t('CommentInterface.PREVIEW', 'Preview'))
- ->addExtraClass('action-minor')
- ->setAttribute('style', 'display: none') // enable through JS
+ $this->getPreviewCommentAction()
);
}
- // required fields for server side
$required = new RequiredFields($this->config()->required_fields);
- // create the comment form
- $form = new Form($this, 'CommentsForm', $fields, $actions, $required);
+ $form = new Form(
+ $this,
+ 'CommentsForm',
+ $fields,
+ $actions,
+ $required
+ );
- // if the record exists load the extra required data
if($record = $this->getOwnerRecord()) {
-
- // Load member data
$member = Member::currentUser();
if(($record->CommentsRequireLogin || $record->PostingRequiredPermission) && $member) {
$fields = $form->Fields();
$fields->removeByName('Name');
$fields->removeByName('Email');
- $fields->insertBefore(new ReadonlyField("NameView", _t('CommentInterface.YOURNAME', 'Your name'), $member->getName()), 'URL');
- $fields->push(new HiddenField("Name", "", $member->getName()));
- $fields->push(new HiddenField("Email", "", $member->Email));
+ $fields->insertBefore(new ReadonlyField('NameView', _t('CommentInterface.YOURNAME', 'Your name'), $member->getName()), 'URL');
+ $fields->push(new HiddenField('Name', '', $member->getName()));
+ $fields->push(new HiddenField('Email', '', $member->Email));
}
-
- // we do not want to read a new URL when the form has already been submitted
- // which in here, it hasn't been.
+
$form->loadDataFrom(array(
- 'ParentID' => $record->ID,
- 'ReturnURL' => $this->request->getURL(),
- 'BaseClass' => $this->getBaseClass()
+ 'ParentID' => $record->ID,
+ 'ReturnURL' => $this->request->getURL(),
+ 'BaseClass' => $this->getBaseClass()
));
}
-
- // Set it so the user gets redirected back down to the form upon form fail
+
$form->setRedirectToFormOnValidationError(true);
- // load any data from the cookies
if($data = Cookie::get('CommentsForm_UserData')) {
- $data = Convert::json2array($data);
-
- $form->loadDataFrom(array(
- "Name" => isset($data['Name']) ? $data['Name'] : '',
- "URL" => isset($data['URL']) ? $data['URL'] : '',
- "Email" => isset($data['Email']) ? $data['Email'] : ''
- ));
- // allow previous value to fill if comment not stored in cookie (i.e. validation error)
+ $data = Convert::json2array($data);
+
+ $data += array(
+ 'Name' => '',
+ 'URL' => '',
+ 'Email' => '',
+ );
+
+ $form->loadDataFrom($data);
+
$prevComment = Cookie::get('CommentsForm_Comment');
- if($prevComment && $prevComment != ''){
- $form->loadDataFrom(array("Comment" => $prevComment));
+
+ if($prevComment && $prevComment != '') {
+ $form->loadDataFrom(array(
+ 'Comment' => $prevComment,
+ ));
}
}
if(!empty($member)) {
$form->loadDataFrom($member);
}
-
- // hook to allow further extensions to alter the comments form
+
$this->extend('alterCommentForm', $form);
return $form;
}
-
+
/**
* Process which creates a {@link Comment} once a user submits a comment from this form.
*
- * @param array $data
+ * @param array $data
* @param Form $form
+ *
+ * @return bool|SS_HTTPResponse
*/
public function doPostComment($data, $form) {
- // Load class and parent from data
if(isset($data['BaseClass'])) {
$this->setBaseClass($data['BaseClass']);
}
+
if(isset($data['ParentID']) && ($class = $this->getBaseClass())) {
$this->setOwnerRecord($class::get()->byID($data['ParentID']));
}
- if(!$this->getOwnerRecord()) return $this->httpError(404);
-
- // cache users data
- Cookie::set("CommentsForm_UserData", Convert::raw2json($data));
- Cookie::set("CommentsForm_Comment", $data['Comment']);
-
- // extend hook to allow extensions. Also see onAfterPostComment
- $this->extend('onBeforePostComment', $form);
-
- // If commenting can only be done by logged in users, make sure the user is logged in
+
+ if(!$this->getOwnerRecord()) {
+ return $this->httpError(404);
+ }
+
+ Cookie::set('CommentsForm_UserData', Convert::raw2json($data));
+ Cookie::set('CommentsForm_Comment', $data['Comment']);
+
+ $this->extend('onBeforePostComment', $form);
+
if(!$this->getOwnerRecord()->canPostComment()) {
return Security::permissionFailure(
$this,
_t(
'CommentingController.PERMISSIONFAILURE',
- "You're not able to post comments to this page. Please ensure you are logged in and have an "
- . "appropriate permission level."
+ 'You\'re not able to post comments to this page. Please ensure you are logged in and have an appropriate permission level.'
)
);
}
if($member = Member::currentUser()) {
- $form->Fields()->push(new HiddenField("AuthorID", "Author ID", $member->ID));
- }
+ $form->Fields()->push(
+ new HiddenField('AuthorID', 'Author ID', $member->ID)
+ );
+ }
- // What kind of moderation is required?
switch($this->getOwnerRecord()->ModerationRequired) {
case 'Required':
$requireModeration = true;
@@ -524,7 +550,6 @@ class CommentingController extends Controller {
case 'NonMembersOnly':
$requireModeration = empty($member);
break;
- case 'None':
default:
$requireModeration = false;
break;
@@ -536,27 +561,20 @@ class CommentingController extends Controller {
$comment->AllowHtml = $this->getOption('html_allowed');
$comment->Moderated = !$requireModeration;
- // Save into DB, or call pre-save hooks to give accurate preview
- $usePreview = $this->getOption('use_preview');
- $isPreview = $usePreview && !empty($data['IsPreview']);
- if($isPreview) {
+ if($this->getOption('use_preview') && !empty($data['IsPreview'])) {
$comment->extend('onBeforeWrite');
} else {
$comment->write();
- // extend hook to allow extensions. Also see onBeforePostComment
$this->extend('onAfterPostComment', $comment);
}
- // we want to show a notification if comments are moderated
- if ($requireModeration && !$comment->IsSpam) {
+ if($requireModeration && !$comment->IsSpam) {
Session::set('CommentsModerated', 1);
}
-
- // clear the users comment since it passed validation
+
Cookie::set('CommentsForm_Comment', false);
- // Find parent link
if(!empty($data['ReturnURL'])) {
$url = $data['ReturnURL'];
} elseif($parent = $comment->getParent()) {
@@ -565,37 +583,44 @@ class CommentingController extends Controller {
return $this->redirectBack();
}
- // Given a redirect page exists, attempt to link to the correct anchor
if(!$comment->Moderated) {
- // Display the "awaiting moderation" text
- $holder = $this->getOption('comments_holder_id');
- $hash = "{$holder}_PostCommentForm_error";
+ $hash = sprintf(
+ '%s_PostCommentForm_error',
+ $this->getOption('comments_holder_id')
+ );
} elseif($comment->IsSpam) {
- // Link to the form with the error message contained
$hash = $form->FormName();
} else {
- // Link to the moderated, non-spam comment
$hash = $comment->Permalink();
}
- return $this->redirect(Controller::join_links($url, "#{$hash}"));
+ return $this->redirect(Controller::join_links($url, '#' . $hash));
}
+ /**
+ * @param array $data
+ * @param Form $form
+ *
+ * @return bool|SS_HTTPResponse
+ */
public function doPreviewComment($data, $form) {
$data['IsPreview'] = 1;
return $this->doPostComment($data, $form);
}
+ /**
+ * In edge-cases, this will be called outside of a handleRequest() context; in that case,
+ * redirect to the homepage. Don't break into the global state at this stage because we'll
+ * be calling from a test context or something else where the global state is inappropriate.
+ *
+ * @return bool|SS_HTTPResponse
+ */
public function redirectBack() {
- // Don't cache the redirect back ever
HTTP::set_cache_age(0);
$url = null;
- // In edge-cases, this will be called outside of a handleRequest() context; in that case,
- // redirect to the homepage - don't break into the global state at this stage because we'll
- // be calling from a test context or something else where the global state is inappropraite
if($this->request) {
if($this->request->requestVar('BackURL')) {
$url = $this->request->requestVar('BackURL');
@@ -606,15 +631,150 @@ class CommentingController extends Controller {
}
}
- if(!$url) $url = $this->fallbackReturnURL;
- if(!$url) $url = Director::baseURL();
+ if(!$url) {
+ $url = $this->fallbackReturnURL;
+ }
+
+ if(!$url) {
+ $url = Director::baseURL();
+ }
- // absolute redirection URLs not located on this site may cause phishing
if(Director::is_site_url($url)) {
return $this->redirect($url);
} else {
return false;
}
+ }
+ /**
+ * @return TextField
+ */
+ protected function getNameField() {
+ $nameFieldLabel = _t(
+ 'CommentInterface.YOURNAME',
+ 'Your name'
+ );
+
+ $nameRequiredLabel = _t(
+ 'CommentInterface.YOURNAME_MESSAGE_REQUIRED',
+ 'Please enter your name'
+ );
+
+ $nameField = TextField::create('Name', $nameFieldLabel);
+
+ $nameField->setCustomValidationMessage($nameRequiredLabel);
+ $nameField->setAttribute('data-msg-required', $nameRequiredLabel);
+
+ return $nameField;
+ }
+
+ /**
+ * @return EmailField
+ */
+ protected function getEmailField() {
+ $emailFieldLabel = _t(
+ 'CommentingController.EMAILADDRESS',
+ 'Your email address (will not be published)'
+ );
+
+ $emailFieldRequiredLabel = _t(
+ 'CommentInterface.EMAILADDRESS_MESSAGE_REQUIRED',
+ 'Please enter your email address'
+ );
+
+ $emailFieldInvalidLabel = _t(
+ 'CommentInterface.EMAILADDRESS_MESSAGE_EMAIL',
+ 'Please enter a valid email address'
+ );
+
+ $emailField = EmailField::create('Email', $emailFieldLabel);
+
+ $emailField->setCustomValidationMessage($emailFieldRequiredLabel);
+ $emailField->setAttribute('data-msg-required', $emailFieldRequiredLabel);
+ $emailField->setAttribute('data-msg-email', $emailFieldInvalidLabel);
+ $emailField->setAttribute('data-rule-email', true);
+
+ return $emailField;
+ }
+
+ /**
+ * @return TextField
+ */
+ protected function getURLField() {
+ $urlFieldLabel = _t(
+ 'CommentingController.WEBSITEURL',
+ 'Your website URL'
+ );
+
+ $urlInvalidLabel = _t(
+ 'CommentInterface.COMMENT_MESSAGE_URL',
+ 'Please enter a valid URL'
+ );
+
+ $urlField = TextField::create('URL', $urlFieldLabel);
+
+ $urlField->setAttribute('data-msg-url', $urlInvalidLabel);
+ $urlField->setAttribute('data-rule-url', true);
+
+ return $urlField;
+ }
+
+ /**
+ * @return TextareaField
+ */
+ protected function getCommentField() {
+ $commentFieldLabel = _t(
+ 'CommentingController.COMMENTS',
+ 'Comments'
+ );
+
+ $commentRequiredLabel = _t(
+ 'CommentInterface.COMMENT_MESSAGE_REQUIRED',
+ 'Please enter your comment'
+ );
+
+ $commentField = TextareaField::create('Comment', $commentFieldLabel);
+
+ $commentField->setCustomValidationMessage($commentRequiredLabel);
+ $commentField->setAttribute('data-msg-required', $commentRequiredLabel);
+
+ return $commentField;
+ }
+
+ /**
+ * @return ReadonlyField
+ */
+ protected function getPreviewCommentField() {
+ $previewCommentFieldLabel = _t(
+ 'CommentInterface.PREVIEWLABEL',
+ 'Preview'
+ );
+
+ $previewCommentField = ReadonlyField::create(
+ 'PreviewComment',
+ $previewCommentFieldLabel
+ );
+
+ $previewCommentField->setAttribute('style', 'display: none');
+
+ return $previewCommentField;
+ }
+
+ /**
+ * @return FormAction
+ */
+ protected function getPreviewCommentAction() {
+ $previewCommentActionLabel = _t(
+ 'CommentInterface.PREVIEW',
+ 'Preview'
+ );
+
+ $previewCommentAction = FormAction::create(
+ 'doPreviewComment',
+ $previewCommentActionLabel
+ );
+
+ $previewCommentAction->addExtraClass('action-minor');
+ $previewCommentAction->setAttribute('style', 'display: none');
}
}
diff --git a/code/extensions/CommentsExtension.php b/code/extensions/CommentsExtension.php
index 626a4a8..3ecfc05 100644
--- a/code/extensions/CommentsExtension.php
+++ b/code/extensions/CommentsExtension.php
@@ -3,6 +3,10 @@
/**
* Extension to {@link DataObject} to enable tracking comments.
*
+ * @property bool $ProvideComments
+ * @property string $ModerationRequired
+ * @property bool $CommentsRequireLogin
+ *
* @package comments
*/
class CommentsExtension extends DataExtension {
@@ -32,9 +36,9 @@ class CommentsExtension extends DataExtension {
* nested_comments: Enable nested comments
* nested_depth: Max depth of nested comments in levels (where root is 1 depth) 0 means no limit.
*
- * @var array
- *
* @config
+ *
+ * @var array
*/
private static $comments = array(
'enabled' => true,
@@ -78,41 +82,50 @@ class CommentsExtension extends DataExtension {
* CMS configurable options should default to the config values
*/
public function populateDefaults() {
- // Set if comments should be enabled by default
- $this->owner->ProvideComments = $this->owner->getCommentsOption('enabled') ? 1 : 0;
+ $this->owner->ProvideComments = 0;
- // If moderation options should be configurable via the CMS then
- if($this->owner->getCommentsOption('require_moderation')) {
- $this->owner->ModerationRequired = 'Required';
- } elseif($this->owner->getCommentsOption('require_moderation_nonmembers')) {
- $this->owner->ModerationRequired = 'NonMembersOnly';
- } else {
- $this->owner->ModerationRequired = 'None';
+ if($this->owner->getCommentsOption('enabled')) {
+ $this->owner->ProvideComments = 1;
}
- $this->owner->CommentsRequireLogin = $this->owner->getCommentsOption('require_login') ? 1 : 0;
+ $this->owner->ModerationRequired = 'None';
+
+ if($this->owner->getCommentsOption('require_moderation')) {
+ $this->owner->ModerationRequired = 'Required';
+ }
+
+ if($this->owner->getCommentsOption('require_moderation_nonmembers')) {
+ $this->owner->ModerationRequired = 'NonMembersOnly';
+ }
+
+ $this->owner->CommentsRequireLogin = 0;
+
+ if($this->owner->getCommentsOption('require_login')) {
+ $this->owner->CommentsRequireLogin = 1;
+ }
}
-
/**
- * If this extension is applied to a {@link SiteTree} record then
- * append a Provide Comments checkbox to allow authors to trigger
- * whether or not to display comments
+ * If this extension is applied to a {@link SiteTree} record then append a Provide Comments
+ * checkbox to allow authors to trigger whether or not to display comments.
*
* @todo Allow customization of other {@link Commenting} configuration
*
* @param FieldList $fields
*/
public function updateSettingsFields(FieldList $fields) {
+ $options = FieldGroup::create();
+ $options->setTitle(_t('CommentsExtension.COMMENTOPTIONS', 'Comments'));
- $options = FieldGroup::create()->setTitle(_t('CommentsExtension.COMMENTOPTIONS', 'Comments'));
-
- // Check if enabled setting should be cms configurable
if($this->owner->getCommentsOption('enabled_cms')) {
- $options->push(new CheckboxField('ProvideComments', _t('Comment.ALLOWCOMMENTS', 'Allow Comments')));
+ $options->push(
+ new CheckboxField(
+ 'ProvideComments',
+ _t('Comment.ALLOWCOMMENTS', 'Allow Comments')
+ )
+ );
}
- // Check if we should require users to login to comment
if($this->owner->getCommentsOption('require_login_cms')) {
$options->push(
new CheckboxField(
@@ -130,16 +143,26 @@ class CommentsExtension extends DataExtension {
}
}
- // Check if moderation should be enabled via cms configurable
if($this->owner->getCommentsOption('require_moderation_cms')) {
- $moderationField = new DropdownField('ModerationRequired', 'Comment Moderation', array(
- 'None' => _t('CommentsExtension.MODERATIONREQUIRED_NONE', 'No moderation required'),
- 'Required' => _t('CommentsExtension.MODERATIONREQUIRED_REQUIRED', 'Moderate all comments'),
- 'NonMembersOnly' => _t(
- 'CommentsExtension.MODERATIONREQUIRED_NONMEMBERSONLY',
- 'Only moderate non-members'
- ),
- ));
+ $moderationField = new DropdownField(
+ 'ModerationRequired',
+ 'Comment Moderation',
+ array(
+ 'None' => _t(
+ 'CommentsExtension.MODERATIONREQUIRED_NONE',
+ 'No moderation required'
+ ),
+ 'Required' => _t(
+ 'CommentsExtension.MODERATIONREQUIRED_REQUIRED',
+ 'Moderate all comments'
+ ),
+ 'NonMembersOnly' => _t(
+ 'CommentsExtension.MODERATIONREQUIRED_NONMEMBERSONLY',
+ 'Only moderate non-members'
+ ),
+ )
+ );
+
if($fields->hasTabSet()) {
$fields->addFieldsToTab('Root.Settings', $moderationField);
} else {
@@ -149,10 +172,10 @@ class CommentsExtension extends DataExtension {
}
/**
- * Get comment moderation rules for this parent
+ * Get comment moderation rules for this parent.
*
- * None: No moderation required
- * Required: All comments
+ * None: No moderation required
+ * Required: All comments
* NonMembersOnly: Only anonymous users
*
* @return string
@@ -160,26 +183,30 @@ class CommentsExtension extends DataExtension {
public function getModerationRequired() {
if($this->owner->getCommentsOption('require_moderation_cms')) {
return $this->owner->getField('ModerationRequired');
- } elseif($this->owner->getCommentsOption('require_moderation')) {
- return 'Required';
- } elseif($this->owner->getCommentsOption('require_moderation_nonmembers')) {
- return 'NonMembersOnly';
- } else {
- return 'None';
}
+
+ if($this->owner->getCommentsOption('require_moderation')) {
+ return 'Required';
+ }
+
+ if($this->owner->getCommentsOption('require_moderation_nonmembers')) {
+ return 'NonMembersOnly';
+ }
+
+ return 'None';
}
/**
- * Determine if users must be logged in to post comments
+ * Determine if users must be logged in to post comments.
*
- * @return boolean
+ * @return bool
*/
public function getCommentsRequireLogin() {
if($this->owner->getCommentsOption('require_login_cms')) {
return (bool) $this->owner->getField('CommentsRequireLogin');
- } else {
- return (bool) $this->owner->getCommentsOption('require_login');
}
+
+ return (bool) $this->owner->getCommentsOption('require_login');
}
/**
@@ -190,105 +217,109 @@ class CommentsExtension extends DataExtension {
*/
public function AllComments() {
$order = $this->owner->getCommentsOption('order_comments_by');
- $comments = CommentList::create($this->ownerBaseClass)
- ->forForeignID($this->owner->ID)
- ->sort($order);
+
+ $comments = CommentList::create($this->ownerBaseClass);
+ $comments->forForeignID($this->owner->ID);
+ $comments->sort($order);
+
$this->owner->extend('updateAllComments', $comments);
+
return $comments;
}
/**
- * Returns all comments against this object, with with spam and unmoderated items excluded, for use in the frontend
+ * Returns all comments against this object, with with spam and un-moderated items excluded.
*
* @return CommentList
*/
public function AllVisibleComments() {
$list = $this->AllComments();
- // Filter spam comments for non-administrators if configured
$showSpam = $this->owner->getCommentsOption('frontend_spam') && $this->owner->canModerateComments();
+
if(!$showSpam) {
$list = $list->filter('IsSpam', 0);
}
- // Filter un-moderated comments for non-administrators if moderation is enabled
- $showUnmoderated = ($this->owner->ModerationRequired === 'None')
- || ($this->owner->getCommentsOption('frontend_moderation') && $this->owner->canModerateComments());
- if(!$showUnmoderated) {
+ $showUnModerated = ($this->owner->ModerationRequired === 'None') || ($this->owner->getCommentsOption('frontend_moderation') && $this->owner->canModerateComments());
+
+ if(!$showUnModerated) {
$list = $list->filter('Moderated', 1);
}
$this->owner->extend('updateAllVisibleComments', $list);
+
return $list;
}
/**
- * Returns the root level comments, with spam and unmoderated items excluded, for use in the frontend
+ * Returns the root level comments, with spam and un-moderated items excluded.
*
* @return CommentList
*/
public function Comments() {
$list = $this->AllVisibleComments();
- // If nesting comments, only show root level
if($this->owner->getCommentsOption('nested_comments')) {
$list = $list->filter('ParentCommentID', 0);
}
$this->owner->extend('updateComments', $list);
+
return $list;
}
/**
- * Returns a paged list of the root level comments, with spam and unmoderated items excluded,
- * for use in the frontend
+ * Returns a paged list of the root level comments, with spam and un-moderated items excluded.
*
* @return PaginatedList
*/
public function PagedComments() {
$list = $this->Comments();
- // Add pagination
$list = new PaginatedList($list, Controller::curr()->getRequest());
$list->setPaginationGetVar('commentsstart' . $this->owner->ID);
$list->setPageLength($this->owner->getCommentsOption('comments_per_page'));
$this->owner->extend('updatePagedComments', $list);
+
return $list;
}
/**
* Check if comments are configured for this page even if they are currently disabled.
- * Do not include the comments on pages which don't have id's such as security pages
+ *
+ * Do not include the comments on pages which don't have id's such as security pages.
*
* @deprecated since version 2.0
*
- * @return boolean
+ * @return bool
*/
public function getCommentsConfigured() {
Deprecation::notice('2.0', 'getCommentsConfigured is deprecated. Use getCommentsEnabled instead');
- return true; // by virtue of all classes with this extension being 'configured'
+
+ return true;
}
/**
- * Determine if comments are enabled for this instance
+ * Determine if comments are enabled for this instance.
*
- * @return boolean
+ * @return bool
*/
public function getCommentsEnabled() {
- // Don't display comments form for pseudo-pages (such as the login form)
- if(!$this->owner->exists()) return false;
-
- // Determine which flag should be used to determine if this is enabled
+ if(!$this->owner->exists()) {
+ return false;
+ }
+
if($this->owner->getCommentsOption('enabled_cms')) {
return $this->owner->ProvideComments;
- } else {
- return $this->owner->getCommentsOption('enabled');
}
+
+ return $this->owner->getCommentsOption('enabled');
}
/**
- * Get the HTML ID for the comment holder in the template
+ * Get the HTML ID for the comment holder in the template.
*
* @return string
*/
@@ -301,71 +332,86 @@ class CommentsExtension extends DataExtension {
*/
public function getPostingRequiresPermission() {
Deprecation::notice('2.0', 'Use getPostingRequiredPermission instead');
+
return $this->getPostingRequiredPermission();
}
/**
- * Permission codes required in order to post (or empty if none required)
+ * Permission codes required in order to post (or empty if none required).
*
- * @return string|array Permission or list of permissions, if required
+ * @return string|array
*/
public function getPostingRequiredPermission() {
return $this->owner->getCommentsOption('required_permission');
}
+ /**
+ * @return bool
+ */
public function canPost() {
Deprecation::notice('2.0', 'Use canPostComment instead');
+
return $this->canPostComment();
}
/**
- * Determine if a user can post comments on this item
+ * Determine if a user can post comments on this item.
*
- * @param Member $member Member to check
+ * @param null|Member $member
*
- * @return boolean
+ * @return bool
*/
public function canPostComment($member = null) {
- // Deny if not enabled for this object
- if(!$this->owner->CommentsEnabled) return false;
+ if(!$this->owner->CommentsEnabled) {
+ return false;
+ }
- // Check if member is required
$requireLogin = $this->owner->CommentsRequireLogin;
- if(!$requireLogin) return true;
- // Check member is logged in
- $member = $member ?: Member::currentUser();
- if(!$member) return false;
+ if(!$requireLogin) {
+ return true;
+ }
+
+ if(!$member) {
+ $member = Member::currentUser();
+ }
+
+ if(!$member) {
+ return false;
+ }
- // If member required check permissions
$requiredPermission = $this->owner->PostingRequiredPermission;
- if($requiredPermission && !Permission::checkMember($member, $requiredPermission)) return false;
+
+ if($requiredPermission && !Permission::checkMember($member, $requiredPermission)) {
+ return false;
+ }
return true;
}
/**
- * Determine if this member can moderate comments in the CMS
+ * Determine if this member can moderate comments in the CMS.
*
- * @param Member $member
+ * @param null|Member $member
*
- * @return boolean
+ * @return bool
*/
public function canModerateComments($member = null) {
- // Deny if not enabled for this object
- if(!$this->owner->CommentsEnabled) return false;
+ if(!$this->owner->CommentsEnabled) {
+ return false;
+ }
- // Fallback to can-edit
return $this->owner->canEdit($member);
}
public function getRssLink() {
Deprecation::notice('2.0', 'Use getCommentRSSLink instead');
+
return $this->getCommentRSSLink();
}
/**
- * Gets the RSS link to all comments
+ * Gets the RSS link to all comments.
*
* @return string
*/
@@ -373,42 +419,44 @@ class CommentsExtension extends DataExtension {
return Controller::join_links(Director::baseURL(), 'CommentingController/rss');
}
+ /**
+ * @return string
+ */
public function getRssLinkPage() {
Deprecation::notice('2.0', 'Use getCommentRSSLinkPage instead');
+
return $this->getCommentRSSLinkPage();
}
/**
- * Get the RSS link to all comments on this page
+ * Get the RSS link to all comments on this page.
*
* @return string
*/
public function getCommentRSSLinkPage() {
return Controller::join_links(
- $this->getCommentRSSLink(), $this->ownerBaseClass, $this->owner->ID
+ $this->getCommentRSSLink(),
+ $this->ownerBaseClass,
+ $this->owner->ID
);
}
/**
- * Comments interface for the front end. Includes the CommentAddForm and the composition
- * of the comments display.
+ * Comments interface for the front end. Includes the CommentAddForm and the composition of the
+ * comments display.
*
- * To customize the html see templates/CommentInterface.ss or extend this function with
- * your own extension.
- *
- * @todo Cleanup the passing of all this configuration based functionality
- *
- * @see docs/en/Extending
+ * To customize the html see templates/CommentInterface.ss or extend this function with your
+ * own extension.
*/
public function CommentsForm() {
- // Check if enabled
$enabled = $this->getCommentsEnabled();
+
if($enabled && $this->owner->getCommentsOption('include_js')) {
Requirements::javascript(THIRDPARTY_DIR . '/jquery/jquery.js');
Requirements::javascript(THIRDPARTY_DIR . '/jquery-entwine/dist/jquery.entwine-dist.js');
Requirements::javascript(THIRDPARTY_DIR . '/jquery-validate/lib/jquery.form.js');
Requirements::javascript(COMMENTS_THIRDPARTY . '/jquery-validate/jquery.validate.min.js');
- Requirements::javascript('comments/javascript/CommentsInterface.js');
+ Requirements::javascript(COMMENTS_DIR . '/javascript/CommentsInterface.js');
}
$controller = CommentingController::create();
@@ -417,12 +465,15 @@ class CommentsExtension extends DataExtension {
$controller->setOwnerController(Controller::curr());
$moderatedSubmitted = Session::get('CommentsModerated');
+
Session::clear('CommentsModerated');
- $form = ($enabled) ? $controller->CommentsForm() : false;
+ $form = false;
+
+ if($enabled) {
+ $form = $controller->CommentsForm();
+ }
- // a little bit all over the show but to ensure a slightly easier upgrade for users
- // return back the same variables as previously done in comments
return $this
->owner
->customise(array(
@@ -433,48 +484,58 @@ class CommentsExtension extends DataExtension {
}
/**
- * Returns whether this extension instance is attached to a {@link SiteTree} object
+ * Returns whether this extension instance is attached to a {@link SiteTree} object.
*
* @return bool
*/
public function attachedToSiteTree() {
$class = $this->ownerBaseClass;
- return (is_subclass_of($class, 'SiteTree')) || ($class == 'SiteTree');
+ return $class === 'SiteTree' || is_subclass_of($class, 'SiteTree');
}
/**
- * @deprecated 1.0 Please use {@link CommentsExtension->CommentsForm()}
+ * Please use {@link CommentsExtension->CommentsForm()}.
+ *
+ * @deprecated 1.0
*/
public function PageComments() {
- // This method is very commonly used, don't throw a warning just yet
Deprecation::notice('1.0', '$PageComments is deprecated. Please use $CommentsForm');
+
return $this->CommentsForm();
}
/**
- * Get the commenting option for this object
+ * Get the commenting option for this object.
*
- * This can be overridden in any instance or extension to customise the option available
+ * This can be overridden in any instance or extension to customise the option available.
*
* @param string $key
*
- * @return mixed Result if the setting is available, or null otherwise
+ * @return mixed
*/
public function getCommentsOption($key) {
- $settings = $this->owner // In case singleton is called on the extension directly
- ? $this->owner->config()->comments
- : Config::inst()->get(__CLASS__, 'comments');
- $value = null;
- if(isset($settings[$key])) $value = $settings[$key];
+ if($this->owner) {
+ $settings = $this->owner->config()->comments;
+ } else {
+ $settings = Config::inst()->get(__CLASS__, 'comments');
+ }
+
+ $value = null;
+
+ if(isset($settings[$key])) {
+ $value = $settings[$key];
+ }
+
+ if($this->owner) {
+ $this->owner->extend('updateCommentsOption', $key, $value);
+ }
- // To allow other extensions to customise this option
- if($this->owner) $this->owner->extend('updateCommentsOption', $key, $value);
return $value;
}
/**
- * Add moderation functions to the current fieldlist
+ * Add moderation functions to the current field list.
*
* @param FieldList $fields
*/
@@ -483,65 +544,91 @@ class CommentsExtension extends DataExtension {
$commentsConfig = CommentsGridFieldConfig::create();
- $newComments = $this->owner->AllComments()->filter('Moderated', 0);
+ $newComments = Comment::get()
+ ->filter('Moderated', 0);
- $newGrid = new CommentsGridField(
+ $newCommentsGrid = new CommentsGridField(
'NewComments',
_t('CommentsAdmin.NewComments', 'New'),
$newComments,
$commentsConfig
);
- $approvedComments = $this->owner->AllComments()->filter('Moderated', 1)->filter('IsSpam', 0);
+ $newCommentsCountLabel = sprintf('(%s)', count($newComments));
- $approvedGrid = new CommentsGridField(
+ $approvedComments = Comment::get()
+ ->filter('Moderated', 1)
+ ->filter('IsSpam', 0);
+
+ $approvedCommentsGrid = new CommentsGridField(
'ApprovedComments',
- _t('CommentsAdmin.Comments', 'Approved'),
+ _t('CommentsAdmin.ApprovedComments', 'Approved'),
$approvedComments,
$commentsConfig
);
- $spamComments = $this->owner->AllComments()->filter('Moderated', 1)->filter('IsSpam', 1);
+ $approvedCommentsCountLabel = sprintf('(%s)', count($approvedComments));
- $spamGrid = new CommentsGridField(
+ $spamComments = Comment::get()
+ ->filter('Moderated', 1)
+ ->filter('IsSpam', 1);
+
+ $spamCommentsGrid = new CommentsGridField(
'SpamComments',
_t('CommentsAdmin.SpamComments', 'Spam'),
$spamComments,
$commentsConfig
);
- $newCount = '(' . count($newComments) . ')';
- $approvedCount = '(' . count($approvedComments) . ')';
- $spamCount = '(' . count($spamComments) . ')';
+ $spamCommentsCountLabel = sprintf('(%s)', count($spamComments));
if($fields->hasTabSet()) {
$tabs = new TabSet(
'Comments',
- new Tab('CommentsNewCommentsTab', _t('CommentAdmin.NewComments', 'New') . ' ' . $newCount,
- $newGrid
+ new Tab(
+ 'NewComments',
+ sprintf(
+ '%s %s',
+ _t('CommentAdmin.NewComments', 'New'),
+ $newCommentsCountLabel
+ ),
+ $newCommentsGrid
),
- new Tab('CommentsCommentsTab', _t('CommentAdmin.Comments', 'Approved') . ' ' . $approvedCount,
- $approvedGrid
+ new Tab(
+ 'ApprovedComments',
+ sprintf(
+ '%s %s',
+ _t('CommentAdmin.ApprovedComments', 'Approved'),
+ $approvedCommentsCountLabel
+ ),
+ $approvedCommentsGrid
),
- new Tab('CommentsSpamCommentsTab', _t('CommentAdmin.SpamComments', 'Spam') . ' ' . $spamCount,
- $spamGrid
+ new Tab(
+ 'SpamComments',
+ sprintf(
+ '%s %s',
+ _t('CommentAdmin.SpamComments', 'Spam'),
+ $spamCommentsCountLabel
+ ),
+ $spamCommentsGrid
)
);
$fields->addFieldToTab('Root', $tabs);
} else {
- $fields->push($newGrid);
- $fields->push($approvedGrid);
- $fields->push($spamGrid);
+ $fields->push($newCommentsGrid);
+ $fields->push($approvedCommentsGrid);
+ $fields->push($spamCommentsGrid);
}
}
+ /**
+ * {@inheritdoc}
+ */
public function updateCMSFields(FieldList $fields) {
- // Disable moderation if not permitted
if($this->owner->canModerateComments()) {
$this->updateModerationFields($fields);
}
- // If this isn't a page we should merge the settings into the CMS fields
if(!$this->attachedToSiteTree()) {
$this->updateSettingsFields($fields);
}
diff --git a/code/model/Comment.php b/code/model/Comment.php
index a6d8da1..f4ca9b9 100755
--- a/code/model/Comment.php
+++ b/code/model/Comment.php
@@ -3,25 +3,25 @@
/**
* Represents a single comment object.
*
- * @property string $Name
- * @property string $Comment
- * @property string $Email
- * @property string $URL
- * @property string $BaseClass
- * @property boolean $Moderated
- * @property boolean $IsSpam True if the comment is known as spam
- * @property integer $ParentID ID of the parent page / dataobject
- * @property boolean $AllowHtml If true, treat $Comment as HTML instead of plain text
- * @property string $SecretToken Secret admin token required to provide moderation links between sessions
- * @property integer $Depth Depth of this comment in the nested chain
+ * @property string $Name
+ * @property string $Comment
+ * @property string $Email
+ * @property string $URL
+ * @property string $BaseClass
+ * @property bool $Moderated
+ * @property bool $IsSpam
+ * @property int $ParentID
+ * @property bool $AllowHtml
+ * @property string $SecretToken
+ * @property int $Depth
+ *
+ * @method HasManyList ChildComments()
+ * @method Member Author()
+ * @method Comment ParentComment()
*
- * @method HasManyList ChildComments() List of child comments
- * @method Member Author() Member object who created this comment
- * @method Comment ParentComment() Parent comment this is a reply to
* @package comments
*/
class Comment extends DataObject {
-
/**
* @var array
*/
@@ -39,22 +39,37 @@ class Comment extends DataObject {
'Depth' => 'Int',
);
+ /**
+ * @var array
+ */
private static $has_one = array(
- "Author" => "Member",
- "ParentComment" => "Comment",
+ 'Author' => 'Member',
+ 'ParentComment' => 'Comment',
);
+ /**
+ * @var array
+ */
private static $has_many = array(
- "ChildComments" => "Comment"
+ 'ChildComments' => 'Comment'
);
+ /**
+ * @var string
+ */
private static $default_sort = '"Created" DESC';
+ /**
+ * @var array
+ */
private static $defaults = array(
'Moderated' => 0,
'IsSpam' => 0,
);
+ /**
+ * @var array
+ */
private static $casting = array(
'Title' => 'Varchar',
'ParentTitle' => 'Varchar',
@@ -68,6 +83,9 @@ class Comment extends DataObject {
'Permalink' => 'Varchar',
);
+ /**
+ * @var array
+ */
private static $searchable_fields = array(
'Name',
'Email',
@@ -76,6 +94,9 @@ class Comment extends DataObject {
'BaseClass',
);
+ /**
+ * @var array
+ */
private static $summary_fields = array(
'Name' => 'Submitted By',
'Email' => 'Email',
@@ -85,26 +106,32 @@ class Comment extends DataObject {
'IsSpam' => 'Is Spam',
);
+ /**
+ * @var array
+ */
private static $field_labels = array(
'Author' => 'Author Member',
);
+ /**
+ * {@inheritdoc
+ */
public function onBeforeWrite() {
parent::onBeforeWrite();
- // Sanitize HTML, because its expected to be passed to the template unescaped later
if($this->AllowHtml) {
$this->Comment = $this->purifyHtml($this->Comment);
}
- // Check comment depth
$this->updateDepth();
}
+ /**
+ * {@inheritdoc
+ */
public function onBeforeDelete() {
parent::onBeforeDelete();
- // Delete all children
foreach($this->ChildComments() as $comment) {
$comment->delete();
}
@@ -118,24 +145,31 @@ class Comment extends DataObject {
}
/**
- * Migrates the old {@link PageComment} objects to {@link Comment}
+ * {@inheritdoc}
+ *
+ * Migrates the old {@link PageComment} objects to {@link Comment}.
*/
public function requireDefaultRecords() {
parent::requireDefaultRecords();
if(DB::getConn()->hasTable('PageComment')) {
- $comments = DB::query('SELECT * FROM "PageComment"');
+ $comments = DB::query('SELECT * FROM PageComment');
if($comments) {
while($pageComment = $comments->nextRecord()) {
- // create a new comment from the older page comment
$comment = new Comment();
$comment->update($pageComment);
- // set the variables which have changed
$comment->BaseClass = 'SiteTree';
- $comment->URL = (isset($pageComment['CommenterURL'])) ? $pageComment['CommenterURL'] : '';
- if((int) $pageComment['NeedsModeration'] == 0) $comment->Moderated = true;
+ $comment->URL = '';
+
+ if(isset($pageComment['CommenterURL'])) {
+ $comment->URL = $pageComment['CommenterURL'];
+ }
+
+ if($pageComment['NeedsModeration'] == false) {
+ $comment->Moderated = true;
+ }
$comment->write();
}
@@ -147,38 +181,36 @@ class Comment extends DataObject {
}
/**
- * Return a link to this comment
+ * Return a link to this comment.
*
* @param string $action
*
- * @return string link to this comment.
+ * @return string
*/
public function Link($action = '') {
if($parent = $this->getParent()) {
return $parent->Link($action) . '#' . $this->Permalink();
}
+
+ return '';
}
/**
- * Returns the permalink for this {@link Comment}. Inserted into
- * the ID tag of the comment
+ * Returns the permalink for this {@link Comment}. Inserted into the ID tag of the comment.
*
* @return string
*/
public function Permalink() {
- $prefix = $this->getOption('comment_permalink_prefix');
- return $prefix . $this->ID;
+ return $this->getOption('comment_permalink_prefix') . $this->ID;
}
/**
- * Translate the form field labels for the CMS administration
+ * {@inheritdoc}
*
- * @param boolean $includerelations
- *
- * @return array
+ * @param bool $includeRelations
*/
- public function fieldLabels($includerelations = true) {
- $labels = parent::fieldLabels($includerelations);
+ public function fieldLabels($includeRelations = true) {
+ $labels = parent::fieldLabels($includeRelations);
$labels['Name'] = _t('Comment.NAME', 'Author Name');
$labels['Comment'] = _t('Comment.COMMENT', 'Comment');
@@ -193,20 +225,18 @@ class Comment extends DataObject {
}
/**
- * Get the commenting option
+ * Get the commenting option.
*
* @param string $key
*
- * @return mixed Result if the setting is available, or null otherwise
+ * @return mixed
*/
public function getOption($key) {
- // If possible use the current record
$record = $this->getParent();
+
if(!$record && $this->BaseClass) {
- // Otherwise a singleton of that record
$record = singleton($this->BaseClass);
} elseif(!$record) {
- // Otherwise just use the default options
$record = singleton('CommentsExtension');
}
@@ -214,30 +244,35 @@ class Comment extends DataObject {
}
/**
- * Returns the parent {@link DataObject} this comment is attached too
+ * Returns the parent {@link DataObject} this comment is attached too.
*
- * @return DataObject
+ * @return null|DataObject
*/
public function getParent() {
- return $this->BaseClass && $this->ParentID
- ? DataObject::get_by_id($this->BaseClass, $this->ParentID, true)
- : null;
+ if($this->BaseClass && $this->ParentID) {
+ return DataObject::get_by_id($this->BaseClass, $this->ParentID, true);
+ }
+
+ return null;
}
-
/**
- * Returns a string to help identify the parent of the comment
+ * Returns a string to help identify the parent of the comment.
*
* @return string
*/
public function getParentTitle() {
- if($parent = $this->getParent()) {
- return $parent->Title ?: ($parent->ClassName . ' #' . $parent->ID);
+ $parent = $this->getParent();
+
+ if($parent && $parent->Title) {
+ return $parent->Title;
}
+
+ return $parent->ClassName . ' #' . $parent->ID;
}
/**
- * Comment-parent classnames obviously vary, return the parent classname
+ * Comment-parent class names may vary, return the parent class name.
*
* @return string
*/
@@ -245,16 +280,19 @@ class Comment extends DataObject {
return $this->BaseClass;
}
+ /**
+ * {@inheritdoc}
+ */
public function castingHelper($field) {
- // Safely escape the comment
if($field === 'EscapedComment') {
return $this->AllowHtml ? 'HTMLText' : 'Text';
}
+
return parent::castingHelper($field);
}
/**
- * Content to be safely escaped on the frontend
+ * @todo escape this comment? (DOH!)
*
* @return string
*/
@@ -263,9 +301,9 @@ class Comment extends DataObject {
}
/**
- * Return whether this comment is a preview (has not been written to the db)
+ * Return whether this comment is a preview (has not been written to the db).
*
- * @return boolean
+ * @return bool
*/
public function isPreview() {
return !$this->exists();
@@ -274,7 +312,7 @@ class Comment extends DataObject {
/**
* @todo needs to compare to the new {@link Commenting} configuration API
*
- * @param Member $member
+ * @param null|Member $member
*
* @return bool
*/
@@ -283,17 +321,18 @@ class Comment extends DataObject {
}
/**
- * Checks for association with a page, and {@link SiteTree->ProvidePermission}
- * flag being set to true.
+ * Checks for association with a page, and {@link SiteTree->ProvidePermission} flag being set
+ * to true.
*
- * @param Member $member
+ * @param null|int|Member $member
*
- * @return Boolean
+ * @return bool
*/
public function canView($member = null) {
$member = $this->getMember($member);
$extended = $this->extendedCan('canView', $member);
+
if($extended !== null) {
return $extended;
}
@@ -303,9 +342,7 @@ class Comment extends DataObject {
}
if($parent = $this->getParent()) {
- return $parent->canView($member)
- && $parent->has_extension('CommentsExtension')
- && $parent->CommentsEnabled;
+ return $parent->canView($member) && $parent->has_extension('CommentsExtension') && $parent->CommentsEnabled;
}
return false;
@@ -316,7 +353,7 @@ class Comment extends DataObject {
*
* @param null|int|Member $member
*
- * @return Boolean
+ * @return bool
*/
public function canEdit($member = null) {
$member = $this->getMember($member);
@@ -326,6 +363,7 @@ class Comment extends DataObject {
}
$extended = $this->extendedCan('canEdit', $member);
+
if($extended !== null) {
return $extended;
}
@@ -346,7 +384,7 @@ class Comment extends DataObject {
*
* @param null|int|Member $member
*
- * @return Boolean
+ * @return bool
*/
public function canDelete($member = null) {
$member = $this->getMember($member);
@@ -356,6 +394,7 @@ class Comment extends DataObject {
}
$extended = $this->extendedCan('canDelete', $member);
+
if($extended !== null) {
return $extended;
}
@@ -366,8 +405,9 @@ class Comment extends DataObject {
/**
* Resolves Member object.
*
- * @param Member|int|null $member
- * @return Member|null
+ * @param null|int|Member $member
+ *
+ * @return null|Member
*/
protected function getMember($member = null) {
if(!$member) {
@@ -382,7 +422,7 @@ class Comment extends DataObject {
}
/**
- * Return the authors name for the comment
+ * Return the authors name for the comment.
*
* @return string
*/
@@ -392,19 +432,26 @@ class Comment extends DataObject {
} else if($author = $this->Author()) {
return $author->getName();
}
+
+ return '';
}
/**
- * Generate a secure admin-action link authorised for the specified member
+ * Generate a secure admin-action link authorised for the specified member.
*
- * @param string $action An action on CommentingController to link to
- * @param Member $member The member authorised to invoke this action
+ * @param string $action
+ * @param null|Member $member
*
* @return string
*/
protected function actionLink($action, $member = null) {
- if(!$member) $member = Member::currentUser();
- if(!$member) return false;
+ if(!$member) {
+ $member = Member::currentUser();
+ }
+
+ if(!$member) {
+ return false;
+ }
$url = Controller::join_links(
Director::baseURL(),
@@ -413,92 +460,103 @@ class Comment extends DataObject {
$this->ID
);
- // Limit access for this user
$token = $this->getSecurityToken();
+
return $token->addToUrl($url, $member);
}
/**
- * Link to delete this comment
+ * Link to delete this comment.
*
- * @param Member $member
+ * @param null|Member $member
*
- * @return string
+ * @return null|string
*/
public function DeleteLink($member = null) {
if($this->canDelete($member)) {
return $this->actionLink('delete', $member);
}
+
+ return null;
}
/**
- * Link to mark as spam
+ * Link to mark as spam.
*
- * @param Member $member
+ * @param null|Member $member
*
- * @return string
+ * @return null|string
*/
public function SpamLink($member = null) {
if($this->canEdit($member) && !$this->IsSpam) {
return $this->actionLink('spam', $member);
}
+
+ return null;
}
/**
- * Link to mark as not-spam (ham)
+ * Link to mark as not-spam.
*
- * @param Member $member
+ * @param null|Member $member
*
- * @return string
+ * @return null|string
*/
public function HamLink($member = null) {
if($this->canEdit($member) && $this->IsSpam) {
return $this->actionLink('ham', $member);
}
+
+ return null;
}
/**
- * Link to approve this comment
+ * Link to approve this comment.
*
- * @param Member $member
+ * @param null|Member $member
*
- * @return string
+ * @return null|string
*/
public function ApproveLink($member = null) {
if($this->canEdit($member) && !$this->Moderated) {
return $this->actionLink('approve', $member);
}
+
+ return null;
}
/**
- * Mark this comment as spam
+ * Mark this comment as spam.
*/
public function markSpam() {
$this->IsSpam = true;
$this->Moderated = true;
$this->write();
+
$this->extend('afterMarkSpam');
}
/**
- * Mark this comment as approved
+ * Mark this comment as approved.
*/
public function markApproved() {
$this->IsSpam = false;
$this->Moderated = true;
$this->write();
+
$this->extend('afterMarkApproved');
}
/**
- * Mark this comment as unapproved
+ * Mark this comment as unapproved.
*/
public function markUnapproved() {
$this->Moderated = false;
$this->write();
+
$this->extend('afterMarkUnapproved');
}
-
+
/**
* @return string
*/
@@ -507,90 +565,120 @@ class Comment extends DataObject {
return 'spam';
} else if(!$this->Moderated) {
return 'unmoderated';
- } else {
- return 'notspam';
}
+
+ return 'notspam';
}
/**
* @return string
*/
public function getTitle() {
- $title = sprintf(_t('Comment.COMMENTBY', 'Comment by %s', 'Name'), $this->getAuthorName());
+ $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);
- }
+ $parent = $this->getParent();
+
+ if($parent && $parent->Title) {
+ $title .= sprintf(
+ ' %s %s',
+ _t('Comment.ON', 'on'),
+ $parent->Title
+ );
}
return $title;
}
- /*
- * Modify the default fields shown to the user
+ /**
+ * Modify the default fields shown to the user.
*/
public function getCMSFields() {
- $commentField = $this->AllowHtml ? 'HtmlEditorField' : 'TextareaField';
+
+ $commentFieldType = 'TextareaField';
+
+ if($this->AllowHtml) {
+ $commentFieldType = 'HtmlEditorField';
+ }
+
+ $createdField = $this->obj('Created')
+ ->scaffoldFormField($this->fieldLabel('Created'))
+ ->performReadonlyTransformation();
+
+ $nameField = TextField::create('Name', $this->fieldLabel('AuthorName'));
+
+ $commentField = $commentFieldType::create('Comment', $this->fieldLabel('Comment'));
+
+ $emailField = EmailField::create('Email', $this->fieldLabel('Email'));
+
+ $urlField = TextField::create('URL', $this->fieldLabel('URL'));
+
+ $moderatedField = CheckboxField::create('Moderated', $this->fieldLabel('Moderated'));
+
+ $spamField = CheckboxField::create('IsSpam', $this->fieldLabel('IsSpam'));
+
+ $fieldGroup = FieldGroup::create(array(
+ $moderatedField,
+ $spamField,
+ ));
+
+ $fieldGroup->setTitle('Options');
+ $fieldGroup->setDescription(_t(
+ 'Comment.OPTION_DESCRIPTION',
+ 'Unmoderated and spam comments will not be displayed until approved'
+ ));
+
$fields = new FieldList(
- $this
- ->obj('Created')
- ->scaffoldFormField($this->fieldLabel('Created'))
- ->performReadonlyTransformation(),
- TextField::create('Name', $this->fieldLabel('AuthorName')),
- $commentField::create('Comment', $this->fieldLabel('Comment')),
- EmailField::create('Email', $this->fieldLabel('Email')),
- TextField::create('URL', $this->fieldLabel('URL')),
- FieldGroup::create(array(
- CheckboxField::create('Moderated', $this->fieldLabel('Moderated')),
- CheckboxField::create('IsSpam', $this->fieldLabel('IsSpam')),
- ))
- ->setTitle('Options')
- ->setDescription(_t(
- 'Comment.OPTION_DESCRIPTION',
- 'Unmoderated and spam comments will not be displayed until approved'
- ))
+ $createdField,
+ $nameField,
+ $commentField,
+ $emailField,
+ $urlField,
+ $fieldGroup
);
- // Show member name if given
- if(($author = $this->Author()) && $author->exists()) {
+ $author = $this->Author();
+
+ if($author && $author->exists()) {
+ $authorMemberField = TextField::create('AuthorMember', $this->fieldLabel('Author'), $author->Title);
+ $authorMemberField->performReadonlyTransformation();
+
$fields->insertAfter(
- TextField::create('AuthorMember', $this->fieldLabel('Author'), $author->Title)
- ->performReadonlyTransformation(),
+ $authorMemberField,
'Name'
);
}
- // Show parent comment if given
- if(($parent = $this->ParentComment()) && $parent->exists()) {
- $fields->push(new HeaderField(
- 'ParentComment_Title',
- _t('Comment.ParentComment_Title', 'This comment is a reply to the below')
- ));
- // Created date
+ $parent = $this->ParentComment();
+
+ if($parent && $parent->exists()) {
$fields->push(
- $parent
- ->obj('Created')
+ new HeaderField(
+ 'ParentComment_Title',
+ _t('Comment.ParentComment_Title', 'This comment is a reply to the below')
+ )
+ );
+
+ $fields->push(
+ $parent->obj('Created')
->scaffoldFormField($parent->fieldLabel('Created'))
->setName('ParentComment_Created')
->setValue($parent->Created)
->performReadonlyTransformation()
);
- // Name (could be member or string value)
$fields->push(
- $parent
- ->obj('AuthorName')
+ $parent->obj('AuthorName')
->scaffoldFormField($parent->fieldLabel('AuthorName'))
->setName('ParentComment_AuthorName')
->setValue($parent->getAuthorName())
->performReadonlyTransformation()
);
- // Comment body
$fields->push(
- $parent
- ->obj('EscapedComment')
+ $parent->obj('EscapedComment')
->scaffoldFormField($parent->fieldLabel('Comment'))
->setName('ParentComment_EscapedComment')
->setValue($parent->Comment)
@@ -599,157 +687,165 @@ class Comment extends DataObject {
}
$this->extend('updateCMSFields', $fields);
+
return $fields;
}
/**
- * @param String $dirtyHtml
+ * @param string $dirtyHtml
*
- * @return String
+ * @return string
*/
public function purifyHtml($dirtyHtml) {
- $purifier = $this->getHtmlPurifierService();
- return $purifier->purify($dirtyHtml);
+ return $this->getHtmlPurifierService()
+ ->purify($dirtyHtml);
}
/**
- * @return HTMLPurifier (or anything with a "purify()" method)
+ * @return HTMLPurifier
*/
public function getHtmlPurifierService() {
$config = HTMLPurifier_Config::createDefault();
+
$config->set('HTML.AllowedElements', $this->getOption('html_allowed_elements'));
$config->set('AutoFormat.AutoParagraph', true);
$config->set('AutoFormat.Linkify', true);
$config->set('URI.DisableExternalResources', true);
$config->set('Cache.SerializerPath', getTempFolder());
+
return new HTMLPurifier($config);
}
/**
- * Calculate the Gravatar link from the email address
+ * Calculate the Gravatar link from the email address.
*
* @return string
*/
public function Gravatar() {
- $gravatar = '';
- $use_gravatar = $this->getOption('use_gravatar');
- if($use_gravatar) {
- $gravatar = 'http://www.gravatar.com/avatar/' . md5(strtolower(trim($this->Email)));
- $gravatarsize = $this->getOption('gravatar_size');
- $gravatardefault = $this->getOption('gravatar_default');
- $gravatarrating = $this->getOption('gravatar_rating');
- $gravatar .= '?s=' . $gravatarsize . '&d=' . $gravatardefault . '&r=' . $gravatarrating;
+ if($this->getOption('use_gravatar')) {
+ return sprintf(
+ 'http://www.gravatar.com/avatar/%s?s=%s&d=%s&r=%s',
+ md5(strtolower(trim($this->Email))),
+ $this->getOption('gravatar_size'),
+ $this->getOption('gravatar_default'),
+ $this->getOption('gravatar_rating')
+ );
}
- return $gravatar;
+ return '';
}
/**
- * Determine if replies are enabled for this instance
+ * Determine if replies are enabled for this instance.
*
- * @return boolean
+ * @return bool
*/
public function getRepliesEnabled() {
- // Check reply option
if(!$this->getOption('nested_comments')) {
return false;
}
- // Check if depth is limited
$maxLevel = $this->getOption('nested_depth');
- return !$maxLevel || $this->Depth < $maxLevel;
+
+ return !$maxLevel || $this->Depth < (int) $maxLevel;
}
/**
- * Returns the list of all replies
+ * Returns the list of all replies.
*
* @return SS_List
*/
public function AllReplies() {
- // No replies if disabled
if(!$this->getRepliesEnabled()) {
return new ArrayList();
}
-
- // Get all non-spam comments
- $order = $this->getOption('order_replies_by')
- ?: $this->getOption('order_comments_by');
+
+ $order = $this->getOption('order_replies_by');
+
+ if(!$order) {
+ $order = $this->getOption('order_comments_by');
+ }
+
$list = $this
->ChildComments()
->sort($order);
$this->extend('updateAllReplies', $list);
+
return $list;
}
/**
- * Returns the list of replies, with spam and unmoderated items excluded, for use in the frontend
+ * Returns the list of replies, with spam and un-moderated items excluded, for use in the
+ * frontend.
*
* @return SS_List
*/
public function Replies() {
- // No replies if disabled
if(!$this->getRepliesEnabled()) {
return new ArrayList();
}
+
$list = $this->AllReplies();
-
- // Filter spam comments for non-administrators if configured
+
$parent = $this->getParent();
- $showSpam = $this->getOption('frontend_spam') && $parent && $parent->canModerateComments();
+
+ $showSpam = $parent && $parent->canModerateComments() && $this->getOption('frontend_spam');
+
if(!$showSpam) {
$list = $list->filter('IsSpam', 0);
}
- // Filter un-moderated comments for non-administrators if moderation is enabled
- $showUnmoderated = $parent && (
- ($parent->ModerationRequired === 'None')
- || ($this->getOption('frontend_moderation') && $parent->canModerateComments())
- );
- if (!$showUnmoderated) {
- $list = $list->filter('Moderated', 1);
+ $noModerationRequired = $parent && $parent->ModerationRequired === 'None';
+
+ $showUnModerated = $noModerationRequired || $showSpam;
+
+ if(!$showUnModerated) {
+ $list = $list->filter('Moderated', 1);
}
$this->extend('updateReplies', $list);
+
return $list;
}
/**
- * Returns the list of replies paged, with spam and unmoderated items excluded, for use in the frontend
+ * Returns the list of replies paged, with spam and un-moderated items excluded, for use in the
+ * frontend.
*
* @return PaginatedList
*/
public function PagedReplies() {
$list = $this->Replies();
- // Add pagination
$list = new PaginatedList($list, Controller::curr()->getRequest());
- $list->setPaginationGetVar('repliesstart'.$this->ID);
+
+ $list->setPaginationGetVar('repliesstart' . $this->ID);
$list->setPageLength($this->getOption('comments_per_page'));
$this->extend('updatePagedReplies', $list);
+
return $list;
}
/**
- * Generate a reply form for this comment
+ * Generate a reply form for this comment.
*
* @return Form
*/
public function ReplyForm() {
- // Ensure replies are enabled
if(!$this->getRepliesEnabled()) {
return null;
}
- // Check parent is available
$parent = $this->getParent();
+
if(!$parent || !$parent->exists()) {
return null;
}
- // Build reply controller
$controller = CommentingController::create();
+
$controller->setOwnerRecord($parent);
$controller->setBaseClass($parent->ClassName);
$controller->setOwnerController(Controller::curr());
@@ -758,12 +854,14 @@ class Comment extends DataObject {
}
/**
- * Refresh of this comment in the hierarchy
+ * Refresh of this comment in the hierarchy.
*/
public function updateDepth() {
$parent = $this->ParentComment();
+
if($parent && $parent->exists()) {
$parent->updateDepth();
+
$this->Depth = $parent->Depth + 1;
} else {
$this->Depth = 1;
@@ -771,27 +869,29 @@ class Comment extends DataObject {
}
}
-
/**
- * Provides the ability to generate cryptographically secure tokens for comment moderation
+ * Provides the ability to generate cryptographically secure tokens for comment moderation.
*/
class Comment_SecurityToken {
-
+ /**
+ * @var null|string
+ */
private $secret = null;
/**
- * @param Comment $comment Comment to generate this token for
+ * @param Comment $comment Comment to generate this token for.
*/
public function __construct($comment) {
if(!$comment->SecretToken) {
$comment->SecretToken = $this->generate();
$comment->write();
}
+
$this->secret = $comment->SecretToken;
}
/**
- * Generate the token for the given salt and current secret
+ * Generate the token for the given salt and current secret.
*
* @param string $salt
*
@@ -805,30 +905,34 @@ class Comment_SecurityToken {
* Get the member-specific salt.
*
* The reason for making the salt specific to a user is that it cannot be "passed in" via a
- * querystring, requiring the same user to be present at both the link generation and the
+ * query string, requiring the same user to be present at both the link generation and the
* controller action.
*
- * @param string $salt Single use salt
- * @param Member $member Member object
+ * @param string $salt
+ * @param Member $member
*
- * @return string Generated salt specific to this member
+ * @return string
*/
protected function memberSalt($salt, $member) {
- // Fallback to salting with ID in case the member has not one set
- return $salt . ($member->Salt ?: $member->ID);
+ $pepper = $member->Salt;
+
+ if(!$pepper) {
+ $pepper = $member->ID;
+ }
+
+ return $salt . $pepper;
}
/**
- * @param string $url Comment action URL
- * @param Member $member Member to restrict access to this action to
+ * @param string $url
+ * @param Member $member
*
* @return string
*/
public function addToUrl($url, $member) {
- $salt = $this->generate(15); // New random salt; Will be passed into url
- // Generate salt specific to this member
- $memberSalt = $this->memberSalt($salt, $member);
- $token = $this->getToken($memberSalt);
+ $salt = $this->generate(15);
+ $token = $this->getToken($this->memberSalt($salt, $member));
+
return Controller::join_links(
$url,
sprintf(
@@ -842,32 +946,37 @@ class Comment_SecurityToken {
/**
* @param SS_HTTPRequest $request
*
- * @return boolean
+ * @return bool
*/
public function checkRequest($request) {
$member = Member::currentUser();
- if(!$member) return false;
+
+ if(!$member) {
+ return false;
+ }
$salt = $request->getVar('s');
- $memberSalt = $this->memberSalt($salt, $member);
- $token = $this->getToken($memberSalt);
+ $token = $this->getToken($this->memberSalt($salt, $member));
- // Ensure tokens match
return $token === $request->getVar('t');
}
-
/**
- * Generates new random key
+ * Generates new random key.
*
- * @param integer $length
+ * @param null|int $length
*
* @return string
*/
protected function generate($length = null) {
$generator = new RandomGenerator();
+
$result = $generator->randomToken('sha256');
- if($length !== null) return substr($result, 0, $length);
+
+ if($length !== null) {
+ return substr($result, 0, $length);
+ }
+
return $result;
}
}
diff --git a/code/model/CommentList.php b/code/model/CommentList.php
index 3296b13..8834943 100644
--- a/code/model/CommentList.php
+++ b/code/model/CommentList.php
@@ -1,16 +1,13 @@
dataQuery->getQueryParam('Foreign.Class');
}
+ /**
+ * {@inheritdoc}
+ */
public function __construct($parentClassName) {
parent::__construct('Comment', 'ParentID');
-
- // Ensure underlying DataQuery globally references the class filter
$this->dataQuery->setQueryParam('Foreign.Class', $parentClassName);
- // For queries with multiple foreign IDs (such as that generated by
- // DataList::relation) the filter must be generalised to filter by subclasses
$classNames = Convert::raw2sql(ClassInfo::subclassesFor($parentClassName));
+
$this->dataQuery->where(sprintf(
- "\"BaseClass\" IN ('%s')", implode("', '", $classNames)
+ 'BaseClass IN (\'%s\')',
+ implode('\', \'', $classNames)
));
}
/**
* Adds the item to this relation.
- *
- * @param Comment $item The comment to be added
+ *
+ * @param Comment $comment
*/
- public function add($item) {
- // Check item given
- if(is_numeric($item)) {
- $item = Comment::get()->byID($item);
- }
- if(!($item instanceof Comment)) {
- throw new InvalidArgumentException("CommentList::add() expecting a Comment object, or ID value");
- }
-
- // Validate foreignID
- $foreignID = $this->getForeignID();
- if(!$foreignID || is_array($foreignID)) {
- throw new InvalidArgumentException("CommentList::add() can't be called until a single foreign ID is set");
+ public function add($comment) {
+ if(is_numeric($comment)) {
+ $comment = Comment::get()->byID($comment);
}
- $item->ParentID = $foreignID;
- $item->BaseClass = $this->getForeignClass();
- $item->write();
- }
- /**
- * Remove a Comment from this relation by clearing the foreign key. Does not actually delete the comment.
- *
- * @param Comment $item The Comment to be removed
- */
- public function remove($item) {
- // Check item given
- if(is_numeric($item)) {
- $item = Comment::get()->byID($item);
+ if(!$comment instanceof Comment) {
+ throw new InvalidArgumentException(
+ 'CommentList::add() expecting a Comment object, or ID value'
+ );
}
- if(!($item instanceof Comment)) {
- throw new InvalidArgumentException("CommentList::remove() expecting a Comment object, or ID",
- E_USER_ERROR);
- }
-
- // Don't remove item with unrelated class key
- $foreignClass = $this->getForeignClass();
- $classNames = ClassInfo::subclassesFor($foreignClass);
- if(!in_array($item->BaseClass, $classNames)) return;
-
- // Don't remove item which doesn't belong to this list
+
$foreignID = $this->getForeignID();
- if( empty($foreignID)
- || (is_array($foreignID) && in_array($item->ParentID, $foreignID))
- || $foreignID == $item->ParentID
- ) {
- $item->ParentID = null;
- $item->BaseClass = null;
- $item->write();
+
+ if(!$foreignID || is_array($foreignID)) {
+ throw new InvalidArgumentException(
+ 'CommentList::add() can\'t be called until a single foreign ID is set'
+ );
+ }
+
+ $comment->ParentID = $foreignID;
+ $comment->BaseClass = $this->getForeignClass();
+ $comment->write();
+ }
+
+ /**
+ * Remove a Comment from this relation by clearing the foreign key. Does not actually delete
+ * the comment.
+ *
+ * @param Comment $comment
+ */
+ public function remove($comment) {
+ if(is_numeric($comment)) {
+ $comment = Comment::get()->byID($comment);
+ }
+
+ if(!$comment instanceof Comment) {
+ throw new InvalidArgumentException(
+ 'CommentList::remove() expecting a Comment object, or ID',
+ E_USER_ERROR
+ );
+ }
+
+ $foreignClass = $this->getForeignClass();
+
+ $subclasses = ClassInfo::subclassesFor($foreignClass);
+
+ if(!in_array($comment->BaseClass, $subclasses)) {
+ return;
+ }
+
+ $foreignID = $this->getForeignID();
+
+ if(empty($foreignID) || $foreignID == $comment->ParentID || (is_array($foreignID) && in_array($comment->ParentID, $foreignID))) {
+ $comment->ParentID = null;
+ $comment->BaseClass = null;
+ $comment->write();
}
}
}
diff --git a/tests/CommentingControllerTest.php b/tests/CommentingControllerTest.php
index 94a09e7..0f83bc5 100644
--- a/tests/CommentingControllerTest.php
+++ b/tests/CommentingControllerTest.php
@@ -1,114 +1,142 @@
securityEnabled) {
SecurityToken::enable();
} else {
SecurityToken::disable();
}
+
parent::tearDown();
}
+ /**
+ * {@inheritdoc}
+ */
public function setUp() {
parent::setUp();
+
$this->securityEnabled = SecurityToken::is_enabled();
}
public function testRSS() {
- $item = $this->objFromFixture('CommentableItem', 'first');
+ $item = $this->objFromFixture('HasComments', 'first');
- // comments sitewide
$response = $this->get('CommentingController/rss');
- $this->assertEquals(10, substr_count($response->getBody(), "- "), "10 approved, non spam comments on page 1");
+
+ $this->assertEquals(10, substr_count($response->getBody(), '
- '), '10 approved, non spam comments on page 1');
$response = $this->get('CommentingController/rss?start=10');
- $this->assertEquals(4, substr_count($response->getBody(), "
- "), "3 approved, non spam comments on page 2");
- // all comments on a type
- $response = $this->get('CommentingController/rss/CommentableItem');
- $this->assertEquals(10, substr_count($response->getBody(), "
- "));
+ $this->assertEquals(4, substr_count($response->getBody(), '
- '), '3 approved, non spam comments on page 2');
- $response = $this->get('CommentingController/rss/CommentableItem?start=10');
- $this->assertEquals(4, substr_count($response->getBody(), "
- "), "3 approved, non spam comments on page 2");
+ $response = $this->get('CommentingController/rss/HasComments');
- // specific page
- $response = $this->get('CommentingController/rss/CommentableItem/'.$item->ID);
- $this->assertEquals(1, substr_count($response->getBody(), "
- "));
+ $this->assertEquals(10, substr_count($response->getBody(), '
- '));
+
+ $response = $this->get('CommentingController/rss/HasComments?start=10');
+
+ $this->assertEquals(4, substr_count($response->getBody(), '
- '), '3 approved, non spam comments on page 2');
+
+ $response = $this->get('CommentingController/rss/HasComments/' . $item->ID);
+
+ $this->assertEquals(1, substr_count($response->getBody(), '
- '));
$this->assertContains('FA', $response->getBody());
- // test accessing comments on a type that doesn't exist
$response = $this->get('CommentingController/rss/Fake');
$this->assertEquals(404, $response->getStatusCode());
}
public function testCommentsForm() {
SecurityToken::disable();
- $this->autoFollowRedirection = false;
- $parent = $this->objFromFixture('CommentableItem', 'first');
- // Test posting to base comment
+ $this->autoFollowRedirection = false;
+
+ $parent = $this->objFromFixture('HasComments', 'first');
+
$response = $this->post('CommentingController/CommentsForm',
array(
'Name' => 'Poster',
'Email' => 'guy@test.com',
'Comment' => 'My Comment',
'ParentID' => $parent->ID,
- 'BaseClass' => 'CommentableItem',
+ 'BaseClass' => 'HasComments',
'action_doPostComment' => 'Post'
)
);
$this->assertEquals(302, $response->getStatusCode());
- $this->assertStringStartsWith('CommentableItem_Controller#comment-', $response->getHeader('Location'));
+ $this->assertStringStartsWith('HasComments_Controller#comment-', $response->getHeader('Location'));
$this->assertDOSEquals(
- array(array(
- 'Name' => 'Poster',
- 'Email' => 'guy@test.com',
- 'Comment' => 'My Comment',
- 'ParentID' => $parent->ID,
- 'BaseClass' => 'CommentableItem',
- )),
+ array(
+ array(
+ 'Name' => 'Poster',
+ 'Email' => 'guy@test.com',
+ 'Comment' => 'My Comment',
+ 'ParentID' => $parent->ID,
+ 'BaseClass' => 'HasComments',
+ )
+ ),
Comment::get()->filter('Email', 'guy@test.com')
);
-
- // Test posting to parent comment
+
+ /**
+ * @var Comment $parentComment
+ */
$parentComment = $this->objFromFixture('Comment', 'firstComA');
+
$this->assertEquals(0, $parentComment->ChildComments()->count());
$response = $this->post(
- 'CommentingController/reply/'.$parentComment->ID,
+ 'CommentingController/reply/' . $parentComment->ID,
array(
'Name' => 'Test Author',
'Email' => 'test@test.com',
'Comment' => 'Making a reply to firstComA',
'ParentID' => $parent->ID,
- 'BaseClass' => 'CommentableItem',
+ 'BaseClass' => 'HasComments',
'ParentCommentID' => $parentComment->ID,
'action_doPostComment' => 'Post'
)
);
+
$this->assertEquals(302, $response->getStatusCode());
- $this->assertStringStartsWith('CommentableItem_Controller#comment-', $response->getHeader('Location'));
- $this->assertDOSEquals(array(array(
- 'Name' => 'Test Author',
+ $this->assertStringStartsWith('HasComments_Controller#comment-', $response->getHeader('Location'));
+ $this->assertDOSEquals(array(
+ array(
+ 'Name' => 'Test Author',
'Email' => 'test@test.com',
'Comment' => 'Making a reply to firstComA',
'ParentID' => $parent->ID,
- 'BaseClass' => 'CommentableItem',
+ 'BaseClass' => 'HasComments',
'ParentCommentID' => $parentComment->ID
- )), $parentComment->ChildComments());
+ )
+ ), $parentComment->ChildComments());
}
}
diff --git a/tests/CommentsTest.php b/tests/CommentsTest.php
index ffd037f..4bd8a0e 100644
--- a/tests/CommentsTest.php
+++ b/tests/CommentsTest.php
@@ -1,21 +1,30 @@
update('CommentsExtension', 'comments', array(
'enabled' => true,
'enabled_cms' => false,
@@ -29,188 +38,244 @@ class CommentsTest extends FunctionalTest {
'frontend_spam' => false,
));
- // Configure this dataobject
- Config::inst()->update('CommentableItem', 'comments', array(
- 'enabled_cms' => true
+ Config::inst()->update('HasComments', 'comments', array(
+ 'enabled_cms' => true,
));
}
+ /**
+ * {@inheritdoc}
+ */
public function tearDown() {
Config::unnest();
+
parent::tearDown();
}
public function testCommentsList() {
- // comments don't require moderation so unmoderated comments can be
- // shown but not spam posts
- Config::inst()->update('CommentableItem', 'comments', array(
+ Config::inst()->update('HasComments', 'comments', array(
'require_moderation_nonmembers' => false,
'require_moderation' => false,
'require_moderation_cms' => false,
));
- $item = $this->objFromFixture('CommentableItem', 'spammed');
+ /**
+ * @var HasComments $item
+ */
+ $item = $this->objFromFixture('HasComments', 'spammed');
+
$this->assertEquals('None', $item->ModerationRequired);
+ $this->assertDOSEquals(
+ array(
+ array('Name' => 'Comment 1'),
+ array('Name' => 'Comment 3')
+ ),
+ $item->Comments(),
+ 'Only 2 non spam posts should be shown'
+ );
- $this->assertDOSEquals(array(
- array('Name' => 'Comment 1'),
- array('Name' => 'Comment 3')
- ), $item->Comments(), 'Only 2 non spam posts should be shown');
+ Config::inst()->update('HasComments', 'comments', array('require_moderation_nonmembers' => true));
- // when moderated, only moderated, non spam posts should be shown.
- Config::inst()->update('CommentableItem', 'comments', array('require_moderation_nonmembers' => true));
$this->assertEquals('NonMembersOnly', $item->ModerationRequired);
- // Check that require_moderation overrides this option
- Config::inst()->update('CommentableItem', 'comments', array('require_moderation' => true));
+ Config::inst()->update('HasComments', 'comments', array('require_moderation' => true));
+
$this->assertEquals('Required', $item->ModerationRequired);
- $this->assertDOSEquals(array(
- array('Name' => 'Comment 3')
- ), $item->Comments(), 'Only 1 non spam, moderated post should be shown');
+ $this->assertDOSEquals(
+ array(
+ array('Name' => 'Comment 3')
+ ),
+ $item->Comments(),
+ 'Only 1 non spam, moderated post should be shown'
+ );
$this->assertEquals(1, $item->Comments()->Count());
- // require_moderation_nonmembers still filters out unmoderated comments
- Config::inst()->update('CommentableItem', 'comments', array('require_moderation' => false));
+ Config::inst()->update('HasComments', 'comments', array('require_moderation' => false));
+
$this->assertEquals(1, $item->Comments()->Count());
-
- Config::inst()->update('CommentableItem', 'comments', array('require_moderation_nonmembers' => false));
+
+ Config::inst()->update('HasComments', 'comments', array('require_moderation_nonmembers' => false));
+
$this->assertEquals(2, $item->Comments()->Count());
- // With unmoderated comments set to display in frontend
- Config::inst()->update('CommentableItem', 'comments', array(
+ Config::inst()->update('HasComments', 'comments', array(
'require_moderation' => true,
- 'frontend_moderation' => true
+ 'frontend_moderation' => true,
));
+
$this->assertEquals(1, $item->Comments()->Count());
$this->logInWithPermission('ADMIN');
+
$this->assertEquals(2, $item->Comments()->Count());
- // With spam comments set to display in frontend
- Config::inst()->update('CommentableItem', 'comments', array(
+ Config::inst()->update('HasComments', 'comments', array(
'require_moderation' => true,
'frontend_moderation' => false,
'frontend_spam' => true,
));
- if($member = Member::currentUser()) $member->logOut();
+
+ if($member = Member::currentUser()) {
+ $member->logOut();
+ }
+
$this->assertEquals(1, $item->Comments()->Count());
$this->logInWithPermission('ADMIN');
+
$this->assertEquals(2, $item->Comments()->Count());
-
- // With spam and unmoderated comments set to display in frontend
- Config::inst()->update('CommentableItem', 'comments', array(
+ Config::inst()->update('HasComments', 'comments', array(
'require_moderation' => true,
'frontend_moderation' => true,
'frontend_spam' => true,
));
- if($member = Member::currentUser()) $member->logOut();
+
+ if($member = Member::currentUser()) {
+ $member->logOut();
+ }
+
$this->assertEquals(1, $item->Comments()->Count());
$this->logInWithPermission('ADMIN');
+
$this->assertEquals(4, $item->Comments()->Count());
}
/**
- * Test moderation options configured via the CMS
+ * Test moderation options configured via the CMS.
*/
public function testCommentCMSModerationList() {
- // comments don't require moderation so unmoderated comments can be
- // shown but not spam posts
- Config::inst()->update('CommentableItem', 'comments', array(
+ Config::inst()->update('HasComments', 'comments', array(
'require_moderation' => true,
'require_moderation_cms' => true,
));
- $item = $this->objFromFixture('CommentableItem', 'spammed');
+ /**
+ * @var HasComments $item
+ */
+ $item = $this->objFromFixture('HasComments', 'spammed');
+
$this->assertEquals('None', $item->ModerationRequired);
+ $this->assertDOSEquals(
+ array(
+ array('Name' => 'Comment 1'),
+ array('Name' => 'Comment 3')
+ ),
+ $item->Comments(),
+ 'Only 2 non spam posts should be shown'
+ );
- $this->assertDOSEquals(array(
- array('Name' => 'Comment 1'),
- array('Name' => 'Comment 3')
- ), $item->Comments(), 'Only 2 non spam posts should be shown');
-
- // when moderated, only moderated, non spam posts should be shown.
$item->ModerationRequired = 'NonMembersOnly';
$item->write();
+
$this->assertEquals('NonMembersOnly', $item->ModerationRequired);
- // Check that require_moderation overrides this option
$item->ModerationRequired = 'Required';
$item->write();
+
$this->assertEquals('Required', $item->ModerationRequired);
- $this->assertDOSEquals(array(
- array('Name' => 'Comment 3')
- ), $item->Comments(), 'Only 1 non spam, moderated post should be shown');
- $this->assertEquals(1, $item->Comments()->Count());
+ $this->assertDOSEquals(
+ array(
+ array('Name' => 'Comment 3')
+ ),
+ $item->Comments(),
+ 'Only 1 non spam, moderated post should be shown'
+ );
- // require_moderation_nonmembers still filters out unmoderated comments
$item->ModerationRequired = 'NonMembersOnly';
$item->write();
+
$this->assertEquals(1, $item->Comments()->Count());
$item->ModerationRequired = 'None';
$item->write();
+
$this->assertEquals(2, $item->Comments()->Count());
}
public function testCanPostComment() {
- Config::inst()->update('CommentableItem', 'comments', array(
+ Config::inst()->update('HasComments', 'comments', array(
'require_login' => false,
'require_login_cms' => false,
'required_permission' => false,
));
- $item = $this->objFromFixture('CommentableItem', 'first');
- $item2 = $this->objFromFixture('CommentableItem', 'second');
- // Test restriction free commenting
- if($member = Member::currentUser()) $member->logOut();
+ /**
+ * @var HasComments $item
+ */
+ $item = $this->objFromFixture('HasComments', 'first');
+
+ /**
+ * @var HasComments $item2
+ */
+ $item2 = $this->objFromFixture('HasComments', 'second');
+
+ if($member = Member::currentUser()) {
+ $member->logOut();
+ }
+
$this->assertFalse($item->CommentsRequireLogin);
$this->assertTrue($item->canPostComment());
- // Test permission required to post
- Config::inst()->update('CommentableItem', 'comments', array(
+ Config::inst()->update('HasComments', 'comments', array(
'require_login' => true,
'required_permission' => 'POSTING_PERMISSION',
));
+
$this->assertTrue($item->CommentsRequireLogin);
$this->assertFalse($item->canPostComment());
+
$this->logInWithPermission('WRONG_ONE');
+
$this->assertFalse($item->canPostComment());
+
$this->logInWithPermission('POSTING_PERMISSION');
- $this->assertTrue($item->canPostComment());
- $this->logInWithPermission('ADMIN');
+
$this->assertTrue($item->canPostComment());
- // Test require login to post, but not any permissions
- Config::inst()->update('CommentableItem', 'comments', array(
+ $this->logInWithPermission('ADMIN');
+
+ $this->assertTrue($item->canPostComment());
+
+ Config::inst()->update('HasComments', 'comments', array(
'required_permission' => false,
));
+
$this->assertTrue($item->CommentsRequireLogin);
- if($member = Member::currentUser()) $member->logOut();
+
+ if($member = Member::currentUser()) {
+ $member->logOut();
+ }
+
$this->assertFalse($item->canPostComment());
+
$this->logInWithPermission('ANY_PERMISSION');
+
$this->assertTrue($item->canPostComment());
- // Test options set via CMS
- Config::inst()->update('CommentableItem', 'comments', array(
+ Config::inst()->update('HasComments', 'comments', array(
'require_login' => true,
'require_login_cms' => true,
));
+
$this->assertFalse($item->CommentsRequireLogin);
$this->assertTrue($item2->CommentsRequireLogin);
- if($member = Member::currentUser()) $member->logOut();
+
+ if($member = Member::currentUser()) {
+ $member->logOut();
+ }
+
$this->assertTrue($item->canPostComment());
$this->assertFalse($item2->canPostComment());
- // Login grants permission to post
$this->logInWithPermission('ANY_PERMISSION');
+
$this->assertTrue($item->canPostComment());
$this->assertTrue($item2->canPostComment());
-
+
}
public function testCanView() {
@@ -218,15 +283,15 @@ class CommentsTest extends FunctionalTest {
$admin = $this->objFromFixture('Member', 'commentadmin');
$comment = $this->objFromFixture('Comment', 'firstComA');
- $this->assertTrue($comment->canView($visitor),
+ $this->assertTrue($comment->canView($visitor),
'Unauthenticated members can view comments associated to a object 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('Comment', 'disabledCom');
-
+
$this->assertFalse($disabledComment->canView($visitor),
'Unauthenticated members can not view comments associated to a object with ProvideComments=0'
);
@@ -235,221 +300,278 @@ class CommentsTest extends FunctionalTest {
'Admins with CMS_ACCESS_CommentAdmin permissions can view comments associated to a page with ProvideComments=0'
);
}
-
+
public function testCanEdit() {
$visitor = $this->objFromFixture('Member', 'visitor');
$admin = $this->objFromFixture('Member', 'commentadmin');
$comment = $this->objFromFixture('Comment', 'firstComA');
-
+
$this->assertFalse($comment->canEdit($visitor));
$this->assertTrue($comment->canEdit($admin));
}
-
+
public function testCanDelete() {
$visitor = $this->objFromFixture('Member', 'visitor');
$admin = $this->objFromFixture('Member', 'commentadmin');
$comment = $this->objFromFixture('Comment', 'firstComA');
-
+
$this->assertFalse($comment->canEdit($visitor));
$this->assertTrue($comment->canEdit($admin));
}
-
+
public function testDeleteComment() {
- // Test anonymous user
- if($member = Member::currentUser()) $member->logOut();
+ if($member = Member::currentUser()) {
+ $member->logOut();
+ }
+
+ /**
+ * @var Comment $comment
+ */
$comment = $this->objFromFixture('Comment', 'firstComA');
- $commentID = $comment->ID;
+
$this->assertNull($comment->DeleteLink(), 'No permission to see delete link');
- $delete = $this->get('CommentingController/delete/'.$comment->ID.'?ajax=1');
+
+ $delete = $this->get(sprintf(
+ 'CommentingController/delete/%s?ajax=1',
+ $comment->ID
+ ));
+
$this->assertEquals(403, $delete->getStatusCode());
- $check = DataObject::get_by_id('Comment', $commentID);
- $this->assertTrue($check && $check->exists());
- // Test non-authenticated user
$this->logInAs('visitor');
+
$this->assertNull($comment->DeleteLink(), 'No permission to see delete link');
- // Test authenticated user
$this->logInAs('commentadmin');
- $comment = $this->objFromFixture('Comment', 'firstComA');
- $commentID = $comment->ID;
- $adminComment1Link = $comment->DeleteLink();
- $this->assertContains('CommentingController/delete/'.$commentID.'?t=', $adminComment1Link);
- // Test that this link can't be shared / XSS exploited
+ $commentAdminLink = $comment->DeleteLink();
+
+ $this->assertContains(
+ sprintf(
+ 'CommentingController/delete/%s?t=',
+ $comment->ID
+ ),
+ $commentAdminLink
+ );
+
$this->logInAs('commentadmin2');
- $delete = $this->get($adminComment1Link);
- $this->assertEquals(400, $delete->getStatusCode());
- $check = DataObject::get_by_id('Comment', $commentID);
- $this->assertTrue($check && $check->exists());
- // Test that this other admin can delete the comment with their own link
- $adminComment2Link = $comment->DeleteLink();
- $this->assertNotEquals($adminComment2Link, $adminComment1Link);
+ $delete = $this->get($commentAdminLink);
+
+ $this->assertEquals(400, $delete->getStatusCode());
+ $this->assertNotEquals($comment->DeleteLink(), $commentAdminLink);
+
$this->autoFollowRedirection = false;
- $delete = $this->get($adminComment2Link);
+
+ $delete = $this->get($comment->DeleteLink());
+
$this->assertEquals(302, $delete->getStatusCode());
- $check = DataObject::get_by_id('Comment', $commentID);
- $this->assertFalse($check && $check->exists());
+ $this->assertFalse(DataObject::get_by_id('Comment', $comment->ID));
}
public function testSpamComment() {
- // Test anonymous user
- if($member = Member::currentUser()) $member->logOut();
+ if($member = Member::currentUser()) {
+ $member->logOut();
+ }
+
+ /**
+ * @var Comment $comment
+ */
$comment = $this->objFromFixture('Comment', 'firstComA');
- $commentID = $comment->ID;
+
$this->assertNull($comment->SpamLink(), 'No permission to see mark as spam link');
- $spam = $this->get('CommentingController/spam/'.$comment->ID.'?ajax=1');
+
+ $spam = $this->get(sprintf(
+ 'CommentingController/spam/%s?ajax=1',
+ $comment->ID
+ ));
+
$this->assertEquals(403, $spam->getStatusCode());
- $check = DataObject::get_by_id('Comment', $commentID);
- $this->assertEquals(0, $check->IsSpam, 'No permission to mark as spam');
+ $this->assertEquals(0, $comment->IsSpam, 'No permission to mark as spam');
- // Test non-authenticated user
$this->logInAs('visitor');
+
$this->assertNull($comment->SpamLink(), 'No permission to see mark as spam link');
- // Test authenticated user
$this->logInAs('commentadmin');
- $comment = $this->objFromFixture('Comment', 'firstComA');
- $commentID = $comment->ID;
- $adminComment1Link = $comment->SpamLink();
- $this->assertContains('CommentingController/spam/'.$commentID.'?t=', $adminComment1Link);
- // Test that this link can't be shared / XSS exploited
+ $commentAdminLink = $comment->SpamLink();
+
+ $this->assertContains(
+ sprintf(
+ 'CommentingController/spam/%s?t=',
+ $comment->ID
+ ),
+ $commentAdminLink
+ );
+
$this->logInAs('commentadmin2');
- $spam = $this->get($adminComment1Link);
+
+ $spam = $this->get($commentAdminLink);
+
$this->assertEquals(400, $spam->getStatusCode());
- $check = DataObject::get_by_id('Comment', $comment->ID);
- $this->assertEquals(0, $check->IsSpam, 'No permission to mark as spam');
+ $this->assertNotEquals($comment->SpamLink(), $commentAdminLink);
- // Test that this other admin can spam the comment with their own link
- $adminComment2Link = $comment->SpamLink();
- $this->assertNotEquals($adminComment2Link, $adminComment1Link);
$this->autoFollowRedirection = false;
- $spam = $this->get($adminComment2Link);
- $this->assertEquals(302, $spam->getStatusCode());
- $check = DataObject::get_by_id('Comment', $commentID);
- $this->assertEquals(1, $check->IsSpam);
- // Cannot re-spam spammed comment
- $this->assertNull($check->SpamLink());
+ $spam = $this->get($comment->SpamLink());
+
+ $this->assertEquals(302, $spam->getStatusCode());
+
+ /**
+ * @var Comment $comment
+ */
+ $comment = DataObject::get_by_id('Comment', $comment->ID);
+
+ $this->assertEquals(1, $comment->IsSpam);
+ $this->assertNull($comment->SpamLink());
}
public function testHamComment() {
- // Test anonymous user
- if($member = Member::currentUser()) $member->logOut();
+ if($member = Member::currentUser()) {
+ $member->logOut();
+ }
+
+ /**
+ * @var Comment $comment
+ */
$comment = $this->objFromFixture('Comment', 'secondComC');
- $commentID = $comment->ID;
+
$this->assertNull($comment->HamLink(), 'No permission to see mark as ham link');
- $ham = $this->get('CommentingController/ham/'.$comment->ID.'?ajax=1');
+
+ $ham = $this->get(sprintf(
+ 'CommentingController/ham/%s?ajax=1',
+ $comment->ID
+ ));
+
$this->assertEquals(403, $ham->getStatusCode());
- $check = DataObject::get_by_id('Comment', $commentID);
- $this->assertEquals(1, $check->IsSpam, 'No permission to mark as ham');
- // Test non-authenticated user
$this->logInAs('visitor');
+
$this->assertNull($comment->HamLink(), 'No permission to see mark as ham link');
- // Test authenticated user
$this->logInAs('commentadmin');
- $comment = $this->objFromFixture('Comment', 'secondComC');
- $commentID = $comment->ID;
- $adminComment1Link = $comment->HamLink();
- $this->assertContains('CommentingController/ham/'.$commentID.'?t=', $adminComment1Link);
- // Test that this link can't be shared / XSS exploited
+ $adminCommentLink = $comment->HamLink();
+
+ $this->assertContains(
+ sprintf(
+ 'CommentingController/ham/%s?t=',
+ $comment->ID
+ ),
+ $adminCommentLink
+ );
+
$this->logInAs('commentadmin2');
- $ham = $this->get($adminComment1Link);
+
+ $ham = $this->get($adminCommentLink);
+
$this->assertEquals(400, $ham->getStatusCode());
- $check = DataObject::get_by_id('Comment', $comment->ID);
- $this->assertEquals(1, $check->IsSpam, 'No permission to mark as ham');
+ $this->assertNotEquals($comment->HamLink(), $adminCommentLink);
- // Test that this other admin can ham the comment with their own link
- $adminComment2Link = $comment->HamLink();
- $this->assertNotEquals($adminComment2Link, $adminComment1Link);
$this->autoFollowRedirection = false;
- $ham = $this->get($adminComment2Link);
+
+ $ham = $this->get($comment->HamLink());
+
$this->assertEquals(302, $ham->getStatusCode());
- $check = DataObject::get_by_id('Comment', $commentID);
- $this->assertEquals(0, $check->IsSpam);
- // Cannot re-ham hammed comment
- $this->assertNull($check->HamLink());
+ /**
+ * @var Comment $comment
+ */
+ $comment = DataObject::get_by_id('Comment', $comment->ID);
+
+ $this->assertEquals(0, $comment->IsSpam);
+ $this->assertNull($comment->HamLink());
}
-
+
public function testApproveComment() {
- // Test anonymous user
- if($member = Member::currentUser()) $member->logOut();
+ if($member = Member::currentUser()) {
+ $member->logOut();
+ }
+
+ /**
+ * @var Comment $comment
+ */
$comment = $this->objFromFixture('Comment', 'secondComB');
- $commentID = $comment->ID;
+
$this->assertNull($comment->ApproveLink(), 'No permission to see approve link');
- $approve = $this->get('CommentingController/approve/'.$comment->ID.'?ajax=1');
+
+ $approve = $this->get(sprintf(
+ 'CommentingController/approve/%s?ajax=1',
+ $comment->ID
+ ));
+
$this->assertEquals(403, $approve->getStatusCode());
- $check = DataObject::get_by_id('Comment', $commentID);
- $this->assertEquals(0, $check->Moderated, 'No permission to approve');
- // Test non-authenticated user
$this->logInAs('visitor');
+
$this->assertNull($comment->ApproveLink(), 'No permission to see approve link');
- // Test authenticated user
$this->logInAs('commentadmin');
- $comment = $this->objFromFixture('Comment', 'secondComB');
- $commentID = $comment->ID;
- $adminComment1Link = $comment->ApproveLink();
- $this->assertContains('CommentingController/approve/'.$commentID.'?t=', $adminComment1Link);
- // Test that this link can't be shared / XSS exploited
+ $adminCommentLink = $comment->ApproveLink();
+
+ $this->assertContains(
+ sprintf(
+ 'CommentingController/approve/%s?t=',
+ $comment->ID
+ ),
+ $adminCommentLink
+ );
+
$this->logInAs('commentadmin2');
- $approve = $this->get($adminComment1Link);
+
+ $approve = $this->get($adminCommentLink);
+
$this->assertEquals(400, $approve->getStatusCode());
- $check = DataObject::get_by_id('Comment', $comment->ID);
- $this->assertEquals(0, $check->Moderated, 'No permission to approve');
- // Test that this other admin can approve the comment with their own link
- $adminComment2Link = $comment->ApproveLink();
- $this->assertNotEquals($adminComment2Link, $adminComment1Link);
+ $this->assertNotEquals($comment->ApproveLink(), $adminCommentLink);
+
$this->autoFollowRedirection = false;
- $approve = $this->get($adminComment2Link);
- $this->assertEquals(302, $approve->getStatusCode());
- $check = DataObject::get_by_id('Comment', $commentID);
- $this->assertEquals(1, $check->Moderated);
- // Cannot re-approve approved comment
- $this->assertNull($check->ApproveLink());
+ $approve = $this->get($comment->ApproveLink());
+
+ $this->assertEquals(302, $approve->getStatusCode());
+
+ /**
+ * @var Comment $comment
+ */
+ $comment = DataObject::get_by_id('Comment', $comment->ID);
+
+ $this->assertEquals(1, $comment->Moderated);
+ $this->assertNull($comment->ApproveLink());
}
public function testCommenterURLWrite() {
$comment = new Comment();
- // We only care about the CommenterURL, so only set that
- // Check a http and https URL. Add more test urls here as needed.
+
$protocols = array(
- 'Http',
- 'Https',
+ 'HTTP',
+ 'HTTPS',
);
+
$url = '://example.com';
foreach($protocols as $protocol) {
- $comment->CommenterURL = $protocol . $url;
- // The protocol should stay as if, assuming it is valid
+ $comment->URL = $protocol . $url;
$comment->write();
- $this->assertEquals($comment->CommenterURL, $protocol . $url, $protocol . ':// is a valid protocol');
+
+ $this->assertEquals($comment->URL, $protocol . $url, $protocol . ':// is a valid protocol');
}
}
public function testSanitizesWithAllowHtml() {
if(!class_exists('HTMLPurifier')) {
$this->markTestSkipped('HTMLPurifier class not found');
- return;
}
- $origAllowed = Commenting::get_config_value('CommentableItem','html_allowed');
-
- // Without HTML allowed
+ $originalHtmlAllowed = Commenting::get_config_value('HasComments', 'html_allowed');
+
$comment1 = new Comment();
- $comment1->BaseClass = 'CommentableItem';
+ $comment1->BaseClass = 'HasComments';
$comment1->Comment = '
my comment
';
$comment1->write();
+
$this->assertEquals(
'my comment
',
$comment1->Comment,
@@ -457,19 +579,20 @@ class CommentsTest extends FunctionalTest {
'which is correct behaviour because the HTML will be escaped'
);
- // With HTML allowed
- Commenting::set_config_value('CommentableItem','html_allowed', true);
+ Commenting::set_config_value('HasComments', 'html_allowed', true);
+
$comment2 = new Comment();
- $comment2->BaseClass = 'CommentableItem';
+ $comment2->BaseClass = 'HasComments';
$comment2->Comment = 'my comment
';
$comment2->write();
+
$this->assertEquals(
'my comment
',
$comment2->Comment,
'Removes HTML tags which are not on the whitelist'
);
- Commenting::set_config_value('CommentableItem','html_allowed', $origAllowed);
+ Commenting::set_config_value('HasComments', 'html_allowed', $originalHtmlAllowed);
}
public function testDefaultTemplateRendersHtmlWithAllowHtml() {
@@ -477,63 +600,92 @@ class CommentsTest extends FunctionalTest {
$this->markTestSkipped('HTMLPurifier class not found');
}
- $origAllowed = Commenting::get_config_value('CommentableItem', 'html_allowed');
- $item = new CommentableItem();
+ $originalHtmlAllowed = Commenting::get_config_value('HasComments', 'html_allowed');
+
+ $item = new HasComments();
$item->write();
- // Without HTML allowed
$comment = new Comment();
$comment->Comment = 'my comment
';
$comment->ParentID = $item->ID;
- $comment->BaseClass = 'CommentableItem';
+ $comment->BaseClass = 'HasComments';
$comment->write();
-
- $html = $item->customise(array('CommentsEnabled' => true))->renderWith('CommentsInterface');
+
+ $html = $item
+ ->customise(array(
+ 'CommentsEnabled' => true,
+ ))
+ ->renderWith('CommentsInterface');
+
$this->assertContains(
'<p>my comment</p>',
$html
);
- Commenting::set_config_value('CommentableItem','html_allowed', true);
- $html = $item->customise(array('CommentsEnabled' => true))->renderWith('CommentsInterface');
+ Commenting::set_config_value('HasComments', 'html_allowed', true);
+
+ $html = $item
+ ->customise(array(
+ 'CommentsEnabled' => true,
+ ))
+ ->renderWith('CommentsInterface');
+
$this->assertContains(
'my comment
',
$html
);
- Commenting::set_config_value('CommentableItem','html_allowed', $origAllowed);
+ Commenting::set_config_value('HasComments', 'html_allowed', $originalHtmlAllowed);
}
}
-
/**
+ * @mixin CommentsExtension
+ *
* @package comments
* @subpackage tests
*/
-class CommentableItem extends DataObject implements TestOnly {
-
+class HasComments extends DataObject implements TestOnly {
+ /**
+ * @var array
+ */
private static $db = array(
'ProvideComments' => 'Boolean',
- 'Title' => 'Varchar'
+ 'Title' => 'Varchar',
);
+ /**
+ * @var array
+ */
private static $extensions = array(
- 'CommentsExtension'
+ 'CommentsExtension',
);
+ /**
+ * @return string
+ */
public function RelativeLink() {
- return "CommentableItem_Controller";
+ return 'HasComments_Controller';
}
+ /**
+ * {@inheritdoc}
+ */
public function canView($member = null) {
return true;
}
+ /**
+ * @return string
+ */
public function Link() {
return $this->RelativeLink();
}
+ /**
+ * @return string
+ */
public function AbsoluteLink() {
return Director::absoluteURL($this->RelativeLink());
}
@@ -543,9 +695,11 @@ class CommentableItem extends DataObject implements TestOnly {
* @package comments
* @subpackage tests
*/
-class CommentableItem_Controller extends Controller implements TestOnly {
-
+class HasComments_Controller extends Controller implements TestOnly {
+ /**
+ * @return Form
+ */
public function index() {
- return CommentableItem::get()->first()->CommentsForm();
+ return HasComments::get()->first()->CommentsForm();
}
}
diff --git a/tests/CommentsTest.yml b/tests/CommentsTest.yml
index 6ea339a..c30b922 100644
--- a/tests/CommentsTest.yml
+++ b/tests/CommentsTest.yml
@@ -16,7 +16,7 @@ Permission:
Code: CMS_ACCESS_CommentAdmin
Group: =>Group.commentadmins
-CommentableItem:
+HasComments:
first:
Title: First
ProvideComments: 1
@@ -38,135 +38,135 @@ CommentableItem:
Comment:
firstComA:
- ParentID: =>CommentableItem.first
+ ParentID: =>HasComments.first
Name: FA
Comment: textFA
- BaseClass: CommentableItem
+ BaseClass: HasComments
Moderated: 1
IsSpam: 0
secondComA:
- ParentID: =>CommentableItem.second
+ ParentID: =>HasComments.second
Name: SA
Comment: textSA
Moderated: 1
IsSpam: 0
- BaseClass: CommentableItem
+ BaseClass: HasComments
secondComB:
- ParentID: =>CommentableItem.second
+ ParentID: =>HasComments.second
Name: SB
Comment: textSB
Moderated: 0
IsSpam: 0
- BaseClass: CommentableItem
+ BaseClass: HasComments
secondComC:
- ParentID: =>CommentableItem.second
+ ParentID: =>HasComments.second
Name: SB
Comment: textSB
Moderated: 1
IsSpam: 1
- BaseClass: CommentableItem
+ BaseClass: HasComments
thirdComA:
- ParentID: =>CommentableItem.third
+ ParentID: =>HasComments.third
Name: TA
Comment: textTA
Moderated: 1
IsSpam: 0
- BaseClass: CommentableItem
+ BaseClass: HasComments
thirdComB:
- ParentID: =>CommentableItem.third
+ ParentID: =>HasComments.third
Name: TB
Comment: textTB
Moderated: 1
IsSpam: 0
- BaseClass: CommentableItem
+ BaseClass: HasComments
thirdComC:
- ParentID: =>CommentableItem.third
+ ParentID: =>HasComments.third
Name: TC
Comment: textTC
Moderated: 1
IsSpam: 0
- BaseClass: CommentableItem
+ BaseClass: HasComments
thirdComD:
- ParentID: =>CommentableItem.third
+ ParentID: =>HasComments.third
Name: TC
Comment: textTC
Moderated: 1
- BaseClass: CommentableItem
+ BaseClass: HasComments
thirdComE:
- ParentID: =>CommentableItem.third
+ ParentID: =>HasComments.third
Name: TC
Comment: textTC
Moderated: 1
- BaseClass: CommentableItem
+ BaseClass: HasComments
thirdComF:
- ParentID: =>CommentableItem.third
+ ParentID: =>HasComments.third
Name: TC
Comment: textTC
Moderated: 1
IsSpam: 0
- BaseClass: CommentableItem
+ BaseClass: HasComments
thirdComG:
- ParentID: =>CommentableItem.third
+ ParentID: =>HasComments.third
Name: TC
Comment: textTC
Moderated: 1
IsSpam: 0
- BaseClass: CommentableItem
+ BaseClass: HasComments
thirdComH:
- ParentID: =>CommentableItem.third
+ ParentID: =>HasComments.third
Name: TC
Comment: textTC
Moderated: 1
IsSpam: 0
- BaseClass: CommentableItem
+ BaseClass: HasComments
thirdComI:
- ParentID: =>CommentableItem.third
+ ParentID: =>HasComments.third
Name: TC
Comment: textTC
Moderated: 1
IsSpam: 0
- BaseClass: CommentableItem
+ BaseClass: HasComments
thirdComJ:
- ParentID: =>CommentableItem.third
+ ParentID: =>HasComments.third
Name: TC
Comment: textTC
Moderated: 1
IsSpam: 0
- BaseClass: CommentableItem
+ BaseClass: HasComments
thirdComK:
- ParentID: =>CommentableItem.third
+ ParentID: =>HasComments.third
Name: TC
Comment: textTC
Moderated: 1
IsSpam: 0
- BaseClass: CommentableItem
+ BaseClass: HasComments
disabledCom:
- ParentID: =>CommentableItem.nocomments
+ ParentID: =>HasComments.nocomments
Name: Disabled
Moderated: 0
IsSpam: 1
- BaseClass: CommentableItem
+ BaseClass: HasComments
testCommentList1:
- ParentID: =>CommentableItem.spammed
+ ParentID: =>HasComments.spammed
Name: Comment 1
Moderated: 0
IsSpam: 0
- BaseClass: CommentableItem
+ BaseClass: HasComments
testCommentList2:
- ParentID: =>CommentableItem.spammed
+ ParentID: =>HasComments.spammed
Name: Comment 2
Moderated: 1
IsSpam: 1
- BaseClass: CommentableItem
+ BaseClass: HasComments
testCommentList3:
- ParentID: =>CommentableItem.spammed
+ ParentID: =>HasComments.spammed
Name: Comment 3
Moderated: 1
IsSpam: 0
- BaseClass: CommentableItem
+ BaseClass: HasComments
testCommentList4:
- ParentID: =>CommentableItem.spammed
+ ParentID: =>HasComments.spammed
Name: Comment 4
Moderated: 0
IsSpam: 1
- BaseClass: CommentableItem
\ No newline at end of file
+ BaseClass: HasComments
\ No newline at end of file