mirror of
https://github.com/silverstripe/silverstripe-comments
synced 2024-10-22 11:05:49 +02:00
Reformat as PSR-2
This commit is contained in:
parent
c2fee6bd33
commit
4b31713128
@ -13,134 +13,150 @@
|
|||||||
*
|
*
|
||||||
* @package comments
|
* @package comments
|
||||||
*/
|
*/
|
||||||
class Commenting {
|
class Commenting
|
||||||
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds commenting to a {@link DataObject}
|
* Adds commenting to a {@link DataObject}
|
||||||
*
|
*
|
||||||
* @deprecated since version 2.0
|
* @deprecated since version 2.0
|
||||||
*
|
*
|
||||||
* @param string classname to add commenting to
|
* @param string classname to add commenting to
|
||||||
* @param array $settings Settings. See {@link self::$default_config} for
|
* @param array $settings Settings. See {@link self::$default_config} for
|
||||||
* available settings
|
* available settings
|
||||||
*
|
*
|
||||||
* @throws InvalidArgumentException
|
* @throws InvalidArgumentException
|
||||||
*/
|
*/
|
||||||
public static function add($class, $settings = false) {
|
public static function add($class, $settings = false)
|
||||||
Deprecation::notice('2.0', 'Using Commenting::add is deprecated. Please use the config API instead');
|
{
|
||||||
Config::inst()->update($class, 'extensions', array('CommentsExtension'));
|
Deprecation::notice('2.0', 'Using Commenting::add is deprecated. Please use the config API instead');
|
||||||
|
Config::inst()->update($class, 'extensions', array('CommentsExtension'));
|
||||||
|
|
||||||
// Check if settings must be customised
|
// Check if settings must be customised
|
||||||
if($settings === false) return;
|
if ($settings === false) {
|
||||||
if(!is_array($settings)) {
|
return;
|
||||||
throw new InvalidArgumentException('$settings needs to be an array or null');
|
}
|
||||||
}
|
if (!is_array($settings)) {
|
||||||
Config::inst()->update($class, 'comments', $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
|
* Removes commenting from a {@link DataObject}. Does not remove existing comments
|
||||||
* but does remove the extension.
|
* but does remove the extension.
|
||||||
*
|
*
|
||||||
* @deprecated since version 2.0
|
* @deprecated since version 2.0
|
||||||
*
|
*
|
||||||
* @param string $class Class to remove {@link CommentsExtension} from
|
* @param string $class Class to remove {@link CommentsExtension} from
|
||||||
*/
|
*/
|
||||||
public static function remove($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');
|
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
|
* @deprecated since version 2.0
|
||||||
*
|
*
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
public static function has_commenting($class) {
|
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');
|
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 a value for a class of a given config setting. Passing 'all' as the class
|
||||||
* sets it for everything
|
* sets it for everything
|
||||||
*
|
*
|
||||||
* @deprecated since version 2.0
|
* @deprecated since version 2.0
|
||||||
*
|
*
|
||||||
* @param string $class Class to set the value on. Passing 'all' will set it to all
|
* @param string $class Class to set the value on. Passing 'all' will set it to all
|
||||||
* active mappings
|
* active mappings
|
||||||
* @param string $key setting to change
|
* @param string $key setting to change
|
||||||
* @param mixed $value value of the setting
|
* @param mixed $value value of the setting
|
||||||
*/
|
*/
|
||||||
public static function set_config_value($class, $key, $value = false) {
|
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';
|
Deprecation::notice('2.0', 'Commenting::set_config_value is deprecated. Use the config api instead');
|
||||||
Config::inst()->update($class, 'comments', array($key => $value));
|
if ($class === "all") {
|
||||||
}
|
$class = 'CommentsExtension';
|
||||||
|
}
|
||||||
|
Config::inst()->update($class, 'comments', array($key => $value));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a given config value for a commenting class
|
* Returns a given config value for a commenting class
|
||||||
*
|
*
|
||||||
* @deprecated since version 2.0
|
* @deprecated since version 2.0
|
||||||
*
|
*
|
||||||
* @param string $class
|
* @param string $class
|
||||||
* @param string $key config value to return
|
* @param string $key config value to return
|
||||||
*
|
*
|
||||||
* @throws Exception
|
* @throws Exception
|
||||||
* @return mixed
|
* @return mixed
|
||||||
*/
|
*/
|
||||||
public static function get_config_value($class, $key) {
|
public static function get_config_value($class, $key)
|
||||||
Deprecation::notice(
|
{
|
||||||
'2.0',
|
Deprecation::notice(
|
||||||
'Using Commenting::get_config_value is deprecated. Please use $parent->getCommentsOption() or '
|
'2.0',
|
||||||
. 'CommentingController::getOption() instead'
|
'Using Commenting::get_config_value is deprecated. Please use $parent->getCommentsOption() or '
|
||||||
);
|
. 'CommentingController::getOption() instead'
|
||||||
|
);
|
||||||
|
|
||||||
// Get settings
|
// Get settings
|
||||||
if(!$class) {
|
if (!$class) {
|
||||||
$class = 'CommentsExtension';
|
$class = 'CommentsExtension';
|
||||||
} elseif(!$class::has_extension('CommentsExtension')) {
|
} elseif (!$class::has_extension('CommentsExtension')) {
|
||||||
throw new InvalidArgumentException("$class does not have commenting enabled");
|
throw new InvalidArgumentException("$class does not have commenting enabled");
|
||||||
}
|
}
|
||||||
return singleton($class)->getCommentsOption($key);
|
return singleton($class)->getCommentsOption($key);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determines whether a config value on the commenting extension
|
* Determines whether a config value on the commenting extension
|
||||||
* matches a given value.
|
* matches a given value.
|
||||||
*
|
*
|
||||||
* @deprecated since version 2.0
|
* @deprecated since version 2.0
|
||||||
*
|
*
|
||||||
* @param string $class
|
* @param string $class
|
||||||
* @param string $key
|
* @param string $key
|
||||||
* @param string $value Expected value
|
* @param string $value Expected value
|
||||||
* @return boolean
|
* @return boolean
|
||||||
*/
|
*/
|
||||||
public static function config_value_equals($class, $key, $value) {
|
public static function config_value_equals($class, $key, $value)
|
||||||
$check = self::get_config_value($class, $key);
|
{
|
||||||
if($check && ($check == $value)) return true;
|
$check = self::get_config_value($class, $key);
|
||||||
}
|
if ($check && ($check == $value)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return whether a user can post on a given commenting instance
|
* Return whether a user can post on a given commenting instance
|
||||||
*
|
*
|
||||||
* @deprecated since version 2.0
|
* @deprecated since version 2.0
|
||||||
*
|
*
|
||||||
* @param string $class
|
* @param string $class
|
||||||
* @return boolean true
|
* @return boolean true
|
||||||
*/
|
*/
|
||||||
public static function can_member_post($class) {
|
public static function can_member_post($class)
|
||||||
Deprecation::notice('2.0', 'Use $instance->canPostComment() directly instead');
|
{
|
||||||
$member = Member::currentUser();
|
Deprecation::notice('2.0', 'Use $instance->canPostComment() directly instead');
|
||||||
|
$member = Member::currentUser();
|
||||||
|
|
||||||
// Check permission
|
// Check permission
|
||||||
$permission = self::get_config_value($class, 'required_permission');
|
$permission = self::get_config_value($class, 'required_permission');
|
||||||
if($permission && !Permission::check($permission)) return false;
|
if ($permission && !Permission::check($permission)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Check login required
|
// Check login required
|
||||||
$requireLogin = self::get_config_value($class, 'require_login');
|
$requireLogin = self::get_config_value($class, 'require_login');
|
||||||
return !$requireLogin || $member;
|
return !$requireLogin || $member;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,114 +5,119 @@
|
|||||||
*
|
*
|
||||||
* @package comments
|
* @package comments
|
||||||
*/
|
*/
|
||||||
class CommentAdmin extends LeftAndMain implements PermissionProvider {
|
class CommentAdmin extends LeftAndMain implements PermissionProvider
|
||||||
|
{
|
||||||
|
|
||||||
private static $url_segment = 'comments';
|
private static $url_segment = 'comments';
|
||||||
|
|
||||||
private static $url_rule = '/$Action';
|
private static $url_rule = '/$Action';
|
||||||
|
|
||||||
private static $menu_title = 'Comments';
|
private static $menu_title = 'Comments';
|
||||||
|
|
||||||
private static $allowed_actions = array(
|
private static $allowed_actions = array(
|
||||||
'approvedmarked',
|
'approvedmarked',
|
||||||
'deleteall',
|
'deleteall',
|
||||||
'deletemarked',
|
'deletemarked',
|
||||||
'hammarked',
|
'hammarked',
|
||||||
'showtable',
|
'showtable',
|
||||||
'spammarked',
|
'spammarked',
|
||||||
'EditForm',
|
'EditForm',
|
||||||
'unmoderated'
|
'unmoderated'
|
||||||
);
|
);
|
||||||
|
|
||||||
public function providePermissions() {
|
public function providePermissions()
|
||||||
return array(
|
{
|
||||||
"CMS_ACCESS_CommentAdmin" => array(
|
return array(
|
||||||
'name' => _t('CommentAdmin.ADMIN_PERMISSION', "Access to 'Comments' section"),
|
"CMS_ACCESS_CommentAdmin" => array(
|
||||||
'category' => _t('Permission.CMS_ACCESS_CATEGORY', 'CMS Access')
|
'name' => _t('CommentAdmin.ADMIN_PERMISSION', "Access to 'Comments' section"),
|
||||||
)
|
'category' => _t('Permission.CMS_ACCESS_CATEGORY', 'CMS Access')
|
||||||
);
|
)
|
||||||
}
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Form
|
* @return Form
|
||||||
*/
|
*/
|
||||||
public function getEditForm($id = null, $fields = null) {
|
public function getEditForm($id = null, $fields = null)
|
||||||
if(!$id) $id = $this->currentPageID();
|
{
|
||||||
|
if (!$id) {
|
||||||
|
$id = $this->currentPageID();
|
||||||
|
}
|
||||||
|
|
||||||
$form = parent::getEditForm($id);
|
$form = parent::getEditForm($id);
|
||||||
$record = $this->getRecord($id);
|
$record = $this->getRecord($id);
|
||||||
|
|
||||||
if($record && !$record->canView()) {
|
if ($record && !$record->canView()) {
|
||||||
return Security::permissionFailure($this);
|
return Security::permissionFailure($this);
|
||||||
}
|
}
|
||||||
|
|
||||||
$newComments = Comment::get()->filter('Moderated', 0);
|
$newComments = Comment::get()->filter('Moderated', 0);
|
||||||
|
|
||||||
$newGrid = new CommentsGridField(
|
$newGrid = new CommentsGridField(
|
||||||
'NewComments',
|
'NewComments',
|
||||||
_t('CommentsAdmin.NewComments', 'New'),
|
_t('CommentsAdmin.NewComments', 'New'),
|
||||||
$newComments,
|
$newComments,
|
||||||
CommentsGridFieldConfig::create()
|
CommentsGridFieldConfig::create()
|
||||||
);
|
);
|
||||||
|
|
||||||
$approvedComments = Comment::get()->filter('Moderated', 1)->filter('IsSpam', 0);
|
$approvedComments = Comment::get()->filter('Moderated', 1)->filter('IsSpam', 0);
|
||||||
|
|
||||||
$approvedGrid = new CommentsGridField(
|
$approvedGrid = new CommentsGridField(
|
||||||
'ApprovedComments',
|
'ApprovedComments',
|
||||||
_t('CommentsAdmin.ApprovedComments', 'Approved'),
|
_t('CommentsAdmin.ApprovedComments', 'Approved'),
|
||||||
$approvedComments,
|
$approvedComments,
|
||||||
CommentsGridFieldConfig::create()
|
CommentsGridFieldConfig::create()
|
||||||
);
|
);
|
||||||
|
|
||||||
$spamComments = Comment::get()->filter('Moderated', 1)->filter('IsSpam', 1);
|
$spamComments = Comment::get()->filter('Moderated', 1)->filter('IsSpam', 1);
|
||||||
|
|
||||||
$spamGrid = new CommentsGridField(
|
$spamGrid = new CommentsGridField(
|
||||||
'SpamComments',
|
'SpamComments',
|
||||||
_t('CommentsAdmin.SpamComments', 'Spam'),
|
_t('CommentsAdmin.SpamComments', 'Spam'),
|
||||||
$spamComments,
|
$spamComments,
|
||||||
CommentsGridFieldConfig::create()
|
CommentsGridFieldConfig::create()
|
||||||
);
|
);
|
||||||
|
|
||||||
$newCount = '(' . count($newComments) . ')';
|
$newCount = '(' . count($newComments) . ')';
|
||||||
$approvedCount = '(' . count($approvedComments) . ')';
|
$approvedCount = '(' . count($approvedComments) . ')';
|
||||||
$spamCount = '(' . count($spamComments) . ')';
|
$spamCount = '(' . count($spamComments) . ')';
|
||||||
|
|
||||||
$fields = new FieldList(
|
$fields = new FieldList(
|
||||||
$root = new TabSet(
|
$root = new TabSet(
|
||||||
'Root',
|
'Root',
|
||||||
new Tab('NewComments', _t('CommentAdmin.NewComments', 'New') . ' ' . $newCount,
|
new Tab('NewComments', _t('CommentAdmin.NewComments', 'New') . ' ' . $newCount,
|
||||||
$newGrid
|
$newGrid
|
||||||
),
|
),
|
||||||
new Tab('ApprovedComments', _t('CommentAdmin.ApprovedComments', 'Approved') . ' ' . $approvedCount,
|
new Tab('ApprovedComments', _t('CommentAdmin.ApprovedComments', 'Approved') . ' ' . $approvedCount,
|
||||||
$approvedGrid
|
$approvedGrid
|
||||||
),
|
),
|
||||||
new Tab('SpamComments', _t('CommentAdmin.SpamComments', 'Spam') . ' ' . $spamCount,
|
new Tab('SpamComments', _t('CommentAdmin.SpamComments', 'Spam') . ' ' . $spamCount,
|
||||||
$spamGrid
|
$spamGrid
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
$root->setTemplate('CMSTabSet');
|
$root->setTemplate('CMSTabSet');
|
||||||
|
|
||||||
$actions = new FieldList();
|
$actions = new FieldList();
|
||||||
|
|
||||||
$form = new Form(
|
$form = new Form(
|
||||||
$this,
|
$this,
|
||||||
'EditForm',
|
'EditForm',
|
||||||
$fields,
|
$fields,
|
||||||
$actions
|
$actions
|
||||||
);
|
);
|
||||||
|
|
||||||
$form->addExtraClass('cms-edit-form');
|
$form->addExtraClass('cms-edit-form');
|
||||||
$form->setTemplate($this->getTemplatesWithSuffix('_EditForm'));
|
$form->setTemplate($this->getTemplatesWithSuffix('_EditForm'));
|
||||||
|
|
||||||
if($form->Fields()->hasTabset()) {
|
if ($form->Fields()->hasTabset()) {
|
||||||
$form->Fields()->findOrMakeTab('Root')->setTemplate('CMSTabSet');
|
$form->Fields()->findOrMakeTab('Root')->setTemplate('CMSTabSet');
|
||||||
$form->addExtraClass('center ss-tabset cms-tabset ' . $this->BaseCSSClasses());
|
$form->addExtraClass('center ss-tabset cms-tabset ' . $this->BaseCSSClasses());
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->extend('updateEditForm', $form);
|
$this->extend('updateEditForm', $form);
|
||||||
|
|
||||||
return $form;
|
return $form;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,22 +1,24 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
class CommentsGridField extends GridField {
|
class CommentsGridField extends GridField
|
||||||
/**
|
{
|
||||||
* {@inheritdoc}
|
/**
|
||||||
*/
|
* {@inheritdoc}
|
||||||
protected function newRow($total, $index, $record, $attributes, $content) {
|
*/
|
||||||
if(!isset($attributes['class'])) {
|
protected function newRow($total, $index, $record, $attributes, $content)
|
||||||
$attributes['class'] = '';
|
{
|
||||||
}
|
if (!isset($attributes['class'])) {
|
||||||
|
$attributes['class'] = '';
|
||||||
|
}
|
||||||
|
|
||||||
if($record->IsSpam) {
|
if ($record->IsSpam) {
|
||||||
$attributes['class'] .= ' spam';
|
$attributes['class'] .= ' spam';
|
||||||
}
|
}
|
||||||
|
|
||||||
return FormField::create_tag(
|
return FormField::create_tag(
|
||||||
'tr',
|
'tr',
|
||||||
$attributes,
|
$attributes,
|
||||||
$content
|
$content
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,100 +1,110 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
class CommentsGridFieldAction implements GridField_ColumnProvider, GridField_ActionProvider {
|
class CommentsGridFieldAction implements GridField_ColumnProvider, GridField_ActionProvider
|
||||||
/**
|
{
|
||||||
* {@inheritdoc}
|
/**
|
||||||
*/
|
* {@inheritdoc}
|
||||||
public function augmentColumns($gridField, &$columns) {
|
*/
|
||||||
if(!in_array('Actions', $columns)) {
|
public function augmentColumns($gridField, &$columns)
|
||||||
$columns[] = 'Actions';
|
{
|
||||||
}
|
if (!in_array('Actions', $columns)) {
|
||||||
}
|
$columns[] = 'Actions';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritdoc}
|
* {@inheritdoc}
|
||||||
*/
|
*/
|
||||||
public function getColumnAttributes($gridField, $record, $columnName) {
|
public function getColumnAttributes($gridField, $record, $columnName)
|
||||||
return array('class' => 'col-buttons');
|
{
|
||||||
}
|
return array('class' => 'col-buttons');
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritdoc}
|
* {@inheritdoc}
|
||||||
*/
|
*/
|
||||||
public function getColumnMetadata($gridField, $columnName) {
|
public function getColumnMetadata($gridField, $columnName)
|
||||||
if($columnName == 'Actions') {
|
{
|
||||||
return array('title' => '');
|
if ($columnName == 'Actions') {
|
||||||
}
|
return array('title' => '');
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritdoc}
|
* {@inheritdoc}
|
||||||
*/
|
*/
|
||||||
public function getColumnsHandled($gridField) {
|
public function getColumnsHandled($gridField)
|
||||||
return array('Actions');
|
{
|
||||||
}
|
return array('Actions');
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritdoc}
|
* {@inheritdoc}
|
||||||
*/
|
*/
|
||||||
public function getColumnContent($gridField, $record, $columnName) {
|
public function getColumnContent($gridField, $record, $columnName)
|
||||||
if(!$record->canEdit()) return;
|
{
|
||||||
|
if (!$record->canEdit()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
$field = "";
|
$field = "";
|
||||||
|
|
||||||
if(!$record->IsSpam || !$record->Moderated) {
|
if (!$record->IsSpam || !$record->Moderated) {
|
||||||
$field .= GridField_FormAction::create(
|
$field .= GridField_FormAction::create(
|
||||||
$gridField,
|
$gridField,
|
||||||
'CustomAction' . $record->ID . 'Spam',
|
'CustomAction' . $record->ID . 'Spam',
|
||||||
'Spam',
|
'Spam',
|
||||||
'spam',
|
'spam',
|
||||||
array('RecordID' => $record->ID)
|
array('RecordID' => $record->ID)
|
||||||
)->Field();
|
)->Field();
|
||||||
}
|
}
|
||||||
|
|
||||||
if($record->IsSpam || !$record->Moderated) {
|
if ($record->IsSpam || !$record->Moderated) {
|
||||||
$field .= GridField_FormAction::create(
|
$field .= GridField_FormAction::create(
|
||||||
$gridField,
|
$gridField,
|
||||||
'CustomAction' . $record->ID . 'Approve',
|
'CustomAction' . $record->ID . 'Approve',
|
||||||
'Approve',
|
'Approve',
|
||||||
'approve',
|
'approve',
|
||||||
array('RecordID' => $record->ID)
|
array('RecordID' => $record->ID)
|
||||||
)->Field();
|
)->Field();
|
||||||
}
|
}
|
||||||
|
|
||||||
return $field;
|
return $field;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritdoc}
|
* {@inheritdoc}
|
||||||
*/
|
*/
|
||||||
public function getActions($gridField) {
|
public function getActions($gridField)
|
||||||
return array('spam', 'approve');
|
{
|
||||||
}
|
return array('spam', 'approve');
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritdoc}
|
* {@inheritdoc}
|
||||||
*/
|
*/
|
||||||
public function handleAction(GridField $gridField, $actionName, $arguments, $data) {
|
public function handleAction(GridField $gridField, $actionName, $arguments, $data)
|
||||||
if($actionName == 'spam') {
|
{
|
||||||
$comment = Comment::get()->byID($arguments["RecordID"]);
|
if ($actionName == 'spam') {
|
||||||
$comment->markSpam();
|
$comment = Comment::get()->byID($arguments["RecordID"]);
|
||||||
|
$comment->markSpam();
|
||||||
|
|
||||||
// output a success message to the user
|
// output a success message to the user
|
||||||
Controller::curr()->getResponse()->setStatusCode(
|
Controller::curr()->getResponse()->setStatusCode(
|
||||||
200,
|
200,
|
||||||
'Comment marked as spam.'
|
'Comment marked as spam.'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if($actionName == 'approve') {
|
if ($actionName == 'approve') {
|
||||||
$comment = Comment::get()->byID($arguments["RecordID"]);
|
$comment = Comment::get()->byID($arguments["RecordID"]);
|
||||||
$comment->markApproved();
|
$comment->markApproved();
|
||||||
|
|
||||||
// output a success message to the user
|
// output a success message to the user
|
||||||
Controller::curr()->getResponse()->setStatusCode(
|
Controller::curr()->getResponse()->setStatusCode(
|
||||||
200,
|
200,
|
||||||
'Comment approved.'
|
'Comment approved.'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,8 +3,8 @@
|
|||||||
/**
|
/**
|
||||||
* @package comments
|
* @package comments
|
||||||
*/
|
*/
|
||||||
class CommentsGridFieldBulkAction extends GridFieldBulkActionHandler {
|
class CommentsGridFieldBulkAction extends GridFieldBulkActionHandler
|
||||||
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -12,53 +12,56 @@ class CommentsGridFieldBulkAction extends GridFieldBulkActionHandler {
|
|||||||
*
|
*
|
||||||
* @package comments
|
* @package comments
|
||||||
*/
|
*/
|
||||||
class CommentsGridFieldBulkAction_Handlers extends CommentsGridFieldBulkAction {
|
class CommentsGridFieldBulkAction_Handlers extends CommentsGridFieldBulkAction
|
||||||
|
{
|
||||||
|
|
||||||
private static $allowed_actions = array(
|
private static $allowed_actions = array(
|
||||||
'spam',
|
'spam',
|
||||||
'approve',
|
'approve',
|
||||||
);
|
);
|
||||||
|
|
||||||
private static $url_handlers = array(
|
private static $url_handlers = array(
|
||||||
'spam' => 'spam',
|
'spam' => 'spam',
|
||||||
'approve' => 'approve',
|
'approve' => 'approve',
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
public function spam(SS_HTTPRequest $request) {
|
public function spam(SS_HTTPRequest $request)
|
||||||
$ids = array();
|
{
|
||||||
|
$ids = array();
|
||||||
|
|
||||||
foreach($this->getRecords() as $record) {
|
foreach ($this->getRecords() as $record) {
|
||||||
array_push($ids, $record->ID);
|
array_push($ids, $record->ID);
|
||||||
$record->markSpam();
|
$record->markSpam();
|
||||||
}
|
}
|
||||||
|
|
||||||
$response = new SS_HTTPResponse(Convert::raw2json(array(
|
$response = new SS_HTTPResponse(Convert::raw2json(array(
|
||||||
'done' => true,
|
'done' => true,
|
||||||
'records' => $ids
|
'records' => $ids
|
||||||
)));
|
)));
|
||||||
|
|
||||||
$response->addHeader('Content-Type', 'text/json');
|
$response->addHeader('Content-Type', 'text/json');
|
||||||
|
|
||||||
return $response;
|
return $response;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public function approve(SS_HTTPRequest $request) {
|
public function approve(SS_HTTPRequest $request)
|
||||||
$ids = array();
|
{
|
||||||
|
$ids = array();
|
||||||
|
|
||||||
foreach($this->getRecords() as $record) {
|
foreach ($this->getRecords() as $record) {
|
||||||
array_push($ids, $record->ID);
|
array_push($ids, $record->ID);
|
||||||
$record->markApproved();
|
$record->markApproved();
|
||||||
}
|
}
|
||||||
|
|
||||||
$response = new SS_HTTPResponse(Convert::raw2json(array(
|
$response = new SS_HTTPResponse(Convert::raw2json(array(
|
||||||
'done' => true,
|
'done' => true,
|
||||||
'records' => $ids
|
'records' => $ids
|
||||||
)));
|
)));
|
||||||
|
|
||||||
$response->addHeader('Content-Type', 'text/json');
|
$response->addHeader('Content-Type', 'text/json');
|
||||||
|
|
||||||
return $response;
|
return $response;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,49 +1,51 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
class CommentsGridFieldConfig extends GridFieldConfig_RecordEditor {
|
class CommentsGridFieldConfig extends GridFieldConfig_RecordEditor
|
||||||
public function __construct($itemsPerPage = 25) {
|
{
|
||||||
parent::__construct($itemsPerPage);
|
public function __construct($itemsPerPage = 25)
|
||||||
|
{
|
||||||
|
parent::__construct($itemsPerPage);
|
||||||
|
|
||||||
// $this->addComponent(new GridFieldExportButton());
|
// $this->addComponent(new GridFieldExportButton());
|
||||||
|
|
||||||
$this->addComponent(new CommentsGridFieldAction());
|
$this->addComponent(new CommentsGridFieldAction());
|
||||||
|
|
||||||
// Format column
|
// Format column
|
||||||
$columns = $this->getComponentByType('GridFieldDataColumns');
|
$columns = $this->getComponentByType('GridFieldDataColumns');
|
||||||
$columns->setFieldFormatting(array(
|
$columns->setFieldFormatting(array(
|
||||||
'ParentTitle' => function($value, &$item) {
|
'ParentTitle' => function ($value, &$item) {
|
||||||
return sprintf(
|
return sprintf(
|
||||||
'<a href="%s" class="cms-panel-link external-link action" target="_blank">%s</a>',
|
'<a href="%s" class="cms-panel-link external-link action" target="_blank">%s</a>',
|
||||||
Convert::raw2att($item->Link()),
|
Convert::raw2att($item->Link()),
|
||||||
$item->obj('ParentTitle')->forTemplate()
|
$item->obj('ParentTitle')->forTemplate()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
));
|
));
|
||||||
|
|
||||||
// Add bulk option
|
// Add bulk option
|
||||||
$manager = new GridFieldBulkManager();
|
$manager = new GridFieldBulkManager();
|
||||||
|
|
||||||
$manager->addBulkAction(
|
$manager->addBulkAction(
|
||||||
'spam', 'Spam', 'CommentsGridFieldBulkAction_Handlers',
|
'spam', 'Spam', 'CommentsGridFieldBulkAction_Handlers',
|
||||||
array(
|
array(
|
||||||
'isAjax' => true,
|
'isAjax' => true,
|
||||||
'icon' => 'cross',
|
'icon' => 'cross',
|
||||||
'isDestructive' => false
|
'isDestructive' => false
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
$manager->addBulkAction(
|
$manager->addBulkAction(
|
||||||
'approve', 'Approve', 'CommentsGridFieldBulkAction_Handlers',
|
'approve', 'Approve', 'CommentsGridFieldBulkAction_Handlers',
|
||||||
array(
|
array(
|
||||||
'isAjax' => true,
|
'isAjax' => true,
|
||||||
'icon' => 'cross',
|
'icon' => 'cross',
|
||||||
'isDestructive' => false
|
'isDestructive' => false
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
$manager->removeBulkAction('bulkEdit');
|
$manager->removeBulkAction('bulkEdit');
|
||||||
$manager->removeBulkAction('unLink');
|
$manager->removeBulkAction('unLink');
|
||||||
|
|
||||||
$this->addComponent($manager);
|
$this->addComponent($manager);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,284 +4,316 @@
|
|||||||
* @package comments
|
* @package comments
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class CommentingController extends Controller {
|
class CommentingController extends Controller
|
||||||
|
{
|
||||||
|
|
||||||
private static $allowed_actions = array(
|
private static $allowed_actions = array(
|
||||||
'delete',
|
'delete',
|
||||||
'spam',
|
'spam',
|
||||||
'ham',
|
'ham',
|
||||||
'approve',
|
'approve',
|
||||||
'rss',
|
'rss',
|
||||||
'CommentsForm',
|
'CommentsForm',
|
||||||
'reply',
|
'reply',
|
||||||
'doPostComment',
|
'doPostComment',
|
||||||
'doPreviewComment'
|
'doPreviewComment'
|
||||||
);
|
);
|
||||||
|
|
||||||
private static $url_handlers = array(
|
private static $url_handlers = array(
|
||||||
'reply/$ParentCommentID//$ID/$OtherID' => 'reply',
|
'reply/$ParentCommentID//$ID/$OtherID' => 'reply',
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fields required for this form
|
* Fields required for this form
|
||||||
*
|
*
|
||||||
* @var array
|
* @var array
|
||||||
* @config
|
* @config
|
||||||
*/
|
*/
|
||||||
private static $required_fields = array(
|
private static $required_fields = array(
|
||||||
'Name',
|
'Name',
|
||||||
'Email',
|
'Email',
|
||||||
'Comment'
|
'Comment'
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base class this commenting form is for
|
* Base class this commenting form is for
|
||||||
*
|
*
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
private $baseClass = "";
|
private $baseClass = "";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The record this commenting form is for
|
* The record this commenting form is for
|
||||||
*
|
*
|
||||||
* @var DataObject
|
* @var DataObject
|
||||||
*/
|
*/
|
||||||
private $ownerRecord = null;
|
private $ownerRecord = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parent controller record
|
* Parent controller record
|
||||||
*
|
*
|
||||||
* @var Controller
|
* @var Controller
|
||||||
*/
|
*/
|
||||||
private $ownerController = null;
|
private $ownerController = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Backup url to return to
|
* Backup url to return to
|
||||||
*
|
*
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
protected $fallbackReturnURL = null;
|
protected $fallbackReturnURL = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the base class to use
|
* Set the base class to use
|
||||||
*
|
*
|
||||||
* @param string $class
|
* @param string $class
|
||||||
*/
|
*/
|
||||||
public function setBaseClass($class) {
|
public function setBaseClass($class)
|
||||||
$this->baseClass = $class;
|
{
|
||||||
}
|
$this->baseClass = $class;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the base class used
|
* Get the base class used
|
||||||
*
|
*
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function getBaseClass() {
|
public function getBaseClass()
|
||||||
return $this->baseClass;
|
{
|
||||||
}
|
return $this->baseClass;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the record this controller is working on
|
* Set the record this controller is working on
|
||||||
*
|
*
|
||||||
* @param DataObject $record
|
* @param DataObject $record
|
||||||
*/
|
*/
|
||||||
public function setOwnerRecord($record) {
|
public function setOwnerRecord($record)
|
||||||
$this->ownerRecord = $record;
|
{
|
||||||
}
|
$this->ownerRecord = $record;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the record
|
* Get the record
|
||||||
*
|
*
|
||||||
* @return DataObject
|
* @return DataObject
|
||||||
*/
|
*/
|
||||||
public function getOwnerRecord() {
|
public function getOwnerRecord()
|
||||||
return $this->ownerRecord;
|
{
|
||||||
}
|
return $this->ownerRecord;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the parent controller
|
* Set the parent controller
|
||||||
*
|
*
|
||||||
* @param Controller $controller
|
* @param Controller $controller
|
||||||
*/
|
*/
|
||||||
public function setOwnerController($controller) {
|
public function setOwnerController($controller)
|
||||||
$this->ownerController = $controller;
|
{
|
||||||
}
|
$this->ownerController = $controller;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the parent controller
|
* Get the parent controller
|
||||||
*
|
*
|
||||||
* @return Controller
|
* @return Controller
|
||||||
*/
|
*/
|
||||||
public function getOwnerController() {
|
public function getOwnerController()
|
||||||
return $this->ownerController;
|
{
|
||||||
}
|
return $this->ownerController;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the commenting option for the current state
|
* Get the commenting option for the current state
|
||||||
*
|
*
|
||||||
* @param string $key
|
* @param string $key
|
||||||
* @return mixed Result if the setting is available, or null otherwise
|
* @return mixed Result if the setting is available, or null otherwise
|
||||||
*/
|
*/
|
||||||
public function getOption($key) {
|
public function getOption($key)
|
||||||
// If possible use the current record
|
{
|
||||||
if($record = $this->getOwnerRecord()) {
|
// If possible use the current record
|
||||||
return $record->getCommentsOption($key);
|
if ($record = $this->getOwnerRecord()) {
|
||||||
}
|
return $record->getCommentsOption($key);
|
||||||
|
}
|
||||||
|
|
||||||
// Otherwise a singleton of that record
|
// Otherwise a singleton of that record
|
||||||
if($class = $this->getBaseClass()) {
|
if ($class = $this->getBaseClass()) {
|
||||||
return singleton($class)->getCommentsOption($key);
|
return singleton($class)->getCommentsOption($key);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise just use the default options
|
// Otherwise just use the default options
|
||||||
return singleton('CommentsExtension')->getCommentsOption($key);
|
return singleton('CommentsExtension')->getCommentsOption($key);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Workaround for generating the link to this controller
|
* Workaround for generating the link to this controller
|
||||||
*
|
*
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function Link($action = '', $id = '', $other = '') {
|
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
|
* @return HTMLText
|
||||||
*/
|
*/
|
||||||
public function rss() {
|
public function rss()
|
||||||
return $this->getFeed($this->request)->outputToBrowser();
|
{
|
||||||
}
|
return $this->getFeed($this->request)->outputToBrowser();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return an RSSFeed of comments for a given set of comments or all
|
* Return an RSSFeed of comments for a given set of comments or all
|
||||||
* comments on the website.
|
* comments on the website.
|
||||||
*
|
*
|
||||||
* To maintain backwards compatibility with 2.4 this supports mapping
|
* To maintain backwards compatibility with 2.4 this supports mapping
|
||||||
* of PageComment/rss?pageid= as well as the new RSS format for comments
|
* of PageComment/rss?pageid= as well as the new RSS format for comments
|
||||||
* of CommentingController/rss/{classname}/{id}
|
* of CommentingController/rss/{classname}/{id}
|
||||||
*
|
*
|
||||||
* @param SS_HTTPRequest
|
* @param SS_HTTPRequest
|
||||||
*
|
*
|
||||||
* @return RSSFeed
|
* @return RSSFeed
|
||||||
*/
|
*/
|
||||||
public function getFeed(SS_HTTPRequest $request) {
|
public function getFeed(SS_HTTPRequest $request)
|
||||||
$link = $this->Link('rss');
|
{
|
||||||
$class = $request->param('ID');
|
$link = $this->Link('rss');
|
||||||
$id = $request->param('OtherID');
|
$class = $request->param('ID');
|
||||||
|
$id = $request->param('OtherID');
|
||||||
|
|
||||||
// Support old pageid param
|
// Support old pageid param
|
||||||
if(!$id && !$class && ($id = $request->getVar('pageid'))) {
|
if (!$id && !$class && ($id = $request->getVar('pageid'))) {
|
||||||
$class = 'SiteTree';
|
$class = 'SiteTree';
|
||||||
}
|
}
|
||||||
|
|
||||||
$comments = Comment::get()->filter(array(
|
$comments = Comment::get()->filter(array(
|
||||||
'Moderated' => 1,
|
'Moderated' => 1,
|
||||||
'IsSpam' => 0,
|
'IsSpam' => 0,
|
||||||
));
|
));
|
||||||
|
|
||||||
// Check if class filter
|
// Check if class filter
|
||||||
if($class) {
|
if ($class) {
|
||||||
if(!is_subclass_of($class, 'DataObject') || !$class::has_extension('CommentsExtension')) {
|
if (!is_subclass_of($class, 'DataObject') || !$class::has_extension('CommentsExtension')) {
|
||||||
return $this->httpError(404);
|
return $this->httpError(404);
|
||||||
}
|
}
|
||||||
$this->setBaseClass($class);
|
$this->setBaseClass($class);
|
||||||
$comments = $comments->filter('BaseClass', $class);
|
$comments = $comments->filter('BaseClass', $class);
|
||||||
$link = Controller::join_links($link, $class);
|
$link = Controller::join_links($link, $class);
|
||||||
|
|
||||||
// Check if id filter
|
// Check if id filter
|
||||||
if($id) {
|
if ($id) {
|
||||||
$comments = $comments->filter('ParentID', $id);
|
$comments = $comments->filter('ParentID', $id);
|
||||||
$link = Controller::join_links($link, $id);
|
$link = Controller::join_links($link, $id);
|
||||||
$this->setOwnerRecord(DataObject::get_by_id($class, $id));
|
$this->setOwnerRecord(DataObject::get_by_id($class, $id));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$title = _t('CommentingController.RSSTITLE', "Comments RSS Feed");
|
$title = _t('CommentingController.RSSTITLE', "Comments RSS Feed");
|
||||||
|
|
||||||
$comments = new PaginatedList($comments, $request);
|
$comments = new PaginatedList($comments, $request);
|
||||||
$comments->setPageLength($this->getOption('comments_per_page'));
|
$comments->setPageLength($this->getOption('comments_per_page'));
|
||||||
|
|
||||||
return new RSSFeed(
|
return new RSSFeed(
|
||||||
$comments,
|
$comments,
|
||||||
$link,
|
$link,
|
||||||
$title,
|
$title,
|
||||||
$link,
|
$link,
|
||||||
'Title', 'EscapedComment', 'AuthorName'
|
'Title', 'EscapedComment', 'AuthorName'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deletes a given {@link Comment} via the URL.
|
* Deletes a given {@link Comment} via the URL.
|
||||||
*/
|
*/
|
||||||
public function delete() {
|
public function delete()
|
||||||
$comment = $this->getComment();
|
{
|
||||||
if(!$comment) return $this->httpError(404);
|
$comment = $this->getComment();
|
||||||
if(!$comment->canDelete()) {
|
if (!$comment) {
|
||||||
return Security::permissionFailure($this, 'You do not have permission to delete this comment');
|
return $this->httpError(404);
|
||||||
}
|
}
|
||||||
if(!$comment->getSecurityToken()->checkRequest($this->request)) return $this->httpError(400);
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
$comment->delete();
|
$comment->delete();
|
||||||
|
|
||||||
return $this->request->isAjax()
|
return $this->request->isAjax()
|
||||||
? true
|
? true
|
||||||
: $this->redirectBack();
|
: $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() {
|
public function spam()
|
||||||
$comment = $this->getComment();
|
{
|
||||||
if(!$comment) return $this->httpError(404);
|
$comment = $this->getComment();
|
||||||
if(!$comment->canEdit()) {
|
if (!$comment) {
|
||||||
return Security::permissionFailure($this, 'You do not have permission to edit this comment');
|
return $this->httpError(404);
|
||||||
}
|
}
|
||||||
if(!$comment->getSecurityToken()->checkRequest($this->request)) return $this->httpError(400);
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
$comment->markSpam();
|
$comment->markSpam();
|
||||||
return $this->renderChangedCommentState($comment);
|
return $this->renderChangedCommentState($comment);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Marks a given {@link Comment} as ham (not spam).
|
* Marks a given {@link Comment} as ham (not spam).
|
||||||
*/
|
*/
|
||||||
public function ham() {
|
public function ham()
|
||||||
$comment = $this->getComment();
|
{
|
||||||
if(!$comment) return $this->httpError(404);
|
$comment = $this->getComment();
|
||||||
if(!$comment->canEdit()) {
|
if (!$comment) {
|
||||||
return Security::permissionFailure($this, 'You do not have permission to edit this comment');
|
return $this->httpError(404);
|
||||||
}
|
}
|
||||||
if(!$comment->getSecurityToken()->checkRequest($this->request)) return $this->httpError(400);
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
$comment->markApproved();
|
$comment->markApproved();
|
||||||
return $this->renderChangedCommentState($comment);
|
return $this->renderChangedCommentState($comment);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Marks a given {@link Comment} as approved.
|
* Marks a given {@link Comment} as approved.
|
||||||
*/
|
*/
|
||||||
public function approve() {
|
public function approve()
|
||||||
$comment = $this->getComment();
|
{
|
||||||
if(!$comment) return $this->httpError(404);
|
$comment = $this->getComment();
|
||||||
if(!$comment->canEdit()) {
|
if (!$comment) {
|
||||||
return Security::permissionFailure($this, 'You do not have permission to approve this comment');
|
return $this->httpError(404);
|
||||||
}
|
}
|
||||||
if(!$comment->getSecurityToken()->checkRequest($this->request)) return $this->httpError(400);
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
$comment->markApproved();
|
$comment->markApproved();
|
||||||
return $this->renderChangedCommentState($comment);
|
return $this->renderChangedCommentState($comment);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Redirect back to referer if available, ensuring that only site URLs
|
* Redirect back to referer if available, ensuring that only site URLs
|
||||||
* are allowed to avoid phishing. If it's an AJAX request render the
|
* are allowed to avoid phishing. If it's an AJAX request render the
|
||||||
* comment in it's new state
|
* comment in it's new state
|
||||||
*/
|
*/
|
||||||
private function renderChangedCommentState($comment) {
|
private function renderChangedCommentState($comment)
|
||||||
|
{
|
||||||
$referer = $this->request->getHeader('Referer');
|
$referer = $this->request->getHeader('Referer');
|
||||||
|
|
||||||
// Render comment using AJAX
|
// Render comment using AJAX
|
||||||
@ -295,7 +327,7 @@ class CommentingController extends Controller {
|
|||||||
// Redirect to the comment, but check for phishing
|
// Redirect to the comment, but check for phishing
|
||||||
$url = $referer . '#comment-' . $comment->ID;
|
$url = $referer . '#comment-' . $comment->ID;
|
||||||
// absolute redirection URLs not located on this site may cause phishing
|
// absolute redirection URLs not located on this site may cause phishing
|
||||||
if(Director::is_site_url($url)) {
|
if (Director::is_site_url($url)) {
|
||||||
return $this->redirect($url);
|
return $this->redirect($url);
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
@ -304,336 +336,348 @@ class CommentingController extends Controller {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the comment referenced in the URL (by ID). Permission checking
|
* Returns the comment referenced in the URL (by ID). Permission checking
|
||||||
* should be done in the callee.
|
* should be done in the callee.
|
||||||
*
|
*
|
||||||
* @return Comment|false
|
* @return Comment|false
|
||||||
*/
|
*/
|
||||||
public function getComment() {
|
public function getComment()
|
||||||
$id = isset($this->urlParams['ID']) ? $this->urlParams['ID'] : false;
|
{
|
||||||
|
$id = isset($this->urlParams['ID']) ? $this->urlParams['ID'] : false;
|
||||||
|
|
||||||
if($id) {
|
if ($id) {
|
||||||
$comment = DataObject::get_by_id('Comment', $id);
|
$comment = DataObject::get_by_id('Comment', $id);
|
||||||
|
|
||||||
if($comment) {
|
if ($comment) {
|
||||||
$this->fallbackReturnURL = $comment->Link();
|
$this->fallbackReturnURL = $comment->Link();
|
||||||
return $comment;
|
return $comment;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a reply form for a specified comment
|
* Create a reply form for a specified comment
|
||||||
*
|
*
|
||||||
* @param Comment $comment
|
* @param Comment $comment
|
||||||
*/
|
*/
|
||||||
public function ReplyForm($comment) {
|
public function ReplyForm($comment)
|
||||||
// Enables multiple forms with different names to use the same handler
|
{
|
||||||
$form = $this->CommentsForm();
|
// Enables multiple forms with different names to use the same handler
|
||||||
$form->setName('ReplyForm_'.$comment->ID);
|
$form = $this->CommentsForm();
|
||||||
$form->addExtraClass('reply-form');
|
$form->setName('ReplyForm_'.$comment->ID);
|
||||||
|
$form->addExtraClass('reply-form');
|
||||||
|
|
||||||
// Load parent into reply form
|
// Load parent into reply form
|
||||||
$form->loadDataFrom(array(
|
$form->loadDataFrom(array(
|
||||||
'ParentCommentID' => $comment->ID
|
'ParentCommentID' => $comment->ID
|
||||||
));
|
));
|
||||||
|
|
||||||
// Customise action
|
// Customise action
|
||||||
$form->setFormAction($this->Link('reply', $comment->ID));
|
$form->setFormAction($this->Link('reply', $comment->ID));
|
||||||
|
|
||||||
$this->extend('updateReplyForm', $form);
|
$this->extend('updateReplyForm', $form);
|
||||||
return $form;
|
return $form;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Request handler for reply 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
|
* @param SS_HTTPRequest $request
|
||||||
*/
|
*/
|
||||||
public function reply(SS_HTTPRequest $request) {
|
public function reply(SS_HTTPRequest $request)
|
||||||
// Extract parent comment from reply and build this way
|
{
|
||||||
if($parentID = $request->param('ParentCommentID')) {
|
// Extract parent comment from reply and build this way
|
||||||
$comment = DataObject::get_by_id('Comment', $parentID, true);
|
if ($parentID = $request->param('ParentCommentID')) {
|
||||||
if($comment) {
|
$comment = DataObject::get_by_id('Comment', $parentID, true);
|
||||||
return $this->ReplyForm($comment);
|
if ($comment) {
|
||||||
}
|
return $this->ReplyForm($comment);
|
||||||
}
|
}
|
||||||
return $this->httpError(404);
|
}
|
||||||
}
|
return $this->httpError(404);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Post a comment form
|
* Post a comment form
|
||||||
*
|
*
|
||||||
* @return Form
|
* @return Form
|
||||||
*/
|
*/
|
||||||
public function CommentsForm() {
|
public function CommentsForm()
|
||||||
$usePreview = $this->getOption('use_preview');
|
{
|
||||||
|
$usePreview = $this->getOption('use_preview');
|
||||||
|
|
||||||
$nameRequired = _t('CommentInterface.YOURNAME_MESSAGE_REQUIRED', 'Please enter your name');
|
$nameRequired = _t('CommentInterface.YOURNAME_MESSAGE_REQUIRED', 'Please enter your name');
|
||||||
$emailRequired = _t('CommentInterface.EMAILADDRESS_MESSAGE_REQUIRED', 'Please enter your email address');
|
$emailRequired = _t('CommentInterface.EMAILADDRESS_MESSAGE_REQUIRED', 'Please enter your email address');
|
||||||
$emailInvalid = _t('CommentInterface.EMAILADDRESS_MESSAGE_EMAIL', 'Please enter a valid 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');
|
$urlInvalid = _t('CommentInterface.COMMENT_MESSAGE_URL', 'Please enter a valid URL');
|
||||||
$commentRequired = _t('CommentInterface.COMMENT_MESSAGE_REQUIRED', 'Please enter your comment');
|
$commentRequired = _t('CommentInterface.COMMENT_MESSAGE_REQUIRED', 'Please enter your comment');
|
||||||
|
|
||||||
$fields = new FieldList(
|
$fields = new FieldList(
|
||||||
$dataFields = new CompositeField(
|
$dataFields = new CompositeField(
|
||||||
// Name
|
// Name
|
||||||
TextField::create("Name", _t('CommentInterface.YOURNAME', 'Your name'))
|
TextField::create("Name", _t('CommentInterface.YOURNAME', 'Your name'))
|
||||||
->setCustomValidationMessage($nameRequired)
|
->setCustomValidationMessage($nameRequired)
|
||||||
->setAttribute('data-msg-required', $nameRequired),
|
->setAttribute('data-msg-required', $nameRequired),
|
||||||
|
|
||||||
// Email
|
// Email
|
||||||
EmailField::create(
|
EmailField::create(
|
||||||
"Email",
|
"Email",
|
||||||
_t('CommentingController.EMAILADDRESS', "Your email address (will not be published)")
|
_t('CommentingController.EMAILADDRESS', "Your email address (will not be published)")
|
||||||
)
|
)
|
||||||
->setCustomValidationMessage($emailRequired)
|
->setCustomValidationMessage($emailRequired)
|
||||||
->setAttribute('data-msg-required', $emailRequired)
|
->setAttribute('data-msg-required', $emailRequired)
|
||||||
->setAttribute('data-msg-email', $emailInvalid)
|
->setAttribute('data-msg-email', $emailInvalid)
|
||||||
->setAttribute('data-rule-email', true),
|
->setAttribute('data-rule-email', true),
|
||||||
|
|
||||||
// Url
|
// Url
|
||||||
TextField::create("URL", _t('CommentingController.WEBSITEURL', "Your website URL"))
|
TextField::create("URL", _t('CommentingController.WEBSITEURL', "Your website URL"))
|
||||||
->setAttribute('data-msg-url', $urlInvalid)
|
->setAttribute('data-msg-url', $urlInvalid)
|
||||||
->setAttribute('data-rule-url', true),
|
->setAttribute('data-rule-url', true),
|
||||||
|
|
||||||
// Comment
|
// Comment
|
||||||
TextareaField::create("Comment", _t('CommentingController.COMMENTS', "Comments"))
|
TextareaField::create("Comment", _t('CommentingController.COMMENTS', "Comments"))
|
||||||
->setCustomValidationMessage($commentRequired)
|
->setCustomValidationMessage($commentRequired)
|
||||||
->setAttribute('data-msg-required', $commentRequired)
|
->setAttribute('data-msg-required', $commentRequired)
|
||||||
),
|
),
|
||||||
HiddenField::create("ParentID"),
|
HiddenField::create("ParentID"),
|
||||||
HiddenField::create("ReturnURL"),
|
HiddenField::create("ReturnURL"),
|
||||||
HiddenField::create("ParentCommentID"),
|
HiddenField::create("ParentCommentID"),
|
||||||
HiddenField::create("BaseClass")
|
HiddenField::create("BaseClass")
|
||||||
);
|
);
|
||||||
|
|
||||||
// Preview formatted comment. Makes most sense when shortcodes or
|
// Preview formatted comment. Makes most sense when shortcodes or
|
||||||
// limited HTML is allowed. Populated by JS/Ajax.
|
// limited HTML is allowed. Populated by JS/Ajax.
|
||||||
if($usePreview) {
|
if ($usePreview) {
|
||||||
$fields->insertAfter(
|
$fields->insertAfter(
|
||||||
ReadonlyField::create('PreviewComment', _t('CommentInterface.PREVIEWLABEL', 'Preview'))
|
ReadonlyField::create('PreviewComment', _t('CommentInterface.PREVIEWLABEL', 'Preview'))
|
||||||
->setAttribute('style', 'display: none'), // enable through JS
|
->setAttribute('style', 'display: none'), // enable through JS
|
||||||
'Comment'
|
'Comment'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
$dataFields->addExtraClass('data-fields');
|
$dataFields->addExtraClass('data-fields');
|
||||||
|
|
||||||
// save actions
|
// save actions
|
||||||
$actions = new FieldList(
|
$actions = new FieldList(
|
||||||
new FormAction("doPostComment", _t('CommentInterface.POST', 'Post'))
|
new FormAction("doPostComment", _t('CommentInterface.POST', 'Post'))
|
||||||
);
|
);
|
||||||
if($usePreview) {
|
if ($usePreview) {
|
||||||
$actions->push(
|
$actions->push(
|
||||||
FormAction::create('doPreviewComment', _t('CommentInterface.PREVIEW', 'Preview'))
|
FormAction::create('doPreviewComment', _t('CommentInterface.PREVIEW', 'Preview'))
|
||||||
->addExtraClass('action-minor')
|
->addExtraClass('action-minor')
|
||||||
->setAttribute('style', 'display: none') // enable through JS
|
->setAttribute('style', 'display: none') // enable through JS
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// required fields for server side
|
// required fields for server side
|
||||||
$required = new RequiredFields($this->config()->required_fields);
|
$required = new RequiredFields($this->config()->required_fields);
|
||||||
|
|
||||||
// create the comment form
|
// 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 the record exists load the extra required data
|
||||||
if($record = $this->getOwnerRecord()) {
|
if ($record = $this->getOwnerRecord()) {
|
||||||
|
|
||||||
// Load member data
|
// Load member data
|
||||||
$member = Member::currentUser();
|
$member = Member::currentUser();
|
||||||
if(($record->CommentsRequireLogin || $record->PostingRequiredPermission) && $member) {
|
if (($record->CommentsRequireLogin || $record->PostingRequiredPermission) && $member) {
|
||||||
$fields = $form->Fields();
|
$fields = $form->Fields();
|
||||||
|
|
||||||
$fields->removeByName('Name');
|
$fields->removeByName('Name');
|
||||||
$fields->removeByName('Email');
|
$fields->removeByName('Email');
|
||||||
$fields->insertBefore(new ReadonlyField("NameView", _t('CommentInterface.YOURNAME', 'Your name'), $member->getName()), 'URL');
|
$fields->insertBefore(new ReadonlyField("NameView", _t('CommentInterface.YOURNAME', 'Your name'), $member->getName()), 'URL');
|
||||||
$fields->push(new HiddenField("Name", "", $member->getName()));
|
$fields->push(new HiddenField("Name", "", $member->getName()));
|
||||||
$fields->push(new HiddenField("Email", "", $member->Email));
|
$fields->push(new HiddenField("Email", "", $member->Email));
|
||||||
}
|
}
|
||||||
|
|
||||||
// we do not want to read a new URL when the form has already been submitted
|
// we do not want to read a new URL when the form has already been submitted
|
||||||
// which in here, it hasn't been.
|
// which in here, it hasn't been.
|
||||||
$form->loadDataFrom(array(
|
$form->loadDataFrom(array(
|
||||||
'ParentID' => $record->ID,
|
'ParentID' => $record->ID,
|
||||||
'ReturnURL' => $this->request->getURL(),
|
'ReturnURL' => $this->request->getURL(),
|
||||||
'BaseClass' => $this->getBaseClass()
|
'BaseClass' => $this->getBaseClass()
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set it so the user gets redirected back down to the form upon form fail
|
// Set it so the user gets redirected back down to the form upon form fail
|
||||||
$form->setRedirectToFormOnValidationError(true);
|
$form->setRedirectToFormOnValidationError(true);
|
||||||
|
|
||||||
// load any data from the cookies
|
// load any data from the cookies
|
||||||
if($data = Cookie::get('CommentsForm_UserData')) {
|
if ($data = Cookie::get('CommentsForm_UserData')) {
|
||||||
$data = Convert::json2array($data);
|
$data = Convert::json2array($data);
|
||||||
|
|
||||||
$form->loadDataFrom(array(
|
$form->loadDataFrom(array(
|
||||||
"Name" => isset($data['Name']) ? $data['Name'] : '',
|
"Name" => isset($data['Name']) ? $data['Name'] : '',
|
||||||
"URL" => isset($data['URL']) ? $data['URL'] : '',
|
"URL" => isset($data['URL']) ? $data['URL'] : '',
|
||||||
"Email" => isset($data['Email']) ? $data['Email'] : ''
|
"Email" => isset($data['Email']) ? $data['Email'] : ''
|
||||||
));
|
));
|
||||||
// allow previous value to fill if comment not stored in cookie (i.e. validation error)
|
// allow previous value to fill if comment not stored in cookie (i.e. validation error)
|
||||||
$prevComment = Cookie::get('CommentsForm_Comment');
|
$prevComment = Cookie::get('CommentsForm_Comment');
|
||||||
if($prevComment && $prevComment != ''){
|
if ($prevComment && $prevComment != '') {
|
||||||
$form->loadDataFrom(array("Comment" => $prevComment));
|
$form->loadDataFrom(array("Comment" => $prevComment));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!empty($member)) {
|
if (!empty($member)) {
|
||||||
$form->loadDataFrom($member);
|
$form->loadDataFrom($member);
|
||||||
}
|
}
|
||||||
|
|
||||||
// hook to allow further extensions to alter the comments form
|
// hook to allow further extensions to alter the comments form
|
||||||
$this->extend('alterCommentForm', $form);
|
$this->extend('alterCommentForm', $form);
|
||||||
|
|
||||||
return $form;
|
return $form;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Process which creates a {@link Comment} once a user submits a comment from this 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
|
* @param Form $form
|
||||||
*/
|
*/
|
||||||
public function doPostComment($data, $form) {
|
public function doPostComment($data, $form)
|
||||||
// Load class and parent from data
|
{
|
||||||
if(isset($data['BaseClass'])) {
|
// Load class and parent from data
|
||||||
$this->setBaseClass($data['BaseClass']);
|
if (isset($data['BaseClass'])) {
|
||||||
}
|
$this->setBaseClass($data['BaseClass']);
|
||||||
if(isset($data['ParentID']) && ($class = $this->getBaseClass())) {
|
}
|
||||||
$this->setOwnerRecord($class::get()->byID($data['ParentID']));
|
if (isset($data['ParentID']) && ($class = $this->getBaseClass())) {
|
||||||
}
|
$this->setOwnerRecord($class::get()->byID($data['ParentID']));
|
||||||
if(!$this->getOwnerRecord()) return $this->httpError(404);
|
}
|
||||||
|
if (!$this->getOwnerRecord()) {
|
||||||
|
return $this->httpError(404);
|
||||||
|
}
|
||||||
|
|
||||||
// cache users data
|
// cache users data
|
||||||
Cookie::set("CommentsForm_UserData", Convert::raw2json($data));
|
Cookie::set("CommentsForm_UserData", Convert::raw2json($data));
|
||||||
Cookie::set("CommentsForm_Comment", $data['Comment']);
|
Cookie::set("CommentsForm_Comment", $data['Comment']);
|
||||||
|
|
||||||
// extend hook to allow extensions. Also see onAfterPostComment
|
// extend hook to allow extensions. Also see onAfterPostComment
|
||||||
$this->extend('onBeforePostComment', $form);
|
$this->extend('onBeforePostComment', $form);
|
||||||
|
|
||||||
// If commenting can only be done by logged in users, make sure the user is logged in
|
// If commenting can only be done by logged in users, make sure the user is logged in
|
||||||
if(!$this->getOwnerRecord()->canPostComment()) {
|
if (!$this->getOwnerRecord()->canPostComment()) {
|
||||||
return Security::permissionFailure(
|
return Security::permissionFailure(
|
||||||
$this,
|
$this,
|
||||||
_t(
|
_t(
|
||||||
'CommentingController.PERMISSIONFAILURE',
|
'CommentingController.PERMISSIONFAILURE',
|
||||||
"You're not able to post comments to this page. Please ensure you are logged in and have an "
|
"You're not able to post comments to this page. Please ensure you are logged in and have an "
|
||||||
. "appropriate permission level."
|
. "appropriate permission level."
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if($member = Member::currentUser()) {
|
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?
|
// What kind of moderation is required?
|
||||||
switch($this->getOwnerRecord()->ModerationRequired) {
|
switch ($this->getOwnerRecord()->ModerationRequired) {
|
||||||
case 'Required':
|
case 'Required':
|
||||||
$requireModeration = true;
|
$requireModeration = true;
|
||||||
break;
|
break;
|
||||||
case 'NonMembersOnly':
|
case 'NonMembersOnly':
|
||||||
$requireModeration = empty($member);
|
$requireModeration = empty($member);
|
||||||
break;
|
break;
|
||||||
case 'None':
|
case 'None':
|
||||||
default:
|
default:
|
||||||
$requireModeration = false;
|
$requireModeration = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
$comment = new Comment();
|
$comment = new Comment();
|
||||||
$form->saveInto($comment);
|
$form->saveInto($comment);
|
||||||
|
|
||||||
$comment->AllowHtml = $this->getOption('html_allowed');
|
$comment->AllowHtml = $this->getOption('html_allowed');
|
||||||
$comment->Moderated = !$requireModeration;
|
$comment->Moderated = !$requireModeration;
|
||||||
|
|
||||||
// Save into DB, or call pre-save hooks to give accurate preview
|
// Save into DB, or call pre-save hooks to give accurate preview
|
||||||
$usePreview = $this->getOption('use_preview');
|
$usePreview = $this->getOption('use_preview');
|
||||||
$isPreview = $usePreview && !empty($data['IsPreview']);
|
$isPreview = $usePreview && !empty($data['IsPreview']);
|
||||||
if($isPreview) {
|
if ($isPreview) {
|
||||||
$comment->extend('onBeforeWrite');
|
$comment->extend('onBeforeWrite');
|
||||||
} else {
|
} else {
|
||||||
$comment->write();
|
$comment->write();
|
||||||
|
|
||||||
// extend hook to allow extensions. Also see onBeforePostComment
|
// extend hook to allow extensions. Also see onBeforePostComment
|
||||||
$this->extend('onAfterPostComment', $comment);
|
$this->extend('onAfterPostComment', $comment);
|
||||||
}
|
}
|
||||||
|
|
||||||
// we want to show a notification if comments are moderated
|
// we want to show a notification if comments are moderated
|
||||||
if ($requireModeration && !$comment->IsSpam) {
|
if ($requireModeration && !$comment->IsSpam) {
|
||||||
Session::set('CommentsModerated', 1);
|
Session::set('CommentsModerated', 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// clear the users comment since it passed validation
|
// clear the users comment since it passed validation
|
||||||
Cookie::set('CommentsForm_Comment', false);
|
Cookie::set('CommentsForm_Comment', false);
|
||||||
|
|
||||||
// Find parent link
|
// Find parent link
|
||||||
if(!empty($data['ReturnURL'])) {
|
if (!empty($data['ReturnURL'])) {
|
||||||
$url = $data['ReturnURL'];
|
$url = $data['ReturnURL'];
|
||||||
} elseif($parent = $comment->getParent()) {
|
} elseif ($parent = $comment->getParent()) {
|
||||||
$url = $parent->Link();
|
$url = $parent->Link();
|
||||||
} else {
|
} else {
|
||||||
return $this->redirectBack();
|
return $this->redirectBack();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Given a redirect page exists, attempt to link to the correct anchor
|
// Given a redirect page exists, attempt to link to the correct anchor
|
||||||
if($comment->IsSpam) {
|
if ($comment->IsSpam) {
|
||||||
// Link to the form with the error message contained
|
// Link to the form with the error message contained
|
||||||
$hash = $form->FormName();
|
$hash = $form->FormName();
|
||||||
} else if(!$comment->Moderated) {
|
} elseif (!$comment->Moderated) {
|
||||||
// Display the "awaiting moderation" text
|
// Display the "awaiting moderation" text
|
||||||
$holder = $this->getOption('comments_holder_id');
|
$holder = $this->getOption('comments_holder_id');
|
||||||
$hash = "{$holder}_PostCommentForm_error";
|
$hash = "{$holder}_PostCommentForm_error";
|
||||||
} else {
|
} else {
|
||||||
// Link to the moderated, non-spam comment
|
// Link to the moderated, non-spam comment
|
||||||
$hash = $comment->Permalink();
|
$hash = $comment->Permalink();
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->redirect(Controller::join_links($url, "#{$hash}"));
|
return $this->redirect(Controller::join_links($url, "#{$hash}"));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function doPreviewComment($data, $form) {
|
public function doPreviewComment($data, $form)
|
||||||
$data['IsPreview'] = 1;
|
{
|
||||||
|
$data['IsPreview'] = 1;
|
||||||
|
|
||||||
return $this->doPostComment($data, $form);
|
return $this->doPostComment($data, $form);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function redirectBack() {
|
public function redirectBack()
|
||||||
// Don't cache the redirect back ever
|
{
|
||||||
HTTP::set_cache_age(0);
|
// Don't cache the redirect back ever
|
||||||
|
HTTP::set_cache_age(0);
|
||||||
|
|
||||||
$url = null;
|
$url = null;
|
||||||
|
|
||||||
// In edge-cases, this will be called outside of a handleRequest() context; in that case,
|
// 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
|
// 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
|
// be calling from a test context or something else where the global state is inappropraite
|
||||||
if($this->request) {
|
if ($this->request) {
|
||||||
if($this->request->requestVar('BackURL')) {
|
if ($this->request->requestVar('BackURL')) {
|
||||||
$url = $this->request->requestVar('BackURL');
|
$url = $this->request->requestVar('BackURL');
|
||||||
} else if($this->request->isAjax() && $this->request->getHeader('X-Backurl')) {
|
} elseif ($this->request->isAjax() && $this->request->getHeader('X-Backurl')) {
|
||||||
$url = $this->request->getHeader('X-Backurl');
|
$url = $this->request->getHeader('X-Backurl');
|
||||||
} else if($this->request->getHeader('Referer')) {
|
} elseif ($this->request->getHeader('Referer')) {
|
||||||
$url = $this->request->getHeader('Referer');
|
$url = $this->request->getHeader('Referer');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!$url) $url = $this->fallbackReturnURL;
|
if (!$url) {
|
||||||
if(!$url) $url = Director::baseURL();
|
$url = $this->fallbackReturnURL;
|
||||||
|
}
|
||||||
|
if (!$url) {
|
||||||
|
$url = Director::baseURL();
|
||||||
|
}
|
||||||
|
|
||||||
// absolute redirection URLs not located on this site may cause phishing
|
// absolute redirection URLs not located on this site may cause phishing
|
||||||
if(Director::is_site_url($url)) {
|
if (Director::is_site_url($url)) {
|
||||||
return $this->redirect($url);
|
return $this->redirect($url);
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -5,558 +5,600 @@
|
|||||||
*
|
*
|
||||||
* @package comments
|
* @package comments
|
||||||
*/
|
*/
|
||||||
class CommentsExtension extends DataExtension {
|
class CommentsExtension extends DataExtension
|
||||||
/**
|
{
|
||||||
* Default configuration values
|
/**
|
||||||
*
|
* Default configuration values
|
||||||
* enabled: Allows commenting to be disabled even if the extension is present
|
*
|
||||||
* enabled_cms: Allows commenting to be enabled or disabled via the CMS
|
* enabled: Allows commenting to be disabled even if the extension is present
|
||||||
* require_login: Boolean, whether a user needs to login (required for required_permission)
|
* enabled_cms: Allows commenting to be enabled or disabled via the CMS
|
||||||
* require_login_cms: Allows require_login to be set via the CMS
|
* require_login: Boolean, whether a user needs to login (required for required_permission)
|
||||||
* required_permission: Permission (or array of permissions) required to comment
|
* require_login_cms: Allows require_login to be set via the CMS
|
||||||
* include_js: Enhance operation by ajax behaviour on moderation links (required for use_preview)
|
* required_permission: Permission (or array of permissions) required to comment
|
||||||
* use_gravatar: Set to true to show gravatar icons
|
* include_js: Enhance operation by ajax behaviour on moderation links (required for use_preview)
|
||||||
* gravatar_default: Theme for 'not found' gravatar {@see http://gravatar.com/site/implement/images}
|
* use_gravatar: Set to true to show gravatar icons
|
||||||
* gravatar_rating: Gravatar rating (same as the standard default)
|
* gravatar_default: Theme for 'not found' gravatar {@see http://gravatar.com/site/implement/images}
|
||||||
* show_comments_when_disabled: Show older comments when commenting has been disabled.
|
* gravatar_rating: Gravatar rating (same as the standard default)
|
||||||
* order_comments_by: Default sort order.
|
* show_comments_when_disabled: Show older comments when commenting has been disabled.
|
||||||
* order_replies_by: Sort order for replies.
|
* order_comments_by: Default sort order.
|
||||||
* comments_holder_id: ID for the comments holder
|
* order_replies_by: Sort order for replies.
|
||||||
* comment_permalink_prefix: ID prefix for each comment
|
* comments_holder_id: ID for the comments holder
|
||||||
* require_moderation: Require moderation for all comments
|
* comment_permalink_prefix: ID prefix for each comment
|
||||||
* require_moderation_cms: Ignore other comment moderation config settings and set via CMS
|
* require_moderation: Require moderation for all comments
|
||||||
* frontend_moderation: Display unmoderated comments in the frontend, if the user can moderate them.
|
* require_moderation_cms: Ignore other comment moderation config settings and set via CMS
|
||||||
* frontend_spam: Display spam comments in the frontend, if the user can moderate them.
|
* frontend_moderation: Display unmoderated comments in the frontend, if the user can moderate them.
|
||||||
* html_allowed: Allow for sanitized HTML in comments
|
* frontend_spam: Display spam comments in the frontend, if the user can moderate them.
|
||||||
* use_preview: Preview formatted comment (when allowing HTML)
|
* html_allowed: Allow for sanitized HTML in comments
|
||||||
* nested_comments: Enable nested comments
|
* use_preview: Preview formatted comment (when allowing HTML)
|
||||||
* nested_depth: Max depth of nested comments in levels (where root is 1 depth) 0 means no limit.
|
* 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
|
*
|
||||||
*
|
* @var array
|
||||||
* @config
|
*
|
||||||
*/
|
* @config
|
||||||
private static $comments = array(
|
*/
|
||||||
'enabled' => true,
|
private static $comments = array(
|
||||||
'enabled_cms' => false,
|
'enabled' => true,
|
||||||
'require_login' => false,
|
'enabled_cms' => false,
|
||||||
'require_login_cms' => false,
|
'require_login' => false,
|
||||||
'required_permission' => false,
|
'require_login_cms' => false,
|
||||||
'include_js' => true,
|
'required_permission' => false,
|
||||||
'use_gravatar' => false,
|
'include_js' => true,
|
||||||
'gravatar_size' => 80,
|
'use_gravatar' => false,
|
||||||
'gravatar_default' => 'identicon',
|
'gravatar_size' => 80,
|
||||||
'gravatar_rating' => 'g',
|
'gravatar_default' => 'identicon',
|
||||||
'show_comments_when_disabled' => false,
|
'gravatar_rating' => 'g',
|
||||||
'order_comments_by' => '"Created" DESC',
|
'show_comments_when_disabled' => false,
|
||||||
'order_replies_by' => false,
|
'order_comments_by' => '"Created" DESC',
|
||||||
'comments_per_page' => 10,
|
'order_replies_by' => false,
|
||||||
'comments_holder_id' => 'comments-holder',
|
'comments_per_page' => 10,
|
||||||
'comment_permalink_prefix' => 'comment-',
|
'comments_holder_id' => 'comments-holder',
|
||||||
'require_moderation' => false,
|
'comment_permalink_prefix' => 'comment-',
|
||||||
'require_moderation_nonmembers' => false,
|
'require_moderation' => false,
|
||||||
'require_moderation_cms' => false,
|
'require_moderation_nonmembers' => false,
|
||||||
'frontend_moderation' => false,
|
'require_moderation_cms' => false,
|
||||||
'frontend_spam' => false,
|
'frontend_moderation' => false,
|
||||||
'html_allowed' => false,
|
'frontend_spam' => false,
|
||||||
'html_allowed_elements' => array('a', 'img', 'i', 'b'),
|
'html_allowed' => false,
|
||||||
'use_preview' => false,
|
'html_allowed_elements' => array('a', 'img', 'i', 'b'),
|
||||||
'nested_comments' => false,
|
'use_preview' => false,
|
||||||
'nested_depth' => 2,
|
'nested_comments' => false,
|
||||||
);
|
'nested_depth' => 2,
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var array
|
* @var array
|
||||||
*/
|
*/
|
||||||
private static $db = array(
|
private static $db = array(
|
||||||
'ProvideComments' => 'Boolean',
|
'ProvideComments' => 'Boolean',
|
||||||
'ModerationRequired' => 'Enum(\'None,Required,NonMembersOnly\',\'None\')',
|
'ModerationRequired' => 'Enum(\'None,Required,NonMembersOnly\',\'None\')',
|
||||||
'CommentsRequireLogin' => 'Boolean',
|
'CommentsRequireLogin' => 'Boolean',
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* CMS configurable options should default to the config values, but respect
|
* CMS configurable options should default to the config values, but respect
|
||||||
* default values specified by the object
|
* default values specified by the object
|
||||||
*/
|
*/
|
||||||
public function populateDefaults() {
|
public function populateDefaults()
|
||||||
$defaults = $this->owner->config()->defaults;
|
{
|
||||||
|
$defaults = $this->owner->config()->defaults;
|
||||||
|
|
||||||
// Set if comments should be enabled by default
|
// Set if comments should be enabled by default
|
||||||
if(isset($defaults['ProvideComments'])) {
|
if (isset($defaults['ProvideComments'])) {
|
||||||
$this->owner->ProvideComments = $defaults['ProvideComments'];
|
$this->owner->ProvideComments = $defaults['ProvideComments'];
|
||||||
} else {
|
} else {
|
||||||
$this->owner->ProvideComments = $this->owner->getCommentsOption('enabled') ? 1 : 0;
|
$this->owner->ProvideComments = $this->owner->getCommentsOption('enabled') ? 1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If moderation options should be configurable via the CMS then
|
// If moderation options should be configurable via the CMS then
|
||||||
if(isset($defaults['ModerationRequired'])) {
|
if (isset($defaults['ModerationRequired'])) {
|
||||||
$this->owner->ModerationRequired = $defaults['ModerationRequired'];
|
$this->owner->ModerationRequired = $defaults['ModerationRequired'];
|
||||||
} elseif($this->owner->getCommentsOption('require_moderation')) {
|
} elseif ($this->owner->getCommentsOption('require_moderation')) {
|
||||||
$this->owner->ModerationRequired = 'Required';
|
$this->owner->ModerationRequired = 'Required';
|
||||||
} elseif($this->owner->getCommentsOption('require_moderation_nonmembers')) {
|
} elseif ($this->owner->getCommentsOption('require_moderation_nonmembers')) {
|
||||||
$this->owner->ModerationRequired = 'NonMembersOnly';
|
$this->owner->ModerationRequired = 'NonMembersOnly';
|
||||||
} else {
|
} else {
|
||||||
$this->owner->ModerationRequired = 'None';
|
$this->owner->ModerationRequired = 'None';
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set login required
|
// Set login required
|
||||||
if(isset($defaults['CommentsRequireLogin'])) {
|
if (isset($defaults['CommentsRequireLogin'])) {
|
||||||
$this->owner->CommentsRequireLogin = $defaults['CommentsRequireLogin'];
|
$this->owner->CommentsRequireLogin = $defaults['CommentsRequireLogin'];
|
||||||
} else {
|
} else {
|
||||||
$this->owner->CommentsRequireLogin = $this->owner->getCommentsOption('require_login') ? 1 : 0;
|
$this->owner->CommentsRequireLogin = $this->owner->getCommentsOption('require_login') ? 1 : 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If this extension is applied to a {@link SiteTree} record then
|
* If this extension is applied to a {@link SiteTree} record then
|
||||||
* append a Provide Comments checkbox to allow authors to trigger
|
* append a Provide Comments checkbox to allow authors to trigger
|
||||||
* whether or not to display comments
|
* whether or not to display comments
|
||||||
*
|
*
|
||||||
* @todo Allow customization of other {@link Commenting} configuration
|
* @todo Allow customization of other {@link Commenting} configuration
|
||||||
*
|
*
|
||||||
* @param FieldList $fields
|
* @param FieldList $fields
|
||||||
*/
|
*/
|
||||||
public function updateSettingsFields(FieldList $fields) {
|
public function updateSettingsFields(FieldList $fields)
|
||||||
|
{
|
||||||
|
$options = FieldGroup::create()->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')));
|
||||||
|
}
|
||||||
|
|
||||||
// Check if enabled setting should be cms configurable
|
// Check if we should require users to login to comment
|
||||||
if($this->owner->getCommentsOption('enabled_cms')) {
|
if ($this->owner->getCommentsOption('require_login_cms')) {
|
||||||
$options->push(new CheckboxField('ProvideComments', _t('Comment.ALLOWCOMMENTS', 'Allow Comments')));
|
$options->push(
|
||||||
}
|
new CheckboxField(
|
||||||
|
'CommentsRequireLogin',
|
||||||
|
_t('Comments.COMMENTSREQUIRELOGIN', 'Require login to comment')
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// Check if we should require users to login to comment
|
if ($options->FieldList()->count()) {
|
||||||
if($this->owner->getCommentsOption('require_login_cms')) {
|
if ($fields->hasTabSet()) {
|
||||||
$options->push(
|
$fields->addFieldsToTab('Root.Settings', $options);
|
||||||
new CheckboxField(
|
} else {
|
||||||
'CommentsRequireLogin',
|
$fields->push($options);
|
||||||
_t('Comments.COMMENTSREQUIRELOGIN', 'Require login to comment')
|
}
|
||||||
)
|
}
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if($options->FieldList()->count()) {
|
// Check if moderation should be enabled via cms configurable
|
||||||
if($fields->hasTabSet()) {
|
if ($this->owner->getCommentsOption('require_moderation_cms')) {
|
||||||
$fields->addFieldsToTab('Root.Settings', $options);
|
$moderationField = new DropdownField('ModerationRequired', 'Comment Moderation', array(
|
||||||
} else {
|
'None' => _t('CommentsExtension.MODERATIONREQUIRED_NONE', 'No moderation required'),
|
||||||
$fields->push($options);
|
'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 {
|
||||||
|
$fields->push($moderationField);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Check if moderation should be enabled via cms configurable
|
/**
|
||||||
if($this->owner->getCommentsOption('require_moderation_cms')) {
|
* Get comment moderation rules for this parent
|
||||||
$moderationField = new DropdownField('ModerationRequired', 'Comment Moderation', array(
|
*
|
||||||
'None' => _t('CommentsExtension.MODERATIONREQUIRED_NONE', 'No moderation required'),
|
* None: No moderation required
|
||||||
'Required' => _t('CommentsExtension.MODERATIONREQUIRED_REQUIRED', 'Moderate all comments'),
|
* Required: All comments
|
||||||
'NonMembersOnly' => _t(
|
* NonMembersOnly: Only anonymous users
|
||||||
'CommentsExtension.MODERATIONREQUIRED_NONMEMBERSONLY',
|
*
|
||||||
'Only moderate non-members'
|
* @return string
|
||||||
),
|
*/
|
||||||
));
|
public function getModerationRequired()
|
||||||
if($fields->hasTabSet()) {
|
{
|
||||||
$fields->addFieldsToTab('Root.Settings', $moderationField);
|
if ($this->owner->getCommentsOption('require_moderation_cms')) {
|
||||||
} else {
|
return $this->owner->getField('ModerationRequired');
|
||||||
$fields->push($moderationField);
|
} elseif ($this->owner->getCommentsOption('require_moderation')) {
|
||||||
}
|
return 'Required';
|
||||||
}
|
} elseif ($this->owner->getCommentsOption('require_moderation_nonmembers')) {
|
||||||
}
|
return 'NonMembersOnly';
|
||||||
|
} else {
|
||||||
|
return 'None';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get comment moderation rules for this parent
|
* Determine if users must be logged in to post comments
|
||||||
*
|
*
|
||||||
* None: No moderation required
|
* @return boolean
|
||||||
* Required: All comments
|
*/
|
||||||
* NonMembersOnly: Only anonymous users
|
public function getCommentsRequireLogin()
|
||||||
*
|
{
|
||||||
* @return string
|
if ($this->owner->getCommentsOption('require_login_cms')) {
|
||||||
*/
|
return (bool) $this->owner->getField('CommentsRequireLogin');
|
||||||
public function getModerationRequired() {
|
} else {
|
||||||
if($this->owner->getCommentsOption('require_moderation_cms')) {
|
return (bool) $this->owner->getCommentsOption('require_login');
|
||||||
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';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determine if users must be logged in to post comments
|
* Returns the RelationList of all comments against this object. Can be used as a data source
|
||||||
*
|
* for a gridfield with write access.
|
||||||
* @return boolean
|
*
|
||||||
*/
|
* @return CommentList
|
||||||
public function getCommentsRequireLogin() {
|
*/
|
||||||
if($this->owner->getCommentsOption('require_login_cms')) {
|
public function AllComments()
|
||||||
return (bool) $this->owner->getField('CommentsRequireLogin');
|
{
|
||||||
} else {
|
$order = $this->owner->getCommentsOption('order_comments_by');
|
||||||
return (bool) $this->owner->getCommentsOption('require_login');
|
$comments = CommentList::create($this->ownerBaseClass)
|
||||||
}
|
->forForeignID($this->owner->ID)
|
||||||
}
|
->sort($order);
|
||||||
|
$this->owner->extend('updateAllComments', $comments);
|
||||||
|
return $comments;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the RelationList of all comments against this object. Can be used as a data source
|
* Returns all comments against this object, with with spam and unmoderated items excluded, for use in the frontend
|
||||||
* for a gridfield with write access.
|
*
|
||||||
*
|
* @return CommentList
|
||||||
* @return CommentList
|
*/
|
||||||
*/
|
public function AllVisibleComments()
|
||||||
public function AllComments() {
|
{
|
||||||
$order = $this->owner->getCommentsOption('order_comments_by');
|
$list = $this->AllComments();
|
||||||
$comments = CommentList::create($this->ownerBaseClass)
|
|
||||||
->forForeignID($this->owner->ID)
|
|
||||||
->sort($order);
|
|
||||||
$this->owner->extend('updateAllComments', $comments);
|
|
||||||
return $comments;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
// Filter spam comments for non-administrators if configured
|
||||||
* Returns all comments against this object, with with spam and unmoderated items excluded, for use in the frontend
|
$showSpam = $this->owner->getCommentsOption('frontend_spam') && $this->owner->canModerateComments();
|
||||||
*
|
if (!$showSpam) {
|
||||||
* @return CommentList
|
$list = $list->filter('IsSpam', 0);
|
||||||
*/
|
}
|
||||||
public function AllVisibleComments() {
|
|
||||||
$list = $this->AllComments();
|
|
||||||
|
|
||||||
// Filter spam comments for non-administrators if configured
|
// Filter un-moderated comments for non-administrators if moderation is enabled
|
||||||
$showSpam = $this->owner->getCommentsOption('frontend_spam') && $this->owner->canModerateComments();
|
$showUnmoderated = ($this->owner->ModerationRequired === 'None')
|
||||||
if(!$showSpam) {
|
|| ($this->owner->getCommentsOption('frontend_moderation') && $this->owner->canModerateComments());
|
||||||
$list = $list->filter('IsSpam', 0);
|
if (!$showUnmoderated) {
|
||||||
}
|
$list = $list->filter('Moderated', 1);
|
||||||
|
}
|
||||||
|
|
||||||
// Filter un-moderated comments for non-administrators if moderation is enabled
|
$this->owner->extend('updateAllVisibleComments', $list);
|
||||||
$showUnmoderated = ($this->owner->ModerationRequired === 'None')
|
return $list;
|
||||||
|| ($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
|
||||||
}
|
*
|
||||||
|
* @return CommentList
|
||||||
|
*/
|
||||||
|
public function Comments()
|
||||||
|
{
|
||||||
|
$list = $this->AllVisibleComments();
|
||||||
|
|
||||||
/**
|
// If nesting comments, only show root level
|
||||||
* Returns the root level comments, with spam and unmoderated items excluded, for use in the frontend
|
if ($this->owner->getCommentsOption('nested_comments')) {
|
||||||
*
|
$list = $list->filter('ParentCommentID', 0);
|
||||||
* @return CommentList
|
}
|
||||||
*/
|
|
||||||
public function Comments() {
|
|
||||||
$list = $this->AllVisibleComments();
|
|
||||||
|
|
||||||
// If nesting comments, only show root level
|
$this->owner->extend('updateComments', $list);
|
||||||
if($this->owner->getCommentsOption('nested_comments')) {
|
return $list;
|
||||||
$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
|
||||||
|
*
|
||||||
|
* @return PaginatedList
|
||||||
|
*/
|
||||||
|
public function PagedComments()
|
||||||
|
{
|
||||||
|
$list = $this->Comments();
|
||||||
|
|
||||||
/**
|
// Add pagination
|
||||||
* Returns a paged list of the root level comments, with spam and unmoderated items excluded,
|
$list = new PaginatedList($list, Controller::curr()->getRequest());
|
||||||
* for use in the frontend
|
$list->setPaginationGetVar('commentsstart' . $this->owner->ID);
|
||||||
*
|
$list->setPageLength($this->owner->getCommentsOption('comments_per_page'));
|
||||||
* @return PaginatedList
|
|
||||||
*/
|
|
||||||
public function PagedComments() {
|
|
||||||
$list = $this->Comments();
|
|
||||||
|
|
||||||
// Add pagination
|
$this->owner->extend('updatePagedComments', $list);
|
||||||
$list = new PaginatedList($list, Controller::curr()->getRequest());
|
return $list;
|
||||||
$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
|
||||||
|
*
|
||||||
|
* @deprecated since version 2.0
|
||||||
|
*
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
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'
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if comments are configured for this page even if they are currently disabled.
|
* Determine if comments are enabled for this instance
|
||||||
* Do not include the comments on pages which don't have id's such as security pages
|
*
|
||||||
*
|
* @return boolean
|
||||||
* @deprecated since version 2.0
|
*/
|
||||||
*
|
public function getCommentsEnabled()
|
||||||
* @return boolean
|
{
|
||||||
*/
|
// Don't display comments form for pseudo-pages (such as the login form)
|
||||||
public function getCommentsConfigured() {
|
if (!$this->owner->exists()) {
|
||||||
Deprecation::notice('2.0', 'getCommentsConfigured is deprecated. Use getCommentsEnabled instead');
|
return false;
|
||||||
return true; // by virtue of all classes with this extension being 'configured'
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
// Determine which flag should be used to determine if this is enabled
|
||||||
* Determine if comments are enabled for this instance
|
if ($this->owner->getCommentsOption('enabled_cms')) {
|
||||||
*
|
return $this->owner->ProvideComments;
|
||||||
* @return boolean
|
} else {
|
||||||
*/
|
return $this->owner->getCommentsOption('enabled');
|
||||||
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->getCommentsOption('enabled_cms')) {
|
* Get the HTML ID for the comment holder in the template
|
||||||
return $this->owner->ProvideComments;
|
*
|
||||||
} else {
|
* @return string
|
||||||
return $this->owner->getCommentsOption('enabled');
|
*/
|
||||||
}
|
public function getCommentHolderID()
|
||||||
}
|
{
|
||||||
|
return $this->owner->getCommentsOption('comments_holder_id');
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the HTML ID for the comment holder in the template
|
* @deprecated since version 2.0
|
||||||
*
|
*/
|
||||||
* @return string
|
public function getPostingRequiresPermission()
|
||||||
*/
|
{
|
||||||
public function getCommentHolderID() {
|
Deprecation::notice('2.0', 'Use getPostingRequiredPermission instead');
|
||||||
return $this->owner->getCommentsOption('comments_holder_id');
|
return $this->getPostingRequiredPermission();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @deprecated since version 2.0
|
* Permission codes required in order to post (or empty if none required)
|
||||||
*/
|
*
|
||||||
public function getPostingRequiresPermission() {
|
* @return string|array Permission or list of permissions, if required
|
||||||
Deprecation::notice('2.0', 'Use getPostingRequiredPermission instead');
|
*/
|
||||||
return $this->getPostingRequiredPermission();
|
public function getPostingRequiredPermission()
|
||||||
}
|
{
|
||||||
|
return $this->owner->getCommentsOption('required_permission');
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
public function canPost()
|
||||||
* Permission codes required in order to post (or empty if none required)
|
{
|
||||||
*
|
Deprecation::notice('2.0', 'Use canPostComment instead');
|
||||||
* @return string|array Permission or list of permissions, if required
|
return $this->canPostComment();
|
||||||
*/
|
}
|
||||||
public function getPostingRequiredPermission() {
|
|
||||||
return $this->owner->getCommentsOption('required_permission');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function canPost() {
|
/**
|
||||||
Deprecation::notice('2.0', 'Use canPostComment instead');
|
* Determine if a user can post comments on this item
|
||||||
return $this->canPostComment();
|
*
|
||||||
}
|
* @param Member $member Member to check
|
||||||
|
*
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function canPostComment($member = null)
|
||||||
|
{
|
||||||
|
// Deny if not enabled for this object
|
||||||
|
if (!$this->owner->CommentsEnabled) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
// Check if member is required
|
||||||
* Determine if a user can post comments on this item
|
$requireLogin = $this->owner->CommentsRequireLogin;
|
||||||
*
|
if (!$requireLogin) {
|
||||||
* @param Member $member Member to check
|
return true;
|
||||||
*
|
}
|
||||||
* @return boolean
|
|
||||||
*/
|
|
||||||
public function canPostComment($member = null) {
|
|
||||||
// Deny if not enabled for this object
|
|
||||||
if(!$this->owner->CommentsEnabled) return false;
|
|
||||||
|
|
||||||
// Check if member is required
|
// Check member is logged in
|
||||||
$requireLogin = $this->owner->CommentsRequireLogin;
|
$member = $member ?: Member::currentUser();
|
||||||
if(!$requireLogin) return true;
|
if (!$member) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Check member is logged in
|
// If member required check permissions
|
||||||
$member = $member ?: Member::currentUser();
|
$requiredPermission = $this->owner->PostingRequiredPermission;
|
||||||
if(!$member) return false;
|
if ($requiredPermission && !Permission::checkMember($member, $requiredPermission)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// If member required check permissions
|
return true;
|
||||||
$requiredPermission = $this->owner->PostingRequiredPermission;
|
}
|
||||||
if($requiredPermission && !Permission::checkMember($member, $requiredPermission)) return false;
|
|
||||||
|
|
||||||
return true;
|
/**
|
||||||
}
|
* Determine if this member can moderate comments in the CMS
|
||||||
|
*
|
||||||
|
* @param Member $member
|
||||||
|
*
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function canModerateComments($member = null)
|
||||||
|
{
|
||||||
|
// Deny if not enabled for this object
|
||||||
|
if (!$this->owner->CommentsEnabled) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
// Fallback to can-edit
|
||||||
* Determine if this member can moderate comments in the CMS
|
return $this->owner->canEdit($member);
|
||||||
*
|
}
|
||||||
* @param Member $member
|
|
||||||
*
|
|
||||||
* @return boolean
|
|
||||||
*/
|
|
||||||
public function canModerateComments($member = null) {
|
|
||||||
// Deny if not enabled for this object
|
|
||||||
if(!$this->owner->CommentsEnabled) return false;
|
|
||||||
|
|
||||||
// Fallback to can-edit
|
public function getRssLink()
|
||||||
return $this->owner->canEdit($member);
|
{
|
||||||
}
|
Deprecation::notice('2.0', 'Use getCommentRSSLink instead');
|
||||||
|
return $this->getCommentRSSLink();
|
||||||
|
}
|
||||||
|
|
||||||
public function getRssLink() {
|
/**
|
||||||
Deprecation::notice('2.0', 'Use getCommentRSSLink instead');
|
* Gets the RSS link to all comments
|
||||||
return $this->getCommentRSSLink();
|
*
|
||||||
}
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getCommentRSSLink()
|
||||||
|
{
|
||||||
|
return Controller::join_links(Director::baseURL(), 'CommentingController/rss');
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
public function getRssLinkPage()
|
||||||
* Gets the RSS link to all comments
|
{
|
||||||
*
|
Deprecation::notice('2.0', 'Use getCommentRSSLinkPage instead');
|
||||||
* @return string
|
return $this->getCommentRSSLinkPage();
|
||||||
*/
|
}
|
||||||
public function getCommentRSSLink() {
|
|
||||||
return Controller::join_links(Director::baseURL(), 'CommentingController/rss');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getRssLinkPage() {
|
/**
|
||||||
Deprecation::notice('2.0', 'Use getCommentRSSLinkPage instead');
|
* Get the RSS link to all comments on this page
|
||||||
return $this->getCommentRSSLinkPage();
|
*
|
||||||
}
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getCommentRSSLinkPage()
|
||||||
|
{
|
||||||
|
return Controller::join_links(
|
||||||
|
$this->getCommentRSSLink(), $this->ownerBaseClass, $this->owner->ID
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the RSS link to all comments on this page
|
* Comments interface for the front end. Includes the CommentAddForm and the composition
|
||||||
*
|
* of the comments display.
|
||||||
* @return string
|
*
|
||||||
*/
|
* To customize the html see templates/CommentInterface.ss or extend this function with
|
||||||
public function getCommentRSSLinkPage() {
|
* your own extension.
|
||||||
return Controller::join_links(
|
*
|
||||||
$this->getCommentRSSLink(), $this->ownerBaseClass, $this->owner->ID
|
* @todo Cleanup the passing of all this configuration based functionality
|
||||||
);
|
*
|
||||||
}
|
* @see docs/en/Extending
|
||||||
|
*/
|
||||||
|
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::add_i18n_javascript('comments/javascript/lang');
|
||||||
|
Requirements::javascript('comments/javascript/CommentsInterface.js');
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
$controller = CommentingController::create();
|
||||||
* Comments interface for the front end. Includes the CommentAddForm and the composition
|
$controller->setOwnerRecord($this->owner);
|
||||||
* of the comments display.
|
$controller->setBaseClass($this->ownerBaseClass);
|
||||||
*
|
$controller->setOwnerController(Controller::curr());
|
||||||
* 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
|
|
||||||
*/
|
|
||||||
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::add_i18n_javascript('comments/javascript/lang');
|
|
||||||
Requirements::javascript('comments/javascript/CommentsInterface.js');
|
|
||||||
}
|
|
||||||
|
|
||||||
$controller = CommentingController::create();
|
$moderatedSubmitted = Session::get('CommentsModerated');
|
||||||
$controller->setOwnerRecord($this->owner);
|
Session::clear('CommentsModerated');
|
||||||
$controller->setBaseClass($this->ownerBaseClass);
|
|
||||||
$controller->setOwnerController(Controller::curr());
|
|
||||||
|
|
||||||
$moderatedSubmitted = Session::get('CommentsModerated');
|
$form = ($enabled) ? $controller->CommentsForm() : false;
|
||||||
Session::clear('CommentsModerated');
|
|
||||||
|
|
||||||
$form = ($enabled) ? $controller->CommentsForm() : false;
|
// 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(
|
||||||
|
'AddCommentForm' => $form,
|
||||||
|
'ModeratedSubmitted' => $moderatedSubmitted,
|
||||||
|
))
|
||||||
|
->renderWith('CommentsInterface');
|
||||||
|
}
|
||||||
|
|
||||||
// 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
|
* Returns whether this extension instance is attached to a {@link SiteTree} object
|
||||||
return $this
|
*
|
||||||
->owner
|
* @return bool
|
||||||
->customise(array(
|
*/
|
||||||
'AddCommentForm' => $form,
|
public function attachedToSiteTree()
|
||||||
'ModeratedSubmitted' => $moderatedSubmitted,
|
{
|
||||||
))
|
$class = $this->ownerBaseClass;
|
||||||
->renderWith('CommentsInterface');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
return (is_subclass_of($class, 'SiteTree')) || ($class == 'SiteTree');
|
||||||
* 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');
|
/**
|
||||||
}
|
* @deprecated 1.0 Please use {@link CommentsExtension->CommentsForm()}
|
||||||
|
*/
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @deprecated 1.0 Please use {@link CommentsExtension->CommentsForm()}
|
* Get the commenting option for this object
|
||||||
*/
|
*
|
||||||
public function PageComments() {
|
* This can be overridden in any instance or extension to customise the option available
|
||||||
// This method is very commonly used, don't throw a warning just yet
|
*
|
||||||
Deprecation::notice('1.0', '$PageComments is deprecated. Please use $CommentsForm');
|
* @param string $key
|
||||||
return $this->CommentsForm();
|
*
|
||||||
}
|
* @return mixed Result if the setting is available, or null otherwise
|
||||||
|
*/
|
||||||
|
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];
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
// To allow other extensions to customise this option
|
||||||
* Get the commenting option for this object
|
if ($this->owner) {
|
||||||
*
|
$this->owner->extend('updateCommentsOption', $key, $value);
|
||||||
* This can be overridden in any instance or extension to customise the option available
|
}
|
||||||
*
|
return $value;
|
||||||
* @param string $key
|
}
|
||||||
*
|
|
||||||
* @return mixed Result if the setting is available, or null otherwise
|
|
||||||
*/
|
|
||||||
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];
|
|
||||||
|
|
||||||
// To allow other extensions to customise this option
|
/**
|
||||||
if($this->owner) $this->owner->extend('updateCommentsOption', $key, $value);
|
* Add moderation functions to the current fieldlist
|
||||||
return $value;
|
*
|
||||||
}
|
* @param FieldList $fields
|
||||||
|
*/
|
||||||
|
protected function updateModerationFields(FieldList $fields)
|
||||||
|
{
|
||||||
|
Requirements::css(COMMENTS_DIR . '/css/cms.css');
|
||||||
|
|
||||||
/**
|
$newComments = $this->owner->AllComments()->filter('Moderated', 0);
|
||||||
* Add moderation functions to the current fieldlist
|
|
||||||
*
|
|
||||||
* @param FieldList $fields
|
|
||||||
*/
|
|
||||||
protected function updateModerationFields(FieldList $fields) {
|
|
||||||
Requirements::css(COMMENTS_DIR . '/css/cms.css');
|
|
||||||
|
|
||||||
$newComments = $this->owner->AllComments()->filter('Moderated', 0);
|
$newGrid = new CommentsGridField(
|
||||||
|
'NewComments',
|
||||||
|
_t('CommentsAdmin.NewComments', 'New'),
|
||||||
|
$newComments,
|
||||||
|
CommentsGridFieldConfig::create()
|
||||||
|
);
|
||||||
|
|
||||||
$newGrid = new CommentsGridField(
|
$approvedComments = $this->owner->AllComments()->filter('Moderated', 1)->filter('IsSpam', 0);
|
||||||
'NewComments',
|
|
||||||
_t('CommentsAdmin.NewComments', 'New'),
|
|
||||||
$newComments,
|
|
||||||
CommentsGridFieldConfig::create()
|
|
||||||
);
|
|
||||||
|
|
||||||
$approvedComments = $this->owner->AllComments()->filter('Moderated', 1)->filter('IsSpam', 0);
|
$approvedGrid = new CommentsGridField(
|
||||||
|
'ApprovedComments',
|
||||||
|
_t('CommentsAdmin.Comments', 'Approved'),
|
||||||
|
$approvedComments,
|
||||||
|
CommentsGridFieldConfig::create()
|
||||||
|
);
|
||||||
|
|
||||||
$approvedGrid = new CommentsGridField(
|
$spamComments = $this->owner->AllComments()->filter('Moderated', 1)->filter('IsSpam', 1);
|
||||||
'ApprovedComments',
|
|
||||||
_t('CommentsAdmin.Comments', 'Approved'),
|
|
||||||
$approvedComments,
|
|
||||||
CommentsGridFieldConfig::create()
|
|
||||||
);
|
|
||||||
|
|
||||||
$spamComments = $this->owner->AllComments()->filter('Moderated', 1)->filter('IsSpam', 1);
|
$spamGrid = new CommentsGridField(
|
||||||
|
'SpamComments',
|
||||||
|
_t('CommentsAdmin.SpamComments', 'Spam'),
|
||||||
|
$spamComments,
|
||||||
|
CommentsGridFieldConfig::create()
|
||||||
|
);
|
||||||
|
|
||||||
$spamGrid = new CommentsGridField(
|
$newCount = '(' . count($newComments) . ')';
|
||||||
'SpamComments',
|
$approvedCount = '(' . count($approvedComments) . ')';
|
||||||
_t('CommentsAdmin.SpamComments', 'Spam'),
|
$spamCount = '(' . count($spamComments) . ')';
|
||||||
$spamComments,
|
|
||||||
CommentsGridFieldConfig::create()
|
|
||||||
);
|
|
||||||
|
|
||||||
$newCount = '(' . count($newComments) . ')';
|
if ($fields->hasTabSet()) {
|
||||||
$approvedCount = '(' . count($approvedComments) . ')';
|
$tabs = new TabSet(
|
||||||
$spamCount = '(' . count($spamComments) . ')';
|
'Comments',
|
||||||
|
new Tab('CommentsNewCommentsTab', _t('CommentAdmin.NewComments', 'New') . ' ' . $newCount,
|
||||||
|
$newGrid
|
||||||
|
),
|
||||||
|
new Tab('CommentsCommentsTab', _t('CommentAdmin.Comments', 'Approved') . ' ' . $approvedCount,
|
||||||
|
$approvedGrid
|
||||||
|
),
|
||||||
|
new Tab('CommentsSpamCommentsTab', _t('CommentAdmin.SpamComments', 'Spam') . ' ' . $spamCount,
|
||||||
|
$spamGrid
|
||||||
|
)
|
||||||
|
);
|
||||||
|
$fields->addFieldToTab('Root', $tabs);
|
||||||
|
} else {
|
||||||
|
$fields->push($newGrid);
|
||||||
|
$fields->push($approvedGrid);
|
||||||
|
$fields->push($spamGrid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if($fields->hasTabSet()) {
|
public function updateCMSFields(FieldList $fields)
|
||||||
$tabs = new TabSet(
|
{
|
||||||
'Comments',
|
// Disable moderation if not permitted
|
||||||
new Tab('CommentsNewCommentsTab', _t('CommentAdmin.NewComments', 'New') . ' ' . $newCount,
|
if ($this->owner->canModerateComments()) {
|
||||||
$newGrid
|
$this->updateModerationFields($fields);
|
||||||
),
|
}
|
||||||
new Tab('CommentsCommentsTab', _t('CommentAdmin.Comments', 'Approved') . ' ' . $approvedCount,
|
|
||||||
$approvedGrid
|
|
||||||
),
|
|
||||||
new Tab('CommentsSpamCommentsTab', _t('CommentAdmin.SpamComments', 'Spam') . ' ' . $spamCount,
|
|
||||||
$spamGrid
|
|
||||||
)
|
|
||||||
);
|
|
||||||
$fields->addFieldToTab('Root', $tabs);
|
|
||||||
} else {
|
|
||||||
$fields->push($newGrid);
|
|
||||||
$fields->push($approvedGrid);
|
|
||||||
$fields->push($spamGrid);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function updateCMSFields(FieldList $fields) {
|
// If this isn't a page we should merge the settings into the CMS fields
|
||||||
// Disable moderation if not permitted
|
if (!$this->attachedToSiteTree()) {
|
||||||
if($this->owner->canModerateComments()) {
|
$this->updateSettingsFields($fields);
|
||||||
$this->updateModerationFields($fields);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If this isn't a page we should merge the settings into the CMS fields
|
|
||||||
if(!$this->attachedToSiteTree()) {
|
|
||||||
$this->updateSettingsFields($fields);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -20,556 +20,593 @@
|
|||||||
* @method Comment ParentComment() Parent comment this is a reply to
|
* @method Comment ParentComment() Parent comment this is a reply to
|
||||||
* @package comments
|
* @package comments
|
||||||
*/
|
*/
|
||||||
class Comment extends DataObject {
|
class Comment extends DataObject
|
||||||
|
{
|
||||||
/**
|
|
||||||
* @var array
|
/**
|
||||||
*/
|
* @var array
|
||||||
private static $db = array(
|
*/
|
||||||
'Name' => 'Varchar(200)',
|
private static $db = array(
|
||||||
'Comment' => 'Text',
|
'Name' => 'Varchar(200)',
|
||||||
'Email' => 'Varchar(200)',
|
'Comment' => 'Text',
|
||||||
'URL' => 'Varchar(255)',
|
'Email' => 'Varchar(200)',
|
||||||
'BaseClass' => 'Varchar(200)',
|
'URL' => 'Varchar(255)',
|
||||||
'Moderated' => 'Boolean(0)',
|
'BaseClass' => 'Varchar(200)',
|
||||||
'IsSpam' => 'Boolean(0)',
|
'Moderated' => 'Boolean(0)',
|
||||||
'ParentID' => 'Int',
|
'IsSpam' => 'Boolean(0)',
|
||||||
'AllowHtml' => 'Boolean',
|
'ParentID' => 'Int',
|
||||||
'SecretToken' => 'Varchar(255)',
|
'AllowHtml' => 'Boolean',
|
||||||
'Depth' => 'Int',
|
'SecretToken' => 'Varchar(255)',
|
||||||
);
|
'Depth' => 'Int',
|
||||||
|
);
|
||||||
private static $has_one = array(
|
|
||||||
"Author" => "Member",
|
private static $has_one = array(
|
||||||
"ParentComment" => "Comment",
|
"Author" => "Member",
|
||||||
);
|
"ParentComment" => "Comment",
|
||||||
|
);
|
||||||
private static $has_many = array(
|
|
||||||
"ChildComments" => "Comment"
|
private static $has_many = array(
|
||||||
);
|
"ChildComments" => "Comment"
|
||||||
|
);
|
||||||
private static $default_sort = '"Created" DESC';
|
|
||||||
|
private static $default_sort = '"Created" DESC';
|
||||||
private static $defaults = array(
|
|
||||||
'Moderated' => 0,
|
private static $defaults = array(
|
||||||
'IsSpam' => 0,
|
'Moderated' => 0,
|
||||||
);
|
'IsSpam' => 0,
|
||||||
|
);
|
||||||
private static $casting = array(
|
|
||||||
'Title' => 'Varchar',
|
private static $casting = array(
|
||||||
'ParentTitle' => 'Varchar',
|
'Title' => 'Varchar',
|
||||||
'ParentClassName' => 'Varchar',
|
'ParentTitle' => 'Varchar',
|
||||||
'AuthorName' => 'Varchar',
|
'ParentClassName' => 'Varchar',
|
||||||
'RSSName' => 'Varchar',
|
'AuthorName' => 'Varchar',
|
||||||
'DeleteLink' => 'Varchar',
|
'RSSName' => 'Varchar',
|
||||||
'SpamLink' => 'Varchar',
|
'DeleteLink' => 'Varchar',
|
||||||
'HamLink' => 'Varchar',
|
'SpamLink' => 'Varchar',
|
||||||
'ApproveLink' => 'Varchar',
|
'HamLink' => 'Varchar',
|
||||||
'Permalink' => 'Varchar',
|
'ApproveLink' => 'Varchar',
|
||||||
);
|
'Permalink' => 'Varchar',
|
||||||
|
);
|
||||||
private static $searchable_fields = array(
|
|
||||||
'Name',
|
private static $searchable_fields = array(
|
||||||
'Email',
|
'Name',
|
||||||
'Comment',
|
'Email',
|
||||||
'Created',
|
'Comment',
|
||||||
'BaseClass',
|
'Created',
|
||||||
);
|
'BaseClass',
|
||||||
|
);
|
||||||
private static $summary_fields = array(
|
|
||||||
'Name' => 'Submitted By',
|
private static $summary_fields = array(
|
||||||
'Email' => 'Email',
|
'Name' => 'Submitted By',
|
||||||
'Comment.LimitWordCount' => 'Comment',
|
'Email' => 'Email',
|
||||||
'Created' => 'Date Posted',
|
'Comment.LimitWordCount' => 'Comment',
|
||||||
'ParentTitle' => 'Post',
|
'Created' => 'Date Posted',
|
||||||
'IsSpam' => 'Is Spam',
|
'ParentTitle' => 'Post',
|
||||||
);
|
'IsSpam' => 'Is Spam',
|
||||||
|
);
|
||||||
private static $field_labels = array(
|
|
||||||
'Author' => 'Author Member',
|
private static $field_labels = array(
|
||||||
);
|
'Author' => 'Author Member',
|
||||||
|
);
|
||||||
public function onBeforeWrite() {
|
|
||||||
parent::onBeforeWrite();
|
public function onBeforeWrite()
|
||||||
|
{
|
||||||
// Sanitize HTML, because its expected to be passed to the template unescaped later
|
parent::onBeforeWrite();
|
||||||
if($this->AllowHtml) {
|
|
||||||
$this->Comment = $this->purifyHtml($this->Comment);
|
// 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();
|
|
||||||
}
|
// Check comment depth
|
||||||
|
$this->updateDepth();
|
||||||
public function onBeforeDelete() {
|
}
|
||||||
parent::onBeforeDelete();
|
|
||||||
|
public function onBeforeDelete()
|
||||||
// Delete all children
|
{
|
||||||
foreach($this->ChildComments() as $comment) {
|
parent::onBeforeDelete();
|
||||||
$comment->delete();
|
|
||||||
}
|
// Delete all children
|
||||||
}
|
foreach ($this->ChildComments() as $comment) {
|
||||||
|
$comment->delete();
|
||||||
/**
|
}
|
||||||
* @return Comment_SecurityToken
|
}
|
||||||
*/
|
|
||||||
public function getSecurityToken() {
|
/**
|
||||||
return Injector::inst()->createWithArgs('Comment_SecurityToken', array($this));
|
* @return Comment_SecurityToken
|
||||||
}
|
*/
|
||||||
|
public function getSecurityToken()
|
||||||
/**
|
{
|
||||||
* Migrates the old {@link PageComment} objects to {@link Comment}
|
return Injector::inst()->createWithArgs('Comment_SecurityToken', array($this));
|
||||||
*/
|
}
|
||||||
public function requireDefaultRecords() {
|
|
||||||
parent::requireDefaultRecords();
|
/**
|
||||||
|
* Migrates the old {@link PageComment} objects to {@link Comment}
|
||||||
if(DB::getConn()->hasTable('PageComment')) {
|
*/
|
||||||
$comments = DB::query('SELECT * FROM "PageComment"');
|
public function requireDefaultRecords()
|
||||||
|
{
|
||||||
if($comments) {
|
parent::requireDefaultRecords();
|
||||||
while($pageComment = $comments->nextRecord()) {
|
|
||||||
// create a new comment from the older page comment
|
if (DB::getConn()->hasTable('PageComment')) {
|
||||||
$comment = new Comment();
|
$comments = DB::query('SELECT * FROM "PageComment"');
|
||||||
$comment->update($pageComment);
|
|
||||||
|
if ($comments) {
|
||||||
// set the variables which have changed
|
while ($pageComment = $comments->nextRecord()) {
|
||||||
$comment->BaseClass = 'SiteTree';
|
// create a new comment from the older page comment
|
||||||
$comment->URL = (isset($pageComment['CommenterURL'])) ? $pageComment['CommenterURL'] : '';
|
$comment = new Comment();
|
||||||
if((int) $pageComment['NeedsModeration'] == 0) $comment->Moderated = true;
|
$comment->update($pageComment);
|
||||||
|
|
||||||
$comment->write();
|
// set the variables which have changed
|
||||||
}
|
$comment->BaseClass = 'SiteTree';
|
||||||
}
|
$comment->URL = (isset($pageComment['CommenterURL'])) ? $pageComment['CommenterURL'] : '';
|
||||||
|
if ((int) $pageComment['NeedsModeration'] == 0) {
|
||||||
DB::alteration_message('Migrated PageComment to Comment', 'changed');
|
$comment->Moderated = true;
|
||||||
DB::getConn()->dontRequireTable('PageComment');
|
}
|
||||||
}
|
|
||||||
}
|
$comment->write();
|
||||||
|
}
|
||||||
/**
|
}
|
||||||
* Return a link to this comment
|
|
||||||
*
|
DB::alteration_message('Migrated PageComment to Comment', 'changed');
|
||||||
* @param string $action
|
DB::getConn()->dontRequireTable('PageComment');
|
||||||
*
|
}
|
||||||
* @return string link to this comment.
|
}
|
||||||
*/
|
|
||||||
public function Link($action = '') {
|
/**
|
||||||
if($parent = $this->getParent()) {
|
* Return a link to this comment
|
||||||
return $parent->Link($action) . '#' . $this->Permalink();
|
*
|
||||||
}
|
* @param string $action
|
||||||
}
|
*
|
||||||
|
* @return string link to this comment.
|
||||||
/**
|
*/
|
||||||
* Returns the permalink for this {@link Comment}. Inserted into
|
public function Link($action = '')
|
||||||
* the ID tag of the comment
|
{
|
||||||
*
|
if ($parent = $this->getParent()) {
|
||||||
* @return string
|
return $parent->Link($action) . '#' . $this->Permalink();
|
||||||
*/
|
}
|
||||||
public function Permalink() {
|
}
|
||||||
$prefix = $this->getOption('comment_permalink_prefix');
|
|
||||||
return $prefix . $this->ID;
|
/**
|
||||||
}
|
* Returns the permalink for this {@link Comment}. Inserted into
|
||||||
|
* the ID tag of the comment
|
||||||
/**
|
*
|
||||||
* Translate the form field labels for the CMS administration
|
* @return string
|
||||||
*
|
*/
|
||||||
* @param boolean $includerelations
|
public function Permalink()
|
||||||
*
|
{
|
||||||
* @return array
|
$prefix = $this->getOption('comment_permalink_prefix');
|
||||||
*/
|
return $prefix . $this->ID;
|
||||||
public function fieldLabels($includerelations = true) {
|
}
|
||||||
$labels = parent::fieldLabels($includerelations);
|
|
||||||
|
/**
|
||||||
$labels['Name'] = _t('Comment.NAME', 'Author Name');
|
* Translate the form field labels for the CMS administration
|
||||||
$labels['Comment'] = _t('Comment.COMMENT', 'Comment');
|
*
|
||||||
$labels['Email'] = _t('Comment.EMAIL', 'Email');
|
* @param boolean $includerelations
|
||||||
$labels['URL'] = _t('Comment.URL', 'URL');
|
*
|
||||||
$labels['IsSpam'] = _t('Comment.ISSPAM', 'Spam?');
|
* @return array
|
||||||
$labels['Moderated'] = _t('Comment.MODERATED', 'Moderated?');
|
*/
|
||||||
$labels['ParentTitle'] = _t('Comment.PARENTTITLE', 'Parent');
|
public function fieldLabels($includerelations = true)
|
||||||
$labels['Created'] = _t('Comment.CREATED', 'Date posted');
|
{
|
||||||
|
$labels = parent::fieldLabels($includerelations);
|
||||||
return $labels;
|
|
||||||
}
|
$labels['Name'] = _t('Comment.NAME', 'Author Name');
|
||||||
|
$labels['Comment'] = _t('Comment.COMMENT', 'Comment');
|
||||||
/**
|
$labels['Email'] = _t('Comment.EMAIL', 'Email');
|
||||||
* Get the commenting option
|
$labels['URL'] = _t('Comment.URL', 'URL');
|
||||||
*
|
$labels['IsSpam'] = _t('Comment.ISSPAM', 'Spam?');
|
||||||
* @param string $key
|
$labels['Moderated'] = _t('Comment.MODERATED', 'Moderated?');
|
||||||
*
|
$labels['ParentTitle'] = _t('Comment.PARENTTITLE', 'Parent');
|
||||||
* @return mixed Result if the setting is available, or null otherwise
|
$labels['Created'] = _t('Comment.CREATED', 'Date posted');
|
||||||
*/
|
|
||||||
public function getOption($key) {
|
return $labels;
|
||||||
// If possible use the current record
|
}
|
||||||
$record = $this->getParent();
|
|
||||||
|
/**
|
||||||
if(!$record && $this->BaseClass) {
|
* Get the commenting option
|
||||||
// Otherwise a singleton of that record
|
*
|
||||||
$record = singleton($this->BaseClass);
|
* @param string $key
|
||||||
}
|
*
|
||||||
else if(!$record) {
|
* @return mixed Result if the setting is available, or null otherwise
|
||||||
// Otherwise just use the default options
|
*/
|
||||||
$record = singleton('CommentsExtension');
|
public function getOption($key)
|
||||||
}
|
{
|
||||||
|
// If possible use the current record
|
||||||
return ($record->hasMethod('getCommentsOption')) ? $record->getCommentsOption($key) : null;
|
$record = $this->getParent();
|
||||||
}
|
|
||||||
|
if (!$record && $this->BaseClass) {
|
||||||
/**
|
// Otherwise a singleton of that record
|
||||||
* Returns the parent {@link DataObject} this comment is attached too
|
$record = singleton($this->BaseClass);
|
||||||
*
|
} elseif (!$record) {
|
||||||
* @return DataObject
|
// Otherwise just use the default options
|
||||||
*/
|
$record = singleton('CommentsExtension');
|
||||||
public function getParent() {
|
}
|
||||||
return $this->BaseClass && $this->ParentID
|
|
||||||
? DataObject::get_by_id($this->BaseClass, $this->ParentID, true)
|
return ($record->hasMethod('getCommentsOption')) ? $record->getCommentsOption($key) : null;
|
||||||
: null;
|
}
|
||||||
}
|
|
||||||
|
/**
|
||||||
|
* Returns the parent {@link DataObject} this comment is attached too
|
||||||
/**
|
*
|
||||||
* Returns a string to help identify the parent of the comment
|
* @return DataObject
|
||||||
*
|
*/
|
||||||
* @return string
|
public function getParent()
|
||||||
*/
|
{
|
||||||
public function getParentTitle() {
|
return $this->BaseClass && $this->ParentID
|
||||||
if($parent = $this->getParent()) {
|
? DataObject::get_by_id($this->BaseClass, $this->ParentID, true)
|
||||||
return $parent->Title ?: ($parent->ClassName . ' #' . $parent->ID);
|
: null;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Comment-parent classnames obviously vary, return the parent classname
|
* Returns a string to help identify the parent of the comment
|
||||||
*
|
*
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function getParentClassName() {
|
public function getParentTitle()
|
||||||
return $this->BaseClass;
|
{
|
||||||
}
|
if ($parent = $this->getParent()) {
|
||||||
|
return $parent->Title ?: ($parent->ClassName . ' #' . $parent->ID);
|
||||||
public function castingHelper($field) {
|
}
|
||||||
// Safely escape the comment
|
}
|
||||||
if($field === 'EscapedComment') {
|
|
||||||
return $this->AllowHtml ? 'HTMLText' : 'Text';
|
/**
|
||||||
}
|
* Comment-parent classnames obviously vary, return the parent classname
|
||||||
return parent::castingHelper($field);
|
*
|
||||||
}
|
* @return string
|
||||||
|
*/
|
||||||
/**
|
public function getParentClassName()
|
||||||
* Content to be safely escaped on the frontend
|
{
|
||||||
*
|
return $this->BaseClass;
|
||||||
* @return string
|
}
|
||||||
*/
|
|
||||||
public function getEscapedComment() {
|
public function castingHelper($field)
|
||||||
return $this->Comment;
|
{
|
||||||
}
|
// Safely escape the comment
|
||||||
|
if ($field === 'EscapedComment') {
|
||||||
/**
|
return $this->AllowHtml ? 'HTMLText' : 'Text';
|
||||||
* Return whether this comment is a preview (has not been written to the db)
|
}
|
||||||
*
|
return parent::castingHelper($field);
|
||||||
* @return boolean
|
}
|
||||||
*/
|
|
||||||
public function isPreview() {
|
/**
|
||||||
return !$this->exists();
|
* Content to be safely escaped on the frontend
|
||||||
}
|
*
|
||||||
|
* @return string
|
||||||
/**
|
*/
|
||||||
* @todo needs to compare to the new {@link Commenting} configuration API
|
public function getEscapedComment()
|
||||||
*
|
{
|
||||||
* @param Member $member
|
return $this->Comment;
|
||||||
*
|
}
|
||||||
* @return bool
|
|
||||||
*/
|
/**
|
||||||
public function canCreate($member = null) {
|
* Return whether this comment is a preview (has not been written to the db)
|
||||||
return false;
|
*
|
||||||
}
|
* @return boolean
|
||||||
|
*/
|
||||||
/**
|
public function isPreview()
|
||||||
* Checks for association with a page, and {@link SiteTree->ProvidePermission}
|
{
|
||||||
* flag being set to true.
|
return !$this->exists();
|
||||||
*
|
}
|
||||||
* @param Member $member
|
|
||||||
*
|
/**
|
||||||
* @return Boolean
|
* @todo needs to compare to the new {@link Commenting} configuration API
|
||||||
*/
|
*
|
||||||
public function canView($member = null) {
|
* @param Member $member
|
||||||
$member = $this->getMember($member);
|
*
|
||||||
|
* @return bool
|
||||||
$extended = $this->extendedCan('canView', $member);
|
*/
|
||||||
if($extended !== null) {
|
public function canCreate($member = null)
|
||||||
return $extended;
|
{
|
||||||
}
|
return false;
|
||||||
|
}
|
||||||
if(Permission::checkMember($member, 'CMS_ACCESS_CommentAdmin')) {
|
|
||||||
return true;
|
/**
|
||||||
}
|
* Checks for association with a page, and {@link SiteTree->ProvidePermission}
|
||||||
|
* flag being set to true.
|
||||||
if($parent = $this->getParent()) {
|
*
|
||||||
return $parent->canView($member)
|
* @param Member $member
|
||||||
&& $parent->has_extension('CommentsExtension')
|
*
|
||||||
&& $parent->CommentsEnabled;
|
* @return Boolean
|
||||||
}
|
*/
|
||||||
|
public function canView($member = null)
|
||||||
return false;
|
{
|
||||||
}
|
$member = $this->getMember($member);
|
||||||
|
|
||||||
/**
|
$extended = $this->extendedCan('canView', $member);
|
||||||
* Checks if the comment can be edited.
|
if ($extended !== null) {
|
||||||
*
|
return $extended;
|
||||||
* @param null|int|Member $member
|
}
|
||||||
*
|
|
||||||
* @return Boolean
|
if (Permission::checkMember($member, 'CMS_ACCESS_CommentAdmin')) {
|
||||||
*/
|
return true;
|
||||||
public function canEdit($member = null) {
|
}
|
||||||
$member = $this->getMember($member);
|
|
||||||
|
if ($parent = $this->getParent()) {
|
||||||
if(!$member) {
|
return $parent->canView($member)
|
||||||
return false;
|
&& $parent->has_extension('CommentsExtension')
|
||||||
}
|
&& $parent->CommentsEnabled;
|
||||||
|
}
|
||||||
$extended = $this->extendedCan('canEdit', $member);
|
|
||||||
if($extended !== null) {
|
return false;
|
||||||
return $extended;
|
}
|
||||||
}
|
|
||||||
|
/**
|
||||||
if(Permission::checkMember($member, 'CMS_ACCESS_CommentAdmin')) {
|
* Checks if the comment can be edited.
|
||||||
return true;
|
*
|
||||||
}
|
* @param null|int|Member $member
|
||||||
|
*
|
||||||
if($parent = $this->getParent()) {
|
* @return Boolean
|
||||||
return $parent->canEdit($member);
|
*/
|
||||||
}
|
public function canEdit($member = null)
|
||||||
|
{
|
||||||
return false;
|
$member = $this->getMember($member);
|
||||||
}
|
|
||||||
|
if (!$member) {
|
||||||
/**
|
return false;
|
||||||
* Checks if the comment can be deleted.
|
}
|
||||||
*
|
|
||||||
* @param null|int|Member $member
|
$extended = $this->extendedCan('canEdit', $member);
|
||||||
*
|
if ($extended !== null) {
|
||||||
* @return Boolean
|
return $extended;
|
||||||
*/
|
}
|
||||||
public function canDelete($member = null) {
|
|
||||||
$member = $this->getMember($member);
|
if (Permission::checkMember($member, 'CMS_ACCESS_CommentAdmin')) {
|
||||||
|
return true;
|
||||||
if(!$member) {
|
}
|
||||||
return false;
|
|
||||||
}
|
if ($parent = $this->getParent()) {
|
||||||
|
return $parent->canEdit($member);
|
||||||
$extended = $this->extendedCan('canDelete', $member);
|
}
|
||||||
if($extended !== null) {
|
|
||||||
return $extended;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->canEdit($member);
|
/**
|
||||||
}
|
* Checks if the comment can be deleted.
|
||||||
|
*
|
||||||
/**
|
* @param null|int|Member $member
|
||||||
* Resolves Member object.
|
*
|
||||||
*
|
* @return Boolean
|
||||||
* @param Member|int|null $member
|
*/
|
||||||
* @return Member|null
|
public function canDelete($member = null)
|
||||||
*/
|
{
|
||||||
protected function getMember($member = null) {
|
$member = $this->getMember($member);
|
||||||
if(!$member) {
|
|
||||||
$member = Member::currentUser();
|
if (!$member) {
|
||||||
}
|
return false;
|
||||||
|
}
|
||||||
if(is_numeric($member)) {
|
|
||||||
$member = DataObject::get_by_id('Member', $member, true);
|
$extended = $this->extendedCan('canDelete', $member);
|
||||||
}
|
if ($extended !== null) {
|
||||||
|
return $extended;
|
||||||
return $member;
|
}
|
||||||
}
|
|
||||||
|
return $this->canEdit($member);
|
||||||
/**
|
}
|
||||||
* Return the authors name for the comment
|
|
||||||
*
|
/**
|
||||||
* @return string
|
* Resolves Member object.
|
||||||
*/
|
*
|
||||||
public function getAuthorName() {
|
* @param Member|int|null $member
|
||||||
if($this->Name) {
|
* @return Member|null
|
||||||
return $this->Name;
|
*/
|
||||||
} else if($author = $this->Author()) {
|
protected function getMember($member = null)
|
||||||
return $author->getName();
|
{
|
||||||
}
|
if (!$member) {
|
||||||
}
|
$member = Member::currentUser();
|
||||||
|
}
|
||||||
/**
|
|
||||||
* Generate a secure admin-action link authorised for the specified member
|
if (is_numeric($member)) {
|
||||||
*
|
$member = DataObject::get_by_id('Member', $member, true);
|
||||||
* @param string $action An action on CommentingController to link to
|
}
|
||||||
* @param Member $member The member authorised to invoke this action
|
|
||||||
*
|
return $member;
|
||||||
* @return string
|
}
|
||||||
*/
|
|
||||||
protected function actionLink($action, $member = null) {
|
/**
|
||||||
if(!$member) $member = Member::currentUser();
|
* Return the authors name for the comment
|
||||||
if(!$member) return false;
|
*
|
||||||
|
* @return string
|
||||||
$url = Controller::join_links(
|
*/
|
||||||
Director::baseURL(),
|
public function getAuthorName()
|
||||||
'CommentingController',
|
{
|
||||||
$action,
|
if ($this->Name) {
|
||||||
$this->ID
|
return $this->Name;
|
||||||
);
|
} elseif ($author = $this->Author()) {
|
||||||
|
return $author->getName();
|
||||||
// Limit access for this user
|
}
|
||||||
$token = $this->getSecurityToken();
|
}
|
||||||
return $token->addToUrl($url, $member);
|
|
||||||
}
|
/**
|
||||||
|
* Generate a secure admin-action link authorised for the specified member
|
||||||
/**
|
*
|
||||||
* Link to delete this comment
|
* @param string $action An action on CommentingController to link to
|
||||||
*
|
* @param Member $member The member authorised to invoke this action
|
||||||
* @param Member $member
|
*
|
||||||
*
|
* @return string
|
||||||
* @return string
|
*/
|
||||||
*/
|
protected function actionLink($action, $member = null)
|
||||||
public function DeleteLink($member = null) {
|
{
|
||||||
if($this->canDelete($member)) {
|
if (!$member) {
|
||||||
return $this->actionLink('delete', $member);
|
$member = Member::currentUser();
|
||||||
}
|
}
|
||||||
}
|
if (!$member) {
|
||||||
|
return false;
|
||||||
/**
|
}
|
||||||
* Link to mark as spam
|
|
||||||
*
|
$url = Controller::join_links(
|
||||||
* @param Member $member
|
Director::baseURL(),
|
||||||
*
|
'CommentingController',
|
||||||
* @return string
|
$action,
|
||||||
*/
|
$this->ID
|
||||||
public function SpamLink($member = null) {
|
);
|
||||||
if($this->canEdit($member) && !$this->IsSpam) {
|
|
||||||
return $this->actionLink('spam', $member);
|
// Limit access for this user
|
||||||
}
|
$token = $this->getSecurityToken();
|
||||||
}
|
return $token->addToUrl($url, $member);
|
||||||
|
}
|
||||||
/**
|
|
||||||
* Link to mark as not-spam (ham)
|
/**
|
||||||
*
|
* Link to delete this comment
|
||||||
* @param Member $member
|
*
|
||||||
*
|
* @param Member $member
|
||||||
* @return string
|
*
|
||||||
*/
|
* @return string
|
||||||
public function HamLink($member = null) {
|
*/
|
||||||
if($this->canEdit($member) && $this->IsSpam) {
|
public function DeleteLink($member = null)
|
||||||
return $this->actionLink('ham', $member);
|
{
|
||||||
}
|
if ($this->canDelete($member)) {
|
||||||
}
|
return $this->actionLink('delete', $member);
|
||||||
|
}
|
||||||
/**
|
}
|
||||||
* Link to approve this comment
|
|
||||||
*
|
/**
|
||||||
* @param Member $member
|
* Link to mark as spam
|
||||||
*
|
*
|
||||||
* @return string
|
* @param Member $member
|
||||||
*/
|
*
|
||||||
public function ApproveLink($member = null) {
|
* @return string
|
||||||
if($this->canEdit($member) && !$this->Moderated) {
|
*/
|
||||||
return $this->actionLink('approve', $member);
|
public function SpamLink($member = null)
|
||||||
}
|
{
|
||||||
}
|
if ($this->canEdit($member) && !$this->IsSpam) {
|
||||||
|
return $this->actionLink('spam', $member);
|
||||||
/**
|
}
|
||||||
* Mark this comment as spam
|
}
|
||||||
*/
|
|
||||||
public function markSpam() {
|
/**
|
||||||
$this->IsSpam = true;
|
* Link to mark as not-spam (ham)
|
||||||
$this->Moderated = true;
|
*
|
||||||
$this->write();
|
* @param Member $member
|
||||||
$this->extend('afterMarkSpam');
|
*
|
||||||
}
|
* @return string
|
||||||
|
*/
|
||||||
/**
|
public function HamLink($member = null)
|
||||||
* Mark this comment as approved
|
{
|
||||||
*/
|
if ($this->canEdit($member) && $this->IsSpam) {
|
||||||
public function markApproved() {
|
return $this->actionLink('ham', $member);
|
||||||
$this->IsSpam = false;
|
}
|
||||||
$this->Moderated = true;
|
}
|
||||||
$this->write();
|
|
||||||
$this->extend('afterMarkApproved');
|
/**
|
||||||
}
|
* Link to approve this comment
|
||||||
|
*
|
||||||
/**
|
* @param Member $member
|
||||||
* Mark this comment as unapproved
|
*
|
||||||
*/
|
* @return string
|
||||||
public function markUnapproved() {
|
*/
|
||||||
$this->Moderated = false;
|
public function ApproveLink($member = null)
|
||||||
$this->write();
|
{
|
||||||
$this->extend('afterMarkUnapproved');
|
if ($this->canEdit($member) && !$this->Moderated) {
|
||||||
}
|
return $this->actionLink('approve', $member);
|
||||||
|
}
|
||||||
/**
|
}
|
||||||
* @return string
|
|
||||||
*/
|
/**
|
||||||
public function SpamClass() {
|
* Mark this comment as spam
|
||||||
if($this->IsSpam) {
|
*/
|
||||||
return 'spam';
|
public function markSpam()
|
||||||
} else if(!$this->Moderated) {
|
{
|
||||||
return 'unmoderated';
|
$this->IsSpam = true;
|
||||||
} else {
|
$this->Moderated = true;
|
||||||
return 'notspam';
|
$this->write();
|
||||||
}
|
$this->extend('afterMarkSpam');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return string
|
* Mark this comment as approved
|
||||||
*/
|
*/
|
||||||
public function getTitle() {
|
public function markApproved()
|
||||||
$title = sprintf(_t('Comment.COMMENTBY', 'Comment by %s', 'Name'), $this->getAuthorName());
|
{
|
||||||
|
$this->IsSpam = false;
|
||||||
if($parent = $this->getParent()) {
|
$this->Moderated = true;
|
||||||
if($parent->Title) {
|
$this->write();
|
||||||
$title .= sprintf(' %s %s', _t('Comment.ON', 'on'), $parent->Title);
|
$this->extend('afterMarkApproved');
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
/**
|
||||||
return $title;
|
* Mark this comment as unapproved
|
||||||
}
|
*/
|
||||||
|
public function markUnapproved()
|
||||||
/*
|
{
|
||||||
* Modify the default fields shown to the user
|
$this->Moderated = false;
|
||||||
*/
|
$this->write();
|
||||||
public function getCMSFields() {
|
$this->extend('afterMarkUnapproved');
|
||||||
$commentField = $this->AllowHtml ? 'HtmlEditorField' : 'TextareaField';
|
}
|
||||||
$fields = new FieldList(
|
|
||||||
$this
|
/**
|
||||||
->obj('Created')
|
* @return string
|
||||||
->scaffoldFormField($this->fieldLabel('Created'))
|
*/
|
||||||
->performReadonlyTransformation(),
|
public function SpamClass()
|
||||||
TextField::create('Name', $this->fieldLabel('AuthorName')),
|
{
|
||||||
$commentField::create('Comment', $this->fieldLabel('Comment')),
|
if ($this->IsSpam) {
|
||||||
EmailField::create('Email', $this->fieldLabel('Email')),
|
return 'spam';
|
||||||
TextField::create('URL', $this->fieldLabel('URL')),
|
} elseif (!$this->Moderated) {
|
||||||
FieldGroup::create(array(
|
return 'unmoderated';
|
||||||
CheckboxField::create('Moderated', $this->fieldLabel('Moderated')),
|
} else {
|
||||||
CheckboxField::create('IsSpam', $this->fieldLabel('IsSpam')),
|
return 'notspam';
|
||||||
))
|
}
|
||||||
->setTitle('Options')
|
}
|
||||||
->setDescription(_t(
|
|
||||||
'Comment.OPTION_DESCRIPTION',
|
/**
|
||||||
'Unmoderated and spam comments will not be displayed until approved'
|
* @return string
|
||||||
))
|
*/
|
||||||
);
|
public function getTitle()
|
||||||
|
{
|
||||||
// Show member name if given
|
$title = sprintf(_t('Comment.COMMENTBY', 'Comment by %s', 'Name'), $this->getAuthorName());
|
||||||
if(($author = $this->Author()) && $author->exists()) {
|
|
||||||
$fields->insertAfter(
|
if ($parent = $this->getParent()) {
|
||||||
TextField::create('AuthorMember', $this->fieldLabel('Author'), $author->Title)
|
if ($parent->Title) {
|
||||||
->performReadonlyTransformation(),
|
$title .= sprintf(' %s %s', _t('Comment.ON', 'on'), $parent->Title);
|
||||||
'Name'
|
}
|
||||||
);
|
}
|
||||||
}
|
|
||||||
|
return $title;
|
||||||
// Show parent comment if given
|
}
|
||||||
if(($parent = $this->ParentComment()) && $parent->exists()) {
|
|
||||||
$fields->push(new HeaderField(
|
/*
|
||||||
'ParentComment_Title',
|
* Modify the default fields shown to the user
|
||||||
_t('Comment.ParentComment_Title', 'This comment is a reply to the below')
|
*/
|
||||||
));
|
public function getCMSFields()
|
||||||
// Created date
|
{
|
||||||
|
$commentField = $this->AllowHtml ? 'HtmlEditorField' : 'TextareaField';
|
||||||
|
$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'
|
||||||
|
))
|
||||||
|
);
|
||||||
|
|
||||||
|
// Show member name if given
|
||||||
|
if (($author = $this->Author()) && $author->exists()) {
|
||||||
|
$fields->insertAfter(
|
||||||
|
TextField::create('AuthorMember', $this->fieldLabel('Author'), $author->Title)
|
||||||
|
->performReadonlyTransformation(),
|
||||||
|
'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
|
||||||
// FIXME - the method setName in DatetimeField is not chainable, hence
|
// FIXME - the method setName in DatetimeField is not chainable, hence
|
||||||
// the lack of chaining here
|
// the lack of chaining here
|
||||||
$createdField = $parent
|
$createdField = $parent
|
||||||
@ -580,46 +617,48 @@ class Comment extends DataObject {
|
|||||||
$createdField->performReadonlyTransformation();
|
$createdField->performReadonlyTransformation();
|
||||||
$fields->push($createdField);
|
$fields->push($createdField);
|
||||||
|
|
||||||
// Name (could be member or string value)
|
// Name (could be member or string value)
|
||||||
$fields->push(
|
$fields->push(
|
||||||
$parent
|
$parent
|
||||||
->obj('AuthorName')
|
->obj('AuthorName')
|
||||||
->scaffoldFormField($parent->fieldLabel('AuthorName'))
|
->scaffoldFormField($parent->fieldLabel('AuthorName'))
|
||||||
->setName('ParentComment_AuthorName')
|
->setName('ParentComment_AuthorName')
|
||||||
->setValue($parent->getAuthorName())
|
->setValue($parent->getAuthorName())
|
||||||
->performReadonlyTransformation()
|
->performReadonlyTransformation()
|
||||||
);
|
);
|
||||||
|
|
||||||
// Comment body
|
// Comment body
|
||||||
$fields->push(
|
$fields->push(
|
||||||
$parent
|
$parent
|
||||||
->obj('EscapedComment')
|
->obj('EscapedComment')
|
||||||
->scaffoldFormField($parent->fieldLabel('Comment'))
|
->scaffoldFormField($parent->fieldLabel('Comment'))
|
||||||
->setName('ParentComment_EscapedComment')
|
->setName('ParentComment_EscapedComment')
|
||||||
->setValue($parent->Comment)
|
->setValue($parent->Comment)
|
||||||
->performReadonlyTransformation()
|
->performReadonlyTransformation()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->extend('updateCMSFields', $fields);
|
$this->extend('updateCMSFields', $fields);
|
||||||
return $fields;
|
return $fields;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param String $dirtyHtml
|
* @param String $dirtyHtml
|
||||||
*
|
*
|
||||||
* @return String
|
* @return String
|
||||||
*/
|
*/
|
||||||
public function purifyHtml($dirtyHtml) {
|
public function purifyHtml($dirtyHtml)
|
||||||
$purifier = $this->getHtmlPurifierService();
|
{
|
||||||
return $purifier->purify($dirtyHtml);
|
$purifier = $this->getHtmlPurifierService();
|
||||||
}
|
return $purifier->purify($dirtyHtml);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return HTMLPurifier (or anything with a "purify()" method)
|
* @return HTMLPurifier (or anything with a "purify()" method)
|
||||||
*/
|
*/
|
||||||
public function getHtmlPurifierService() {
|
public function getHtmlPurifierService()
|
||||||
$config = HTMLPurifier_Config::createDefault();
|
{
|
||||||
|
$config = HTMLPurifier_Config::createDefault();
|
||||||
$allowedElements = $this->getOption('html_allowed_elements');
|
$allowedElements = $this->getOption('html_allowed_elements');
|
||||||
$config->set('HTML.AllowedElements', $allowedElements);
|
$config->set('HTML.AllowedElements', $allowedElements);
|
||||||
|
|
||||||
@ -628,256 +667,274 @@ class Comment extends DataObject {
|
|||||||
$config->set('AutoFormat.AutoParagraph', true);
|
$config->set('AutoFormat.AutoParagraph', true);
|
||||||
}
|
}
|
||||||
|
|
||||||
$config->set('AutoFormat.Linkify', true);
|
$config->set('AutoFormat.Linkify', true);
|
||||||
$config->set('URI.DisableExternalResources', true);
|
$config->set('URI.DisableExternalResources', true);
|
||||||
$config->set('Cache.SerializerPath', getTempFolder());
|
$config->set('Cache.SerializerPath', getTempFolder());
|
||||||
return new HTMLPurifier($config);
|
return new HTMLPurifier($config);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculate the Gravatar link from the email address
|
* Calculate the Gravatar link from the email address
|
||||||
*
|
*
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function Gravatar() {
|
public function Gravatar()
|
||||||
$gravatar = '';
|
{
|
||||||
$use_gravatar = $this->getOption('use_gravatar');
|
$gravatar = '';
|
||||||
if($use_gravatar) {
|
$use_gravatar = $this->getOption('use_gravatar');
|
||||||
$gravatar = 'http://www.gravatar.com/avatar/' . md5(strtolower(trim($this->Email)));
|
if ($use_gravatar) {
|
||||||
$gravatarsize = $this->getOption('gravatar_size');
|
$gravatar = 'http://www.gravatar.com/avatar/' . md5(strtolower(trim($this->Email)));
|
||||||
$gravatardefault = $this->getOption('gravatar_default');
|
$gravatarsize = $this->getOption('gravatar_size');
|
||||||
$gravatarrating = $this->getOption('gravatar_rating');
|
$gravatardefault = $this->getOption('gravatar_default');
|
||||||
$gravatar .= '?s=' . $gravatarsize . '&d=' . $gravatardefault . '&r=' . $gravatarrating;
|
$gravatarrating = $this->getOption('gravatar_rating');
|
||||||
}
|
$gravatar .= '?s=' . $gravatarsize . '&d=' . $gravatardefault . '&r=' . $gravatarrating;
|
||||||
|
}
|
||||||
|
|
||||||
return $gravatar;
|
return $gravatar;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determine if replies are enabled for this instance
|
* Determine if replies are enabled for this instance
|
||||||
*
|
*
|
||||||
* @return boolean
|
* @return boolean
|
||||||
*/
|
*/
|
||||||
public function getRepliesEnabled() {
|
public function getRepliesEnabled()
|
||||||
// Check reply option
|
{
|
||||||
if(!$this->getOption('nested_comments')) {
|
// Check reply option
|
||||||
return false;
|
if (!$this->getOption('nested_comments')) {
|
||||||
}
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Check if depth is limited
|
// Check if depth is limited
|
||||||
$maxLevel = $this->getOption('nested_depth');
|
$maxLevel = $this->getOption('nested_depth');
|
||||||
$notSpam = ($this->SpamClass() == 'notspam');
|
$notSpam = ($this->SpamClass() == 'notspam');
|
||||||
return $notSpam && (!$maxLevel || $this->Depth < $maxLevel);
|
return $notSpam && (!$maxLevel || $this->Depth < $maxLevel);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the list of all replies
|
* Returns the list of all replies
|
||||||
*
|
*
|
||||||
* @return SS_List
|
* @return SS_List
|
||||||
*/
|
*/
|
||||||
public function AllReplies() {
|
public function AllReplies()
|
||||||
// No replies if disabled
|
{
|
||||||
if(!$this->getRepliesEnabled()) {
|
// No replies if disabled
|
||||||
return new ArrayList();
|
if (!$this->getRepliesEnabled()) {
|
||||||
}
|
return new ArrayList();
|
||||||
|
}
|
||||||
|
|
||||||
// Get all non-spam comments
|
// Get all non-spam comments
|
||||||
$order = $this->getOption('order_replies_by')
|
$order = $this->getOption('order_replies_by')
|
||||||
?: $this->getOption('order_comments_by');
|
?: $this->getOption('order_comments_by');
|
||||||
$list = $this
|
$list = $this
|
||||||
->ChildComments()
|
->ChildComments()
|
||||||
->sort($order);
|
->sort($order);
|
||||||
|
|
||||||
$this->extend('updateAllReplies', $list);
|
$this->extend('updateAllReplies', $list);
|
||||||
return $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 unmoderated items excluded, for use in the frontend
|
||||||
*
|
*
|
||||||
* @return SS_List
|
* @return SS_List
|
||||||
*/
|
*/
|
||||||
public function Replies() {
|
public function Replies()
|
||||||
// No replies if disabled
|
{
|
||||||
if(!$this->getRepliesEnabled()) {
|
// No replies if disabled
|
||||||
return new ArrayList();
|
if (!$this->getRepliesEnabled()) {
|
||||||
}
|
return new ArrayList();
|
||||||
$list = $this->AllReplies();
|
}
|
||||||
|
$list = $this->AllReplies();
|
||||||
|
|
||||||
// Filter spam comments for non-administrators if configured
|
// Filter spam comments for non-administrators if configured
|
||||||
$parent = $this->getParent();
|
$parent = $this->getParent();
|
||||||
$showSpam = $this->getOption('frontend_spam') && $parent && $parent->canModerateComments();
|
$showSpam = $this->getOption('frontend_spam') && $parent && $parent->canModerateComments();
|
||||||
if(!$showSpam) {
|
if (!$showSpam) {
|
||||||
$list = $list->filter('IsSpam', 0);
|
$list = $list->filter('IsSpam', 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Filter un-moderated comments for non-administrators if moderation is enabled
|
// Filter un-moderated comments for non-administrators if moderation is enabled
|
||||||
$showUnmoderated = $parent && (
|
$showUnmoderated = $parent && (
|
||||||
($parent->ModerationRequired === 'None')
|
($parent->ModerationRequired === 'None')
|
||||||
|| ($this->getOption('frontend_moderation') && $parent->canModerateComments())
|
|| ($this->getOption('frontend_moderation') && $parent->canModerateComments())
|
||||||
);
|
);
|
||||||
if (!$showUnmoderated) {
|
if (!$showUnmoderated) {
|
||||||
$list = $list->filter('Moderated', 1);
|
$list = $list->filter('Moderated', 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->extend('updateReplies', $list);
|
$this->extend('updateReplies', $list);
|
||||||
return $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 unmoderated items excluded, for use in the frontend
|
||||||
*
|
*
|
||||||
* @return PaginatedList
|
* @return PaginatedList
|
||||||
*/
|
*/
|
||||||
public function PagedReplies() {
|
public function PagedReplies()
|
||||||
$list = $this->Replies();
|
{
|
||||||
|
$list = $this->Replies();
|
||||||
|
|
||||||
// Add pagination
|
// Add pagination
|
||||||
$list = new PaginatedList($list, Controller::curr()->getRequest());
|
$list = new PaginatedList($list, Controller::curr()->getRequest());
|
||||||
$list->setPaginationGetVar('repliesstart'.$this->ID);
|
$list->setPaginationGetVar('repliesstart'.$this->ID);
|
||||||
$list->setPageLength($this->getOption('comments_per_page'));
|
$list->setPageLength($this->getOption('comments_per_page'));
|
||||||
|
|
||||||
$this->extend('updatePagedReplies', $list);
|
$this->extend('updatePagedReplies', $list);
|
||||||
return $list;
|
return $list;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate a reply form for this comment
|
* Generate a reply form for this comment
|
||||||
*
|
*
|
||||||
* @return Form
|
* @return Form
|
||||||
*/
|
*/
|
||||||
public function ReplyForm() {
|
public function ReplyForm()
|
||||||
// Ensure replies are enabled
|
{
|
||||||
if(!$this->getRepliesEnabled()) {
|
// Ensure replies are enabled
|
||||||
return null;
|
if (!$this->getRepliesEnabled()) {
|
||||||
}
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
// Check parent is available
|
// Check parent is available
|
||||||
$parent = $this->getParent();
|
$parent = $this->getParent();
|
||||||
if(!$parent || !$parent->exists()) {
|
if (!$parent || !$parent->exists()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build reply controller
|
// Build reply controller
|
||||||
$controller = CommentingController::create();
|
$controller = CommentingController::create();
|
||||||
$controller->setOwnerRecord($parent);
|
$controller->setOwnerRecord($parent);
|
||||||
$controller->setBaseClass($parent->ClassName);
|
$controller->setBaseClass($parent->ClassName);
|
||||||
$controller->setOwnerController(Controller::curr());
|
$controller->setOwnerController(Controller::curr());
|
||||||
|
|
||||||
return $controller->ReplyForm($this);
|
return $controller->ReplyForm($this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Refresh of this comment in the hierarchy
|
* Refresh of this comment in the hierarchy
|
||||||
*/
|
*/
|
||||||
public function updateDepth() {
|
public function updateDepth()
|
||||||
$parent = $this->ParentComment();
|
{
|
||||||
if($parent && $parent->exists()) {
|
$parent = $this->ParentComment();
|
||||||
$parent->updateDepth();
|
if ($parent && $parent->exists()) {
|
||||||
$this->Depth = $parent->Depth + 1;
|
$parent->updateDepth();
|
||||||
} else {
|
$this->Depth = $parent->Depth + 1;
|
||||||
$this->Depth = 1;
|
} else {
|
||||||
}
|
$this->Depth = 1;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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 {
|
class Comment_SecurityToken
|
||||||
|
{
|
||||||
|
|
||||||
private $secret = null;
|
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) {
|
public function __construct($comment)
|
||||||
if(!$comment->SecretToken) {
|
{
|
||||||
$comment->SecretToken = $this->generate();
|
if (!$comment->SecretToken) {
|
||||||
$comment->write();
|
$comment->SecretToken = $this->generate();
|
||||||
}
|
$comment->write();
|
||||||
$this->secret = $comment->SecretToken;
|
}
|
||||||
}
|
$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
|
* @param string $salt
|
||||||
*
|
*
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
protected function getToken($salt) {
|
protected function getToken($salt)
|
||||||
return hash_pbkdf2('sha256', $this->secret, $salt, 1000, 30);
|
{
|
||||||
}
|
return hash_pbkdf2('sha256', $this->secret, $salt, 1000, 30);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the member-specific salt.
|
* Get the member-specific salt.
|
||||||
*
|
*
|
||||||
* The reason for making the salt specific to a user is that it cannot be "passed in" via a
|
* 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
|
* querystring, requiring the same user to be present at both the link generation and the
|
||||||
* controller action.
|
* controller action.
|
||||||
*
|
*
|
||||||
* @param string $salt Single use salt
|
* @param string $salt Single use salt
|
||||||
* @param Member $member Member object
|
* @param Member $member Member object
|
||||||
*
|
*
|
||||||
* @return string Generated salt specific to this member
|
* @return string Generated salt specific to this member
|
||||||
*/
|
*/
|
||||||
protected function memberSalt($salt, $member) {
|
protected function memberSalt($salt, $member)
|
||||||
// Fallback to salting with ID in case the member has not one set
|
{
|
||||||
return $salt . ($member->Salt ?: $member->ID);
|
// Fallback to salting with ID in case the member has not one set
|
||||||
}
|
return $salt . ($member->Salt ?: $member->ID);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $url Comment action URL
|
* @param string $url Comment action URL
|
||||||
* @param Member $member Member to restrict access to this action to
|
* @param Member $member Member to restrict access to this action to
|
||||||
*
|
*
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function addToUrl($url, $member) {
|
public function addToUrl($url, $member)
|
||||||
$salt = $this->generate(15); // New random salt; Will be passed into url
|
{
|
||||||
// Generate salt specific to this member
|
$salt = $this->generate(15); // New random salt; Will be passed into url
|
||||||
$memberSalt = $this->memberSalt($salt, $member);
|
// Generate salt specific to this member
|
||||||
$token = $this->getToken($memberSalt);
|
$memberSalt = $this->memberSalt($salt, $member);
|
||||||
return Controller::join_links(
|
$token = $this->getToken($memberSalt);
|
||||||
$url,
|
return Controller::join_links(
|
||||||
sprintf(
|
$url,
|
||||||
'?t=%s&s=%s',
|
sprintf(
|
||||||
urlencode($token),
|
'?t=%s&s=%s',
|
||||||
urlencode($salt)
|
urlencode($token),
|
||||||
)
|
urlencode($salt)
|
||||||
);
|
)
|
||||||
}
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param SS_HTTPRequest $request
|
* @param SS_HTTPRequest $request
|
||||||
*
|
*
|
||||||
* @return boolean
|
* @return boolean
|
||||||
*/
|
*/
|
||||||
public function checkRequest($request) {
|
public function checkRequest($request)
|
||||||
$member = Member::currentUser();
|
{
|
||||||
if(!$member) return false;
|
$member = Member::currentUser();
|
||||||
|
if (!$member) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
$salt = $request->getVar('s');
|
$salt = $request->getVar('s');
|
||||||
$memberSalt = $this->memberSalt($salt, $member);
|
$memberSalt = $this->memberSalt($salt, $member);
|
||||||
$token = $this->getToken($memberSalt);
|
$token = $this->getToken($memberSalt);
|
||||||
|
|
||||||
// Ensure tokens match
|
// Ensure tokens match
|
||||||
return $token === $request->getVar('t');
|
return $token === $request->getVar('t');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates new random key
|
* Generates new random key
|
||||||
*
|
*
|
||||||
* @param integer $length
|
* @param integer $length
|
||||||
*
|
*
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
protected function generate($length = null) {
|
protected function generate($length = null)
|
||||||
$generator = new RandomGenerator();
|
{
|
||||||
$result = $generator->randomToken('sha256');
|
$generator = new RandomGenerator();
|
||||||
if($length !== null) return substr($result, 0, $length);
|
$result = $generator->randomToken('sha256');
|
||||||
return $result;
|
if ($length !== null) {
|
||||||
}
|
return substr($result, 0, $length);
|
||||||
|
}
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,85 +7,92 @@
|
|||||||
*
|
*
|
||||||
* @author dmooyman
|
* @author dmooyman
|
||||||
*/
|
*/
|
||||||
class CommentList extends HasManyList {
|
class CommentList extends HasManyList
|
||||||
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve the name of the class this relation is filtered by
|
* Retrieve the name of the class this relation is filtered by
|
||||||
*
|
*
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function getForeignClass() {
|
public function getForeignClass()
|
||||||
return $this->dataQuery->getQueryParam('Foreign.Class');
|
{
|
||||||
}
|
return $this->dataQuery->getQueryParam('Foreign.Class');
|
||||||
|
}
|
||||||
|
|
||||||
public function __construct($parentClassName) {
|
public function __construct($parentClassName)
|
||||||
parent::__construct('Comment', 'ParentID');
|
{
|
||||||
|
parent::__construct('Comment', 'ParentID');
|
||||||
|
|
||||||
|
|
||||||
// Ensure underlying DataQuery globally references the class filter
|
// Ensure underlying DataQuery globally references the class filter
|
||||||
$this->dataQuery->setQueryParam('Foreign.Class', $parentClassName);
|
$this->dataQuery->setQueryParam('Foreign.Class', $parentClassName);
|
||||||
|
|
||||||
// For queries with multiple foreign IDs (such as that generated by
|
// For queries with multiple foreign IDs (such as that generated by
|
||||||
// DataList::relation) the filter must be generalised to filter by subclasses
|
// DataList::relation) the filter must be generalised to filter by subclasses
|
||||||
$classNames = Convert::raw2sql(ClassInfo::subclassesFor($parentClassName));
|
$classNames = Convert::raw2sql(ClassInfo::subclassesFor($parentClassName));
|
||||||
$this->dataQuery->where(sprintf(
|
$this->dataQuery->where(sprintf(
|
||||||
"\"BaseClass\" IN ('%s')", implode("', '", $classNames)
|
"\"BaseClass\" IN ('%s')", implode("', '", $classNames)
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds the item to this relation.
|
* Adds the item to this relation.
|
||||||
*
|
*
|
||||||
* @param Comment $item The comment to be added
|
* @param Comment $item The comment to be added
|
||||||
*/
|
*/
|
||||||
public function add($item) {
|
public function add($item)
|
||||||
// Check item given
|
{
|
||||||
if(is_numeric($item)) {
|
// Check item given
|
||||||
$item = Comment::get()->byID($item);
|
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");
|
if (!($item instanceof Comment)) {
|
||||||
}
|
throw new InvalidArgumentException("CommentList::add() expecting a Comment object, or ID value");
|
||||||
|
}
|
||||||
// Validate foreignID
|
|
||||||
$foreignID = $this->getForeignID();
|
// Validate foreignID
|
||||||
if(!$foreignID || is_array($foreignID)) {
|
$foreignID = $this->getForeignID();
|
||||||
throw new InvalidArgumentException("CommentList::add() can't be called until a single foreign ID is set");
|
if (!$foreignID || is_array($foreignID)) {
|
||||||
}
|
throw new InvalidArgumentException("CommentList::add() can't be called until a single foreign ID is set");
|
||||||
|
}
|
||||||
|
|
||||||
$item->ParentID = $foreignID;
|
$item->ParentID = $foreignID;
|
||||||
$item->BaseClass = $this->getForeignClass();
|
$item->BaseClass = $this->getForeignClass();
|
||||||
$item->write();
|
$item->write();
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Remove a Comment from this relation by clearing the foreign key. Does not actually delete the comment.
|
* 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
|
* @param Comment $item The Comment to be removed
|
||||||
*/
|
*/
|
||||||
public function remove($item) {
|
public function remove($item)
|
||||||
// Check item given
|
{
|
||||||
if(is_numeric($item)) {
|
// Check item given
|
||||||
$item = Comment::get()->byID($item);
|
if (is_numeric($item)) {
|
||||||
}
|
$item = Comment::get()->byID($item);
|
||||||
if(!($item instanceof Comment)) {
|
}
|
||||||
throw new InvalidArgumentException("CommentList::remove() expecting a Comment object, or ID",
|
if (!($item instanceof Comment)) {
|
||||||
E_USER_ERROR);
|
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();
|
// Don't remove item with unrelated class key
|
||||||
$classNames = ClassInfo::subclassesFor($foreignClass);
|
$foreignClass = $this->getForeignClass();
|
||||||
if(!in_array($item->BaseClass, $classNames)) return;
|
$classNames = ClassInfo::subclassesFor($foreignClass);
|
||||||
|
if (!in_array($item->BaseClass, $classNames)) {
|
||||||
// Don't remove item which doesn't belong to this list
|
return;
|
||||||
$foreignID = $this->getForeignID();
|
}
|
||||||
if( empty($foreignID)
|
|
||||||
|| (is_array($foreignID) && in_array($item->ParentID, $foreignID))
|
// Don't remove item which doesn't belong to this list
|
||||||
|| $foreignID == $item->ParentID
|
$foreignID = $this->getForeignID();
|
||||||
) {
|
if (empty($foreignID)
|
||||||
$item->ParentID = null;
|
|| (is_array($foreignID) && in_array($item->ParentID, $foreignID))
|
||||||
$item->BaseClass = null;
|
|| $foreignID == $item->ParentID
|
||||||
$item->write();
|
) {
|
||||||
}
|
$item->ParentID = null;
|
||||||
}
|
$item->BaseClass = null;
|
||||||
|
$item->write();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
class CommentAdminTest extends SapphireTest {
|
class CommentAdminTest extends SapphireTest
|
||||||
public function testProvidePermissions() {
|
{
|
||||||
|
public function testProvidePermissions()
|
||||||
|
{
|
||||||
$commentAdmin = new CommentAdmin();
|
$commentAdmin = new CommentAdmin();
|
||||||
$locale = i18n::get_locale();
|
$locale = i18n::get_locale();
|
||||||
|
|
||||||
@ -24,12 +26,13 @@ class CommentAdminTest extends SapphireTest {
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
$this->assertEquals($expected, $commentAdmin->providePermissions());
|
$this->assertEquals($expected, $commentAdmin->providePermissions());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testGetEditForm() {
|
public function testGetEditForm()
|
||||||
|
{
|
||||||
$commentAdmin = new CommentAdmin();
|
$commentAdmin = new CommentAdmin();
|
||||||
$this->logInWithPermission('CMS_ACCESS_CommentAdmin');
|
$this->logInWithPermission('CMS_ACCESS_CommentAdmin');
|
||||||
$form = $commentAdmin->getEditForm();
|
$form = $commentAdmin->getEditForm();
|
||||||
$names = $this->getFormFieldNames($form);
|
$names = $this->getFormFieldNames($form);
|
||||||
$expected = array(
|
$expected = array(
|
||||||
'NewComments',
|
'NewComments',
|
||||||
@ -38,12 +41,15 @@ class CommentAdminTest extends SapphireTest {
|
|||||||
);
|
);
|
||||||
$this->assertEquals($expected, $names);
|
$this->assertEquals($expected, $names);
|
||||||
|
|
||||||
if($member = Member::currentUser()) $member->logOut();
|
if ($member = Member::currentUser()) {
|
||||||
|
$member->logOut();
|
||||||
|
}
|
||||||
|
|
||||||
$form = $commentAdmin->getEditForm();
|
$form = $commentAdmin->getEditForm();
|
||||||
}
|
}
|
||||||
|
|
||||||
private function getFormFieldNames($form) {
|
private function getFormFieldNames($form)
|
||||||
|
{
|
||||||
$result = array();
|
$result = array();
|
||||||
$fields = $form->Fields();
|
$fields = $form->Fields();
|
||||||
$tab = $fields->findOrMakeTab('Root');
|
$tab = $fields->findOrMakeTab('Root');
|
||||||
@ -53,5 +59,4 @@ class CommentAdminTest extends SapphireTest {
|
|||||||
}
|
}
|
||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
class CommentListTest extends FunctionalTest {
|
class CommentListTest extends FunctionalTest
|
||||||
|
{
|
||||||
|
|
||||||
public static $fixture_file = 'comments/tests/CommentsTest.yml';
|
public static $fixture_file = 'comments/tests/CommentsTest.yml';
|
||||||
|
|
||||||
@ -10,7 +11,8 @@ class CommentListTest extends FunctionalTest {
|
|||||||
'CommentableItemDisabled'
|
'CommentableItemDisabled'
|
||||||
);
|
);
|
||||||
|
|
||||||
public function setUp() {
|
public function setUp()
|
||||||
|
{
|
||||||
parent::setUp();
|
parent::setUp();
|
||||||
Config::nest();
|
Config::nest();
|
||||||
|
|
||||||
@ -34,20 +36,23 @@ class CommentListTest extends FunctionalTest {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function tearDown() {
|
public function tearDown()
|
||||||
|
{
|
||||||
Config::unnest();
|
Config::unnest();
|
||||||
parent::tearDown();
|
parent::tearDown();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testGetForeignClass() {
|
public function testGetForeignClass()
|
||||||
|
{
|
||||||
$item = $this->objFromFixture('CommentableItem', 'first');
|
$item = $this->objFromFixture('CommentableItem', 'first');
|
||||||
|
|
||||||
// This is the class the Comments are related to
|
// This is the class the Comments are related to
|
||||||
$this->assertEquals('CommentableItem',
|
$this->assertEquals('CommentableItem',
|
||||||
$item->Comments()->getForeignClass());
|
$item->Comments()->getForeignClass());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testAddNonComment() {
|
public function testAddNonComment()
|
||||||
|
{
|
||||||
$item = $this->objFromFixture('CommentableItem', 'first');
|
$item = $this->objFromFixture('CommentableItem', 'first');
|
||||||
$comments = $item->Comments();
|
$comments = $item->Comments();
|
||||||
$this->assertEquals(4, $comments->count());
|
$this->assertEquals(4, $comments->count());
|
||||||
@ -63,7 +68,8 @@ class CommentListTest extends FunctionalTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testAddComment() {
|
public function testAddComment()
|
||||||
|
{
|
||||||
$item = $this->objFromFixture('CommentableItem', 'first');
|
$item = $this->objFromFixture('CommentableItem', 'first');
|
||||||
$firstComment = $this->objFromFixture('Comment', 'firstComA');
|
$firstComment = $this->objFromFixture('Comment', 'firstComA');
|
||||||
$comments = $item->Comments();//->sort('Created');
|
$comments = $item->Comments();//->sort('Created');
|
||||||
@ -97,9 +103,10 @@ class CommentListTest extends FunctionalTest {
|
|||||||
);
|
);
|
||||||
$list = new CommentList('CommentableItem');
|
$list = new CommentList('CommentableItem');
|
||||||
$list->add($newComment);
|
$list->add($newComment);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testRemoveComment() {
|
public function testRemoveComment()
|
||||||
|
{
|
||||||
// remove by comment
|
// remove by comment
|
||||||
$item = $this->objFromFixture('CommentableItem', 'first');
|
$item = $this->objFromFixture('CommentableItem', 'first');
|
||||||
$this->assertEquals(4, $item->Comments()->count());
|
$this->assertEquals(4, $item->Comments()->count());
|
||||||
@ -114,7 +121,8 @@ class CommentListTest extends FunctionalTest {
|
|||||||
$this->assertEquals(2, $item->Comments()->count());
|
$this->assertEquals(2, $item->Comments()->count());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testRemoveNonComment() {
|
public function testRemoveNonComment()
|
||||||
|
{
|
||||||
$item = $this->objFromFixture('CommentableItem', 'first');
|
$item = $this->objFromFixture('CommentableItem', 'first');
|
||||||
$this->assertEquals(4, $item->Comments()->count());
|
$this->assertEquals(4, $item->Comments()->count());
|
||||||
$comments = $item->Comments();
|
$comments = $item->Comments();
|
||||||
@ -134,5 +142,4 @@ class CommentListTest extends FunctionalTest {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,17 +1,20 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
class CommentTestHelper {
|
class CommentTestHelper
|
||||||
|
{
|
||||||
/*
|
/*
|
||||||
This only works if the last section is not a field group, e.g. a Comments
|
This only works if the last section is not a field group, e.g. a Comments
|
||||||
field group inside of a Root.Settings tab will not work
|
field group inside of a Root.Settings tab will not work
|
||||||
*/
|
*/
|
||||||
public static function assertFieldsForTab($context, $tabName, $expected, $fields) {
|
public static function assertFieldsForTab($context, $tabName, $expected, $fields)
|
||||||
|
{
|
||||||
$tab = $fields->findOrMakeTab($tabName);
|
$tab = $fields->findOrMakeTab($tabName);
|
||||||
$fields = $tab->FieldList();
|
$fields = $tab->FieldList();
|
||||||
CommentTestHelper::assertFieldNames($context, $expected, $fields);
|
CommentTestHelper::assertFieldNames($context, $expected, $fields);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function assertFieldNames($context, $expected, $fields) {
|
public static function assertFieldNames($context, $expected, $fields)
|
||||||
|
{
|
||||||
$actual = array();
|
$actual = array();
|
||||||
foreach ($fields as $field) {
|
foreach ($fields as $field) {
|
||||||
if (get_class($field) == 'FieldGroup') {
|
if (get_class($field) == 'FieldGroup') {
|
||||||
|
@ -4,31 +4,35 @@
|
|||||||
* @package comments
|
* @package comments
|
||||||
* @subpackage tests
|
* @subpackage tests
|
||||||
*/
|
*/
|
||||||
class CommentingControllerTest extends FunctionalTest {
|
class CommentingControllerTest extends FunctionalTest
|
||||||
|
{
|
||||||
|
|
||||||
public static $fixture_file = 'CommentsTest.yml';
|
public static $fixture_file = 'CommentsTest.yml';
|
||||||
|
|
||||||
protected $extraDataObjects = array(
|
protected $extraDataObjects = array(
|
||||||
'CommentableItem'
|
'CommentableItem'
|
||||||
);
|
);
|
||||||
|
|
||||||
protected $securityEnabled;
|
protected $securityEnabled;
|
||||||
|
|
||||||
public function tearDown() {
|
public function tearDown()
|
||||||
if($this->securityEnabled) {
|
{
|
||||||
SecurityToken::enable();
|
if ($this->securityEnabled) {
|
||||||
} else {
|
SecurityToken::enable();
|
||||||
SecurityToken::disable();
|
} else {
|
||||||
}
|
SecurityToken::disable();
|
||||||
parent::tearDown();
|
}
|
||||||
}
|
parent::tearDown();
|
||||||
|
}
|
||||||
|
|
||||||
public function setUp() {
|
public function setUp()
|
||||||
parent::setUp();
|
{
|
||||||
$this->securityEnabled = SecurityToken::is_enabled();
|
parent::setUp();
|
||||||
}
|
$this->securityEnabled = SecurityToken::is_enabled();
|
||||||
|
}
|
||||||
|
|
||||||
public function testApprove() {
|
public function testApprove()
|
||||||
|
{
|
||||||
SecurityToken::disable();
|
SecurityToken::disable();
|
||||||
|
|
||||||
// mark a comment as spam then approve it
|
// mark a comment as spam then approve it
|
||||||
@ -49,10 +53,10 @@ class CommentingControllerTest extends FunctionalTest {
|
|||||||
// try and approve a non existent comment
|
// try and approve a non existent comment
|
||||||
$response = $this->get('CommentingController/approve/100000');
|
$response = $this->get('CommentingController/approve/100000');
|
||||||
$this->assertEquals(404, $response->getStatusCode());
|
$this->assertEquals(404, $response->getStatusCode());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testSetGetOwnerController() {
|
public function testSetGetOwnerController()
|
||||||
|
{
|
||||||
$commController = new CommentingController();
|
$commController = new CommentingController();
|
||||||
$commController->setOwnerController(Controller::curr());
|
$commController->setOwnerController(Controller::curr());
|
||||||
$this->assertEquals(Controller::curr(), $commController->getOwnerController());
|
$this->assertEquals(Controller::curr(), $commController->getOwnerController());
|
||||||
@ -60,7 +64,8 @@ class CommentingControllerTest extends FunctionalTest {
|
|||||||
$this->assertNull($commController->getOwnerController());
|
$this->assertNull($commController->getOwnerController());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testHam() {
|
public function testHam()
|
||||||
|
{
|
||||||
SecurityToken::disable();
|
SecurityToken::disable();
|
||||||
|
|
||||||
// mark a comment as spam then ham it
|
// mark a comment as spam then ham it
|
||||||
@ -81,10 +86,10 @@ class CommentingControllerTest extends FunctionalTest {
|
|||||||
// try and ham a non existent comment
|
// try and ham a non existent comment
|
||||||
$response = $this->get('CommentingController/ham/100000');
|
$response = $this->get('CommentingController/ham/100000');
|
||||||
$this->assertEquals(404, $response->getStatusCode());
|
$this->assertEquals(404, $response->getStatusCode());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testSpam() {
|
public function testSpam()
|
||||||
|
{
|
||||||
// mark a comment as approved then spam it
|
// mark a comment as approved then spam it
|
||||||
$this->logInWithPermission('CMS_ACCESS_CommentAdmin');
|
$this->logInWithPermission('CMS_ACCESS_CommentAdmin');
|
||||||
$comment = $this->objFromFixture('Comment', 'firstComA');
|
$comment = $this->objFromFixture('Comment', 'firstComA');
|
||||||
@ -103,10 +108,10 @@ class CommentingControllerTest extends FunctionalTest {
|
|||||||
// try and spam a non existent comment
|
// try and spam a non existent comment
|
||||||
$response = $this->get('CommentingController/spam/100000');
|
$response = $this->get('CommentingController/spam/100000');
|
||||||
$this->assertEquals(404, $response->getStatusCode());
|
$this->assertEquals(404, $response->getStatusCode());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testRSS() {
|
public function testRSS()
|
||||||
|
{
|
||||||
// Delete the newly added children of firstComA so as not to have to recalculate values below
|
// Delete the newly added children of firstComA so as not to have to recalculate values below
|
||||||
$this->objFromFixture('Comment', 'firstComAChild1')->delete();
|
$this->objFromFixture('Comment', 'firstComAChild1')->delete();
|
||||||
$this->objFromFixture('Comment', 'firstComAChild2')->delete();
|
$this->objFromFixture('Comment', 'firstComAChild2')->delete();
|
||||||
@ -115,29 +120,29 @@ class CommentingControllerTest extends FunctionalTest {
|
|||||||
$item = $this->objFromFixture('CommentableItem', 'first');
|
$item = $this->objFromFixture('CommentableItem', 'first');
|
||||||
|
|
||||||
|
|
||||||
// comments sitewide
|
// comments sitewide
|
||||||
$response = $this->get('CommentingController/rss');
|
$response = $this->get('CommentingController/rss');
|
||||||
$this->assertEquals(10, substr_count($response->getBody(), "<item>"), "10 approved, non spam comments on page 1");
|
$this->assertEquals(10, substr_count($response->getBody(), "<item>"), "10 approved, non spam comments on page 1");
|
||||||
|
|
||||||
$response = $this->get('CommentingController/rss?start=10');
|
$response = $this->get('CommentingController/rss?start=10');
|
||||||
$this->assertEquals(4, substr_count($response->getBody(), "<item>"), "3 approved, non spam comments on page 2");
|
$this->assertEquals(4, substr_count($response->getBody(), "<item>"), "3 approved, non spam comments on page 2");
|
||||||
|
|
||||||
// all comments on a type
|
// all comments on a type
|
||||||
$response = $this->get('CommentingController/rss/CommentableItem');
|
$response = $this->get('CommentingController/rss/CommentableItem');
|
||||||
$this->assertEquals(10, substr_count($response->getBody(), "<item>"));
|
$this->assertEquals(10, substr_count($response->getBody(), "<item>"));
|
||||||
|
|
||||||
$response = $this->get('CommentingController/rss/CommentableItem?start=10');
|
$response = $this->get('CommentingController/rss/CommentableItem?start=10');
|
||||||
$this->assertEquals(4, substr_count($response->getBody(), "<item>"), "3 approved, non spam comments on page 2");
|
$this->assertEquals(4, substr_count($response->getBody(), "<item>"), "3 approved, non spam comments on page 2");
|
||||||
|
|
||||||
// specific page
|
// specific page
|
||||||
$response = $this->get('CommentingController/rss/CommentableItem/'.$item->ID);
|
$response = $this->get('CommentingController/rss/CommentableItem/'.$item->ID);
|
||||||
$this->assertEquals(1, substr_count($response->getBody(), "<item>"));
|
$this->assertEquals(1, substr_count($response->getBody(), "<item>"));
|
||||||
$this->assertContains('<dc:creator>FA</dc:creator>', $response->getBody());
|
$this->assertContains('<dc:creator>FA</dc:creator>', $response->getBody());
|
||||||
|
|
||||||
// test accessing comments on a type that doesn't exist
|
// test accessing comments on a type that doesn't exist
|
||||||
$response = $this->get('CommentingController/rss/Fake');
|
$response = $this->get('CommentingController/rss/Fake');
|
||||||
$this->assertEquals(404, $response->getStatusCode());
|
$this->assertEquals(404, $response->getStatusCode());
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is returning a 404 which looks logical code wise but also a bit weird.
|
// This is returning a 404 which looks logical code wise but also a bit weird.
|
||||||
// Test module on a clean install and check what the actual URL is first
|
// Test module on a clean install and check what the actual URL is first
|
||||||
@ -177,7 +182,8 @@ class CommentingControllerTest extends FunctionalTest {
|
|||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public function testCommentsFormUsePreview() {
|
public function testCommentsFormUsePreview()
|
||||||
|
{
|
||||||
// test with preview on
|
// test with preview on
|
||||||
Config::inst()->update('CommentableItem', 'comments', array(
|
Config::inst()->update('CommentableItem', 'comments', array(
|
||||||
'use_preview' => true
|
'use_preview' => true
|
||||||
@ -208,67 +214,66 @@ class CommentingControllerTest extends FunctionalTest {
|
|||||||
CommentTestHelper::assertFieldNames($this, $expected, $commentsFields);
|
CommentTestHelper::assertFieldNames($this, $expected, $commentsFields);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testCommentsForm() {
|
public function testCommentsForm()
|
||||||
|
{
|
||||||
// Delete the newly added children of firstComA so as not to change this test
|
// Delete the newly added children of firstComA so as not to change this test
|
||||||
$this->objFromFixture('Comment', 'firstComAChild1')->delete();
|
$this->objFromFixture('Comment', 'firstComAChild1')->delete();
|
||||||
$this->objFromFixture('Comment', 'firstComAChild2')->delete();
|
$this->objFromFixture('Comment', 'firstComAChild2')->delete();
|
||||||
$this->objFromFixture('Comment', 'firstComAChild3')->delete();
|
$this->objFromFixture('Comment', 'firstComAChild3')->delete();
|
||||||
|
|
||||||
SecurityToken::disable();
|
SecurityToken::disable();
|
||||||
$this->autoFollowRedirection = false;
|
$this->autoFollowRedirection = false;
|
||||||
$parent = $this->objFromFixture('CommentableItem', 'first');
|
$parent = $this->objFromFixture('CommentableItem', 'first');
|
||||||
|
|
||||||
// Test posting to base comment
|
// Test posting to base comment
|
||||||
$response = $this->post('CommentingController/CommentsForm',
|
$response = $this->post('CommentingController/CommentsForm',
|
||||||
array(
|
array(
|
||||||
'Name' => 'Poster',
|
'Name' => 'Poster',
|
||||||
'Email' => 'guy@test.com',
|
'Email' => 'guy@test.com',
|
||||||
'Comment' => 'My Comment',
|
'Comment' => 'My Comment',
|
||||||
'ParentID' => $parent->ID,
|
'ParentID' => $parent->ID,
|
||||||
'BaseClass' => 'CommentableItem',
|
'BaseClass' => 'CommentableItem',
|
||||||
'action_doPostComment' => 'Post'
|
'action_doPostComment' => 'Post'
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
$this->assertEquals(302, $response->getStatusCode());
|
$this->assertEquals(302, $response->getStatusCode());
|
||||||
$this->assertStringStartsWith('CommentableItem_Controller#comment-', $response->getHeader('Location'));
|
$this->assertStringStartsWith('CommentableItem_Controller#comment-', $response->getHeader('Location'));
|
||||||
$this->assertDOSEquals(
|
$this->assertDOSEquals(
|
||||||
array(array(
|
array(array(
|
||||||
'Name' => 'Poster',
|
'Name' => 'Poster',
|
||||||
'Email' => 'guy@test.com',
|
'Email' => 'guy@test.com',
|
||||||
'Comment' => 'My Comment',
|
'Comment' => 'My Comment',
|
||||||
'ParentID' => $parent->ID,
|
'ParentID' => $parent->ID,
|
||||||
'BaseClass' => 'CommentableItem',
|
'BaseClass' => 'CommentableItem',
|
||||||
)),
|
)),
|
||||||
Comment::get()->filter('Email', 'guy@test.com')
|
Comment::get()->filter('Email', 'guy@test.com')
|
||||||
);
|
);
|
||||||
|
|
||||||
// Test posting to parent comment
|
// Test posting to parent comment
|
||||||
$parentComment = $this->objFromFixture('Comment', 'firstComA');
|
$parentComment = $this->objFromFixture('Comment', 'firstComA');
|
||||||
$this->assertEquals(0, $parentComment->ChildComments()->count());
|
$this->assertEquals(0, $parentComment->ChildComments()->count());
|
||||||
|
|
||||||
$response = $this->post(
|
$response = $this->post(
|
||||||
'CommentingController/reply/'.$parentComment->ID,
|
'CommentingController/reply/'.$parentComment->ID,
|
||||||
array(
|
array(
|
||||||
'Name' => 'Test Author',
|
'Name' => 'Test Author',
|
||||||
'Email' => 'test@test.com',
|
'Email' => 'test@test.com',
|
||||||
'Comment' => 'Making a reply to firstComA',
|
'Comment' => 'Making a reply to firstComA',
|
||||||
'ParentID' => $parent->ID,
|
'ParentID' => $parent->ID,
|
||||||
'BaseClass' => 'CommentableItem',
|
'BaseClass' => 'CommentableItem',
|
||||||
'ParentCommentID' => $parentComment->ID,
|
'ParentCommentID' => $parentComment->ID,
|
||||||
'action_doPostComment' => 'Post'
|
'action_doPostComment' => 'Post'
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
$this->assertEquals(302, $response->getStatusCode());
|
$this->assertEquals(302, $response->getStatusCode());
|
||||||
$this->assertStringStartsWith('CommentableItem_Controller#comment-', $response->getHeader('Location'));
|
$this->assertStringStartsWith('CommentableItem_Controller#comment-', $response->getHeader('Location'));
|
||||||
$this->assertDOSEquals(array(array(
|
$this->assertDOSEquals(array(array(
|
||||||
'Name' => 'Test Author',
|
'Name' => 'Test Author',
|
||||||
'Email' => 'test@test.com',
|
'Email' => 'test@test.com',
|
||||||
'Comment' => 'Making a reply to firstComA',
|
'Comment' => 'Making a reply to firstComA',
|
||||||
'ParentID' => $parent->ID,
|
'ParentID' => $parent->ID,
|
||||||
'BaseClass' => 'CommentableItem',
|
'BaseClass' => 'CommentableItem',
|
||||||
'ParentCommentID' => $parentComment->ID
|
'ParentCommentID' => $parentComment->ID
|
||||||
)), $parentComment->ChildComments());
|
)), $parentComment->ChildComments());
|
||||||
|
}
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,15 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
class CommentingTest extends SapphireTest {
|
class CommentingTest extends SapphireTest
|
||||||
|
{
|
||||||
|
|
||||||
public function setUpOnce() {
|
public function setUpOnce()
|
||||||
|
{
|
||||||
parent::setUpOnce();
|
parent::setUpOnce();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testDeprecatedMethods() {
|
public function testDeprecatedMethods()
|
||||||
|
{
|
||||||
$methods = array('add', 'remove', 'has_commenting');
|
$methods = array('add', 'remove', 'has_commenting');
|
||||||
foreach ($methods as $methodName) {
|
foreach ($methods as $methodName) {
|
||||||
try {
|
try {
|
||||||
@ -20,8 +23,9 @@ class CommentingTest extends SapphireTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public function test_set_config_value() {
|
public function test_set_config_value()
|
||||||
// public static function set_config_value($class, $key, $value = false) {
|
{
|
||||||
|
// public static function set_config_value($class, $key, $value = false) {
|
||||||
Commenting::set_config_value(
|
Commenting::set_config_value(
|
||||||
'CommentableItem',
|
'CommentableItem',
|
||||||
'comments_holder_id',
|
'comments_holder_id',
|
||||||
@ -44,7 +48,7 @@ class CommentingTest extends SapphireTest {
|
|||||||
'all_items_actually_commentsextension'
|
'all_items_actually_commentsextension'
|
||||||
);
|
);
|
||||||
|
|
||||||
$config = Config::inst()->get(
|
$config = Config::inst()->get(
|
||||||
'CommentsExtension',
|
'CommentsExtension',
|
||||||
'comments'
|
'comments'
|
||||||
);
|
);
|
||||||
@ -53,10 +57,11 @@ class CommentingTest extends SapphireTest {
|
|||||||
'all_items_actually_commentsextension',
|
'all_items_actually_commentsextension',
|
||||||
$actual
|
$actual
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function test_get_config_value() {
|
public function test_get_config_value()
|
||||||
Config::inst()->update('CommentableItem', 'comments',
|
{
|
||||||
|
Config::inst()->update('CommentableItem', 'comments',
|
||||||
array(
|
array(
|
||||||
'comments_holder_id' => 'commentable_item'
|
'comments_holder_id' => 'commentable_item'
|
||||||
)
|
)
|
||||||
@ -82,10 +87,11 @@ class CommentingTest extends SapphireTest {
|
|||||||
'Member does not have commenting enabled'
|
'Member does not have commenting enabled'
|
||||||
);
|
);
|
||||||
Commenting::get_config_value('Member', 'comments_holder_id');
|
Commenting::get_config_value('Member', 'comments_holder_id');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function test_config_value_equals() {
|
public function test_config_value_equals()
|
||||||
Config::inst()->update('CommentableItem', 'comments',
|
{
|
||||||
|
Config::inst()->update('CommentableItem', 'comments',
|
||||||
array(
|
array(
|
||||||
'comments_holder_id' => 'some_value'
|
'comments_holder_id' => 'some_value'
|
||||||
)
|
)
|
||||||
@ -106,9 +112,10 @@ class CommentingTest extends SapphireTest {
|
|||||||
'not_some_value'
|
'not_some_value'
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function test_add() {
|
public function test_add()
|
||||||
|
{
|
||||||
Commenting::add('Member', array('comments_holder_id' => 'test_add_value'));
|
Commenting::add('Member', array('comments_holder_id' => 'test_add_value'));
|
||||||
|
|
||||||
$config = Config::inst()->get(
|
$config = Config::inst()->get(
|
||||||
@ -136,13 +143,14 @@ class CommentingTest extends SapphireTest {
|
|||||||
|
|
||||||
$this->setExpectedException('InvalidArgumentException', "\$settings needs to be an array or null");
|
$this->setExpectedException('InvalidArgumentException', "\$settings needs to be an array or null");
|
||||||
Commenting::add('Member', 'illegal format, not an array');
|
Commenting::add('Member', 'illegal format, not an array');
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function test_can_member_post() {
|
public function test_can_member_post()
|
||||||
|
{
|
||||||
// logout
|
// logout
|
||||||
if($member = Member::currentUser()) $member->logOut();
|
if ($member = Member::currentUser()) {
|
||||||
|
$member->logOut();
|
||||||
|
}
|
||||||
|
|
||||||
Config::inst()->update('CommentableItem', 'comments',
|
Config::inst()->update('CommentableItem', 'comments',
|
||||||
array(
|
array(
|
||||||
@ -168,6 +176,5 @@ class CommentingTest extends SapphireTest {
|
|||||||
);
|
);
|
||||||
|
|
||||||
$this->assertTrue(Commenting::can_member_post('CommentableItem'));
|
$this->assertTrue(Commenting::can_member_post('CommentableItem'));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
class CommentsExtensionTest extends SapphireTest {
|
class CommentsExtensionTest extends SapphireTest
|
||||||
|
{
|
||||||
|
|
||||||
public static $fixture_file = 'comments/tests/CommentsTest.yml';
|
public static $fixture_file = 'comments/tests/CommentsTest.yml';
|
||||||
|
|
||||||
@ -10,7 +11,8 @@ class CommentsExtensionTest extends SapphireTest {
|
|||||||
'CommentableItemDisabled'
|
'CommentableItemDisabled'
|
||||||
);
|
);
|
||||||
|
|
||||||
public function setUp() {
|
public function setUp()
|
||||||
|
{
|
||||||
parent::setUp();
|
parent::setUp();
|
||||||
Config::nest();
|
Config::nest();
|
||||||
|
|
||||||
@ -38,20 +40,24 @@ class CommentsExtensionTest extends SapphireTest {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function tearDown() {
|
public function tearDown()
|
||||||
|
{
|
||||||
Config::unnest();
|
Config::unnest();
|
||||||
parent::tearDown();
|
parent::tearDown();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPopulateDefaults() {
|
public function testPopulateDefaults()
|
||||||
$this->markTestSkipped('TODO');
|
{
|
||||||
}
|
$this->markTestSkipped('TODO');
|
||||||
|
}
|
||||||
|
|
||||||
public function testUpdateSettingsFields() {
|
public function testUpdateSettingsFields()
|
||||||
|
{
|
||||||
$this->markTestSkipped('This needs SiteTree installed');
|
$this->markTestSkipped('This needs SiteTree installed');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testGetModerationRequired() {
|
public function testGetModerationRequired()
|
||||||
|
{
|
||||||
|
|
||||||
// the 3 options take precedence in this order, executed if true
|
// the 3 options take precedence in this order, executed if true
|
||||||
Config::inst()->update('CommentableItem', 'comments', array(
|
Config::inst()->update('CommentableItem', 'comments', array(
|
||||||
@ -90,10 +96,11 @@ class CommentsExtensionTest extends SapphireTest {
|
|||||||
'require_moderation_nonmembers' => false
|
'require_moderation_nonmembers' => false
|
||||||
));
|
));
|
||||||
$this->assertEquals('None', $item->getModerationRequired());
|
$this->assertEquals('None', $item->getModerationRequired());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testGetCommentsRequireLogin() {
|
public function testGetCommentsRequireLogin()
|
||||||
Config::inst()->update('CommentableItem', 'comments', array(
|
{
|
||||||
|
Config::inst()->update('CommentableItem', 'comments', array(
|
||||||
'require_login_cms' => true
|
'require_login_cms' => true
|
||||||
));
|
));
|
||||||
|
|
||||||
@ -115,26 +122,30 @@ class CommentsExtensionTest extends SapphireTest {
|
|||||||
'require_login' => true
|
'require_login' => true
|
||||||
));
|
));
|
||||||
$this->assertTrue($item->getCommentsRequireLogin());
|
$this->assertTrue($item->getCommentsRequireLogin());
|
||||||
|
}
|
||||||
|
|
||||||
}
|
public function testAllComments()
|
||||||
|
{
|
||||||
|
$this->markTestSkipped('TODO');
|
||||||
|
}
|
||||||
|
|
||||||
public function testAllComments() {
|
public function testAllVisibleComments()
|
||||||
$this->markTestSkipped('TODO');
|
{
|
||||||
}
|
$this->markTestSkipped('TODO');
|
||||||
|
}
|
||||||
|
|
||||||
public function testAllVisibleComments() {
|
public function testComments()
|
||||||
$this->markTestSkipped('TODO');
|
{
|
||||||
}
|
$this->markTestSkipped('TODO');
|
||||||
|
}
|
||||||
|
|
||||||
public function testComments() {
|
public function testGetCommentsEnabled()
|
||||||
$this->markTestSkipped('TODO');
|
{
|
||||||
}
|
$this->markTestSkipped('TODO');
|
||||||
|
}
|
||||||
|
|
||||||
public function testGetCommentsEnabled() {
|
public function testGetCommentHolderID()
|
||||||
$this->markTestSkipped('TODO');
|
{
|
||||||
}
|
|
||||||
|
|
||||||
public function testGetCommentHolderID() {
|
|
||||||
$item = $this->objFromFixture('CommentableItem', 'first');
|
$item = $this->objFromFixture('CommentableItem', 'first');
|
||||||
Config::inst()->update('CommentableItem', 'comments', array(
|
Config::inst()->update('CommentableItem', 'comments', array(
|
||||||
'comments_holder_id' => 'commentid_test1',
|
'comments_holder_id' => 'commentid_test1',
|
||||||
@ -145,47 +156,53 @@ class CommentsExtensionTest extends SapphireTest {
|
|||||||
'comments_holder_id' => 'commtentid_test_another',
|
'comments_holder_id' => 'commtentid_test_another',
|
||||||
));
|
));
|
||||||
$this->assertEquals('commtentid_test_another', $item->getCommentHolderID());
|
$this->assertEquals('commtentid_test_another', $item->getCommentHolderID());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public function testGetPostingRequiredPermission() {
|
public function testGetPostingRequiredPermission()
|
||||||
$this->markTestSkipped('TODO');
|
{
|
||||||
}
|
$this->markTestSkipped('TODO');
|
||||||
|
}
|
||||||
|
|
||||||
public function testCanModerateComments() {
|
public function testCanModerateComments()
|
||||||
|
{
|
||||||
// ensure nobody logged in
|
// ensure nobody logged in
|
||||||
if(Member::currentUser()) { Member::currentUser()->logOut(); }
|
if (Member::currentUser()) {
|
||||||
|
Member::currentUser()->logOut();
|
||||||
|
}
|
||||||
|
|
||||||
$item = $this->objFromFixture('CommentableItem', 'first');
|
$item = $this->objFromFixture('CommentableItem', 'first');
|
||||||
$this->assertFalse($item->canModerateComments());
|
$this->assertFalse($item->canModerateComments());
|
||||||
|
|
||||||
$this->logInWithPermission('CMS_ACCESS_CommentAdmin');
|
$this->logInWithPermission('CMS_ACCESS_CommentAdmin');
|
||||||
$this->assertTrue($item->canModerateComments());
|
$this->assertTrue($item->canModerateComments());
|
||||||
|
}
|
||||||
|
|
||||||
}
|
public function testGetCommentRSSLink()
|
||||||
|
{
|
||||||
public function testGetCommentRSSLink() {
|
$item = $this->objFromFixture('CommentableItem', 'first');
|
||||||
$item = $this->objFromFixture('CommentableItem', 'first');
|
$link = $item->getCommentRSSLink();
|
||||||
$link = $item->getCommentRSSLink();
|
$this->assertEquals('/CommentingController/rss', $link);
|
||||||
$this->assertEquals('/CommentingController/rss', $link);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public function testGetCommentRSSLinkPage() {
|
public function testGetCommentRSSLinkPage()
|
||||||
$item = $this->objFromFixture('CommentableItem', 'first');
|
{
|
||||||
|
$item = $this->objFromFixture('CommentableItem', 'first');
|
||||||
$page = $item->getCommentRSSLinkPage();
|
$page = $item->getCommentRSSLinkPage();
|
||||||
$this->assertEquals(
|
$this->assertEquals(
|
||||||
'/CommentingController/rss/CommentableItem/' . $item->ID,
|
'/CommentingController/rss/CommentableItem/' . $item->ID,
|
||||||
$page
|
$page
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testCommentsForm() {
|
public function testCommentsForm()
|
||||||
|
{
|
||||||
Config::inst()->update('CommentableItem', 'comments', array(
|
Config::inst()->update('CommentableItem', 'comments', array(
|
||||||
'include_js' => false
|
'include_js' => false
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
$item = $this->objFromFixture('CommentableItem', 'first');
|
$item = $this->objFromFixture('CommentableItem', 'first');
|
||||||
|
|
||||||
// The comments form is HTML to do assertions by contains
|
// The comments form is HTML to do assertions by contains
|
||||||
$cf = $item->CommentsForm();
|
$cf = $item->CommentsForm();
|
||||||
@ -255,13 +272,15 @@ class CommentsExtensionTest extends SapphireTest {
|
|||||||
),
|
),
|
||||||
$backend->get_javascript()
|
$backend->get_javascript()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testAttachedToSiteTree() {
|
public function testAttachedToSiteTree()
|
||||||
$this->markTestSkipped('TODO');
|
{
|
||||||
}
|
$this->markTestSkipped('TODO');
|
||||||
|
}
|
||||||
|
|
||||||
public function testPagedComments() {
|
public function testPagedComments()
|
||||||
|
{
|
||||||
$item = $this->objFromFixture('CommentableItem', 'first');
|
$item = $this->objFromFixture('CommentableItem', 'first');
|
||||||
// Ensure Created times are set, as order not guaranteed if all set to 0
|
// Ensure Created times are set, as order not guaranteed if all set to 0
|
||||||
$comments = $item->PagedComments()->sort('ID');
|
$comments = $item->PagedComments()->sort('ID');
|
||||||
@ -276,7 +295,7 @@ class CommentsExtensionTest extends SapphireTest {
|
|||||||
$results = $item->PagedComments()->toArray();
|
$results = $item->PagedComments()->toArray();
|
||||||
|
|
||||||
foreach ($results as $result) {
|
foreach ($results as $result) {
|
||||||
$result->sourceQueryParams = null;
|
$result->sourceQueryParams = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->assertEquals(
|
$this->assertEquals(
|
||||||
@ -297,23 +316,26 @@ class CommentsExtensionTest extends SapphireTest {
|
|||||||
);
|
);
|
||||||
|
|
||||||
$this->assertEquals(4, sizeof($results));
|
$this->assertEquals(4, sizeof($results));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testGetCommentsOption() {
|
public function testGetCommentsOption()
|
||||||
$this->markTestSkipped('TODO');
|
{
|
||||||
}
|
$this->markTestSkipped('TODO');
|
||||||
|
}
|
||||||
|
|
||||||
public function testUpdateModerationFields() {
|
public function testUpdateModerationFields()
|
||||||
$this->markTestSkipped('TODO');
|
{
|
||||||
}
|
$this->markTestSkipped('TODO');
|
||||||
|
}
|
||||||
|
|
||||||
public function testUpdateCMSFields() {
|
public function testUpdateCMSFields()
|
||||||
|
{
|
||||||
Config::inst()->update('CommentableItem', 'comments', array(
|
Config::inst()->update('CommentableItem', 'comments', array(
|
||||||
'require_login_cms' => false
|
'require_login_cms' => false
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
$this->logInWithPermission('ADMIN');
|
$this->logInWithPermission('ADMIN');
|
||||||
$item = $this->objFromFixture('CommentableItem', 'first');
|
$item = $this->objFromFixture('CommentableItem', 'first');
|
||||||
$item->ProvideComments = true;
|
$item->ProvideComments = true;
|
||||||
$item->write();
|
$item->write();
|
||||||
$fields = $item->getCMSFields();
|
$fields = $item->getCMSFields();
|
||||||
@ -376,11 +398,12 @@ class CommentsExtensionTest extends SapphireTest {
|
|||||||
array('ProvideComments', 'CommentsRequireLogin'),
|
array('ProvideComments', 'CommentsRequireLogin'),
|
||||||
$fields
|
$fields
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public function testDeprecatedMethods() {
|
public function testDeprecatedMethods()
|
||||||
|
{
|
||||||
$item = $this->objFromFixture('CommentableItem', 'first');
|
$item = $this->objFromFixture('CommentableItem', 'first');
|
||||||
$methodNames = array(
|
$methodNames = array(
|
||||||
'getRssLinkPage',
|
'getRssLinkPage',
|
||||||
@ -403,7 +426,5 @@ class CommentsExtensionTest extends SapphireTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ooh, $this->setExpectedException('ExpectedException', 'Expected Message');
|
// ooh, $this->setExpectedException('ExpectedException', 'Expected Message');
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
class CommentsGridFieldActionTest extends SapphireTest {
|
class CommentsGridFieldActionTest extends SapphireTest
|
||||||
|
{
|
||||||
|
|
||||||
/** @var ArrayList */
|
/** @var ArrayList */
|
||||||
protected $list;
|
protected $list;
|
||||||
@ -11,7 +12,8 @@ class CommentsGridFieldActionTest extends SapphireTest {
|
|||||||
/** @var Form */
|
/** @var Form */
|
||||||
protected $form;
|
protected $form;
|
||||||
|
|
||||||
public function setUp() {
|
public function setUp()
|
||||||
|
{
|
||||||
parent::setUp();
|
parent::setUp();
|
||||||
$this->list = new DataList('GridFieldAction_Delete_Team');
|
$this->list = new DataList('GridFieldAction_Delete_Team');
|
||||||
$config = CommentsGridFieldConfig::create()->addComponent(new GridFieldDeleteAction());
|
$config = CommentsGridFieldConfig::create()->addComponent(new GridFieldDeleteAction());
|
||||||
@ -19,7 +21,8 @@ class CommentsGridFieldActionTest extends SapphireTest {
|
|||||||
$this->form = new Form(new Controller(), 'mockform', new FieldList(array($this->gridField)), new FieldList());
|
$this->form = new Form(new Controller(), 'mockform', new FieldList(array($this->gridField)), new FieldList());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testAugmentColumns() {
|
public function testAugmentColumns()
|
||||||
|
{
|
||||||
$action = new CommentsGridFieldAction();
|
$action = new CommentsGridFieldAction();
|
||||||
|
|
||||||
// an entry called 'Actions' is added to the columns array
|
// an entry called 'Actions' is added to the columns array
|
||||||
@ -32,32 +35,36 @@ class CommentsGridFieldActionTest extends SapphireTest {
|
|||||||
$action->augmentColumns($this->gridField, $columns);
|
$action->augmentColumns($this->gridField, $columns);
|
||||||
$expected = array('Actions');
|
$expected = array('Actions');
|
||||||
$this->assertEquals($expected, $columns);
|
$this->assertEquals($expected, $columns);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testGetColumnAttributes() {
|
public function testGetColumnAttributes()
|
||||||
$action = new CommentsGridFieldAction();
|
{
|
||||||
|
$action = new CommentsGridFieldAction();
|
||||||
$record = new Comment();
|
$record = new Comment();
|
||||||
$attrs = $action->getColumnAttributes($this->gridField, $record, 'Comment');
|
$attrs = $action->getColumnAttributes($this->gridField, $record, 'Comment');
|
||||||
$this->assertEquals(array('class' => 'col-buttons'), $attrs);
|
$this->assertEquals(array('class' => 'col-buttons'), $attrs);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testGetColumnMetadata() {
|
public function testGetColumnMetadata()
|
||||||
$action = new CommentsGridFieldAction();
|
{
|
||||||
|
$action = new CommentsGridFieldAction();
|
||||||
$result = $action->getColumnMetadata($this->gridField, 'Actions');
|
$result = $action->getColumnMetadata($this->gridField, 'Actions');
|
||||||
$this->assertEquals(array('title' => ''), $result);
|
$this->assertEquals(array('title' => ''), $result);
|
||||||
$result = $action->getColumnMetadata($this->gridField, 'SomethingElse');
|
$result = $action->getColumnMetadata($this->gridField, 'SomethingElse');
|
||||||
$this->assertNull($result);
|
$this->assertNull($result);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testGetColumnsHandled() {
|
public function testGetColumnsHandled()
|
||||||
$action = new CommentsGridFieldAction();
|
{
|
||||||
|
$action = new CommentsGridFieldAction();
|
||||||
$result = $action->getColumnsHandled($this->gridField);
|
$result = $action->getColumnsHandled($this->gridField);
|
||||||
$this->assertEquals(array('Actions'), $result);
|
$this->assertEquals(array('Actions'), $result);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testGetColumnContent() {
|
public function testGetColumnContent()
|
||||||
|
{
|
||||||
$this->logInWithPermission('CMS_ACCESS_CommentAdmin');
|
$this->logInWithPermission('CMS_ACCESS_CommentAdmin');
|
||||||
$action = new CommentsGridFieldAction();
|
$action = new CommentsGridFieldAction();
|
||||||
$record = new Comment();
|
$record = new Comment();
|
||||||
$record->Name = 'Name of commeter';
|
$record->Name = 'Name of commeter';
|
||||||
$record->Comment = 'This is a comment';
|
$record->Comment = 'This is a comment';
|
||||||
@ -87,17 +94,19 @@ class CommentsGridFieldActionTest extends SapphireTest {
|
|||||||
$html = $action->getColumnContent($this->gridField, $record, 'Comment');
|
$html = $action->getColumnContent($this->gridField, $record, 'Comment');
|
||||||
$this->assertNotContains($approveAction, $html);
|
$this->assertNotContains($approveAction, $html);
|
||||||
$this->assertContains($spamAction, $html);
|
$this->assertContains($spamAction, $html);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testGetActions() {
|
public function testGetActions()
|
||||||
$action = new CommentsGridFieldAction();
|
{
|
||||||
|
$action = new CommentsGridFieldAction();
|
||||||
$result = $action->getActions($this->gridField);
|
$result = $action->getActions($this->gridField);
|
||||||
$this->assertEquals(array('spam', 'approve'), $result);
|
$this->assertEquals(array('spam', 'approve'), $result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public function testHandleAction() {
|
public function testHandleAction()
|
||||||
$action = new CommentsGridFieldAction();
|
{
|
||||||
|
$action = new CommentsGridFieldAction();
|
||||||
$record = new Comment();
|
$record = new Comment();
|
||||||
$record->Name = 'Name of commeter';
|
$record->Name = 'Name of commeter';
|
||||||
$record->Comment = 'This is a comment';
|
$record->Comment = 'This is a comment';
|
||||||
@ -105,7 +114,7 @@ class CommentsGridFieldActionTest extends SapphireTest {
|
|||||||
$recordID = $record->ID;
|
$recordID = $record->ID;
|
||||||
$arguments = array('RecordID' => $recordID);
|
$arguments = array('RecordID' => $recordID);
|
||||||
$data = array();
|
$data = array();
|
||||||
$result = $action->handleAction($this->gridField, 'spam', $arguments, $data );
|
$result = $action->handleAction($this->gridField, 'spam', $arguments, $data);
|
||||||
$this->assertEquals(200, Controller::curr()->getResponse()->getStatusCode());
|
$this->assertEquals(200, Controller::curr()->getResponse()->getStatusCode());
|
||||||
$this->assertEquals(
|
$this->assertEquals(
|
||||||
'Comment marked as spam.',
|
'Comment marked as spam.',
|
||||||
@ -116,7 +125,7 @@ class CommentsGridFieldActionTest extends SapphireTest {
|
|||||||
$this->assertEquals(1, $record->IsSpam);
|
$this->assertEquals(1, $record->IsSpam);
|
||||||
|
|
||||||
//getStatusDescription
|
//getStatusDescription
|
||||||
$result = $action->handleAction($this->gridField, 'approve', $arguments, $data );
|
$result = $action->handleAction($this->gridField, 'approve', $arguments, $data);
|
||||||
$this->assertEquals(200, Controller::curr()->getResponse()->getStatusCode());
|
$this->assertEquals(200, Controller::curr()->getResponse()->getStatusCode());
|
||||||
$this->assertEquals(
|
$this->assertEquals(
|
||||||
'Comment approved.',
|
'Comment approved.',
|
||||||
@ -128,6 +137,5 @@ class CommentsGridFieldActionTest extends SapphireTest {
|
|||||||
$this->assertEquals(0, $record->IsSpam);
|
$this->assertEquals(0, $record->IsSpam);
|
||||||
|
|
||||||
error_log(Controller::curr()->getResponse()->getStatusCode());
|
error_log(Controller::curr()->getResponse()->getStatusCode());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,14 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
class CommentsGridFieldBulkActionTest extends SapphireTest {
|
class CommentsGridFieldBulkActionTest extends SapphireTest
|
||||||
public function testSpam() {
|
{
|
||||||
$this->markTestSkipped('TODO');
|
public function testSpam()
|
||||||
}
|
{
|
||||||
|
$this->markTestSkipped('TODO');
|
||||||
public function testApprove() {
|
}
|
||||||
$this->markTestSkipped('TODO');
|
|
||||||
}
|
|
||||||
|
|
||||||
|
public function testApprove()
|
||||||
|
{
|
||||||
|
$this->markTestSkipped('TODO');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
class CommentsGridFieldConfigTest extends SapphireTest {
|
class CommentsGridFieldConfigTest extends SapphireTest
|
||||||
public function test__construct() {
|
{
|
||||||
|
public function test__construct()
|
||||||
|
{
|
||||||
$config = new CommentsGridFieldConfigTest();
|
$config = new CommentsGridFieldConfigTest();
|
||||||
$this->markTestSkipped('TODO');
|
$this->markTestSkipped('TODO');
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,22 +1,22 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
class CommentsGridFieldTest extends SapphireTest {
|
class CommentsGridFieldTest extends SapphireTest
|
||||||
public function testNewRow() {
|
{
|
||||||
$gridfield = new CommentsGridField('testfield', 'testfield');
|
public function testNewRow()
|
||||||
|
{
|
||||||
|
$gridfield = new CommentsGridField('testfield', 'testfield');
|
||||||
// protected function newRow($total, $index, $record, $attributes, $content) {
|
// protected function newRow($total, $index, $record, $attributes, $content) {
|
||||||
$comment = new Comment();
|
$comment = new Comment();
|
||||||
$comment->Name = 'Fred Bloggs';
|
$comment->Name = 'Fred Bloggs';
|
||||||
$comment->Comment = 'This is a comment';
|
$comment->Comment = 'This is a comment';
|
||||||
$attr = array();
|
$attr = array();
|
||||||
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$class = new ReflectionClass($gridfield);
|
$class = new ReflectionClass($gridfield);
|
||||||
$method = $class->getMethod('newRow');
|
$method = $class->getMethod('newRow');
|
||||||
$method->setAccessible(true);
|
$method->setAccessible(true);
|
||||||
}
|
} catch (ReflectionException $e) {
|
||||||
|
|
||||||
catch (ReflectionException $e) {
|
|
||||||
$this->fail($e->getMessage());
|
$this->fail($e->getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -33,8 +33,5 @@ class CommentsGridFieldTest extends SapphireTest {
|
|||||||
$params = array(1, 1, $comment, $attr, $comment->Comment);
|
$params = array(1, 1, $comment, $attr, $comment->Comment);
|
||||||
$newRow = $method->invokeArgs($gridfield, $params);
|
$newRow = $method->invokeArgs($gridfield, $params);
|
||||||
$this->assertEquals('<tr class="cssClass spam">This is a comment</tr>', $newRow);
|
$this->assertEquals('<tr class="cssClass spam">This is a comment</tr>', $newRow);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -3,405 +3,434 @@
|
|||||||
/**
|
/**
|
||||||
* @package comments
|
* @package comments
|
||||||
*/
|
*/
|
||||||
class CommentsTest extends FunctionalTest {
|
class CommentsTest extends FunctionalTest
|
||||||
|
{
|
||||||
|
|
||||||
public static $fixture_file = 'comments/tests/CommentsTest.yml';
|
public static $fixture_file = 'comments/tests/CommentsTest.yml';
|
||||||
|
|
||||||
protected $extraDataObjects = array(
|
protected $extraDataObjects = array(
|
||||||
'CommentableItem',
|
'CommentableItem',
|
||||||
'CommentableItemEnabled',
|
'CommentableItemEnabled',
|
||||||
'CommentableItemDisabled'
|
'CommentableItemDisabled'
|
||||||
);
|
);
|
||||||
|
|
||||||
public function setUp() {
|
public function setUp()
|
||||||
parent::setUp();
|
{
|
||||||
Config::nest();
|
parent::setUp();
|
||||||
|
Config::nest();
|
||||||
|
|
||||||
// Set good default values
|
// Set good default values
|
||||||
Config::inst()->update('CommentsExtension', 'comments', array(
|
Config::inst()->update('CommentsExtension', 'comments', array(
|
||||||
'enabled' => true,
|
'enabled' => true,
|
||||||
'enabled_cms' => false,
|
'enabled_cms' => false,
|
||||||
'require_login' => false,
|
'require_login' => false,
|
||||||
'require_login_cms' => false,
|
'require_login_cms' => false,
|
||||||
'required_permission' => false,
|
'required_permission' => false,
|
||||||
'require_moderation_nonmembers' => false,
|
'require_moderation_nonmembers' => false,
|
||||||
'require_moderation' => false,
|
'require_moderation' => false,
|
||||||
'require_moderation_cms' => false,
|
'require_moderation_cms' => false,
|
||||||
'frontend_moderation' => false,
|
'frontend_moderation' => false,
|
||||||
'frontend_spam' => false,
|
'frontend_spam' => false,
|
||||||
));
|
));
|
||||||
|
|
||||||
// Configure this dataobject
|
// Configure this dataobject
|
||||||
Config::inst()->update('CommentableItem', 'comments', array(
|
Config::inst()->update('CommentableItem', 'comments', array(
|
||||||
'enabled_cms' => true
|
'enabled_cms' => true
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function tearDown() {
|
public function tearDown()
|
||||||
Config::unnest();
|
{
|
||||||
parent::tearDown();
|
Config::unnest();
|
||||||
}
|
parent::tearDown();
|
||||||
|
}
|
||||||
|
|
||||||
public function testCommentsList() {
|
public function testCommentsList()
|
||||||
// comments don't require moderation so unmoderated comments can be
|
{
|
||||||
// shown but not spam posts
|
// comments don't require moderation so unmoderated comments can be
|
||||||
Config::inst()->update('CommentableItem', 'comments', array(
|
// shown but not spam posts
|
||||||
'require_moderation_nonmembers' => false,
|
Config::inst()->update('CommentableItem', 'comments', array(
|
||||||
'require_moderation' => false,
|
'require_moderation_nonmembers' => false,
|
||||||
'require_moderation_cms' => false,
|
'require_moderation' => false,
|
||||||
));
|
'require_moderation_cms' => false,
|
||||||
|
));
|
||||||
|
|
||||||
$item = $this->objFromFixture('CommentableItem', 'spammed');
|
$item = $this->objFromFixture('CommentableItem', 'spammed');
|
||||||
$this->assertEquals('None', $item->ModerationRequired);
|
$this->assertEquals('None', $item->ModerationRequired);
|
||||||
|
|
||||||
$this->assertDOSEquals(array(
|
$this->assertDOSEquals(array(
|
||||||
array('Name' => 'Comment 1'),
|
array('Name' => 'Comment 1'),
|
||||||
array('Name' => 'Comment 3')
|
array('Name' => 'Comment 3')
|
||||||
), $item->Comments(), 'Only 2 non spam posts should be shown');
|
), $item->Comments(), 'Only 2 non spam posts should be shown');
|
||||||
|
|
||||||
// when moderated, only moderated, non spam posts should be shown.
|
// when moderated, only moderated, non spam posts should be shown.
|
||||||
Config::inst()->update('CommentableItem', 'comments', array('require_moderation_nonmembers' => true));
|
Config::inst()->update('CommentableItem', 'comments', array('require_moderation_nonmembers' => true));
|
||||||
$this->assertEquals('NonMembersOnly', $item->ModerationRequired);
|
$this->assertEquals('NonMembersOnly', $item->ModerationRequired);
|
||||||
|
|
||||||
// Check that require_moderation overrides this option
|
// Check that require_moderation overrides this option
|
||||||
Config::inst()->update('CommentableItem', 'comments', array('require_moderation' => true));
|
Config::inst()->update('CommentableItem', 'comments', array('require_moderation' => true));
|
||||||
$this->assertEquals('Required', $item->ModerationRequired);
|
$this->assertEquals('Required', $item->ModerationRequired);
|
||||||
|
|
||||||
$this->assertDOSEquals(array(
|
$this->assertDOSEquals(array(
|
||||||
array('Name' => 'Comment 3')
|
array('Name' => 'Comment 3')
|
||||||
), $item->Comments(), 'Only 1 non spam, moderated post should be shown');
|
), $item->Comments(), 'Only 1 non spam, moderated post should be shown');
|
||||||
$this->assertEquals(1, $item->Comments()->Count());
|
$this->assertEquals(1, $item->Comments()->Count());
|
||||||
|
|
||||||
// require_moderation_nonmembers still filters out unmoderated comments
|
// require_moderation_nonmembers still filters out unmoderated comments
|
||||||
Config::inst()->update('CommentableItem', 'comments', array('require_moderation' => false));
|
Config::inst()->update('CommentableItem', 'comments', array('require_moderation' => false));
|
||||||
$this->assertEquals(1, $item->Comments()->Count());
|
$this->assertEquals(1, $item->Comments()->Count());
|
||||||
|
|
||||||
Config::inst()->update('CommentableItem', 'comments', array('require_moderation_nonmembers' => false));
|
Config::inst()->update('CommentableItem', 'comments', array('require_moderation_nonmembers' => false));
|
||||||
$this->assertEquals(2, $item->Comments()->Count());
|
$this->assertEquals(2, $item->Comments()->Count());
|
||||||
|
|
||||||
// With unmoderated comments set to display in frontend
|
// With unmoderated comments set to display in frontend
|
||||||
Config::inst()->update('CommentableItem', 'comments', array(
|
Config::inst()->update('CommentableItem', 'comments', array(
|
||||||
'require_moderation' => true,
|
'require_moderation' => true,
|
||||||
'frontend_moderation' => true
|
'frontend_moderation' => true
|
||||||
));
|
));
|
||||||
$this->assertEquals(1, $item->Comments()->Count());
|
$this->assertEquals(1, $item->Comments()->Count());
|
||||||
|
|
||||||
$this->logInWithPermission('ADMIN');
|
$this->logInWithPermission('ADMIN');
|
||||||
$this->assertEquals(2, $item->Comments()->Count());
|
$this->assertEquals(2, $item->Comments()->Count());
|
||||||
|
|
||||||
// With spam comments set to display in frontend
|
// With spam comments set to display in frontend
|
||||||
Config::inst()->update('CommentableItem', 'comments', array(
|
Config::inst()->update('CommentableItem', 'comments', array(
|
||||||
'require_moderation' => true,
|
'require_moderation' => true,
|
||||||
'frontend_moderation' => false,
|
'frontend_moderation' => false,
|
||||||
'frontend_spam' => true,
|
'frontend_spam' => true,
|
||||||
));
|
));
|
||||||
if($member = Member::currentUser()) $member->logOut();
|
if ($member = Member::currentUser()) {
|
||||||
$this->assertEquals(1, $item->Comments()->Count());
|
$member->logOut();
|
||||||
|
}
|
||||||
|
$this->assertEquals(1, $item->Comments()->Count());
|
||||||
|
|
||||||
$this->logInWithPermission('ADMIN');
|
$this->logInWithPermission('ADMIN');
|
||||||
$this->assertEquals(2, $item->Comments()->Count());
|
$this->assertEquals(2, $item->Comments()->Count());
|
||||||
|
|
||||||
|
|
||||||
// With spam and unmoderated comments set to display in frontend
|
// With spam and unmoderated comments set to display in frontend
|
||||||
Config::inst()->update('CommentableItem', 'comments', array(
|
Config::inst()->update('CommentableItem', 'comments', array(
|
||||||
'require_moderation' => true,
|
'require_moderation' => true,
|
||||||
'frontend_moderation' => true,
|
'frontend_moderation' => true,
|
||||||
'frontend_spam' => true,
|
'frontend_spam' => true,
|
||||||
));
|
));
|
||||||
if($member = Member::currentUser()) $member->logOut();
|
if ($member = Member::currentUser()) {
|
||||||
$this->assertEquals(1, $item->Comments()->Count());
|
$member->logOut();
|
||||||
|
}
|
||||||
|
$this->assertEquals(1, $item->Comments()->Count());
|
||||||
|
|
||||||
$this->logInWithPermission('ADMIN');
|
$this->logInWithPermission('ADMIN');
|
||||||
$this->assertEquals(4, $item->Comments()->Count());
|
$this->assertEquals(4, $item->Comments()->Count());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test moderation options configured via the CMS
|
* Test moderation options configured via the CMS
|
||||||
*/
|
*/
|
||||||
public function testCommentCMSModerationList() {
|
public function testCommentCMSModerationList()
|
||||||
// comments don't require moderation so unmoderated comments can be
|
{
|
||||||
// shown but not spam posts
|
// comments don't require moderation so unmoderated comments can be
|
||||||
Config::inst()->update('CommentableItem', 'comments', array(
|
// shown but not spam posts
|
||||||
'require_moderation' => true,
|
Config::inst()->update('CommentableItem', 'comments', array(
|
||||||
'require_moderation_cms' => true,
|
'require_moderation' => true,
|
||||||
));
|
'require_moderation_cms' => true,
|
||||||
|
));
|
||||||
|
|
||||||
$item = $this->objFromFixture('CommentableItem', 'spammed');
|
$item = $this->objFromFixture('CommentableItem', 'spammed');
|
||||||
$this->assertEquals('None', $item->ModerationRequired);
|
$this->assertEquals('None', $item->ModerationRequired);
|
||||||
|
|
||||||
$this->assertDOSEquals(array(
|
$this->assertDOSEquals(array(
|
||||||
array('Name' => 'Comment 1'),
|
array('Name' => 'Comment 1'),
|
||||||
array('Name' => 'Comment 3')
|
array('Name' => 'Comment 3')
|
||||||
), $item->Comments(), 'Only 2 non spam posts should be shown');
|
), $item->Comments(), 'Only 2 non spam posts should be shown');
|
||||||
|
|
||||||
// when moderated, only moderated, non spam posts should be shown.
|
// when moderated, only moderated, non spam posts should be shown.
|
||||||
$item->ModerationRequired = 'NonMembersOnly';
|
$item->ModerationRequired = 'NonMembersOnly';
|
||||||
$item->write();
|
$item->write();
|
||||||
$this->assertEquals('NonMembersOnly', $item->ModerationRequired);
|
$this->assertEquals('NonMembersOnly', $item->ModerationRequired);
|
||||||
|
|
||||||
// Check that require_moderation overrides this option
|
// Check that require_moderation overrides this option
|
||||||
$item->ModerationRequired = 'Required';
|
$item->ModerationRequired = 'Required';
|
||||||
$item->write();
|
$item->write();
|
||||||
$this->assertEquals('Required', $item->ModerationRequired);
|
$this->assertEquals('Required', $item->ModerationRequired);
|
||||||
|
|
||||||
$this->assertDOSEquals(array(
|
$this->assertDOSEquals(array(
|
||||||
array('Name' => 'Comment 3')
|
array('Name' => 'Comment 3')
|
||||||
), $item->Comments(), 'Only 1 non spam, moderated post should be shown');
|
), $item->Comments(), 'Only 1 non spam, moderated post should be shown');
|
||||||
$this->assertEquals(1, $item->Comments()->Count());
|
$this->assertEquals(1, $item->Comments()->Count());
|
||||||
|
|
||||||
// require_moderation_nonmembers still filters out unmoderated comments
|
// require_moderation_nonmembers still filters out unmoderated comments
|
||||||
$item->ModerationRequired = 'NonMembersOnly';
|
$item->ModerationRequired = 'NonMembersOnly';
|
||||||
$item->write();
|
$item->write();
|
||||||
$this->assertEquals(1, $item->Comments()->Count());
|
$this->assertEquals(1, $item->Comments()->Count());
|
||||||
|
|
||||||
$item->ModerationRequired = 'None';
|
$item->ModerationRequired = 'None';
|
||||||
$item->write();
|
$item->write();
|
||||||
$this->assertEquals(2, $item->Comments()->Count());
|
$this->assertEquals(2, $item->Comments()->Count());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testCanPostComment() {
|
public function testCanPostComment()
|
||||||
Config::inst()->update('CommentableItem', 'comments', array(
|
{
|
||||||
'require_login' => false,
|
Config::inst()->update('CommentableItem', 'comments', array(
|
||||||
'require_login_cms' => false,
|
'require_login' => false,
|
||||||
'required_permission' => false,
|
'require_login_cms' => false,
|
||||||
));
|
'required_permission' => false,
|
||||||
$item = $this->objFromFixture('CommentableItem', 'first');
|
));
|
||||||
$item2 = $this->objFromFixture('CommentableItem', 'second');
|
$item = $this->objFromFixture('CommentableItem', 'first');
|
||||||
|
$item2 = $this->objFromFixture('CommentableItem', 'second');
|
||||||
|
|
||||||
// Test restriction free commenting
|
// Test restriction free commenting
|
||||||
if($member = Member::currentUser()) $member->logOut();
|
if ($member = Member::currentUser()) {
|
||||||
$this->assertFalse($item->CommentsRequireLogin);
|
$member->logOut();
|
||||||
$this->assertTrue($item->canPostComment());
|
}
|
||||||
|
$this->assertFalse($item->CommentsRequireLogin);
|
||||||
|
$this->assertTrue($item->canPostComment());
|
||||||
|
|
||||||
// Test permission required to post
|
// Test permission required to post
|
||||||
Config::inst()->update('CommentableItem', 'comments', array(
|
Config::inst()->update('CommentableItem', 'comments', array(
|
||||||
'require_login' => true,
|
'require_login' => true,
|
||||||
'required_permission' => 'POSTING_PERMISSION',
|
'required_permission' => 'POSTING_PERMISSION',
|
||||||
));
|
));
|
||||||
$this->assertTrue($item->CommentsRequireLogin);
|
$this->assertTrue($item->CommentsRequireLogin);
|
||||||
$this->assertFalse($item->canPostComment());
|
$this->assertFalse($item->canPostComment());
|
||||||
$this->logInWithPermission('WRONG_ONE');
|
$this->logInWithPermission('WRONG_ONE');
|
||||||
$this->assertFalse($item->canPostComment());
|
$this->assertFalse($item->canPostComment());
|
||||||
$this->logInWithPermission('POSTING_PERMISSION');
|
$this->logInWithPermission('POSTING_PERMISSION');
|
||||||
$this->assertTrue($item->canPostComment());
|
$this->assertTrue($item->canPostComment());
|
||||||
$this->logInWithPermission('ADMIN');
|
$this->logInWithPermission('ADMIN');
|
||||||
$this->assertTrue($item->canPostComment());
|
$this->assertTrue($item->canPostComment());
|
||||||
|
|
||||||
// Test require login to post, but not any permissions
|
// Test require login to post, but not any permissions
|
||||||
Config::inst()->update('CommentableItem', 'comments', array(
|
Config::inst()->update('CommentableItem', 'comments', array(
|
||||||
'required_permission' => false,
|
'required_permission' => false,
|
||||||
));
|
));
|
||||||
$this->assertTrue($item->CommentsRequireLogin);
|
$this->assertTrue($item->CommentsRequireLogin);
|
||||||
if($member = Member::currentUser()) $member->logOut();
|
if ($member = Member::currentUser()) {
|
||||||
$this->assertFalse($item->canPostComment());
|
$member->logOut();
|
||||||
$this->logInWithPermission('ANY_PERMISSION');
|
}
|
||||||
$this->assertTrue($item->canPostComment());
|
$this->assertFalse($item->canPostComment());
|
||||||
|
$this->logInWithPermission('ANY_PERMISSION');
|
||||||
|
$this->assertTrue($item->canPostComment());
|
||||||
|
|
||||||
// Test options set via CMS
|
// Test options set via CMS
|
||||||
Config::inst()->update('CommentableItem', 'comments', array(
|
Config::inst()->update('CommentableItem', 'comments', array(
|
||||||
'require_login' => true,
|
'require_login' => true,
|
||||||
'require_login_cms' => true,
|
'require_login_cms' => true,
|
||||||
));
|
));
|
||||||
$this->assertFalse($item->CommentsRequireLogin);
|
$this->assertFalse($item->CommentsRequireLogin);
|
||||||
$this->assertTrue($item2->CommentsRequireLogin);
|
$this->assertTrue($item2->CommentsRequireLogin);
|
||||||
if($member = Member::currentUser()) $member->logOut();
|
if ($member = Member::currentUser()) {
|
||||||
$this->assertTrue($item->canPostComment());
|
$member->logOut();
|
||||||
$this->assertFalse($item2->canPostComment());
|
}
|
||||||
|
$this->assertTrue($item->canPostComment());
|
||||||
|
$this->assertFalse($item2->canPostComment());
|
||||||
|
|
||||||
// Login grants permission to post
|
// Login grants permission to post
|
||||||
$this->logInWithPermission('ANY_PERMISSION');
|
$this->logInWithPermission('ANY_PERMISSION');
|
||||||
$this->assertTrue($item->canPostComment());
|
$this->assertTrue($item->canPostComment());
|
||||||
$this->assertTrue($item2->canPostComment());
|
$this->assertTrue($item2->canPostComment());
|
||||||
|
}
|
||||||
|
public function testDeleteComment()
|
||||||
|
{
|
||||||
|
// Test anonymous user
|
||||||
|
if ($member = Member::currentUser()) {
|
||||||
|
$member->logOut();
|
||||||
|
}
|
||||||
|
$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');
|
||||||
|
$this->assertEquals(403, $delete->getStatusCode());
|
||||||
|
$check = DataObject::get_by_id('Comment', $commentID);
|
||||||
|
$this->assertTrue($check && $check->exists());
|
||||||
|
|
||||||
}
|
// Test non-authenticated user
|
||||||
public function testDeleteComment() {
|
$this->logInAs('visitor');
|
||||||
// Test anonymous user
|
$this->assertNull($comment->DeleteLink(), 'No permission to see delete link');
|
||||||
if($member = Member::currentUser()) $member->logOut();
|
|
||||||
$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');
|
|
||||||
$this->assertEquals(403, $delete->getStatusCode());
|
|
||||||
$check = DataObject::get_by_id('Comment', $commentID);
|
|
||||||
$this->assertTrue($check && $check->exists());
|
|
||||||
|
|
||||||
// Test non-authenticated user
|
// Test authenticated user
|
||||||
$this->logInAs('visitor');
|
$this->logInAs('commentadmin');
|
||||||
$this->assertNull($comment->DeleteLink(), 'No permission to see delete link');
|
$comment = $this->objFromFixture('Comment', 'firstComA');
|
||||||
|
$commentID = $comment->ID;
|
||||||
|
$adminComment1Link = $comment->DeleteLink();
|
||||||
|
$this->assertContains('CommentingController/delete/'.$commentID.'?t=', $adminComment1Link);
|
||||||
|
|
||||||
// Test authenticated user
|
// Test that this link can't be shared / XSS exploited
|
||||||
$this->logInAs('commentadmin');
|
$this->logInAs('commentadmin2');
|
||||||
$comment = $this->objFromFixture('Comment', 'firstComA');
|
$delete = $this->get($adminComment1Link);
|
||||||
$commentID = $comment->ID;
|
$this->assertEquals(400, $delete->getStatusCode());
|
||||||
$adminComment1Link = $comment->DeleteLink();
|
$check = DataObject::get_by_id('Comment', $commentID);
|
||||||
$this->assertContains('CommentingController/delete/'.$commentID.'?t=', $adminComment1Link);
|
$this->assertTrue($check && $check->exists());
|
||||||
|
|
||||||
// Test that this link can't be shared / XSS exploited
|
// Test that this other admin can delete the comment with their own link
|
||||||
$this->logInAs('commentadmin2');
|
$adminComment2Link = $comment->DeleteLink();
|
||||||
$delete = $this->get($adminComment1Link);
|
$this->assertNotEquals($adminComment2Link, $adminComment1Link);
|
||||||
$this->assertEquals(400, $delete->getStatusCode());
|
$this->autoFollowRedirection = false;
|
||||||
$check = DataObject::get_by_id('Comment', $commentID);
|
$delete = $this->get($adminComment2Link);
|
||||||
$this->assertTrue($check && $check->exists());
|
$this->assertEquals(302, $delete->getStatusCode());
|
||||||
|
$check = DataObject::get_by_id('Comment', $commentID);
|
||||||
|
$this->assertFalse($check && $check->exists());
|
||||||
|
}
|
||||||
|
|
||||||
// Test that this other admin can delete the comment with their own link
|
public function testSpamComment()
|
||||||
$adminComment2Link = $comment->DeleteLink();
|
{
|
||||||
$this->assertNotEquals($adminComment2Link, $adminComment1Link);
|
// Test anonymous user
|
||||||
$this->autoFollowRedirection = false;
|
if ($member = Member::currentUser()) {
|
||||||
$delete = $this->get($adminComment2Link);
|
$member->logOut();
|
||||||
$this->assertEquals(302, $delete->getStatusCode());
|
}
|
||||||
$check = DataObject::get_by_id('Comment', $commentID);
|
$comment = $this->objFromFixture('Comment', 'firstComA');
|
||||||
$this->assertFalse($check && $check->exists());
|
$commentID = $comment->ID;
|
||||||
}
|
$this->assertNull($comment->SpamLink(), 'No permission to see mark as spam link');
|
||||||
|
$spam = $this->get('CommentingController/spam/'.$comment->ID.'?ajax=1');
|
||||||
|
$this->assertEquals(403, $spam->getStatusCode());
|
||||||
|
$check = DataObject::get_by_id('Comment', $commentID);
|
||||||
|
$this->assertEquals(0, $check->IsSpam, 'No permission to mark as spam');
|
||||||
|
|
||||||
public function testSpamComment() {
|
// Test non-authenticated user
|
||||||
// Test anonymous user
|
$this->logInAs('visitor');
|
||||||
if($member = Member::currentUser()) $member->logOut();
|
$this->assertNull($comment->SpamLink(), 'No permission to see mark as spam link');
|
||||||
$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');
|
|
||||||
$this->assertEquals(403, $spam->getStatusCode());
|
|
||||||
$check = DataObject::get_by_id('Comment', $commentID);
|
|
||||||
$this->assertEquals(0, $check->IsSpam, 'No permission to mark as spam');
|
|
||||||
|
|
||||||
// Test non-authenticated user
|
// Test authenticated user
|
||||||
$this->logInAs('visitor');
|
$this->logInAs('commentadmin');
|
||||||
$this->assertNull($comment->SpamLink(), 'No permission to see mark as spam link');
|
$comment = $this->objFromFixture('Comment', 'firstComA');
|
||||||
|
$commentID = $comment->ID;
|
||||||
|
$adminComment1Link = $comment->SpamLink();
|
||||||
|
$this->assertContains('CommentingController/spam/'.$commentID.'?t=', $adminComment1Link);
|
||||||
|
|
||||||
// Test authenticated user
|
// Test that this link can't be shared / XSS exploited
|
||||||
$this->logInAs('commentadmin');
|
$this->logInAs('commentadmin2');
|
||||||
$comment = $this->objFromFixture('Comment', 'firstComA');
|
$spam = $this->get($adminComment1Link);
|
||||||
$commentID = $comment->ID;
|
$this->assertEquals(400, $spam->getStatusCode());
|
||||||
$adminComment1Link = $comment->SpamLink();
|
$check = DataObject::get_by_id('Comment', $comment->ID);
|
||||||
$this->assertContains('CommentingController/spam/'.$commentID.'?t=', $adminComment1Link);
|
$this->assertEquals(0, $check->IsSpam, 'No permission to mark as spam');
|
||||||
|
|
||||||
// Test that this link can't be shared / XSS exploited
|
// Test that this other admin can spam the comment with their own link
|
||||||
$this->logInAs('commentadmin2');
|
$adminComment2Link = $comment->SpamLink();
|
||||||
$spam = $this->get($adminComment1Link);
|
$this->assertNotEquals($adminComment2Link, $adminComment1Link);
|
||||||
$this->assertEquals(400, $spam->getStatusCode());
|
$this->autoFollowRedirection = false;
|
||||||
$check = DataObject::get_by_id('Comment', $comment->ID);
|
$spam = $this->get($adminComment2Link);
|
||||||
$this->assertEquals(0, $check->IsSpam, 'No permission to mark as spam');
|
$this->assertEquals(302, $spam->getStatusCode());
|
||||||
|
$check = DataObject::get_by_id('Comment', $commentID);
|
||||||
|
$this->assertEquals(1, $check->IsSpam);
|
||||||
|
|
||||||
// Test that this other admin can spam the comment with their own link
|
// Cannot re-spam spammed comment
|
||||||
$adminComment2Link = $comment->SpamLink();
|
$this->assertNull($check->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
|
public function testHamComment()
|
||||||
$this->assertNull($check->SpamLink());
|
{
|
||||||
}
|
// Test anonymous user
|
||||||
|
if ($member = Member::currentUser()) {
|
||||||
|
$member->logOut();
|
||||||
|
}
|
||||||
|
$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');
|
||||||
|
$this->assertEquals(403, $ham->getStatusCode());
|
||||||
|
$check = DataObject::get_by_id('Comment', $commentID);
|
||||||
|
$this->assertEquals(1, $check->IsSpam, 'No permission to mark as ham');
|
||||||
|
|
||||||
public function testHamComment() {
|
// Test non-authenticated user
|
||||||
// Test anonymous user
|
$this->logInAs('visitor');
|
||||||
if($member = Member::currentUser()) $member->logOut();
|
$this->assertNull($comment->HamLink(), 'No permission to see mark as ham link');
|
||||||
$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');
|
|
||||||
$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
|
// Test authenticated user
|
||||||
$this->logInAs('visitor');
|
$this->logInAs('commentadmin');
|
||||||
$this->assertNull($comment->HamLink(), 'No permission to see mark as ham link');
|
$comment = $this->objFromFixture('Comment', 'secondComC');
|
||||||
|
$commentID = $comment->ID;
|
||||||
|
$adminComment1Link = $comment->HamLink();
|
||||||
|
$this->assertContains('CommentingController/ham/'.$commentID.'?t=', $adminComment1Link);
|
||||||
|
|
||||||
// Test authenticated user
|
// Test that this link can't be shared / XSS exploited
|
||||||
$this->logInAs('commentadmin');
|
$this->logInAs('commentadmin2');
|
||||||
$comment = $this->objFromFixture('Comment', 'secondComC');
|
$ham = $this->get($adminComment1Link);
|
||||||
$commentID = $comment->ID;
|
$this->assertEquals(400, $ham->getStatusCode());
|
||||||
$adminComment1Link = $comment->HamLink();
|
$check = DataObject::get_by_id('Comment', $comment->ID);
|
||||||
$this->assertContains('CommentingController/ham/'.$commentID.'?t=', $adminComment1Link);
|
$this->assertEquals(1, $check->IsSpam, 'No permission to mark as ham');
|
||||||
|
|
||||||
// Test that this link can't be shared / XSS exploited
|
// Test that this other admin can ham the comment with their own link
|
||||||
$this->logInAs('commentadmin2');
|
$adminComment2Link = $comment->HamLink();
|
||||||
$ham = $this->get($adminComment1Link);
|
$this->assertNotEquals($adminComment2Link, $adminComment1Link);
|
||||||
$this->assertEquals(400, $ham->getStatusCode());
|
$this->autoFollowRedirection = false;
|
||||||
$check = DataObject::get_by_id('Comment', $comment->ID);
|
$ham = $this->get($adminComment2Link);
|
||||||
$this->assertEquals(1, $check->IsSpam, 'No permission to mark as ham');
|
$this->assertEquals(302, $ham->getStatusCode());
|
||||||
|
$check = DataObject::get_by_id('Comment', $commentID);
|
||||||
|
$this->assertEquals(0, $check->IsSpam);
|
||||||
|
|
||||||
// Test that this other admin can ham the comment with their own link
|
// Cannot re-ham hammed comment
|
||||||
$adminComment2Link = $comment->HamLink();
|
$this->assertNull($check->HamLink());
|
||||||
$this->assertNotEquals($adminComment2Link, $adminComment1Link);
|
}
|
||||||
$this->autoFollowRedirection = false;
|
|
||||||
$ham = $this->get($adminComment2Link);
|
|
||||||
$this->assertEquals(302, $ham->getStatusCode());
|
|
||||||
$check = DataObject::get_by_id('Comment', $commentID);
|
|
||||||
$this->assertEquals(0, $check->IsSpam);
|
|
||||||
|
|
||||||
// Cannot re-ham hammed comment
|
public function testApproveComment()
|
||||||
$this->assertNull($check->HamLink());
|
{
|
||||||
}
|
// Test anonymous user
|
||||||
|
if ($member = Member::currentUser()) {
|
||||||
|
$member->logOut();
|
||||||
|
}
|
||||||
|
$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');
|
||||||
|
$this->assertEquals(403, $approve->getStatusCode());
|
||||||
|
$check = DataObject::get_by_id('Comment', $commentID);
|
||||||
|
$this->assertEquals(0, $check->Moderated, 'No permission to approve');
|
||||||
|
|
||||||
public function testApproveComment() {
|
// Test non-authenticated user
|
||||||
// Test anonymous user
|
$this->logInAs('visitor');
|
||||||
if($member = Member::currentUser()) $member->logOut();
|
$this->assertNull($comment->ApproveLink(), 'No permission to see approve link');
|
||||||
$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');
|
|
||||||
$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
|
// Test authenticated user
|
||||||
$this->logInAs('visitor');
|
$this->logInAs('commentadmin');
|
||||||
$this->assertNull($comment->ApproveLink(), 'No permission to see approve link');
|
$comment = $this->objFromFixture('Comment', 'secondComB');
|
||||||
|
$commentID = $comment->ID;
|
||||||
|
$adminComment1Link = $comment->ApproveLink();
|
||||||
|
$this->assertContains('CommentingController/approve/'.$commentID.'?t=', $adminComment1Link);
|
||||||
|
|
||||||
// Test authenticated user
|
// Test that this link can't be shared / XSS exploited
|
||||||
$this->logInAs('commentadmin');
|
$this->logInAs('commentadmin2');
|
||||||
$comment = $this->objFromFixture('Comment', 'secondComB');
|
$approve = $this->get($adminComment1Link);
|
||||||
$commentID = $comment->ID;
|
$this->assertEquals(400, $approve->getStatusCode());
|
||||||
$adminComment1Link = $comment->ApproveLink();
|
$check = DataObject::get_by_id('Comment', $comment->ID);
|
||||||
$this->assertContains('CommentingController/approve/'.$commentID.'?t=', $adminComment1Link);
|
$this->assertEquals(0, $check->Moderated, 'No permission to approve');
|
||||||
|
|
||||||
// Test that this link can't be shared / XSS exploited
|
// Test that this other admin can approve the comment with their own link
|
||||||
$this->logInAs('commentadmin2');
|
$adminComment2Link = $comment->ApproveLink();
|
||||||
$approve = $this->get($adminComment1Link);
|
$this->assertNotEquals($adminComment2Link, $adminComment1Link);
|
||||||
$this->assertEquals(400, $approve->getStatusCode());
|
$this->autoFollowRedirection = false;
|
||||||
$check = DataObject::get_by_id('Comment', $comment->ID);
|
$approve = $this->get($adminComment2Link);
|
||||||
$this->assertEquals(0, $check->Moderated, 'No permission to approve');
|
$this->assertEquals(302, $approve->getStatusCode());
|
||||||
|
$check = DataObject::get_by_id('Comment', $commentID);
|
||||||
|
$this->assertEquals(1, $check->Moderated);
|
||||||
|
|
||||||
// Test that this other admin can approve the comment with their own link
|
// Cannot re-approve approved comment
|
||||||
$adminComment2Link = $comment->ApproveLink();
|
$this->assertNull($check->ApproveLink());
|
||||||
$this->assertNotEquals($adminComment2Link, $adminComment1Link);
|
}
|
||||||
$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
|
public function testCommenterURLWrite()
|
||||||
$this->assertNull($check->ApproveLink());
|
{
|
||||||
}
|
$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',
|
||||||
|
);
|
||||||
|
$url = '://example.com';
|
||||||
|
|
||||||
public function testCommenterURLWrite() {
|
foreach ($protocols as $protocol) {
|
||||||
$comment = new Comment();
|
$comment->CommenterURL = $protocol . $url;
|
||||||
// We only care about the CommenterURL, so only set that
|
// The protocol should stay as if, assuming it is valid
|
||||||
// Check a http and https URL. Add more test urls here as needed.
|
$comment->write();
|
||||||
$protocols = array(
|
$this->assertEquals($comment->CommenterURL, $protocol . $url, $protocol . ':// is a valid protocol');
|
||||||
'Http',
|
}
|
||||||
'Https',
|
}
|
||||||
);
|
|
||||||
$url = '://example.com';
|
|
||||||
|
|
||||||
foreach($protocols as $protocol) {
|
public function testSanitizesWithAllowHtml()
|
||||||
$comment->CommenterURL = $protocol . $url;
|
{
|
||||||
// The protocol should stay as if, assuming it is valid
|
if (!class_exists('HTMLPurifier')) {
|
||||||
$comment->write();
|
$this->markTestSkipped('HTMLPurifier class not found');
|
||||||
$this->assertEquals($comment->CommenterURL, $protocol . $url, $protocol . ':// is a valid protocol');
|
return;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public function testSanitizesWithAllowHtml() {
|
|
||||||
if(!class_exists('HTMLPurifier')) {
|
|
||||||
$this->markTestSkipped('HTMLPurifier class not found');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add p for paragraph
|
// Add p for paragraph
|
||||||
// NOTE: The config method appears to append to the existing array
|
// NOTE: The config method appears to append to the existing array
|
||||||
@ -409,125 +438,127 @@ class CommentsTest extends FunctionalTest {
|
|||||||
'html_allowed_elements' => array('p'),
|
'html_allowed_elements' => array('p'),
|
||||||
));
|
));
|
||||||
|
|
||||||
// Without HTML allowed
|
// Without HTML allowed
|
||||||
$comment1 = new Comment();
|
$comment1 = new Comment();
|
||||||
$comment1->AllowHtml = false;
|
$comment1->AllowHtml = false;
|
||||||
$comment1->BaseClass = 'CommentableItem';
|
$comment1->BaseClass = 'CommentableItem';
|
||||||
$comment1->Comment = '<p><script>alert("w00t")</script>my comment</p>';
|
$comment1->Comment = '<p><script>alert("w00t")</script>my comment</p>';
|
||||||
$comment1->write();
|
$comment1->write();
|
||||||
$this->assertEquals(
|
$this->assertEquals(
|
||||||
'<p><script>alert("w00t")</script>my comment</p>',
|
'<p><script>alert("w00t")</script>my comment</p>',
|
||||||
$comment1->Comment,
|
$comment1->Comment,
|
||||||
'Does not remove HTML tags with html_allowed=false, ' .
|
'Does not remove HTML tags with html_allowed=false, ' .
|
||||||
'which is correct behaviour because the HTML will be escaped'
|
'which is correct behaviour because the HTML will be escaped'
|
||||||
);
|
);
|
||||||
|
|
||||||
// With HTML allowed
|
// With HTML allowed
|
||||||
$comment2 = new Comment();
|
$comment2 = new Comment();
|
||||||
$comment2->AllowHtml = true;
|
$comment2->AllowHtml = true;
|
||||||
$comment2->BaseClass = 'CommentableItem';
|
$comment2->BaseClass = 'CommentableItem';
|
||||||
$comment2->Comment = '<p><script>alert("w00t")</script>my comment</p>';
|
$comment2->Comment = '<p><script>alert("w00t")</script>my comment</p>';
|
||||||
$comment2->write();
|
$comment2->write();
|
||||||
$this->assertEquals(
|
$this->assertEquals(
|
||||||
'<p>my comment</p>',
|
'<p>my comment</p>',
|
||||||
$comment2->Comment,
|
$comment2->Comment,
|
||||||
'Removes HTML tags which are not on the whitelist'
|
'Removes HTML tags which are not on the whitelist'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testDefaultTemplateRendersHtmlWithAllowHtml() {
|
public function testDefaultTemplateRendersHtmlWithAllowHtml()
|
||||||
if(!class_exists('HTMLPurifier')) {
|
{
|
||||||
$this->markTestSkipped('HTMLPurifier class not found');
|
if (!class_exists('HTMLPurifier')) {
|
||||||
}
|
$this->markTestSkipped('HTMLPurifier class not found');
|
||||||
|
}
|
||||||
|
|
||||||
Config::inst()->update('CommentableItem', 'comments', array(
|
Config::inst()->update('CommentableItem', 'comments', array(
|
||||||
'html_allowed_elements' => array('p'),
|
'html_allowed_elements' => array('p'),
|
||||||
));
|
));
|
||||||
|
|
||||||
$item = new CommentableItem();
|
$item = new CommentableItem();
|
||||||
$item->write();
|
$item->write();
|
||||||
|
|
||||||
// Without HTML allowed
|
// Without HTML allowed
|
||||||
$comment = new Comment();
|
$comment = new Comment();
|
||||||
$comment->Comment = '<p>my comment</p>';
|
$comment->Comment = '<p>my comment</p>';
|
||||||
$comment->AllowHtml = false;
|
$comment->AllowHtml = false;
|
||||||
$comment->ParentID = $item->ID;
|
$comment->ParentID = $item->ID;
|
||||||
$comment->BaseClass = 'CommentableItem';
|
$comment->BaseClass = 'CommentableItem';
|
||||||
$comment->write();
|
$comment->write();
|
||||||
|
|
||||||
$html = $item->customise(array('CommentsEnabled' => true))->renderWith('CommentsInterface');
|
$html = $item->customise(array('CommentsEnabled' => true))->renderWith('CommentsInterface');
|
||||||
$this->assertContains(
|
$this->assertContains(
|
||||||
'<p>my comment</p>',
|
'<p>my comment</p>',
|
||||||
$html
|
$html
|
||||||
);
|
);
|
||||||
|
|
||||||
$comment->AllowHtml = true;
|
$comment->AllowHtml = true;
|
||||||
$comment->write();
|
$comment->write();
|
||||||
$html = $item->customise(array('CommentsEnabled' => true))->renderWith('CommentsInterface');
|
$html = $item->customise(array('CommentsEnabled' => true))->renderWith('CommentsInterface');
|
||||||
$this->assertContains(
|
$this->assertContains(
|
||||||
'<p>my comment</p>',
|
'<p>my comment</p>',
|
||||||
$html
|
$html
|
||||||
);
|
);
|
||||||
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests whether comments are enabled or disabled by default
|
* Tests whether comments are enabled or disabled by default
|
||||||
*/
|
*/
|
||||||
public function testDefaultEnabled() {
|
public function testDefaultEnabled()
|
||||||
// Ensure values are set via cms (not via config)
|
{
|
||||||
Config::inst()->update('CommentableItem', 'comments', array(
|
// Ensure values are set via cms (not via config)
|
||||||
'enabled_cms' => true,
|
Config::inst()->update('CommentableItem', 'comments', array(
|
||||||
'require_moderation_cms' => true,
|
'enabled_cms' => true,
|
||||||
'require_login_cms' => true
|
'require_moderation_cms' => true,
|
||||||
));
|
'require_login_cms' => true
|
||||||
|
));
|
||||||
|
|
||||||
// With default = true
|
// With default = true
|
||||||
$obj = new CommentableItem();
|
$obj = new CommentableItem();
|
||||||
$this->assertTrue((bool)$obj->getCommentsOption('enabled'), "Default setting is enabled");
|
$this->assertTrue((bool)$obj->getCommentsOption('enabled'), "Default setting is enabled");
|
||||||
$this->assertTrue((bool)$obj->ProvideComments);
|
$this->assertTrue((bool)$obj->ProvideComments);
|
||||||
$this->assertEquals('None', $obj->ModerationRequired);
|
$this->assertEquals('None', $obj->ModerationRequired);
|
||||||
$this->assertFalse((bool)$obj->CommentsRequireLogin);
|
$this->assertFalse((bool)$obj->CommentsRequireLogin);
|
||||||
|
|
||||||
$obj = new CommentableItemEnabled();
|
$obj = new CommentableItemEnabled();
|
||||||
$this->assertTrue((bool)$obj->ProvideComments);
|
$this->assertTrue((bool)$obj->ProvideComments);
|
||||||
$this->assertEquals('Required', $obj->ModerationRequired);
|
$this->assertEquals('Required', $obj->ModerationRequired);
|
||||||
$this->assertTrue((bool)$obj->CommentsRequireLogin);
|
$this->assertTrue((bool)$obj->CommentsRequireLogin);
|
||||||
|
|
||||||
$obj = new CommentableItemDisabled();
|
$obj = new CommentableItemDisabled();
|
||||||
$this->assertFalse((bool)$obj->ProvideComments);
|
$this->assertFalse((bool)$obj->ProvideComments);
|
||||||
$this->assertEquals('None', $obj->ModerationRequired);
|
$this->assertEquals('None', $obj->ModerationRequired);
|
||||||
$this->assertFalse((bool)$obj->CommentsRequireLogin);
|
$this->assertFalse((bool)$obj->CommentsRequireLogin);
|
||||||
|
|
||||||
// With default = false
|
// With default = false
|
||||||
// Because of config rules about falsey values, apply config to object directly
|
// Because of config rules about falsey values, apply config to object directly
|
||||||
Config::inst()->update('CommentableItem', 'comments', array(
|
Config::inst()->update('CommentableItem', 'comments', array(
|
||||||
'enabled' => false,
|
'enabled' => false,
|
||||||
'require_login' => true,
|
'require_login' => true,
|
||||||
'require_moderation' => true
|
'require_moderation' => true
|
||||||
));
|
));
|
||||||
$obj = new CommentableItem();
|
$obj = new CommentableItem();
|
||||||
$this->assertFalse((bool)$obj->getCommentsOption('enabled'), "Default setting is disabled");
|
$this->assertFalse((bool)$obj->getCommentsOption('enabled'), "Default setting is disabled");
|
||||||
$this->assertFalse((bool)$obj->ProvideComments);
|
$this->assertFalse((bool)$obj->ProvideComments);
|
||||||
$this->assertEquals('Required', $obj->ModerationRequired);
|
$this->assertEquals('Required', $obj->ModerationRequired);
|
||||||
$this->assertTrue((bool)$obj->CommentsRequireLogin);
|
$this->assertTrue((bool)$obj->CommentsRequireLogin);
|
||||||
|
|
||||||
$obj = new CommentableItemEnabled();
|
$obj = new CommentableItemEnabled();
|
||||||
$this->assertTrue((bool)$obj->ProvideComments);
|
$this->assertTrue((bool)$obj->ProvideComments);
|
||||||
$this->assertEquals('Required', $obj->ModerationRequired);
|
$this->assertEquals('Required', $obj->ModerationRequired);
|
||||||
$this->assertTrue((bool)$obj->CommentsRequireLogin);
|
$this->assertTrue((bool)$obj->CommentsRequireLogin);
|
||||||
|
|
||||||
$obj = new CommentableItemDisabled();
|
$obj = new CommentableItemDisabled();
|
||||||
$this->assertFalse((bool)$obj->ProvideComments);
|
$this->assertFalse((bool)$obj->ProvideComments);
|
||||||
$this->assertEquals('None', $obj->ModerationRequired);
|
$this->assertEquals('None', $obj->ModerationRequired);
|
||||||
$this->assertFalse((bool)$obj->CommentsRequireLogin);
|
$this->assertFalse((bool)$obj->CommentsRequireLogin);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
When a parent comment is deleted, remove the children
|
When a parent comment is deleted, remove the children
|
||||||
*/
|
*/
|
||||||
public function testOnBeforeDelete() {
|
public function testOnBeforeDelete()
|
||||||
|
{
|
||||||
$comment = $this->objFromFixture('Comment', 'firstComA');
|
$comment = $this->objFromFixture('Comment', 'firstComA');
|
||||||
|
|
||||||
$child = new Comment();
|
$child = new Comment();
|
||||||
@ -547,11 +578,13 @@ class CommentsTest extends FunctionalTest {
|
|||||||
$this->assertFalse(DataObject::get_by_id('Comment', $childCommentID));
|
$this->assertFalse(DataObject::get_by_id('Comment', $childCommentID));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testRequireDefaultRecords() {
|
public function testRequireDefaultRecords()
|
||||||
|
{
|
||||||
$this->markTestSkipped('TODO');
|
$this->markTestSkipped('TODO');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testLink() {
|
public function testLink()
|
||||||
|
{
|
||||||
$comment = $this->objFromFixture('Comment', 'thirdComD');
|
$comment = $this->objFromFixture('Comment', 'thirdComD');
|
||||||
$this->assertEquals('CommentableItem_Controller#comment-'.$comment->ID,
|
$this->assertEquals('CommentableItem_Controller#comment-'.$comment->ID,
|
||||||
$comment->Link());
|
$comment->Link());
|
||||||
@ -563,7 +596,8 @@ class CommentsTest extends FunctionalTest {
|
|||||||
$this->assertEquals('', $comment->Link());
|
$this->assertEquals('', $comment->Link());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPermalink() {
|
public function testPermalink()
|
||||||
|
{
|
||||||
$comment = $this->objFromFixture('Comment', 'thirdComD');
|
$comment = $this->objFromFixture('Comment', 'thirdComD');
|
||||||
$this->assertEquals('comment-' . $comment->ID, $comment->Permalink());
|
$this->assertEquals('comment-' . $comment->ID, $comment->Permalink());
|
||||||
}
|
}
|
||||||
@ -571,7 +605,8 @@ class CommentsTest extends FunctionalTest {
|
|||||||
/*
|
/*
|
||||||
Test field labels in 2 languages
|
Test field labels in 2 languages
|
||||||
*/
|
*/
|
||||||
public function testFieldLabels() {
|
public function testFieldLabels()
|
||||||
|
{
|
||||||
$locale = i18n::get_locale();
|
$locale = i18n::get_locale();
|
||||||
i18n::set_locale('fr');
|
i18n::set_locale('fr');
|
||||||
$comment = $this->objFromFixture('Comment', 'firstComA');
|
$comment = $this->objFromFixture('Comment', 'firstComA');
|
||||||
@ -619,18 +654,21 @@ class CommentsTest extends FunctionalTest {
|
|||||||
$this->assertEquals($expected, $labels);
|
$this->assertEquals($expected, $labels);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testGetOption() {
|
public function testGetOption()
|
||||||
|
{
|
||||||
$this->markTestSkipped('TODO');
|
$this->markTestSkipped('TODO');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testGetParent() {
|
public function testGetParent()
|
||||||
|
{
|
||||||
$comment = $this->objFromFixture('Comment', 'firstComA');
|
$comment = $this->objFromFixture('Comment', 'firstComA');
|
||||||
$item = $this->objFromFixture('CommentableItem', 'first');
|
$item = $this->objFromFixture('CommentableItem', 'first');
|
||||||
$parent = $comment->getParent();
|
$parent = $comment->getParent();
|
||||||
$this->assertEquals($item, $parent);
|
$this->assertEquals($item, $parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testGetParentTitle() {
|
public function testGetParentTitle()
|
||||||
|
{
|
||||||
$comment = $this->objFromFixture('Comment', 'firstComA');
|
$comment = $this->objFromFixture('Comment', 'firstComA');
|
||||||
$title = $comment->getParentTitle();
|
$title = $comment->getParentTitle();
|
||||||
$this->assertEquals('First', $title);
|
$this->assertEquals('First', $title);
|
||||||
@ -641,21 +679,25 @@ class CommentsTest extends FunctionalTest {
|
|||||||
$this->assertEquals('', $comment->getParentTitle());
|
$this->assertEquals('', $comment->getParentTitle());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testGetParentClassName() {
|
public function testGetParentClassName()
|
||||||
|
{
|
||||||
$comment = $this->objFromFixture('Comment', 'firstComA');
|
$comment = $this->objFromFixture('Comment', 'firstComA');
|
||||||
$className = $comment->getParentClassName();
|
$className = $comment->getParentClassName();
|
||||||
$this->assertEquals('CommentableItem', $className);
|
$this->assertEquals('CommentableItem', $className);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testCastingHelper() {
|
public function testCastingHelper()
|
||||||
|
{
|
||||||
$this->markTestSkipped('TODO');
|
$this->markTestSkipped('TODO');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testGetEscapedComment() {
|
public function testGetEscapedComment()
|
||||||
|
{
|
||||||
$this->markTestSkipped('TODO');
|
$this->markTestSkipped('TODO');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testIsPreview() {
|
public function testIsPreview()
|
||||||
|
{
|
||||||
$comment = new Comment();
|
$comment = new Comment();
|
||||||
$comment->Name = 'Fred Bloggs';
|
$comment->Name = 'Fred Bloggs';
|
||||||
$comment->Comment = 'this is a test comment';
|
$comment->Comment = 'this is a test comment';
|
||||||
@ -664,7 +706,8 @@ class CommentsTest extends FunctionalTest {
|
|||||||
$this->assertFalse($comment->isPreview());
|
$this->assertFalse($comment->isPreview());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testCanCreate() {
|
public function testCanCreate()
|
||||||
|
{
|
||||||
$comment = $this->objFromFixture('Comment', 'firstComA');
|
$comment = $this->objFromFixture('Comment', 'firstComA');
|
||||||
|
|
||||||
// admin can create - this is always false
|
// admin can create - this is always false
|
||||||
@ -676,7 +719,8 @@ class CommentsTest extends FunctionalTest {
|
|||||||
$this->assertFalse($comment->canCreate());
|
$this->assertFalse($comment->canCreate());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testCanView() {
|
public function testCanView()
|
||||||
|
{
|
||||||
$comment = $this->objFromFixture('Comment', 'firstComA');
|
$comment = $this->objFromFixture('Comment', 'firstComA');
|
||||||
|
|
||||||
// admin can view
|
// admin can view
|
||||||
@ -692,7 +736,8 @@ class CommentsTest extends FunctionalTest {
|
|||||||
$this->assertFalse($comment->canView());
|
$this->assertFalse($comment->canView());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testCanEdit() {
|
public function testCanEdit()
|
||||||
|
{
|
||||||
$comment = $this->objFromFixture('Comment', 'firstComA');
|
$comment = $this->objFromFixture('Comment', 'firstComA');
|
||||||
|
|
||||||
// admin can edit
|
// admin can edit
|
||||||
@ -708,7 +753,8 @@ class CommentsTest extends FunctionalTest {
|
|||||||
$this->assertFalse($comment->canEdit());
|
$this->assertFalse($comment->canEdit());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testCanDelete() {
|
public function testCanDelete()
|
||||||
|
{
|
||||||
$comment = $this->objFromFixture('Comment', 'firstComA');
|
$comment = $this->objFromFixture('Comment', 'firstComA');
|
||||||
|
|
||||||
// admin can delete
|
// admin can delete
|
||||||
@ -724,7 +770,8 @@ class CommentsTest extends FunctionalTest {
|
|||||||
$this->assertFalse($comment->canDelete());
|
$this->assertFalse($comment->canDelete());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testGetMember() {
|
public function testGetMember()
|
||||||
|
{
|
||||||
$this->logInAs('visitor');
|
$this->logInAs('visitor');
|
||||||
$current = Member::currentUser();
|
$current = Member::currentUser();
|
||||||
$comment = $this->objFromFixture('Comment', 'firstComA');
|
$comment = $this->objFromFixture('Comment', 'firstComA');
|
||||||
@ -743,7 +790,8 @@ class CommentsTest extends FunctionalTest {
|
|||||||
$this->assertEquals($current, $member);
|
$this->assertEquals($current, $member);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testGetAuthorName() {
|
public function testGetAuthorName()
|
||||||
|
{
|
||||||
$comment = $this->objFromFixture('Comment', 'firstComA');
|
$comment = $this->objFromFixture('Comment', 'firstComA');
|
||||||
$this->assertEquals(
|
$this->assertEquals(
|
||||||
'FA',
|
'FA',
|
||||||
@ -768,11 +816,11 @@ class CommentsTest extends FunctionalTest {
|
|||||||
$comment->Name = null;
|
$comment->Name = null;
|
||||||
$comment->AuthorID = 0;
|
$comment->AuthorID = 0;
|
||||||
$this->assertNull($comment->getAuthorName());
|
$this->assertNull($comment->getAuthorName());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public function testLinks() {
|
public function testLinks()
|
||||||
|
{
|
||||||
$comment = $this->objFromFixture('Comment', 'firstComA');
|
$comment = $this->objFromFixture('Comment', 'firstComA');
|
||||||
$this->logInAs('commentadmin');
|
$this->logInAs('commentadmin');
|
||||||
|
|
||||||
@ -808,27 +856,31 @@ class CommentsTest extends FunctionalTest {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testMarkSpam() {
|
public function testMarkSpam()
|
||||||
|
{
|
||||||
$comment = $this->objFromFixture('Comment', 'firstComA');
|
$comment = $this->objFromFixture('Comment', 'firstComA');
|
||||||
$comment->markSpam();
|
$comment->markSpam();
|
||||||
$this->assertTrue($comment->Moderated);
|
$this->assertTrue($comment->Moderated);
|
||||||
$this->assertTrue($comment->IsSpam);
|
$this->assertTrue($comment->IsSpam);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testMarkApproved() {
|
public function testMarkApproved()
|
||||||
|
{
|
||||||
$comment = $this->objFromFixture('Comment', 'firstComA');
|
$comment = $this->objFromFixture('Comment', 'firstComA');
|
||||||
$comment->markApproved();
|
$comment->markApproved();
|
||||||
$this->assertTrue($comment->Moderated);
|
$this->assertTrue($comment->Moderated);
|
||||||
$this->assertFalse($comment->IsSpam);
|
$this->assertFalse($comment->IsSpam);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testMarkUnapproved() {
|
public function testMarkUnapproved()
|
||||||
|
{
|
||||||
$comment = $this->objFromFixture('Comment', 'firstComA');
|
$comment = $this->objFromFixture('Comment', 'firstComA');
|
||||||
$comment->markApproved();
|
$comment->markApproved();
|
||||||
$this->assertTrue($comment->Moderated);
|
$this->assertTrue($comment->Moderated);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testSpamClass() {
|
public function testSpamClass()
|
||||||
|
{
|
||||||
$comment = $this->objFromFixture('Comment', 'firstComA');
|
$comment = $this->objFromFixture('Comment', 'firstComA');
|
||||||
$this->assertEquals('notspam', $comment->spamClass());
|
$this->assertEquals('notspam', $comment->spamClass());
|
||||||
$comment->Moderated = false;
|
$comment->Moderated = false;
|
||||||
@ -837,7 +889,8 @@ class CommentsTest extends FunctionalTest {
|
|||||||
$this->assertEquals('spam', $comment->spamClass());
|
$this->assertEquals('spam', $comment->spamClass());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testGetTitle() {
|
public function testGetTitle()
|
||||||
|
{
|
||||||
$comment = $this->objFromFixture('Comment', 'firstComA');
|
$comment = $this->objFromFixture('Comment', 'firstComA');
|
||||||
$this->assertEquals(
|
$this->assertEquals(
|
||||||
'Comment by FA on First',
|
'Comment by FA on First',
|
||||||
@ -845,7 +898,8 @@ class CommentsTest extends FunctionalTest {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testGetCMSFields() {
|
public function testGetCMSFields()
|
||||||
|
{
|
||||||
$comment = $this->objFromFixture('Comment', 'firstComA');
|
$comment = $this->objFromFixture('Comment', 'firstComA');
|
||||||
$fields = $comment->getCMSFields();
|
$fields = $comment->getCMSFields();
|
||||||
$names = array();
|
$names = array();
|
||||||
@ -863,7 +917,8 @@ class CommentsTest extends FunctionalTest {
|
|||||||
$this->assertEquals($expected, $names);
|
$this->assertEquals($expected, $names);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testGetCMSFieldsCommentHasAuthor() {
|
public function testGetCMSFieldsCommentHasAuthor()
|
||||||
|
{
|
||||||
$member = Member::get()->filter('FirstName', 'visitor')->first();
|
$member = Member::get()->filter('FirstName', 'visitor')->first();
|
||||||
$comment = $this->objFromFixture('Comment', 'firstComA');
|
$comment = $this->objFromFixture('Comment', 'firstComA');
|
||||||
$comment->AuthorID = $member->ID;
|
$comment->AuthorID = $member->ID;
|
||||||
@ -886,7 +941,8 @@ class CommentsTest extends FunctionalTest {
|
|||||||
$this->assertEquals($expected, $names);
|
$this->assertEquals($expected, $names);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testGetCMSFieldsWithParentComment() {
|
public function testGetCMSFieldsWithParentComment()
|
||||||
|
{
|
||||||
$comment = $this->objFromFixture('Comment', 'firstComA');
|
$comment = $this->objFromFixture('Comment', 'firstComA');
|
||||||
|
|
||||||
$child = new Comment();
|
$child = new Comment();
|
||||||
@ -916,7 +972,8 @@ class CommentsTest extends FunctionalTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public function testPurifyHtml() {
|
public function testPurifyHtml()
|
||||||
|
{
|
||||||
$comment = $this->objFromFixture('Comment', 'firstComA');
|
$comment = $this->objFromFixture('Comment', 'firstComA');
|
||||||
|
|
||||||
$dirtyHTML = '<p><script>alert("w00t")</script>my comment</p>';
|
$dirtyHTML = '<p><script>alert("w00t")</script>my comment</p>';
|
||||||
@ -926,7 +983,8 @@ class CommentsTest extends FunctionalTest {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testGravatar() {
|
public function testGravatar()
|
||||||
|
{
|
||||||
// Turn gravatars on
|
// Turn gravatars on
|
||||||
Config::inst()->update('CommentableItem', 'comments', array(
|
Config::inst()->update('CommentableItem', 'comments', array(
|
||||||
'use_gravatar' => true
|
'use_gravatar' => true
|
||||||
@ -951,7 +1009,8 @@ class CommentsTest extends FunctionalTest {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testGetRepliesEnabled() {
|
public function testGetRepliesEnabled()
|
||||||
|
{
|
||||||
$comment = $this->objFromFixture('Comment', 'firstComA');
|
$comment = $this->objFromFixture('Comment', 'firstComA');
|
||||||
Config::inst()->update('CommentableItem', 'comments', array(
|
Config::inst()->update('CommentableItem', 'comments', array(
|
||||||
'nested_comments' => false
|
'nested_comments' => false
|
||||||
@ -983,11 +1042,10 @@ class CommentsTest extends FunctionalTest {
|
|||||||
|
|
||||||
$comment->markApproved();
|
$comment->markApproved();
|
||||||
$this->assertTrue($comment->getRepliesEnabled());
|
$this->assertTrue($comment->getRepliesEnabled());
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testAllReplies() {
|
public function testAllReplies()
|
||||||
|
{
|
||||||
Config::inst()->update('CommentableItem', 'comments', array(
|
Config::inst()->update('CommentableItem', 'comments', array(
|
||||||
'nested_comments' => true,
|
'nested_comments' => true,
|
||||||
'nested_depth' => 4
|
'nested_depth' => 4
|
||||||
@ -1018,7 +1076,8 @@ class CommentsTest extends FunctionalTest {
|
|||||||
$this->assertEquals(0, $comment->allReplies()->count());
|
$this->assertEquals(0, $comment->allReplies()->count());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testReplies() {
|
public function testReplies()
|
||||||
|
{
|
||||||
CommentableItem::add_extension('CommentsExtension');
|
CommentableItem::add_extension('CommentsExtension');
|
||||||
$this->logInWithPermission('ADMIN');
|
$this->logInWithPermission('ADMIN');
|
||||||
Config::inst()->update('CommentableItem', 'comments', array(
|
Config::inst()->update('CommentableItem', 'comments', array(
|
||||||
@ -1085,7 +1144,8 @@ class CommentsTest extends FunctionalTest {
|
|||||||
CommentableItem::remove_extension('CommentsExtension');
|
CommentableItem::remove_extension('CommentsExtension');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPagedReplies() {
|
public function testPagedReplies()
|
||||||
|
{
|
||||||
Config::inst()->update('CommentableItem', 'comments', array(
|
Config::inst()->update('CommentableItem', 'comments', array(
|
||||||
'nested_comments' => true,
|
'nested_comments' => true,
|
||||||
'nested_depth' => 4,
|
'nested_depth' => 4,
|
||||||
@ -1111,7 +1171,8 @@ class CommentsTest extends FunctionalTest {
|
|||||||
$this->assertEquals(0, $comment->PagedReplies()->count());
|
$this->assertEquals(0, $comment->PagedReplies()->count());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testReplyForm() {
|
public function testReplyForm()
|
||||||
|
{
|
||||||
Config::inst()->update('CommentableItem', 'comments', array(
|
Config::inst()->update('CommentableItem', 'comments', array(
|
||||||
'nested_comments' => false,
|
'nested_comments' => false,
|
||||||
'nested_depth' => 4
|
'nested_depth' => 4
|
||||||
@ -1154,7 +1215,8 @@ class CommentsTest extends FunctionalTest {
|
|||||||
$this->assertNull($form);
|
$this->assertNull($form);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testUpdateDepth() {
|
public function testUpdateDepth()
|
||||||
|
{
|
||||||
Config::inst()->update('CommentableItem', 'comments', array(
|
Config::inst()->update('CommentableItem', 'comments', array(
|
||||||
'nested_comments' => true,
|
'nested_comments' => true,
|
||||||
'nested_depth' => 4
|
'nested_depth' => 4
|
||||||
@ -1175,34 +1237,39 @@ class CommentsTest extends FunctionalTest {
|
|||||||
$this->assertEquals(4, $reply3->Depth);
|
$this->assertEquals(4, $reply3->Depth);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testGetToken() {
|
public function testGetToken()
|
||||||
|
{
|
||||||
$this->markTestSkipped('TODO');
|
$this->markTestSkipped('TODO');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testMemberSalt() {
|
public function testMemberSalt()
|
||||||
|
{
|
||||||
$this->markTestSkipped('TODO');
|
$this->markTestSkipped('TODO');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testAddToUrl() {
|
public function testAddToUrl()
|
||||||
|
{
|
||||||
$this->markTestSkipped('TODO');
|
$this->markTestSkipped('TODO');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testCheckRequest() {
|
public function testCheckRequest()
|
||||||
|
{
|
||||||
$this->markTestSkipped('TODO');
|
$this->markTestSkipped('TODO');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testGenerate() {
|
public function testGenerate()
|
||||||
|
{
|
||||||
$this->markTestSkipped('TODO');
|
$this->markTestSkipped('TODO');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected static function getMethod($name) {
|
protected static function getMethod($name)
|
||||||
|
{
|
||||||
$class = new ReflectionClass('Comment');
|
$class = new ReflectionClass('Comment');
|
||||||
$method = $class->getMethod($name);
|
$method = $class->getMethod($name);
|
||||||
$method->setAccessible(true);
|
$method->setAccessible(true);
|
||||||
return $method;
|
return $method;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1210,67 +1277,83 @@ class CommentsTest extends FunctionalTest {
|
|||||||
* @package comments
|
* @package comments
|
||||||
* @subpackage tests
|
* @subpackage tests
|
||||||
*/
|
*/
|
||||||
class CommentableItem extends DataObject implements TestOnly {
|
class CommentableItem extends DataObject implements TestOnly
|
||||||
|
{
|
||||||
|
|
||||||
private static $db = array(
|
private static $db = array(
|
||||||
'Title' => 'Varchar'
|
'Title' => 'Varchar'
|
||||||
);
|
);
|
||||||
|
|
||||||
private static $extensions = array(
|
private static $extensions = array(
|
||||||
'CommentsExtension'
|
'CommentsExtension'
|
||||||
);
|
);
|
||||||
|
|
||||||
public function RelativeLink() {
|
public function RelativeLink()
|
||||||
return "CommentableItem_Controller";
|
{
|
||||||
}
|
return "CommentableItem_Controller";
|
||||||
|
}
|
||||||
|
|
||||||
public function canView($member = null) {
|
public function canView($member = null)
|
||||||
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is needed for canModerateComments
|
// This is needed for canModerateComments
|
||||||
public function canEdit($member = null) {
|
public function canEdit($member = null)
|
||||||
if($member instanceof Member) $memberID = $member->ID;
|
{
|
||||||
else if(is_numeric($member)) $memberID = $member;
|
if ($member instanceof Member) {
|
||||||
else $memberID = Member::currentUserID();
|
$memberID = $member->ID;
|
||||||
|
} elseif (is_numeric($member)) {
|
||||||
|
$memberID = $member;
|
||||||
|
} else {
|
||||||
|
$memberID = Member::currentUserID();
|
||||||
|
}
|
||||||
|
|
||||||
if($memberID && Permission::checkMember($memberID, array("ADMIN", "CMS_ACCESS_CommentAdmin"))) return true;
|
if ($memberID && Permission::checkMember($memberID, array("ADMIN", "CMS_ACCESS_CommentAdmin"))) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function Link() {
|
public function Link()
|
||||||
return $this->RelativeLink();
|
{
|
||||||
}
|
return $this->RelativeLink();
|
||||||
|
}
|
||||||
|
|
||||||
public function AbsoluteLink() {
|
public function AbsoluteLink()
|
||||||
return Director::absoluteURL($this->RelativeLink());
|
{
|
||||||
}
|
return Director::absoluteURL($this->RelativeLink());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class CommentableItemEnabled extends CommentableItem {
|
class CommentableItemEnabled extends CommentableItem
|
||||||
private static $defaults = array(
|
{
|
||||||
'ProvideComments' => true,
|
private static $defaults = array(
|
||||||
'ModerationRequired' => 'Required',
|
'ProvideComments' => true,
|
||||||
'CommentsRequireLogin' => true
|
'ModerationRequired' => 'Required',
|
||||||
);
|
'CommentsRequireLogin' => true
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class CommentableItemDisabled extends CommentableItem {
|
class CommentableItemDisabled extends CommentableItem
|
||||||
private static $defaults = array(
|
{
|
||||||
'ProvideComments' => false,
|
private static $defaults = array(
|
||||||
'ModerationRequired' => 'None',
|
'ProvideComments' => false,
|
||||||
'CommentsRequireLogin' => false
|
'ModerationRequired' => 'None',
|
||||||
);
|
'CommentsRequireLogin' => false
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @package comments
|
* @package comments
|
||||||
* @subpackage tests
|
* @subpackage tests
|
||||||
*/
|
*/
|
||||||
class CommentableItem_Controller extends Controller implements TestOnly {
|
class CommentableItem_Controller extends Controller implements TestOnly
|
||||||
|
{
|
||||||
|
|
||||||
public function index() {
|
public function index()
|
||||||
return CommentableItem::get()->first()->CommentsForm();
|
{
|
||||||
}
|
return CommentableItem::get()->first()->CommentsForm();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user