mirror of
https://github.com/silverstripe/silverstripe-comments
synced 2024-10-22 11:05:49 +02:00
SS4 compatibility updates - ORM, Form, Controller changes
* Remove CommentList and replace with a polymorphic has_one relationship * Tweaks for unit tests. Add tests for encode/decodeClassName.
This commit is contained in:
parent
c698632aae
commit
ab3f35257b
@ -43,7 +43,7 @@ before_script:
|
||||
- composer self-update || true
|
||||
- git clone git://github.com/silverstripe-labs/silverstripe-travis-support.git ~/travis-support
|
||||
# Install suggested modules in order to maximize test coverage
|
||||
- php ~/travis-support/travis_setup.php --source `pwd` --target ~/builds/ss --require "ezyang/htmlpurifier:4.*,silverstripe/cms:~3.1"
|
||||
- php ~/travis-support/travis_setup.php --source `pwd` --target ~/builds/ss --require "silverstripe/cms:^4.0@dev"
|
||||
- cd ~/builds/ss
|
||||
|
||||
script:
|
||||
|
28
.upgrade.yml
Normal file
28
.upgrade.yml
Normal file
@ -0,0 +1,28 @@
|
||||
mappings:
|
||||
Commenting: SilverStripe\Comments\Commenting
|
||||
CommentAdmin: SilverStripe\Comments\Admin\CommentAdmin
|
||||
CommentsGridField: SilverStripe\Comments\Admin\CommentsGridField
|
||||
CommentsGridFieldAction: SilverStripe\Comments\Admin\CommentsGridFieldAction
|
||||
CommentsGridFieldBulkAction: SilverStripe\Comments\Admin\CommentsGridFieldBulkAction
|
||||
CommentsGridFieldBulkAction_Handlers: SilverStripe\Comments\Admin\CommentsGridFieldBulkAction_Handlers
|
||||
CommentsGridFieldConfig: SilverStripe\Comments\Admin\CommentsGridFieldConfig
|
||||
CommentingController: SilverStripe\Comments\Controllers\CommentingController
|
||||
CommentsExtension: SilverStripe\Comments\Extensions\CommentsExtension
|
||||
Comment: SilverStripe\Comments\Model\Comment
|
||||
Comment_SecurityToken: SilverStripe\Comments\Model\Comment_SecurityToken
|
||||
CommentList: SilverStripe\Comments\Model\CommentList
|
||||
CommentAdminTest: SilverStripe\Comments\Tests\CommentAdminTest
|
||||
CommentingControllerTest: SilverStripe\Comments\Tests\CommentingControllerTest
|
||||
CommentingTest: SilverStripe\Comments\Tests\CommentingTest
|
||||
CommentListTest: SilverStripe\Comments\Tests\CommentListTest
|
||||
CommentsExtensionTest: SilverStripe\Comments\Tests\CommentsExtensionTest
|
||||
CommentsGridFieldActionTest: SilverStripe\Comments\Tests\CommentsGridFieldActionTest
|
||||
CommentsGridFieldBulkActionTest: SilverStripe\Comments\Tests\CommentsGridFieldBulkActionTest
|
||||
CommentsGridFieldConfigTest: SilverStripe\Comments\Tests\CommentsGridFieldConfigTest
|
||||
CommentsGridFieldTest: SilverStripe\Comments\Tests\CommentsGridFieldTest
|
||||
CommentsTest: SilverStripe\Comments\Tests\CommentsTest
|
||||
CommentableItem: SilverStripe\Comments\Tests\CommentableItem
|
||||
CommentableItemEnabled: SilverStripe\Comments\Tests\CommentableItemEnabled
|
||||
CommentableItemDisabled: SilverStripe\Comments\Tests\CommentableItemDisabled
|
||||
CommentableItem_Controller: SilverStripe\Comments\Tests\CommentableItem_Controller
|
||||
CommentTestHelper: SilverStripe\Comments\Tests\CommentTestHelper
|
@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
Deprecation::notification_version('2.0', 'comments');
|
||||
\SilverStripe\Dev\Deprecation::notification_version('2.0', 'comments');
|
||||
|
||||
define('COMMENTS_DIR', basename(__DIR__));
|
||||
define('COMMENTS_THIRDPARTY', COMMENTS_DIR . DIRECTORY_SEPARATOR . 'thirdparty');
|
||||
|
@ -4,7 +4,8 @@ After: framework/routes#coreroutes
|
||||
---
|
||||
SilverStripe\Control\Director:
|
||||
rules:
|
||||
comments: SilverStripe\Comments\Controllers\CommentingController
|
||||
# handle old 2.4 style urls
|
||||
'CommentingController//$Action/$ID/$OtherID': 'SilverStripe\Comments\Controllers\CommentingController'
|
||||
'PageComments/$Action/$ID/$OtherID': 'SilverStripe\Comments\Controllers\CommentingController'
|
||||
'PageComments_Controller/$Action/$ID/$OtherID': 'SilverStripe\Comments\Controllers\CommentingController'
|
||||
CommentingController//$Action/$ID/$OtherID: SilverStripe\Comments\Controllers\CommentingController
|
||||
PageComments/$Action/$ID/$OtherID: SilverStripe\Comments\Controllers\CommentingController
|
||||
PageCommentsController/$Action/$ID/$OtherID: SilverStripe\Comments\Controllers\CommentingController
|
||||
|
@ -12,7 +12,6 @@
|
||||
"colymba/gridfield-bulk-editing-tools": "~2.1"
|
||||
},
|
||||
"suggest": {
|
||||
"ezyang/htmlpurifier": "Standards compliant HTML filter written in PHP",
|
||||
"silverstripe/cms": "The SilverStripe Content Management System"
|
||||
},
|
||||
"require-dev": {
|
||||
@ -23,5 +22,11 @@
|
||||
"dev-master": "3.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"SilverStripe\\Comments\\": "src/",
|
||||
"SilverStripe\\Comments\\Tests\\": "tests/"
|
||||
}
|
||||
},
|
||||
"license": "BSD-3-Clause"
|
||||
}
|
||||
|
@ -9,9 +9,9 @@ In order to add commenting to your site, the minimum amount of work necessary is
|
||||
the base class for the object which holds comments.
|
||||
|
||||
```yaml
|
||||
SiteTree:
|
||||
SilverStripe\CMS\Model\SiteTree:
|
||||
extensions:
|
||||
- CommentsExtension
|
||||
- SilverStripe\Comments\Extensions\CommentsExtension
|
||||
```
|
||||
|
||||
## Configuration
|
||||
@ -20,9 +20,9 @@ In order to configure options for any class you should assign the specific optio
|
||||
config of the specified class.
|
||||
|
||||
```yaml
|
||||
SiteTree:
|
||||
SilverStripe\CMS\Model\SiteTree:
|
||||
extensions:
|
||||
- CommentsExtension
|
||||
- SilverStripe\Comments\Extensions\CommentsExtension
|
||||
comments:
|
||||
enabled: true # Enables commenting to be disabled for a specific class (or subclass of a parent with commenting enabled)
|
||||
enabled_cms: false # The 'enabled' option will be set via the CMS instead of config
|
||||
@ -63,7 +63,7 @@ the extension (or on the built-in SiteTree commenting) use `set_config_value`
|
||||
|
||||
```yaml
|
||||
# Set the default option for pages to require login
|
||||
SiteTree:
|
||||
SilverStripe\CMS\Model\SiteTree:
|
||||
comments:
|
||||
require_login: true
|
||||
```
|
||||
@ -71,7 +71,7 @@ SiteTree:
|
||||
|
||||
```php
|
||||
// Get the setting
|
||||
$loginRequired = singleton('SiteTree')->getCommentsOption('require_login');
|
||||
$loginRequired = singleton('SilverStripe\\CMS\\Model\\SiteTree')->getCommentsOption('require_login');
|
||||
```
|
||||
|
||||
|
||||
@ -86,9 +86,11 @@ In order to use this feature, you need to install the
|
||||
[HTMLPurifier](http://htmlpurifier.org/) library. The easiest way to do this is
|
||||
through [Composer](http://getcomposer.org).
|
||||
|
||||
{
|
||||
"require": {"ezyang/htmlpurifier": "4.*"}
|
||||
}
|
||||
```json
|
||||
{
|
||||
"require": {"ezyang/htmlpurifier": "^4.8"}
|
||||
}
|
||||
```
|
||||
|
||||
**Important**: Rendering user-provided HTML on your website always risks
|
||||
exposing your users to cross-site scripting (XSS) attacks, if the HTML isn't
|
||||
@ -99,7 +101,7 @@ properly sanitized. Don't allow tags like `<script>` or arbitrary attributes.
|
||||
Gravatars can be turned on by adding this to your mysite/_config/config.yml file
|
||||
|
||||
```yaml
|
||||
SiteTree:
|
||||
SilverStripe\CMS\Model\SiteTree:
|
||||
comments:
|
||||
use_gravatar: true
|
||||
````
|
||||
@ -108,7 +110,7 @@ The default size is 80 pixels, as per the gravatar site if the 's' parameter is
|
||||
omitted. To change this add the following (again to mysite/_config/config.yml):
|
||||
|
||||
```yaml
|
||||
SiteTree:
|
||||
SilverStripe\CMS\Model\SiteTree:
|
||||
comments:
|
||||
gravatar_size: 40
|
||||
```
|
||||
@ -132,7 +134,7 @@ purposes)
|
||||
To change the default image style, add the following to mysite/_config/config.yml
|
||||
|
||||
```yaml
|
||||
SiteTree:
|
||||
SilverStripe\CMS\Model\SiteTree:
|
||||
comments:
|
||||
gravatar_default: 'retro'
|
||||
```
|
||||
@ -141,7 +143,7 @@ The rating of the image can be changed by adding a line similar to this to
|
||||
mysite/_config/config.yml
|
||||
|
||||
```yaml
|
||||
SiteTree:
|
||||
SilverStripe\CMS\Model\SiteTree:
|
||||
comments:
|
||||
gravatar_rating: 'r'
|
||||
```
|
||||
|
@ -18,7 +18,7 @@ After you have finished downloading the file, extract the downloaded file to you
|
||||
|
||||
## All
|
||||
|
||||
Run a database rebuild by visiting *http://yoursite.com/dev/build*. This will add the required database columns and tables for the module to function.
|
||||
Run a database rebuild by visiting *http://yoursite.com/dev/build?flush=1*. This will add the required database columns and tables for the module to function, and refresh the configuration manifest.
|
||||
|
||||
If you previously had SilverStripe version 2.4 installed then you'll also need to run the migration script provided. More information on this is provided in the next section.
|
||||
|
||||
@ -34,4 +34,4 @@ For more configuration options see [Configuration](Configuration.md).
|
||||
|
||||
This module replaces the built-in commenting system available in versions up to SilverStripe 2.4. To migrate from that you'll need to run `dev/build` after installing the module.
|
||||
|
||||
You can do this via sake (`sake dev/build`) or via a web browser by visiting `http://yoursite.com/dev/build`
|
||||
You can do this via sake (`sake dev/build flush=1`) or via a web browser by visiting `http://yoursite.com/dev/build?flush=1`
|
||||
|
@ -1,5 +1,17 @@
|
||||
<?php
|
||||
|
||||
namespace SilverStripe\Comments\Admin;
|
||||
|
||||
use SilverStripe\Admin\LeftAndMain;
|
||||
use SilverStripe\Comments\Admin\CommentsGridField;
|
||||
use SilverStripe\Comments\Model\Comment;
|
||||
use SilverStripe\Forms\Tab;
|
||||
use SilverStripe\Forms\TabSet;
|
||||
use SilverStripe\Forms\FieldList;
|
||||
use SilverStripe\Forms\Form;
|
||||
use SilverStripe\Security\PermissionProvider;
|
||||
use SilverStripe\Security\Security;
|
||||
|
||||
/**
|
||||
* Comment administration system within the CMS
|
||||
*
|
||||
|
@ -1,5 +1,10 @@
|
||||
<?php
|
||||
|
||||
namespace SilverStripe\Comments\Admin;
|
||||
|
||||
use SilverStripe\Forms\FormField;
|
||||
use SilverStripe\Forms\GridField\GridField;
|
||||
|
||||
class CommentsGridField extends GridField
|
||||
{
|
||||
/**
|
||||
|
@ -1,5 +1,14 @@
|
||||
<?php
|
||||
|
||||
namespace SilverStripe\Comments\Admin;
|
||||
|
||||
use SilverStripe\Comments\Model\Comment;
|
||||
use SilverStripe\Control\Controller;
|
||||
use SilverStripe\Forms\GridField\GridField;
|
||||
use SilverStripe\Forms\GridField\GridField_ActionProvider;
|
||||
use SilverStripe\Forms\GridField\GridField_ColumnProvider;
|
||||
use SilverStripe\Forms\GridField\GridField_FormAction;
|
||||
|
||||
class CommentsGridFieldAction implements GridField_ColumnProvider, GridField_ActionProvider
|
||||
{
|
||||
/**
|
||||
@ -47,7 +56,7 @@ class CommentsGridFieldAction implements GridField_ColumnProvider, GridField_Act
|
||||
return;
|
||||
}
|
||||
|
||||
$field = "";
|
||||
$field = '';
|
||||
|
||||
if (!$record->IsSpam || !$record->Moderated) {
|
||||
$field .= GridField_FormAction::create(
|
||||
@ -86,7 +95,7 @@ class CommentsGridFieldAction implements GridField_ColumnProvider, GridField_Act
|
||||
public function handleAction(GridField $gridField, $actionName, $arguments, $data)
|
||||
{
|
||||
if ($actionName == 'spam') {
|
||||
$comment = Comment::get()->byID($arguments["RecordID"]);
|
||||
$comment = Comment::get()->byID($arguments['RecordID']);
|
||||
$comment->markSpam();
|
||||
|
||||
// output a success message to the user
|
||||
@ -97,7 +106,7 @@ class CommentsGridFieldAction implements GridField_ColumnProvider, GridField_Act
|
||||
}
|
||||
|
||||
if ($actionName == 'approve') {
|
||||
$comment = Comment::get()->byID($arguments["RecordID"]);
|
||||
$comment = Comment::get()->byID($arguments['RecordID']);
|
||||
$comment->markApproved();
|
||||
|
||||
// output a success message to the user
|
||||
|
@ -1,67 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace SilverStripe\Comments\Admin;
|
||||
|
||||
use Colymba\BulkManager\GridFieldBulkActionHandler;
|
||||
|
||||
/**
|
||||
* @package comments
|
||||
*/
|
||||
class CommentsGridFieldBulkAction extends GridFieldBulkActionHandler
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* A {@link GridFieldBulkActionHandler} for bulk marking comments as spam
|
||||
*
|
||||
* @package comments
|
||||
*/
|
||||
class CommentsGridFieldBulkAction_Handlers extends CommentsGridFieldBulkAction
|
||||
{
|
||||
|
||||
private static $allowed_actions = array(
|
||||
'spam',
|
||||
'approve',
|
||||
);
|
||||
|
||||
private static $url_handlers = array(
|
||||
'spam' => 'spam',
|
||||
'approve' => 'approve',
|
||||
);
|
||||
|
||||
|
||||
public function spam(SS_HTTPRequest $request)
|
||||
{
|
||||
$ids = array();
|
||||
|
||||
foreach ($this->getRecords() as $record) {
|
||||
array_push($ids, $record->ID);
|
||||
$record->markSpam();
|
||||
}
|
||||
|
||||
$response = new SS_HTTPResponse(Convert::raw2json(array(
|
||||
'done' => true,
|
||||
'records' => $ids
|
||||
)));
|
||||
|
||||
$response->addHeader('Content-Type', 'text/json');
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
|
||||
public function approve(SS_HTTPRequest $request)
|
||||
{
|
||||
$ids = array();
|
||||
|
||||
foreach ($this->getRecords() as $record) {
|
||||
array_push($ids, $record->ID);
|
||||
$record->markApproved();
|
||||
}
|
||||
|
||||
$response = new SS_HTTPResponse(Convert::raw2json(array(
|
||||
'done' => true,
|
||||
'records' => $ids
|
||||
)));
|
||||
|
||||
$response->addHeader('Content-Type', 'text/json');
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
}
|
||||
|
78
src/Admin/CommentsGridFieldBulkAction/Handler.php
Normal file
78
src/Admin/CommentsGridFieldBulkAction/Handler.php
Normal file
@ -0,0 +1,78 @@
|
||||
<?php
|
||||
|
||||
namespace SilverStripe\Comments\Admin\CommentsGridFieldBulkAction;
|
||||
|
||||
use SilverStripe\Core\Convert;
|
||||
use SilverStripe\Comments\Admin\CommentsGridFieldBulkAction;
|
||||
use SilverStripe\Control\HTTPRequest;
|
||||
use SilverStripe\Control\HTTPResponse;
|
||||
|
||||
/**
|
||||
* A {@link GridFieldBulkActionHandler} for bulk marking comments as spam
|
||||
*
|
||||
* @package comments
|
||||
*/
|
||||
class Handlers extends CommentsGridFieldBulkAction
|
||||
{
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
private static $allowed_actions = array(
|
||||
'spam',
|
||||
'approve',
|
||||
);
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
private static $url_handlers = array(
|
||||
'spam' => 'spam',
|
||||
'approve' => 'approve',
|
||||
);
|
||||
|
||||
/**
|
||||
* @param HTTPRequest $request
|
||||
* @return HTTPResponse
|
||||
*/
|
||||
public function spam(HTTPRequest $request)
|
||||
{
|
||||
$ids = array();
|
||||
|
||||
foreach ($this->getRecords() as $record) {
|
||||
array_push($ids, $record->ID);
|
||||
$record->markSpam();
|
||||
}
|
||||
|
||||
$response = new HTTPResponse(Convert::raw2json(array(
|
||||
'done' => true,
|
||||
'records' => $ids
|
||||
)));
|
||||
|
||||
$response->addHeader('Content-Type', 'text/json');
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param HTTPRequest $request
|
||||
* @return HTTPResponse
|
||||
*/
|
||||
public function approve(HTTPRequest $request)
|
||||
{
|
||||
$ids = array();
|
||||
|
||||
foreach ($this->getRecords() as $record) {
|
||||
array_push($ids, $record->ID);
|
||||
$record->markApproved();
|
||||
}
|
||||
|
||||
$response = new HTTPResponse(Convert::raw2json(array(
|
||||
'done' => true,
|
||||
'records' => $ids
|
||||
)));
|
||||
|
||||
$response->addHeader('Content-Type', 'text/json');
|
||||
|
||||
return $response;
|
||||
}
|
||||
}
|
@ -1,5 +1,16 @@
|
||||
<?php
|
||||
|
||||
namespace SilverStripe\Comments\Admin;
|
||||
|
||||
use Colymba\BulkManager\GridFieldBulkManager;
|
||||
use SilverStripe\Comments\Admin\CommentsGridFieldBulkAction\Handlers;
|
||||
use SilverStripe\Core\Convert;
|
||||
use SilverStripe\Forms\GridField\GridFieldConfig_RecordEditor;
|
||||
use SilverStripe\Forms\GridField\GridFieldDataColumns;
|
||||
|
||||
/**
|
||||
* @package comments
|
||||
*/
|
||||
class CommentsGridFieldConfig extends GridFieldConfig_RecordEditor
|
||||
{
|
||||
public function __construct($itemsPerPage = 25)
|
||||
@ -11,7 +22,7 @@ class CommentsGridFieldConfig extends GridFieldConfig_RecordEditor
|
||||
$this->addComponent(new CommentsGridFieldAction());
|
||||
|
||||
// Format column
|
||||
$columns = $this->getComponentByType('GridFieldDataColumns');
|
||||
$columns = $this->getComponentByType(GridFieldDataColumns::class);
|
||||
$columns->setFieldFormatting(array(
|
||||
'ParentTitle' => function ($value, &$item) {
|
||||
return sprintf(
|
||||
@ -28,7 +39,7 @@ class CommentsGridFieldConfig extends GridFieldConfig_RecordEditor
|
||||
$manager->addBulkAction(
|
||||
'spam',
|
||||
_t('CommentsGridFieldConfig.SPAM', 'Spam'),
|
||||
'CommentsGridFieldBulkAction_Handlers',
|
||||
Handlers::class,
|
||||
array(
|
||||
'isAjax' => true,
|
||||
'icon' => 'cross',
|
||||
@ -39,7 +50,7 @@ class CommentsGridFieldConfig extends GridFieldConfig_RecordEditor
|
||||
$manager->addBulkAction(
|
||||
'approve',
|
||||
_t('CommentsGridFieldConfig.APPROVE', 'Approve'),
|
||||
'CommentsGridFieldBulkAction_Handlers',
|
||||
Handlers::class,
|
||||
array(
|
||||
'isAjax' => true,
|
||||
'icon' => 'cross',
|
||||
|
@ -1,5 +1,14 @@
|
||||
<?php
|
||||
|
||||
namespace SilverStripe\Comments;
|
||||
|
||||
use InvalidArgumentException;
|
||||
use SilverStripe\Comments\Extensions\CommentsExtension;
|
||||
use SilverStripe\Core\Config\Config;
|
||||
use SilverStripe\Dev\Deprecation;
|
||||
use SilverStripe\Security\Member;
|
||||
use SilverStripe\Security\Permission;
|
||||
|
||||
/**
|
||||
* Helper Class for storing the configuration options. Retains the mapping between
|
||||
* objects which have comments attached and the related configuration options.
|
||||
@ -15,7 +24,6 @@
|
||||
*/
|
||||
class Commenting
|
||||
{
|
||||
|
||||
/**
|
||||
* Adds commenting to a {@link DataObject}
|
||||
*
|
||||
@ -23,14 +31,14 @@ class Commenting
|
||||
*
|
||||
* @param string classname to add commenting to
|
||||
* @param array $settings Settings. See {@link self::$default_config} for
|
||||
* available settings
|
||||
* available settings
|
||||
*
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
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'));
|
||||
Config::inst()->update($class, 'extensions', array(CommentsExtension::class));
|
||||
|
||||
// Check if settings must be customised
|
||||
if ($settings === false) {
|
||||
@ -53,7 +61,7 @@ class Commenting
|
||||
public static function remove($class)
|
||||
{
|
||||
Deprecation::notice('2.0', 'Using Commenting::remove is deprecated. Please use the config API instead');
|
||||
$class::remove_extension('CommentsExtension');
|
||||
$class::remove_extension(CommentsExtension::class);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -66,7 +74,7 @@ class Commenting
|
||||
public static function has_commenting($class)
|
||||
{
|
||||
Deprecation::notice('2.0', 'Using Commenting::has_commenting is deprecated. Please use the config API instead');
|
||||
return $class::has_extension('CommentsExtension');
|
||||
return $class::has_extension(CommentsExtension::class);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -76,15 +84,15 @@ class Commenting
|
||||
* @deprecated since version 2.0
|
||||
*
|
||||
* @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 mixed $value value of the setting
|
||||
*/
|
||||
public static function set_config_value($class, $key, $value = false)
|
||||
{
|
||||
Deprecation::notice('2.0', 'Commenting::set_config_value is deprecated. Use the config api instead');
|
||||
if ($class === "all") {
|
||||
$class = 'CommentsExtension';
|
||||
if ($class === 'all') {
|
||||
$class = CommentsExtension::class;
|
||||
}
|
||||
Config::inst()->update($class, 'comments', array($key => $value));
|
||||
}
|
||||
@ -110,8 +118,8 @@ class Commenting
|
||||
|
||||
// Get settings
|
||||
if (!$class) {
|
||||
$class = 'CommentsExtension';
|
||||
} elseif (!$class::has_extension('CommentsExtension')) {
|
||||
$class = CommentsExtension::class;
|
||||
} elseif (!$class::has_extension(CommentsExtension::class)) {
|
||||
throw new InvalidArgumentException("$class does not have commenting enabled");
|
||||
}
|
||||
return singleton($class)->getCommentsOption($key);
|
||||
|
@ -1,12 +1,42 @@
|
||||
<?php
|
||||
|
||||
namespace SilverStripe\Comments\Controllers;
|
||||
|
||||
use SilverStripe\CMS\Model\SiteTree;
|
||||
use SilverStripe\Comments\Extensions\CommentsExtension;
|
||||
use SilverStripe\Comments\Model\Comment;
|
||||
use SilverStripe\Control\Cookie;
|
||||
use SilverStripe\Control\Director;
|
||||
use SilverStripe\Control\Controller;
|
||||
use SilverStripe\Control\Email\Email;
|
||||
use SilverStripe\Control\HTTP;
|
||||
use SilverStripe\Control\HTTPRequest;
|
||||
use SilverStripe\Control\RSS\RSSFeed;
|
||||
use SilverStripe\Control\Session;
|
||||
use SilverStripe\Core\Convert;
|
||||
use SilverStripe\Forms\CompositeField;
|
||||
use SilverStripe\Forms\EmailField;
|
||||
use SilverStripe\Forms\FieldList;
|
||||
use SilverStripe\Forms\Form;
|
||||
use SilverStripe\Forms\FormAction;
|
||||
use SilverStripe\Forms\HiddenField;
|
||||
use SilverStripe\Forms\ReadonlyField;
|
||||
use SilverStripe\Forms\RequiredFields;
|
||||
use SilverStripe\Forms\TextareaField;
|
||||
use SilverStripe\Forms\TextField;
|
||||
use SilverStripe\ORM\DataObject;
|
||||
use SilverStripe\ORM\PaginatedList;
|
||||
use SilverStripe\Security\Member;
|
||||
use SilverStripe\Security\Security;
|
||||
|
||||
/**
|
||||
* @package comments
|
||||
*/
|
||||
|
||||
class CommentingController extends Controller
|
||||
{
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
private static $allowed_actions = array(
|
||||
'delete',
|
||||
'spam',
|
||||
@ -19,6 +49,9 @@ class CommentingController extends Controller
|
||||
'doPreviewComment'
|
||||
);
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
private static $url_handlers = array(
|
||||
'reply/$ParentCommentID//$ID/$OtherID' => 'reply',
|
||||
);
|
||||
@ -36,11 +69,11 @@ class CommentingController extends Controller
|
||||
);
|
||||
|
||||
/**
|
||||
* Base class this commenting form is for
|
||||
* Parent class this commenting form is for
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $baseClass = "";
|
||||
private $parentClass = '';
|
||||
|
||||
/**
|
||||
* The record this commenting form is for
|
||||
@ -64,23 +97,45 @@ class CommentingController extends Controller
|
||||
protected $fallbackReturnURL = null;
|
||||
|
||||
/**
|
||||
* Set the base class to use
|
||||
* Set the parent class name to use
|
||||
*
|
||||
* @param string $class
|
||||
*/
|
||||
public function setBaseClass($class)
|
||||
public function setParentClass($class)
|
||||
{
|
||||
$this->baseClass = $class;
|
||||
$this->parentClass = $this->encodeClassName($class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the base class used
|
||||
* Get the parent class name used
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getBaseClass()
|
||||
public function getParentClass()
|
||||
{
|
||||
return $this->baseClass;
|
||||
return $this->decodeClassName($this->parentClass);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode a fully qualified class name to a URL-safe version
|
||||
*
|
||||
* @param string $input
|
||||
* @return string
|
||||
*/
|
||||
public function encodeClassName($input)
|
||||
{
|
||||
return str_replace('\\', '-', $input);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode an "encoded" fully qualified class name back to its original
|
||||
*
|
||||
* @param string $input
|
||||
* @return string
|
||||
*/
|
||||
public function decodeClassName($input)
|
||||
{
|
||||
return str_replace('-', '\\', $input);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -137,22 +192,25 @@ class CommentingController extends Controller
|
||||
}
|
||||
|
||||
// Otherwise a singleton of that record
|
||||
if ($class = $this->getBaseClass()) {
|
||||
if ($class = $this->getParentClass()) {
|
||||
return singleton($class)->getCommentsOption($key);
|
||||
}
|
||||
|
||||
// Otherwise just use the default options
|
||||
return singleton('CommentsExtension')->getCommentsOption($key);
|
||||
return singleton(CommentsExtension::class)->getCommentsOption($key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Workaround for generating the link to this controller
|
||||
*
|
||||
* @param string $action
|
||||
* @param int $id
|
||||
* @param string $other
|
||||
* @return string
|
||||
*/
|
||||
public function Link($action = '', $id = '', $other = '')
|
||||
{
|
||||
return Controller::join_links(Director::baseURL(), __CLASS__, $action, $id, $other);
|
||||
return Controller::join_links(Director::baseURL(), 'comments', $action, $id, $other);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -169,23 +227,19 @@ class CommentingController extends Controller
|
||||
* Return an RSSFeed of comments for a given set of comments or all
|
||||
* comments on the website.
|
||||
*
|
||||
* To maintain backwards compatibility with 2.4 this supports mapping
|
||||
* of PageComment/rss?pageid= as well as the new RSS format for comments
|
||||
* of CommentingController/rss/{classname}/{id}
|
||||
*
|
||||
* @param SS_HTTPRequest
|
||||
* @param HTTPRequest
|
||||
*
|
||||
* @return RSSFeed
|
||||
*/
|
||||
public function getFeed(SS_HTTPRequest $request)
|
||||
public function getFeed(HTTPRequest $request)
|
||||
{
|
||||
$link = $this->Link('rss');
|
||||
$class = $request->param('ID');
|
||||
$class = $this->decodeClassName($request->param('ID'));
|
||||
$id = $request->param('OtherID');
|
||||
|
||||
// Support old pageid param
|
||||
if (!$id && !$class && ($id = $request->getVar('pageid'))) {
|
||||
$class = 'SiteTree';
|
||||
$class = SiteTree::class;
|
||||
}
|
||||
|
||||
$comments = Comment::get()->filter(array(
|
||||
@ -195,12 +249,12 @@ class CommentingController extends Controller
|
||||
|
||||
// Check if class filter
|
||||
if ($class) {
|
||||
if (!is_subclass_of($class, 'DataObject') || !$class::has_extension('CommentsExtension')) {
|
||||
if (!is_subclass_of($class, DataObject::class) || !$class::has_extension(CommentsExtension::class)) {
|
||||
return $this->httpError(404);
|
||||
}
|
||||
$this->setBaseClass($class);
|
||||
$comments = $comments->filter('BaseClass', $class);
|
||||
$link = Controller::join_links($link, $class);
|
||||
$this->setParentClass($class);
|
||||
$comments = $comments->filter('ParentClass', $class);
|
||||
$link = Controller::join_links($link, $this->encodeClassName($class));
|
||||
|
||||
// Check if id filter
|
||||
if ($id) {
|
||||
@ -211,7 +265,6 @@ class CommentingController extends Controller
|
||||
}
|
||||
|
||||
$title = _t('CommentingController.RSSTITLE', "Comments RSS Feed");
|
||||
|
||||
$comments = new PaginatedList($comments, $request);
|
||||
$comments->setPageLength($this->getOption('comments_per_page'));
|
||||
|
||||
@ -220,7 +273,9 @@ class CommentingController extends Controller
|
||||
$link,
|
||||
$title,
|
||||
$link,
|
||||
'Title', 'EscapedComment', 'AuthorName'
|
||||
'Title',
|
||||
'EscapedComment',
|
||||
'AuthorName'
|
||||
);
|
||||
}
|
||||
|
||||
@ -302,7 +357,6 @@ class CommentingController extends Controller
|
||||
if (!$comment->getSecurityToken()->checkRequest($this->request)) {
|
||||
return $this->httpError(400);
|
||||
}
|
||||
|
||||
$comment->markApproved();
|
||||
return $this->renderChangedCommentState($comment);
|
||||
}
|
||||
@ -318,7 +372,7 @@ class CommentingController extends Controller
|
||||
|
||||
// Render comment using AJAX
|
||||
if ($this->request->isAjax()) {
|
||||
return $comment->renderWith('CommentsInterface_singlecomment');
|
||||
return $comment->renderWith('Includes/CommentsInterface_singlecomment');
|
||||
} else {
|
||||
// Redirect to either the comment or start of the page
|
||||
if (empty($referer)) {
|
||||
@ -345,10 +399,8 @@ class CommentingController extends Controller
|
||||
public function getComment()
|
||||
{
|
||||
$id = isset($this->urlParams['ID']) ? $this->urlParams['ID'] : false;
|
||||
|
||||
if ($id) {
|
||||
$comment = DataObject::get_by_id('Comment', $id);
|
||||
|
||||
$comment = Comment::get()->byId($id);
|
||||
if ($comment) {
|
||||
$this->fallbackReturnURL = $comment->Link();
|
||||
return $comment;
|
||||
@ -361,13 +413,14 @@ class CommentingController extends Controller
|
||||
/**
|
||||
* Create a reply form for a specified comment
|
||||
*
|
||||
* @param Comment $comment
|
||||
* @param Comment $comment
|
||||
* @return Form
|
||||
*/
|
||||
public function ReplyForm($comment)
|
||||
{
|
||||
// Enables multiple forms with different names to use the same handler
|
||||
$form = $this->CommentsForm();
|
||||
$form->setName('ReplyForm_'.$comment->ID);
|
||||
$form->setName('ReplyForm_' . $comment->ID);
|
||||
$form->addExtraClass('reply-form');
|
||||
|
||||
// Load parent into reply form
|
||||
@ -387,13 +440,14 @@ class CommentingController extends Controller
|
||||
* Request handler for reply form.
|
||||
* This method will disambiguate multiple reply forms in the same method
|
||||
*
|
||||
* @param SS_HTTPRequest $request
|
||||
* @param HTTPRequest $request
|
||||
* @throws HTTPResponse_Exception
|
||||
*/
|
||||
public function reply(SS_HTTPRequest $request)
|
||||
public function reply(HTTPRequest $request)
|
||||
{
|
||||
// Extract parent comment from reply and build this way
|
||||
if ($parentID = $request->param('ParentCommentID')) {
|
||||
$comment = DataObject::get_by_id('Comment', $parentID, true);
|
||||
$comment = DataObject::get_by_id(Comment::class, $parentID, true);
|
||||
if ($comment) {
|
||||
return $this->ReplyForm($comment);
|
||||
}
|
||||
@ -419,34 +473,31 @@ class CommentingController extends Controller
|
||||
$fields = new FieldList(
|
||||
$dataFields = new CompositeField(
|
||||
// Name
|
||||
TextField::create("Name", _t('CommentInterface.YOURNAME', 'Your name'))
|
||||
$a = TextField::create('Name', _t('CommentInterface.YOURNAME', 'Your name'))
|
||||
->setCustomValidationMessage($nameRequired)
|
||||
->setAttribute('data-msg-required', $nameRequired),
|
||||
|
||||
// Email
|
||||
EmailField::create(
|
||||
"Email",
|
||||
_t('CommentingController.EMAILADDRESS', "Your email address (will not be published)")
|
||||
'Email',
|
||||
_t('CommentingController.EMAILADDRESS', 'Your email address (will not be published)')
|
||||
)
|
||||
->setCustomValidationMessage($emailRequired)
|
||||
->setAttribute('data-msg-required', $emailRequired)
|
||||
->setAttribute('data-msg-email', $emailInvalid)
|
||||
->setAttribute('data-rule-email', true),
|
||||
|
||||
// Url
|
||||
TextField::create("URL", _t('CommentingController.WEBSITEURL', "Your website URL"))
|
||||
TextField::create('URL', _t('CommentingController.WEBSITEURL', 'Your website URL'))
|
||||
->setAttribute('data-msg-url', $urlInvalid)
|
||||
->setAttribute('data-rule-url', true),
|
||||
|
||||
// Comment
|
||||
TextareaField::create("Comment", _t('CommentingController.COMMENTS', "Comments"))
|
||||
TextareaField::create('Comment', _t('CommentingController.COMMENTS', 'Comments'))
|
||||
->setCustomValidationMessage($commentRequired)
|
||||
->setAttribute('data-msg-required', $commentRequired)
|
||||
),
|
||||
HiddenField::create("ParentID"),
|
||||
HiddenField::create("ReturnURL"),
|
||||
HiddenField::create("ParentCommentID"),
|
||||
HiddenField::create("BaseClass")
|
||||
HiddenField::create('ParentID'),
|
||||
HiddenField::create('ParentClassName'),
|
||||
HiddenField::create('ReturnURL'),
|
||||
HiddenField::create('ParentCommentID')
|
||||
);
|
||||
|
||||
// Preview formatted comment. Makes most sense when shortcodes or
|
||||
@ -463,7 +514,7 @@ class CommentingController extends Controller
|
||||
|
||||
// save actions
|
||||
$actions = new FieldList(
|
||||
new FormAction("doPostComment", _t('CommentInterface.POST', 'Post'))
|
||||
$postAction = new FormAction('doPostComment', _t('CommentInterface.POST', 'Post'))
|
||||
);
|
||||
if ($usePreview) {
|
||||
$actions->push(
|
||||
@ -481,7 +532,6 @@ class CommentingController extends Controller
|
||||
|
||||
// if the record exists load the extra required data
|
||||
if ($record = $this->getOwnerRecord()) {
|
||||
|
||||
// Load member data
|
||||
$member = Member::currentUser();
|
||||
if (($record->CommentsRequireLogin || $record->PostingRequiredPermission) && $member) {
|
||||
@ -489,17 +539,24 @@ class CommentingController extends Controller
|
||||
|
||||
$fields->removeByName('Name');
|
||||
$fields->removeByName('Email');
|
||||
$fields->insertBefore(new ReadonlyField("NameView", _t('CommentInterface.YOURNAME', 'Your name'), $member->getName()), 'URL');
|
||||
$fields->push(new HiddenField("Name", "", $member->getName()));
|
||||
$fields->push(new HiddenField("Email", "", $member->Email));
|
||||
$fields->insertBefore(
|
||||
new ReadonlyField(
|
||||
'NameView',
|
||||
_t('CommentInterface.YOURNAME', 'Your name'),
|
||||
$member->getName()
|
||||
),
|
||||
'URL'
|
||||
);
|
||||
$fields->push(new HiddenField('Name', '', $member->getName()));
|
||||
$fields->push(new HiddenField('Email', '', $member->Email));
|
||||
}
|
||||
|
||||
// we do not want to read a new URL when the form has already been submitted
|
||||
// which in here, it hasn't been.
|
||||
$form->loadDataFrom(array(
|
||||
'ParentID' => $record->ID,
|
||||
'ReturnURL' => $this->request->getURL(),
|
||||
'BaseClass' => $this->getBaseClass()
|
||||
'ParentID' => $record->ID,
|
||||
'ReturnURL' => $this->request->getURL(),
|
||||
'ParentClassName' => $this->getParentClass()
|
||||
));
|
||||
}
|
||||
|
||||
@ -511,14 +568,14 @@ class CommentingController extends Controller
|
||||
$data = Convert::json2array($data);
|
||||
|
||||
$form->loadDataFrom(array(
|
||||
"Name" => isset($data['Name']) ? $data['Name'] : '',
|
||||
"URL" => isset($data['URL']) ? $data['URL'] : '',
|
||||
"Email" => isset($data['Email']) ? $data['Email'] : ''
|
||||
'Name' => isset($data['Name']) ? $data['Name'] : '',
|
||||
'URL' => isset($data['URL']) ? $data['URL'] : '',
|
||||
'Email' => isset($data['Email']) ? $data['Email'] : ''
|
||||
));
|
||||
// allow previous value to fill if comment not stored in cookie (i.e. validation error)
|
||||
$prevComment = Cookie::get('CommentsForm_Comment');
|
||||
if ($prevComment && $prevComment != '') {
|
||||
$form->loadDataFrom(array("Comment" => $prevComment));
|
||||
$form->loadDataFrom(array('Comment' => $prevComment));
|
||||
}
|
||||
}
|
||||
|
||||
@ -535,24 +592,26 @@ class CommentingController extends Controller
|
||||
/**
|
||||
* Process which creates a {@link Comment} once a user submits a comment from this form.
|
||||
*
|
||||
* @param array $data
|
||||
* @param Form $form
|
||||
* @param array $data
|
||||
* @param Form $form
|
||||
* @return HTTPResponse
|
||||
*/
|
||||
public function doPostComment($data, $form)
|
||||
{
|
||||
// Load class and parent from data
|
||||
if (isset($data['BaseClass'])) {
|
||||
$this->setBaseClass($data['BaseClass']);
|
||||
if (isset($data['ParentClassName'])) {
|
||||
$this->setParentClass($data['ParentClassName']);
|
||||
}
|
||||
if (isset($data['ParentID']) && ($class = $this->getBaseClass())) {
|
||||
if (isset($data['ParentID']) && ($class = $this->getParentClass())) {
|
||||
$this->setOwnerRecord($class::get()->byID($data['ParentID']));
|
||||
}
|
||||
if (!$this->getOwnerRecord()) {
|
||||
return $this->httpError(404);
|
||||
}
|
||||
|
||||
// cache users data
|
||||
Cookie::set("CommentsForm_UserData", Convert::raw2json($data));
|
||||
Cookie::set("CommentsForm_Comment", $data['Comment']);
|
||||
Cookie::set('CommentsForm_UserData', Convert::raw2json($data));
|
||||
Cookie::set('CommentsForm_Comment', $data['Comment']);
|
||||
|
||||
// extend hook to allow extensions. Also see onAfterPostComment
|
||||
$this->extend('onBeforePostComment', $form);
|
||||
@ -564,13 +623,13 @@ class CommentingController extends Controller
|
||||
_t(
|
||||
'CommentingController.PERMISSIONFAILURE',
|
||||
"You're not able to post comments to this page. Please ensure you are logged in and have an "
|
||||
. "appropriate permission level."
|
||||
. 'appropriate permission level.'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
if ($member = Member::currentUser()) {
|
||||
$form->Fields()->push(new HiddenField("AuthorID", "Author ID", $member->ID));
|
||||
$form->Fields()->push(new HiddenField('AuthorID', 'Author ID', $member->ID));
|
||||
}
|
||||
|
||||
// What kind of moderation is required?
|
||||
@ -590,6 +649,9 @@ class CommentingController extends Controller
|
||||
$comment = new Comment();
|
||||
$form->saveInto($comment);
|
||||
|
||||
$comment->ParentID = $data['ParentID'];
|
||||
$comment->ParentClass = $data['ParentClassName'];
|
||||
|
||||
$comment->AllowHtml = $this->getOption('html_allowed');
|
||||
$comment->Moderated = !$requireModeration;
|
||||
|
||||
@ -616,7 +678,7 @@ class CommentingController extends Controller
|
||||
// Find parent link
|
||||
if (!empty($data['ReturnURL'])) {
|
||||
$url = $data['ReturnURL'];
|
||||
} elseif ($parent = $comment->getParent()) {
|
||||
} elseif ($parent = $comment->Parent()) {
|
||||
$url = $parent->Link();
|
||||
} else {
|
||||
return $this->redirectBack();
|
||||
@ -628,7 +690,7 @@ class CommentingController extends Controller
|
||||
$hash = $form->FormName();
|
||||
} elseif (!$comment->Moderated) {
|
||||
// Display the "awaiting moderation" text
|
||||
$hash = "moderated";
|
||||
$hash = 'moderated';
|
||||
} else {
|
||||
// Link to the moderated, non-spam comment
|
||||
$hash = $comment->Permalink();
|
||||
@ -637,6 +699,11 @@ class CommentingController extends Controller
|
||||
return $this->redirect(Controller::join_links($url, "#{$hash}"));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
* @param Form $form
|
||||
* @return HTTPResponse
|
||||
*/
|
||||
public function doPreviewComment($data, $form)
|
||||
{
|
||||
$data['IsPreview'] = 1;
|
||||
@ -644,6 +711,9 @@ class CommentingController extends Controller
|
||||
return $this->doPostComment($data, $form);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return HTTPResponse|false
|
||||
*/
|
||||
public function redirectBack()
|
||||
{
|
||||
// Don't cache the redirect back ever
|
||||
|
@ -1,5 +1,28 @@
|
||||
<?php
|
||||
|
||||
namespace SilverStripe\Comments\Extensions;
|
||||
|
||||
use SilverStripe\Comments\Admin\CommentsGridField;
|
||||
use SilverStripe\Comments\Admin\CommentsGridFieldConfig;
|
||||
use SilverStripe\Comments\Controllers\CommentingController;
|
||||
use SilverStripe\Comments\Model\Comment;
|
||||
use SilverStripe\Control\Controller;
|
||||
use SilverStripe\Control\Director;
|
||||
use SilverStripe\Control\Session;
|
||||
use SilverStripe\Core\Config\Config;
|
||||
use SilverStripe\Dev\Deprecation;
|
||||
use SilverStripe\Forms\CheckboxField;
|
||||
use SilverStripe\Forms\DropdownField;
|
||||
use SilverStripe\Forms\FieldGroup;
|
||||
use SilverStripe\Forms\FieldList;
|
||||
use SilverStripe\Forms\Tab;
|
||||
use SilverStripe\Forms\TabSet;
|
||||
use SilverStripe\ORM\DataExtension;
|
||||
use SilverStripe\ORM\PaginatedList;
|
||||
use SilverStripe\Security\Member;
|
||||
use SilverStripe\Security\Permission;
|
||||
use SilverStripe\View\Requirements;
|
||||
|
||||
/**
|
||||
* Extension to {@link DataObject} to enable tracking comments.
|
||||
*
|
||||
@ -75,6 +98,13 @@ class CommentsExtension extends DataExtension
|
||||
'CommentsRequireLogin' => 'Boolean',
|
||||
);
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
private static $has_many = [
|
||||
'Commments' => 'SilverStripe\\Comments\\Model\\Comment.Parent'
|
||||
];
|
||||
|
||||
/**
|
||||
* CMS configurable options should default to the config values, but respect
|
||||
* default values specified by the object
|
||||
@ -204,13 +234,13 @@ class CommentsExtension extends DataExtension
|
||||
* Returns the RelationList of all comments against this object. Can be used as a data source
|
||||
* for a gridfield with write access.
|
||||
*
|
||||
* @return CommentList
|
||||
* @return DataList
|
||||
*/
|
||||
public function AllComments()
|
||||
{
|
||||
$order = $this->owner->getCommentsOption('order_comments_by');
|
||||
$comments = CommentList::create($this->ownerBaseClass)
|
||||
->forForeignID($this->owner->ID)
|
||||
$comments = Comment::get()
|
||||
->filter('ParentID', $this->owner->ID)
|
||||
->sort($order);
|
||||
$this->owner->extend('updateAllComments', $comments);
|
||||
return $comments;
|
||||
@ -219,7 +249,7 @@ class CommentsExtension extends DataExtension
|
||||
/**
|
||||
* Returns all comments against this object, with with spam and unmoderated items excluded, for use in the frontend
|
||||
*
|
||||
* @return CommentList
|
||||
* @return DataList
|
||||
*/
|
||||
public function AllVisibleComments()
|
||||
{
|
||||
@ -245,7 +275,7 @@ class CommentsExtension extends DataExtension
|
||||
/**
|
||||
* Returns the root level comments, with spam and unmoderated items excluded, for use in the frontend
|
||||
*
|
||||
* @return CommentList
|
||||
* @return DataList
|
||||
*/
|
||||
public function Comments()
|
||||
{
|
||||
@ -414,7 +444,7 @@ class CommentsExtension extends DataExtension
|
||||
*/
|
||||
public function getCommentRSSLink()
|
||||
{
|
||||
return Controller::join_links(Director::baseURL(), 'CommentingController/rss');
|
||||
return Controller::join_links(Director::baseURL(), 'comments/rss');
|
||||
}
|
||||
|
||||
public function getRssLinkPage()
|
||||
@ -431,7 +461,9 @@ class CommentsExtension extends DataExtension
|
||||
public function getCommentRSSLinkPage()
|
||||
{
|
||||
return Controller::join_links(
|
||||
$this->getCommentRSSLink(), $this->ownerBaseClass, $this->owner->ID
|
||||
$this->getCommentRSSLink(),
|
||||
str_replace('\\', '-', $this->ownerBaseClass),
|
||||
$this->owner->ID
|
||||
);
|
||||
}
|
||||
|
||||
@ -451,9 +483,9 @@ class CommentsExtension extends DataExtension
|
||||
// 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(ADMIN_THIRDPARTY_DIR . '/jquery/jquery.js');
|
||||
Requirements::javascript(ADMIN_THIRDPARTY_DIR . '/jquery-entwine/dist/jquery.entwine-dist.js');
|
||||
Requirements::javascript(ADMIN_THIRDPARTY_DIR . '/jquery-form/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');
|
||||
@ -461,7 +493,7 @@ class CommentsExtension extends DataExtension
|
||||
|
||||
$controller = CommentingController::create();
|
||||
$controller->setOwnerRecord($this->owner);
|
||||
$controller->setBaseClass($this->ownerBaseClass);
|
||||
$controller->setParentClass($this->owner->getClassName());
|
||||
$controller->setOwnerController(Controller::curr());
|
||||
|
||||
$moderatedSubmitted = Session::get('CommentsModerated');
|
||||
@ -489,7 +521,7 @@ class CommentsExtension extends DataExtension
|
||||
{
|
||||
$class = $this->ownerBaseClass;
|
||||
|
||||
return (is_subclass_of($class, 'SiteTree')) || ($class == 'SiteTree');
|
||||
return (is_subclass_of($class, SiteTree::class)) || ($class == SiteTree::class);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1,5 +1,31 @@
|
||||
<?php
|
||||
|
||||
namespace SilverStripe\Comments\Model;
|
||||
|
||||
use HTMLPurifier_Config;
|
||||
use HTMLPurifier;
|
||||
use SilverStripe\Comments\Controllers\CommentingController;
|
||||
use SilverStripe\Comments\Extensions\CommentsExtension;
|
||||
use SilverStripe\Comments\Model\Comment\SecurityToken;
|
||||
use SilverStripe\Control\Controller;
|
||||
use SilverStripe\Control\Director;
|
||||
use SilverStripe\Core\Email\Email;
|
||||
use SilverStripe\Core\Injector\Injector;
|
||||
use SilverStripe\Forms\CheckboxField;
|
||||
use SilverStripe\Forms\EmailField;
|
||||
use SilverStripe\Forms\FieldGroup;
|
||||
use SilverStripe\Forms\FieldList;
|
||||
use SilverStripe\Forms\HeaderField;
|
||||
use SilverStripe\Forms\HTMLEditor\HTMLEditorField;
|
||||
use SilverStripe\Forms\TextareaField;
|
||||
use SilverStripe\Forms\TextField;
|
||||
use SilverStripe\ORM\ArrayList;
|
||||
use SilverStripe\ORM\DataObject;
|
||||
use SilverStripe\ORM\DB;
|
||||
use SilverStripe\ORM\PaginatedList;
|
||||
use SilverStripe\Security\Member;
|
||||
use SilverStripe\Security\Permission;
|
||||
|
||||
/**
|
||||
* Represents a single comment object.
|
||||
*
|
||||
@ -22,40 +48,53 @@
|
||||
*/
|
||||
class Comment extends DataObject
|
||||
{
|
||||
|
||||
/**
|
||||
* @var array
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
private static $db = array(
|
||||
'Name' => 'Varchar(200)',
|
||||
'Comment' => 'Text',
|
||||
'Email' => 'Varchar(200)',
|
||||
'URL' => 'Varchar(255)',
|
||||
'BaseClass' => 'Varchar(200)',
|
||||
'Moderated' => 'Boolean(0)',
|
||||
'IsSpam' => 'Boolean(0)',
|
||||
'ParentID' => 'Int',
|
||||
'AllowHtml' => 'Boolean',
|
||||
'SecretToken' => 'Varchar(255)',
|
||||
'Depth' => 'Int',
|
||||
'Depth' => 'Int'
|
||||
);
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
private static $has_one = array(
|
||||
"Author" => "Member",
|
||||
"ParentComment" => "Comment",
|
||||
'Author' => Member::class,
|
||||
'ParentComment' => self::class,
|
||||
'Parent' => DataObject::class
|
||||
);
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
private static $has_many = array(
|
||||
"ChildComments" => "Comment"
|
||||
'ChildComments' => self::class
|
||||
);
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
private static $default_sort = '"Created" DESC';
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
private static $defaults = array(
|
||||
'Moderated' => 0,
|
||||
'IsSpam' => 0,
|
||||
);
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
private static $casting = array(
|
||||
'Title' => 'Varchar',
|
||||
'ParentTitle' => 'Varchar',
|
||||
@ -66,30 +105,46 @@ class Comment extends DataObject
|
||||
'SpamLink' => 'Varchar',
|
||||
'HamLink' => 'Varchar',
|
||||
'ApproveLink' => 'Varchar',
|
||||
'Permalink' => 'Varchar',
|
||||
'Permalink' => 'Varchar'
|
||||
);
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
private static $searchable_fields = array(
|
||||
'Name',
|
||||
'Email',
|
||||
'Comment',
|
||||
'Created',
|
||||
'BaseClass',
|
||||
'Created'
|
||||
);
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
private static $summary_fields = array(
|
||||
'Name' => 'Submitted By',
|
||||
'Email' => 'Email',
|
||||
'Comment.LimitWordCount' => 'Comment',
|
||||
'Created' => 'Date Posted',
|
||||
'ParentTitle' => 'Post',
|
||||
'IsSpam' => 'Is Spam',
|
||||
'Parent.Title' => 'Post',
|
||||
'IsSpam' => 'Is Spam'
|
||||
);
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
private static $field_labels = array(
|
||||
'Author' => 'Author Member',
|
||||
'Author' => 'Author Member'
|
||||
);
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
private static $table_name = 'Comment';
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function onBeforeWrite()
|
||||
{
|
||||
parent::onBeforeWrite();
|
||||
@ -103,6 +158,9 @@ class Comment extends DataObject
|
||||
$this->updateDepth();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function onBeforeDelete()
|
||||
{
|
||||
parent::onBeforeDelete();
|
||||
@ -118,7 +176,7 @@ class Comment extends DataObject
|
||||
*/
|
||||
public function getSecurityToken()
|
||||
{
|
||||
return Injector::inst()->createWithArgs('Comment_SecurityToken', array($this));
|
||||
return Injector::inst()->createWithArgs(SecurityToken::class, array($this));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -128,7 +186,7 @@ class Comment extends DataObject
|
||||
{
|
||||
parent::requireDefaultRecords();
|
||||
|
||||
if (DB::getConn()->hasTable('PageComment')) {
|
||||
if (DB::get_schema()->hasTable('PageComment')) {
|
||||
$comments = DB::query('SELECT * FROM "PageComment"');
|
||||
|
||||
if ($comments) {
|
||||
@ -138,7 +196,7 @@ class Comment extends DataObject
|
||||
$comment->update($pageComment);
|
||||
|
||||
// set the variables which have changed
|
||||
$comment->BaseClass = 'SiteTree';
|
||||
$comment->BaseClass = SiteTree::class;
|
||||
$comment->URL = (isset($pageComment['CommenterURL'])) ? $pageComment['CommenterURL'] : '';
|
||||
if ((int) $pageComment['NeedsModeration'] == 0) {
|
||||
$comment->Moderated = true;
|
||||
@ -149,7 +207,7 @@ class Comment extends DataObject
|
||||
}
|
||||
|
||||
DB::alteration_message('Migrated PageComment to Comment', 'changed');
|
||||
DB::getConn()->dontRequireTable('PageComment');
|
||||
DB::get_schema()->dontRequireTable('PageComment');
|
||||
}
|
||||
}
|
||||
|
||||
@ -162,7 +220,7 @@ class Comment extends DataObject
|
||||
*/
|
||||
public function Link($action = '')
|
||||
{
|
||||
if ($parent = $this->getParent()) {
|
||||
if ($parent = $this->Parent()) {
|
||||
return $parent->Link($action) . '#' . $this->Permalink();
|
||||
}
|
||||
}
|
||||
@ -212,22 +270,25 @@ class Comment extends DataObject
|
||||
public function getOption($key)
|
||||
{
|
||||
// If possible use the current record
|
||||
$record = $this->getParent();
|
||||
$record = $this->Parent();
|
||||
|
||||
if (!$record && $this->BaseClass) {
|
||||
if (!$record && $this->Parent()) {
|
||||
// Otherwise a singleton of that record
|
||||
$record = singleton($this->BaseClass);
|
||||
$record = singleton($this->Parent()->dataClass());
|
||||
} elseif (!$record) {
|
||||
// Otherwise just use the default options
|
||||
$record = singleton('CommentsExtension');
|
||||
$record = singleton(CommentsExtension::class);
|
||||
}
|
||||
|
||||
return ($record->hasMethod('getCommentsOption')) ? $record->getCommentsOption($key) : null;
|
||||
return ($record instanceof CommentsExtension || $record->hasExtension(CommentsExtension::class))
|
||||
? $record->getCommentsOption($key)
|
||||
: null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the parent {@link DataObject} this comment is attached too
|
||||
*
|
||||
* @deprecated 4.0.0 Use $this->Parent() instead
|
||||
* @return DataObject
|
||||
*/
|
||||
public function getParent()
|
||||
@ -245,7 +306,7 @@ class Comment extends DataObject
|
||||
*/
|
||||
public function getParentTitle()
|
||||
{
|
||||
if ($parent = $this->getParent()) {
|
||||
if ($parent = $this->Parent()) {
|
||||
return $parent->Title ?: ($parent->ClassName . ' #' . $parent->ID);
|
||||
}
|
||||
}
|
||||
@ -257,13 +318,16 @@ class Comment extends DataObject
|
||||
*/
|
||||
public function getParentClassName()
|
||||
{
|
||||
return $this->BaseClass;
|
||||
return $this->Parent()->getClassName();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function castingHelper($field)
|
||||
{
|
||||
// Safely escape the comment
|
||||
if ($field === 'EscapedComment') {
|
||||
if (in_array($field, ['EscapedComment', 'Comment'], true)) {
|
||||
return $this->AllowHtml ? 'HTMLText' : 'Text';
|
||||
}
|
||||
return parent::castingHelper($field);
|
||||
@ -293,10 +357,10 @@ class Comment extends DataObject
|
||||
* @todo needs to compare to the new {@link Commenting} configuration API
|
||||
*
|
||||
* @param Member $member
|
||||
*
|
||||
* @param array $context
|
||||
* @return bool
|
||||
*/
|
||||
public function canCreate($member = null)
|
||||
public function canCreate($member = null, $context = [])
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@ -306,7 +370,6 @@ class Comment extends DataObject
|
||||
* flag being set to true.
|
||||
*
|
||||
* @param Member $member
|
||||
*
|
||||
* @return Boolean
|
||||
*/
|
||||
public function canView($member = null)
|
||||
@ -322,9 +385,9 @@ class Comment extends DataObject
|
||||
return true;
|
||||
}
|
||||
|
||||
if ($parent = $this->getParent()) {
|
||||
if ($parent = $this->Parent()) {
|
||||
return $parent->canView($member)
|
||||
&& $parent->has_extension('CommentsExtension')
|
||||
&& $parent->hasExtension(CommentsExtension::class)
|
||||
&& $parent->CommentsEnabled;
|
||||
}
|
||||
|
||||
@ -335,7 +398,6 @@ class Comment extends DataObject
|
||||
* Checks if the comment can be edited.
|
||||
*
|
||||
* @param null|int|Member $member
|
||||
*
|
||||
* @return Boolean
|
||||
*/
|
||||
public function canEdit($member = null)
|
||||
@ -355,7 +417,7 @@ class Comment extends DataObject
|
||||
return true;
|
||||
}
|
||||
|
||||
if ($parent = $this->getParent()) {
|
||||
if ($parent = $this->Parent()) {
|
||||
return $parent->canEdit($member);
|
||||
}
|
||||
|
||||
@ -366,7 +428,6 @@ class Comment extends DataObject
|
||||
* Checks if the comment can be deleted.
|
||||
*
|
||||
* @param null|int|Member $member
|
||||
*
|
||||
* @return Boolean
|
||||
*/
|
||||
public function canDelete($member = null)
|
||||
@ -398,7 +459,7 @@ class Comment extends DataObject
|
||||
}
|
||||
|
||||
if (is_numeric($member)) {
|
||||
$member = DataObject::get_by_id('Member', $member, true);
|
||||
$member = DataObject::get_by_id(Member::class, $member, true);
|
||||
}
|
||||
|
||||
return $member;
|
||||
@ -435,9 +496,17 @@ class Comment extends DataObject
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @todo: How do we handle "DataObject" instances that don't have a Link to reject/spam/delete?? This may
|
||||
* we have to make CMS a hard dependency instead.
|
||||
*/
|
||||
// if (!$this->Parent()->hasMethod('Link')) {
|
||||
// return false;
|
||||
// }
|
||||
|
||||
$url = Controller::join_links(
|
||||
Director::baseURL(),
|
||||
'CommentingController',
|
||||
'comments',
|
||||
$action,
|
||||
$this->ID
|
||||
);
|
||||
@ -556,7 +625,7 @@ class Comment extends DataObject
|
||||
{
|
||||
$title = sprintf(_t('Comment.COMMENTBY', 'Comment by %s', 'Name'), $this->getAuthorName());
|
||||
|
||||
if ($parent = $this->getParent()) {
|
||||
if ($parent = $this->Parent()) {
|
||||
if ($parent->Title) {
|
||||
$title .= sprintf(' %s %s', _t('Comment.ON', 'on'), $parent->Title);
|
||||
}
|
||||
@ -570,7 +639,7 @@ class Comment extends DataObject
|
||||
*/
|
||||
public function getCMSFields()
|
||||
{
|
||||
$commentField = $this->AllowHtml ? 'HtmlEditorField' : 'TextareaField';
|
||||
$commentField = $this->AllowHtml ? HTMLEditorField::class : TextareaField::class;
|
||||
$fields = new FieldList(
|
||||
$this
|
||||
->obj('Created')
|
||||
@ -610,8 +679,8 @@ class Comment extends DataObject
|
||||
// FIXME - the method setName in DatetimeField is not chainable, hence
|
||||
// the lack of chaining here
|
||||
$createdField = $parent
|
||||
->obj('Created')
|
||||
->scaffoldFormField($parent->fieldLabel('Created'));
|
||||
->obj('Created')
|
||||
->scaffoldFormField($parent->fieldLabel('Created'));
|
||||
$createdField->setName('ParentComment_Created');
|
||||
$createdField->setValue($parent->Created);
|
||||
$createdField->performReadonlyTransformation();
|
||||
@ -631,7 +700,7 @@ class Comment extends DataObject
|
||||
$fields->push(
|
||||
$parent
|
||||
->obj('EscapedComment')
|
||||
->scaffoldFormField($parent->fieldLabel('Comment'))
|
||||
->scaffoldFormField($parent->fieldLabel(self::class))
|
||||
->setName('ParentComment_EscapedComment')
|
||||
->setValue($parent->Comment)
|
||||
->performReadonlyTransformation()
|
||||
@ -643,9 +712,9 @@ class Comment extends DataObject
|
||||
}
|
||||
|
||||
/**
|
||||
* @param String $dirtyHtml
|
||||
* @param string $dirtyHtml
|
||||
*
|
||||
* @return String
|
||||
* @return string
|
||||
*/
|
||||
public function purifyHtml($dirtyHtml)
|
||||
{
|
||||
@ -659,8 +728,10 @@ class Comment extends DataObject
|
||||
public function getHtmlPurifierService()
|
||||
{
|
||||
$config = HTMLPurifier_Config::createDefault();
|
||||
$allowedElements = $this->getOption('html_allowed_elements');
|
||||
$config->set('HTML.AllowedElements', $allowedElements);
|
||||
$allowedElements = (array) $this->getOption('html_allowed_elements');
|
||||
if (!empty($allowedElements)) {
|
||||
$config->set('HTML.AllowedElements', $allowedElements);
|
||||
}
|
||||
|
||||
// This injector cannot be set unless the 'p' element is allowed
|
||||
if (in_array('p', $allowedElements)) {
|
||||
@ -748,7 +819,7 @@ class Comment extends DataObject
|
||||
$list = $this->AllReplies();
|
||||
|
||||
// Filter spam comments for non-administrators if configured
|
||||
$parent = $this->getParent();
|
||||
$parent = $this->Parent();
|
||||
$showSpam = $this->getOption('frontend_spam') && $parent && $parent->canModerateComments();
|
||||
if (!$showSpam) {
|
||||
$list = $list->filter('IsSpam', 0);
|
||||
@ -778,7 +849,7 @@ class Comment extends DataObject
|
||||
|
||||
// Add pagination
|
||||
$list = new PaginatedList($list, Controller::curr()->getRequest());
|
||||
$list->setPaginationGetVar('repliesstart'.$this->ID);
|
||||
$list->setPaginationGetVar('repliesstart' . $this->ID);
|
||||
$list->setPageLength($this->getOption('comments_per_page'));
|
||||
|
||||
$this->extend('updatePagedReplies', $list);
|
||||
@ -798,7 +869,7 @@ class Comment extends DataObject
|
||||
}
|
||||
|
||||
// Check parent is available
|
||||
$parent = $this->getParent();
|
||||
$parent = $this->Parent();
|
||||
if (!$parent || !$parent->exists()) {
|
||||
return null;
|
||||
}
|
||||
@ -806,7 +877,7 @@ class Comment extends DataObject
|
||||
// Build reply controller
|
||||
$controller = CommentingController::create();
|
||||
$controller->setOwnerRecord($parent);
|
||||
$controller->setBaseClass($parent->ClassName);
|
||||
$controller->setParentClass($parent->ClassName);
|
||||
$controller->setOwnerController(Controller::curr());
|
||||
|
||||
return $controller->ReplyForm($this);
|
||||
@ -826,115 +897,3 @@ class Comment extends DataObject
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Provides the ability to generate cryptographically secure tokens for comment moderation
|
||||
*/
|
||||
class Comment_SecurityToken
|
||||
{
|
||||
|
||||
private $secret = null;
|
||||
|
||||
/**
|
||||
* @param Comment $comment Comment to generate this token for
|
||||
*/
|
||||
public function __construct($comment)
|
||||
{
|
||||
if (!$comment->SecretToken) {
|
||||
$comment->SecretToken = $this->generate();
|
||||
$comment->write();
|
||||
}
|
||||
$this->secret = $comment->SecretToken;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the token for the given salt and current secret
|
||||
*
|
||||
* @param string $salt
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function getToken($salt)
|
||||
{
|
||||
return hash_pbkdf2('sha256', $this->secret, $salt, 1000, 30);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the member-specific salt.
|
||||
*
|
||||
* The reason for making the salt specific to a user is that it cannot be "passed in" via a
|
||||
* querystring, requiring the same user to be present at both the link generation and the
|
||||
* controller action.
|
||||
*
|
||||
* @param string $salt Single use salt
|
||||
* @param Member $member Member object
|
||||
*
|
||||
* @return string Generated salt specific to this 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);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $url Comment action URL
|
||||
* @param Member $member Member to restrict access to this action to
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function addToUrl($url, $member)
|
||||
{
|
||||
$salt = $this->generate(15); // New random salt; Will be passed into url
|
||||
// Generate salt specific to this member
|
||||
$memberSalt = $this->memberSalt($salt, $member);
|
||||
$token = $this->getToken($memberSalt);
|
||||
return Controller::join_links(
|
||||
$url,
|
||||
sprintf(
|
||||
'?t=%s&s=%s',
|
||||
urlencode($token),
|
||||
urlencode($salt)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param SS_HTTPRequest $request
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function checkRequest($request)
|
||||
{
|
||||
$member = Member::currentUser();
|
||||
if (!$member) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$salt = $request->getVar('s');
|
||||
$memberSalt = $this->memberSalt($salt, $member);
|
||||
$token = $this->getToken($memberSalt);
|
||||
|
||||
// Ensure tokens match
|
||||
return $token === $request->getVar('t');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Generates new random key
|
||||
*
|
||||
* @param integer $length
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function generate($length = null)
|
||||
{
|
||||
$generator = new RandomGenerator();
|
||||
$result = $generator->randomToken('sha256');
|
||||
if ($length !== null) {
|
||||
return substr($result, 0, $length);
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
|
120
src/Model/Comment/SecurityToken.php
Normal file
120
src/Model/Comment/SecurityToken.php
Normal file
@ -0,0 +1,120 @@
|
||||
<?php
|
||||
|
||||
namespace SilverStripe\Comments\Model\Comment;
|
||||
|
||||
use SilverStripe\Control\Controller;
|
||||
use SilverStripe\Security\Member;
|
||||
use SilverStripe\Security\RandomGenerator;
|
||||
|
||||
/**
|
||||
* Provides the ability to generate cryptographically secure tokens for comment moderation
|
||||
*/
|
||||
class SecurityToken
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $secret = null;
|
||||
|
||||
/**
|
||||
* @param Comment $comment Comment to generate this token for
|
||||
*/
|
||||
public function __construct($comment)
|
||||
{
|
||||
if (!$comment->SecretToken) {
|
||||
$comment->SecretToken = $this->generate();
|
||||
$comment->write();
|
||||
}
|
||||
$this->secret = $comment->SecretToken;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the token for the given salt and current secret
|
||||
*
|
||||
* @param string $salt
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function getToken($salt)
|
||||
{
|
||||
return hash_pbkdf2('sha256', $this->secret, $salt, 1000, 30);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the member-specific salt.
|
||||
*
|
||||
* The reason for making the salt specific to a user is that it cannot be "passed in" via a
|
||||
* querystring, requiring the same user to be present at both the link generation and the
|
||||
* controller action.
|
||||
*
|
||||
* @param string $salt Single use salt
|
||||
* @param Member $member Member object
|
||||
*
|
||||
* @return string Generated salt specific to this 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);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $url Comment action URL
|
||||
* @param Member $member Member to restrict access to this action to
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function addToUrl($url, $member)
|
||||
{
|
||||
$salt = $this->generate(15); // New random salt; Will be passed into url
|
||||
// Generate salt specific to this member
|
||||
$memberSalt = $this->memberSalt($salt, $member);
|
||||
$token = $this->getToken($memberSalt);
|
||||
return Controller::join_links(
|
||||
$url,
|
||||
sprintf(
|
||||
'?t=%s&s=%s',
|
||||
urlencode($token),
|
||||
urlencode($salt)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param SS_HTTPRequest $request
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function checkRequest($request)
|
||||
{
|
||||
$member = Member::currentUser();
|
||||
if (!$member) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$salt = $request->getVar('s');
|
||||
$memberSalt = $this->memberSalt($salt, $member);
|
||||
$token = $this->getToken($memberSalt);
|
||||
|
||||
// Ensure tokens match
|
||||
return $token === $request->getVar('t');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Generates new random key
|
||||
*
|
||||
* @param integer $length
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function generate($length = null)
|
||||
{
|
||||
$generator = new RandomGenerator();
|
||||
$result = $generator->randomToken('sha256');
|
||||
if ($length !== null) {
|
||||
return substr($result, 0, $length);
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
}
|
@ -1,98 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Handles polymorphic relation for commentlist
|
||||
*
|
||||
* Uses elements of PolymorphicHasManyList in 3.2
|
||||
*
|
||||
* @author dmooyman
|
||||
*/
|
||||
class CommentList extends HasManyList
|
||||
{
|
||||
|
||||
/**
|
||||
* Retrieve the name of the class this relation is filtered by
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getForeignClass()
|
||||
{
|
||||
return $this->dataQuery->getQueryParam('Foreign.Class');
|
||||
}
|
||||
|
||||
public function __construct($parentClassName)
|
||||
{
|
||||
parent::__construct('Comment', 'ParentID');
|
||||
|
||||
|
||||
// Ensure underlying DataQuery globally references the class filter
|
||||
$this->dataQuery->setQueryParam('Foreign.Class', $parentClassName);
|
||||
|
||||
// For queries with multiple foreign IDs (such as that generated by
|
||||
// DataList::relation) the filter must be generalised to filter by subclasses
|
||||
$classNames = Convert::raw2sql(ClassInfo::subclassesFor($parentClassName));
|
||||
$this->dataQuery->where(sprintf(
|
||||
"\"BaseClass\" IN ('%s')", implode("', '", $classNames)
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the item to this relation.
|
||||
*
|
||||
* @param Comment $item The comment to be added
|
||||
*/
|
||||
public function add($item)
|
||||
{
|
||||
// Check item given
|
||||
if (is_numeric($item)) {
|
||||
$item = Comment::get()->byID($item);
|
||||
}
|
||||
if (!($item instanceof Comment)) {
|
||||
throw new InvalidArgumentException("CommentList::add() expecting a Comment object, or ID value");
|
||||
}
|
||||
|
||||
// Validate foreignID
|
||||
$foreignID = $this->getForeignID();
|
||||
if (!$foreignID || is_array($foreignID)) {
|
||||
throw new InvalidArgumentException("CommentList::add() can't be called until a single foreign ID is set");
|
||||
}
|
||||
|
||||
$item->ParentID = $foreignID;
|
||||
$item->BaseClass = $this->getForeignClass();
|
||||
$item->write();
|
||||
}
|
||||
/**
|
||||
* Remove a Comment from this relation by clearing the foreign key. Does not actually delete the comment.
|
||||
*
|
||||
* @param Comment $item The Comment to be removed
|
||||
*/
|
||||
public function remove($item)
|
||||
{
|
||||
// Check item given
|
||||
if (is_numeric($item)) {
|
||||
$item = Comment::get()->byID($item);
|
||||
}
|
||||
if (!($item instanceof Comment)) {
|
||||
throw new InvalidArgumentException("CommentList::remove() expecting a Comment object, or ID",
|
||||
E_USER_ERROR);
|
||||
}
|
||||
|
||||
// Don't remove item with unrelated class key
|
||||
$foreignClass = $this->getForeignClass();
|
||||
$classNames = ClassInfo::subclassesFor($foreignClass);
|
||||
if (!in_array($item->BaseClass, $classNames)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Don't remove item which doesn't belong to this list
|
||||
$foreignID = $this->getForeignID();
|
||||
if (empty($foreignID)
|
||||
|| (is_array($foreignID) && in_array($item->ParentID, $foreignID))
|
||||
|| $foreignID == $item->ParentID
|
||||
) {
|
||||
$item->ParentID = null;
|
||||
$item->BaseClass = null;
|
||||
$item->write();
|
||||
}
|
||||
}
|
||||
}
|
47
src/Tasks/MigrateCommentParentsTask.php
Normal file
47
src/Tasks/MigrateCommentParentsTask.php
Normal file
@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
namespace SilverStripe\Comments\Tasks;
|
||||
|
||||
use SilverStripe\Core\Config\Config;
|
||||
use SilverStripe\Dev\BuildTask;
|
||||
use SilverStripe\ORM\DB;
|
||||
|
||||
/**
|
||||
* Migrates all 3.x comment's BaseClass fields to the new ParentClass fields
|
||||
*
|
||||
* @package comments
|
||||
*/
|
||||
class MigrateCommentParentsTask extends BuildTask
|
||||
{
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
private static $segment = 'MigrateCommentParentsTask';
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
protected $title = 'Migrate Comment Parent classes from 3.x';
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
protected $description = 'Migrates all 3.x Comment BaseClass fields to the new ParentClass fields in 4.0';
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function run($request)
|
||||
{
|
||||
// Set the class names to fully qualified class names first
|
||||
$remapping = Config::inst()->get('SilverStripe\\ORM\\DatabaseAdmin', 'classname_value_remapping');
|
||||
$updateQuery = "UPDATE \"Comment\" SET \"BaseClass\" = ? WHERE \"BaseClass\" = ?";
|
||||
foreach ($remapping as $old => $new) {
|
||||
DB::prepared_query($updateQuery, [$new, $old]);
|
||||
}
|
||||
|
||||
// Move these values to ParentClass (the 4.x column name)
|
||||
DB::query('UPDATE "Comment" SET "ParentClass" = "BaseClass"');
|
||||
DB::alteration_message('Finished updating any applicable Comment class columns', 'notice');
|
||||
}
|
||||
}
|
@ -1,23 +0,0 @@
|
||||
<% if $RepliesEnabled %>
|
||||
<div class="comment-replies-container">
|
||||
|
||||
<div class="comment-reply-form-holder">
|
||||
$ReplyForm
|
||||
</div>
|
||||
|
||||
<div class="comment-replies-holder">
|
||||
<% if $Replies %>
|
||||
<ul class="comments-list level-{$Depth}">
|
||||
<% loop $Replies %>
|
||||
<li class="comment $EvenOdd<% if FirstLast %> $FirstLast <% end_if %> $SpamClass">
|
||||
<% include CommentsInterface_singlecomment %>
|
||||
</li>
|
||||
<% end_loop %>
|
||||
</ul>
|
||||
<% with $Replies %>
|
||||
<% include ReplyPagination %>
|
||||
<% end_with %>
|
||||
<% end_if %>
|
||||
</div>
|
||||
</div>
|
||||
<% end_if %>
|
@ -11,7 +11,7 @@
|
||||
<% end_if %>
|
||||
$AddCommentForm
|
||||
<% else %>
|
||||
<p><% _t('CommentsInterface_ss.COMMENTLOGINERROR', 'You cannot post comments until you have logged in') %><% if $PostingRequiredPermission %>,<% _t('CommentsInterface_ss.COMMENTPERMISSIONERROR', 'and that you have an appropriate permission level') %><% end_if %>.
|
||||
<p><% _t('CommentsInterface_ss.COMMENTLOGINERROR', 'You cannot post comments until you have logged in') %><% if $PostingRequiredPermission %>, <% _t('CommentsInterface_ss.COMMENTPERMISSIONERROR', 'and have an appropriate permission level') %><% end_if %>.
|
||||
<a href="Security/login?BackURL={$Parent.Link}" title="<% _t('CommentsInterface_ss.LOGINTOPOSTCOMMENT', 'Login to post a comment') %>"><% _t('CommentsInterface_ss.COMMENTPOSTLOGIN', 'Login Here') %></a>.
|
||||
</p>
|
||||
<% end_if %>
|
||||
|
25
templates/Includes/CommentReplies.ss
Normal file
25
templates/Includes/CommentReplies.ss
Normal file
@ -0,0 +1,25 @@
|
||||
<% if $RepliesEnabled %>
|
||||
<div class="comment-replies-container">
|
||||
|
||||
<% if $canPostComment %>
|
||||
<div class="comment-reply-form-holder">
|
||||
$ReplyForm
|
||||
</div>
|
||||
<% end_if %>
|
||||
|
||||
<div class="comment-replies-holder">
|
||||
<% if $Replies %>
|
||||
<ul class="comments-list level-{$Depth}">
|
||||
<% loop $Replies %>
|
||||
<li class="comment $EvenOdd<% if FirstLast %> $FirstLast <% end_if %> $SpamClass">
|
||||
<% include CommentsInterface_singlecomment %>
|
||||
</li>
|
||||
<% end_loop %>
|
||||
</ul>
|
||||
<% with $Replies %>
|
||||
<% include ReplyPagination %>
|
||||
<% end_with %>
|
||||
<% end_if %>
|
||||
</div>
|
||||
</div>
|
||||
<% end_if %>
|
@ -32,7 +32,7 @@
|
||||
<a href="$DeleteLink.ATT" class="delete"><% _t('CommentsInterface_singlecomment_ss.REMCOM','reject it') %></a>
|
||||
<% end_if %>
|
||||
</div>
|
||||
<% if $RepliesEnabled %>
|
||||
<% if $RepliesEnabled && $canPostComment %>
|
||||
<a class="comment-reply-link" href="#{$ReplyForm.FormName}"><% _t('CommentsInterface_singlecomment_ss.REPLYTO','Reply to') %> $AuthorName.XML</a>
|
||||
<% end_if %>
|
||||
</div>
|
@ -1,8 +1,17 @@
|
||||
<?php
|
||||
|
||||
namespace SilverStripe\Comments\Tests;
|
||||
|
||||
use SilverStripe\Comments\Admin\CommentAdmin;
|
||||
use SilverStripe\Dev\SapphireTest;
|
||||
use SilverStripe\i18n\i18n;
|
||||
use SilverStripe\Security\Member;
|
||||
|
||||
class CommentAdminTest extends SapphireTest
|
||||
{
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
protected $usesDatabase = true;
|
||||
|
||||
public function testProvidePermissions()
|
||||
|
@ -1,145 +0,0 @@
|
||||
<?php
|
||||
|
||||
class CommentListTest extends FunctionalTest
|
||||
{
|
||||
|
||||
public static $fixture_file = 'comments/tests/CommentsTest.yml';
|
||||
|
||||
protected $extraDataObjects = array(
|
||||
'CommentableItem',
|
||||
'CommentableItemEnabled',
|
||||
'CommentableItemDisabled'
|
||||
);
|
||||
|
||||
public function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
Config::nest();
|
||||
|
||||
// Set good default values
|
||||
Config::inst()->update('CommentsExtension', 'comments', array(
|
||||
'enabled' => true,
|
||||
'enabled_cms' => false,
|
||||
'require_login' => false,
|
||||
'require_login_cms' => false,
|
||||
'required_permission' => false,
|
||||
'require_moderation_nonmembers' => false,
|
||||
'require_moderation' => false,
|
||||
'require_moderation_cms' => false,
|
||||
'frontend_moderation' => false,
|
||||
'frontend_spam' => false,
|
||||
));
|
||||
|
||||
// Configure this dataobject
|
||||
Config::inst()->update('CommentableItem', 'comments', array(
|
||||
'enabled_cms' => true
|
||||
));
|
||||
}
|
||||
|
||||
public function tearDown()
|
||||
{
|
||||
Config::unnest();
|
||||
parent::tearDown();
|
||||
}
|
||||
|
||||
public function testGetForeignClass()
|
||||
{
|
||||
$item = $this->objFromFixture('CommentableItem', 'first');
|
||||
|
||||
// This is the class the Comments are related to
|
||||
$this->assertEquals('CommentableItem',
|
||||
$item->Comments()->getForeignClass());
|
||||
}
|
||||
|
||||
public function testAddNonComment()
|
||||
{
|
||||
$item = $this->objFromFixture('CommentableItem', 'first');
|
||||
$comments = $item->Comments();
|
||||
$this->assertEquals(4, $comments->count());
|
||||
$member = Member::get()->first();
|
||||
try {
|
||||
$comments->add($member);
|
||||
$this->fail('Should not have been able to add member to comments');
|
||||
} catch (InvalidArgumentException $e) {
|
||||
$this->assertEquals(
|
||||
'CommentList::add() expecting a Comment object, or ID value',
|
||||
$e->getMessage()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public function testAddComment()
|
||||
{
|
||||
$item = $this->objFromFixture('CommentableItem', 'first');
|
||||
$firstComment = $this->objFromFixture('Comment', 'firstComA');
|
||||
$comments = $item->Comments();//->sort('Created');
|
||||
|
||||
foreach ($comments as $comment) {
|
||||
error_log($comment->ID . ' ' . $comment->Created .' ' . $comment->Comment);
|
||||
}
|
||||
|
||||
$this->assertEquals(4, $comments->count());
|
||||
$newComment = new Comment();
|
||||
$newComment->Name = 'Fred Bloggs';
|
||||
$newComment->Comment = 'This is a test comment';
|
||||
$newComment->write();
|
||||
|
||||
$comments->add($newComment);
|
||||
// As a comment has been added, there should be 5 comments now
|
||||
$this->assertEquals(5, $item->Comments()->count());
|
||||
|
||||
$newComment2 = new Comment();
|
||||
$newComment2->Name = 'John Smith';
|
||||
$newComment2->Comment = 'This is another test comment';
|
||||
$newComment2->write();
|
||||
|
||||
// test adding the same comment by ID
|
||||
$comments->add($newComment2->ID);
|
||||
$this->assertEquals(6, $item->Comments()->count());
|
||||
|
||||
$this->setExpectedException(
|
||||
'InvalidArgumentException',
|
||||
"CommentList::add() can't be called until a single foreign ID is set"
|
||||
);
|
||||
$list = new CommentList('CommentableItem');
|
||||
$list->add($newComment);
|
||||
}
|
||||
|
||||
public function testRemoveComment()
|
||||
{
|
||||
// remove by comment
|
||||
$item = $this->objFromFixture('CommentableItem', 'first');
|
||||
$this->assertEquals(4, $item->Comments()->count());
|
||||
$comments = $item->Comments();
|
||||
$comment = $comments->first();
|
||||
$comments->remove($comment);
|
||||
|
||||
// now remove by ID
|
||||
$comments = $item->Comments();
|
||||
$comment = $comments->first();
|
||||
$comments->remove($comment->ID);
|
||||
$this->assertEquals(2, $item->Comments()->count());
|
||||
}
|
||||
|
||||
public function testRemoveNonComment()
|
||||
{
|
||||
$item = $this->objFromFixture('CommentableItem', 'first');
|
||||
$this->assertEquals(4, $item->Comments()->count());
|
||||
$comments = $item->Comments();
|
||||
|
||||
// try and remove a non comment
|
||||
$member = Member::get()->first();
|
||||
|
||||
|
||||
|
||||
try {
|
||||
$comments->remove($member);
|
||||
$this->fail('Should not have been able to remove member from comments');
|
||||
} catch (InvalidArgumentException $e) {
|
||||
$this->assertEquals(
|
||||
'CommentList::remove() expecting a Comment object, or ID',
|
||||
$e->getMessage()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,27 +1,28 @@
|
||||
<?php
|
||||
|
||||
class CommentTestHelper
|
||||
namespace SilverStripe\Comments\Tests;
|
||||
|
||||
use SilverStripe\Dev\TestOnly;
|
||||
use SilverStripe\Forms\FieldGroup;
|
||||
|
||||
class CommentTestHelper implements TestOnly
|
||||
{
|
||||
/*
|
||||
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
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
public static function assertFieldsForTab($context, $tabName, $expected, $fields)
|
||||
{
|
||||
$tab = $fields->findOrMakeTab($tabName);
|
||||
$fields = $tab->FieldList();
|
||||
CommentTestHelper::assertFieldNames($context, $expected, $fields);
|
||||
self::assertFieldNames($context, $expected, $fields);
|
||||
}
|
||||
|
||||
public static function assertFieldNames($context, $expected, $fields)
|
||||
{
|
||||
$actual = array();
|
||||
foreach ($fields as $field) {
|
||||
if (get_class($field) == 'FieldGroup') {
|
||||
array_push($actual, $field->Name());
|
||||
} else {
|
||||
array_push($actual, $field->getName());
|
||||
}
|
||||
array_push($actual, $field->getName());
|
||||
}
|
||||
$context->assertEquals($expected, $actual);
|
||||
}
|
||||
|
@ -1,16 +1,36 @@
|
||||
<?php
|
||||
|
||||
namespace SilverStripe\Comments\Tests;
|
||||
|
||||
use SilverStripe\Comments\Controllers\CommentingController;
|
||||
use SilverStripe\Comments\Model\Comment;
|
||||
use SilverStripe\Comments\Model\Comment\SecurityToken as CommentSecurityToken;
|
||||
use SilverStripe\Comments\Tests\Stubs\CommentableItem;
|
||||
use SilverStripe\Comments\Tests\CommentTestHelper;
|
||||
use SilverStripe\Control\Controller;
|
||||
use SilverStripe\Core\Config\Config;
|
||||
use SilverStripe\Core\Email\Email;
|
||||
use SilverStripe\Dev\FunctionalTest;
|
||||
use SilverStripe\ORM\DataObject;
|
||||
use SilverStripe\Security\Member;
|
||||
use SilverStripe\Security\SecurityToken;
|
||||
|
||||
/**
|
||||
* @package comments
|
||||
* @subpackage tests
|
||||
*/
|
||||
class CommentingControllerTest extends FunctionalTest
|
||||
{
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public static $fixture_file = 'CommentsTest.yml';
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
protected $extraDataObjects = array(
|
||||
'CommentableItem'
|
||||
CommentableItem::class
|
||||
);
|
||||
|
||||
protected $securityEnabled;
|
||||
@ -18,9 +38,9 @@ class CommentingControllerTest extends FunctionalTest
|
||||
public function tearDown()
|
||||
{
|
||||
if ($this->securityEnabled) {
|
||||
SecurityToken::enable();
|
||||
SecurityToken::inst()->enable();
|
||||
} else {
|
||||
SecurityToken::disable();
|
||||
SecurityToken::inst()->disable();
|
||||
}
|
||||
parent::tearDown();
|
||||
}
|
||||
@ -28,30 +48,32 @@ class CommentingControllerTest extends FunctionalTest
|
||||
public function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
$this->securityEnabled = SecurityToken::is_enabled();
|
||||
$this->securityEnabled = SecurityToken::inst()->is_enabled();
|
||||
|
||||
// We will assert against explicit responses, unless handed otherwise in a test for redirects
|
||||
$this->autoFollowRedirection = false;
|
||||
}
|
||||
|
||||
public function testApprove()
|
||||
public function testApproveUnmoderatedComment()
|
||||
{
|
||||
SecurityToken::disable();
|
||||
SecurityToken::inst()->disable();
|
||||
|
||||
// mark a comment as spam then approve it
|
||||
$this->logInWithPermission('CMS_ACCESS_CommentAdmin');
|
||||
$comment = $this->objFromFixture('Comment', 'firstComA');
|
||||
$comment->markSpam();
|
||||
$st = new Comment_SecurityToken($comment);
|
||||
$url = 'CommentingController/approve/' . $comment->ID;
|
||||
$comment = $this->objFromFixture(Comment::class, 'testModeratedComment1');
|
||||
$st = new CommentSecurityToken($comment);
|
||||
$url = 'comments/approve/' . $comment->ID;
|
||||
$url = $st->addToUrl($url, Member::currentUser());
|
||||
$response = $this->get($url);
|
||||
$this->assertEquals(200, $response->getStatusCode());
|
||||
$comment = DataObject::get_by_id('Comment', $comment->ID);
|
||||
$response = $this->get($url, null, ['Referer' => '/']);
|
||||
$this->assertEquals(302, $response->getStatusCode());
|
||||
$comment = DataObject::get_by_id(Comment::class, $comment->ID);
|
||||
|
||||
// Need to use 0,1 here instead of false, true for SQLite
|
||||
$this->assertEquals(0, $comment->IsSpam);
|
||||
$this->assertEquals(1, $comment->Moderated);
|
||||
|
||||
// try and approve a non existent comment
|
||||
$response = $this->get('CommentingController/approve/100000');
|
||||
$response = $this->get('comments/approve/100000');
|
||||
$this->assertEquals(404, $response->getStatusCode());
|
||||
}
|
||||
|
||||
@ -66,25 +88,25 @@ class CommentingControllerTest extends FunctionalTest
|
||||
|
||||
public function testHam()
|
||||
{
|
||||
SecurityToken::disable();
|
||||
SecurityToken::inst()->disable();
|
||||
|
||||
// mark a comment as spam then ham it
|
||||
$this->logInWithPermission('CMS_ACCESS_CommentAdmin');
|
||||
$comment = $this->objFromFixture('Comment', 'firstComA');
|
||||
$comment = $this->objFromFixture(Comment::class, 'firstComA');
|
||||
$comment->markSpam();
|
||||
$st = new Comment_SecurityToken($comment);
|
||||
$url = 'CommentingController/ham/' . $comment->ID;
|
||||
$st = new CommentSecurityToken($comment);
|
||||
$url = 'comments/ham/' . $comment->ID;
|
||||
$url = $st->addToUrl($url, Member::currentUser());
|
||||
$response = $this->get($url);
|
||||
$this->assertEquals(200, $response->getStatusCode());
|
||||
$comment = DataObject::get_by_id('Comment', $comment->ID);
|
||||
$this->assertEquals(302, $response->getStatusCode());
|
||||
$comment = DataObject::get_by_id(Comment::class, $comment->ID);
|
||||
|
||||
// Need to use 0,1 here instead of false, true for SQLite
|
||||
$this->assertEquals(0, $comment->IsSpam);
|
||||
$this->assertEquals(1, $comment->Moderated);
|
||||
|
||||
// try and ham a non existent comment
|
||||
$response = $this->get('CommentingController/ham/100000');
|
||||
$response = $this->get('comments/ham/100000');
|
||||
$this->assertEquals(404, $response->getStatusCode());
|
||||
}
|
||||
|
||||
@ -92,55 +114,54 @@ class CommentingControllerTest extends FunctionalTest
|
||||
{
|
||||
// mark a comment as approved then spam it
|
||||
$this->logInWithPermission('CMS_ACCESS_CommentAdmin');
|
||||
$comment = $this->objFromFixture('Comment', 'firstComA');
|
||||
$comment = $this->objFromFixture(Comment::class, 'firstComA');
|
||||
$comment->markApproved();
|
||||
$st = new Comment_SecurityToken($comment);
|
||||
$url = 'CommentingController/spam/' . $comment->ID;
|
||||
$st = new CommentSecurityToken($comment);
|
||||
$url = 'comments/spam/' . $comment->ID;
|
||||
$url = $st->addToUrl($url, Member::currentUser());
|
||||
$response = $this->get($url);
|
||||
$this->assertEquals(200, $response->getStatusCode());
|
||||
$comment = DataObject::get_by_id('Comment', $comment->ID);
|
||||
$this->assertEquals(302, $response->getStatusCode());
|
||||
$comment = DataObject::get_by_id(Comment::class, $comment->ID);
|
||||
|
||||
// Need to use 0,1 here instead of false, true for SQLite
|
||||
$this->assertEquals(1, $comment->IsSpam);
|
||||
$this->assertEquals(1, $comment->Moderated);
|
||||
|
||||
// try and spam a non existent comment
|
||||
$response = $this->get('CommentingController/spam/100000');
|
||||
$response = $this->get('comments/spam/100000');
|
||||
$this->assertEquals(404, $response->getStatusCode());
|
||||
}
|
||||
|
||||
public function testRSS()
|
||||
{
|
||||
// Delete the newly added children of firstComA so as not to have to recalculate values below
|
||||
$this->objFromFixture('Comment', 'firstComAChild1')->delete();
|
||||
$this->objFromFixture('Comment', 'firstComAChild2')->delete();
|
||||
$this->objFromFixture('Comment', 'firstComAChild3')->delete();
|
||||
|
||||
$item = $this->objFromFixture('CommentableItem', 'first');
|
||||
$this->objFromFixture(Comment::class, 'firstComAChild1')->delete();
|
||||
$this->objFromFixture(Comment::class, 'firstComAChild2')->delete();
|
||||
$this->objFromFixture(Comment::class, 'firstComAChild3')->delete();
|
||||
|
||||
$item = $this->objFromFixture(CommentableItem::class, 'first');
|
||||
|
||||
// comments sitewide
|
||||
$response = $this->get('CommentingController/rss');
|
||||
$response = $this->get('comments/rss');
|
||||
$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('comments/rss?start=10');
|
||||
$this->assertEquals(4, substr_count($response->getBody(), "<item>"), "3 approved, non spam comments on page 2");
|
||||
|
||||
// all comments on a type
|
||||
$response = $this->get('CommentingController/rss/CommentableItem');
|
||||
$response = $this->get('comments/rss/SilverStripe-Comments-Tests-Stubs-CommentableItem');
|
||||
$this->assertEquals(10, substr_count($response->getBody(), "<item>"));
|
||||
|
||||
$response = $this->get('CommentingController/rss/CommentableItem?start=10');
|
||||
$response = $this->get('comments/rss/SilverStripe-Comments-Tests-Stubs-CommentableItem?start=10');
|
||||
$this->assertEquals(4, substr_count($response->getBody(), "<item>"), "3 approved, non spam comments on page 2");
|
||||
|
||||
// specific page
|
||||
$response = $this->get('CommentingController/rss/CommentableItem/'.$item->ID);
|
||||
$response = $this->get('comments/rss/SilverStripe-Comments-Tests-Stubs-CommentableItem/'.$item->ID);
|
||||
$this->assertEquals(1, substr_count($response->getBody(), "<item>"));
|
||||
$this->assertContains('<dc:creator>FA</dc:creator>', $response->getBody());
|
||||
|
||||
// test accessing comments on a type that doesn't exist
|
||||
$response = $this->get('CommentingController/rss/Fake');
|
||||
$response = $this->get('comments/rss/Fake');
|
||||
$this->assertEquals(404, $response->getStatusCode());
|
||||
}
|
||||
|
||||
@ -151,8 +172,8 @@ class CommentingControllerTest extends FunctionalTest
|
||||
$comment = $this->objFromFixture('Comment', 'firstComA');
|
||||
$item = $this->objFromFixture('CommentableItem', 'first');
|
||||
|
||||
$st = new Comment_SecurityToken($comment);
|
||||
$url = 'CommentingController/reply/' . $item->ID.'?ParentCommentID=' . $comment->ID;
|
||||
$st = new CommentSecurityToken($comment);
|
||||
$url = 'comments/reply/' . $item->ID.'?ParentCommentID=' . $comment->ID;
|
||||
error_log($url);
|
||||
$response = $this->get($url);
|
||||
error_log(print_r($response,1));
|
||||
@ -167,7 +188,7 @@ class CommentingControllerTest extends FunctionalTest
|
||||
'use_preview' => false
|
||||
));
|
||||
$this->logInAs('visitor');
|
||||
SecurityToken::disable();
|
||||
SecurityToken::inst()->disable();
|
||||
$parent = $this->objFromFixture('CommentableItem', 'first');
|
||||
$parent->CommentsRequireLogin = true;
|
||||
$parent->PostingRequiredPermission = true;
|
||||
@ -185,17 +206,17 @@ class CommentingControllerTest extends FunctionalTest
|
||||
public function testCommentsFormUsePreview()
|
||||
{
|
||||
// test with preview on
|
||||
Config::inst()->update('CommentableItem', 'comments', array(
|
||||
Config::inst()->update(CommentableItem::class, 'comments', array(
|
||||
'use_preview' => true
|
||||
));
|
||||
|
||||
$this->objFromFixture('Comment', 'firstComAChild1')->delete();
|
||||
$this->objFromFixture('Comment', 'firstComAChild2')->delete();
|
||||
$this->objFromFixture('Comment', 'firstComAChild3')->delete();
|
||||
$this->objFromFixture(Comment::class, 'firstComAChild1')->delete();
|
||||
$this->objFromFixture(Comment::class, 'firstComAChild2')->delete();
|
||||
$this->objFromFixture(Comment::class, 'firstComAChild3')->delete();
|
||||
|
||||
SecurityToken::disable();
|
||||
SecurityToken::inst()->disable();
|
||||
$this->autoFollowRedirection = false;
|
||||
$parent = $this->objFromFixture('CommentableItem', 'first');
|
||||
$parent = $this->objFromFixture(CommentableItem::class, 'first');
|
||||
$commController = new CommentingController();
|
||||
$commController->setOwnerRecord($parent);
|
||||
|
||||
@ -205,7 +226,7 @@ class CommentingControllerTest extends FunctionalTest
|
||||
CommentTestHelper::assertFieldNames($this, $expected, $commentsFields);
|
||||
|
||||
// Turn off preview. Assert lack of preview field
|
||||
Config::inst()->update('CommentableItem', 'comments', array(
|
||||
Config::inst()->update(CommentableItem::class, 'comments', array(
|
||||
'use_preview' => false
|
||||
));
|
||||
$form = $commController->CommentsForm();
|
||||
@ -216,64 +237,89 @@ class CommentingControllerTest extends FunctionalTest
|
||||
|
||||
public function testCommentsForm()
|
||||
{
|
||||
// Delete the newly added children of firstComA so as not to change this test
|
||||
$this->objFromFixture('Comment', 'firstComAChild1')->delete();
|
||||
$this->objFromFixture('Comment', 'firstComAChild2')->delete();
|
||||
$this->objFromFixture('Comment', 'firstComAChild3')->delete();
|
||||
$this->autoFollowRedirection = true;
|
||||
|
||||
SecurityToken::disable();
|
||||
// Delete the newly added children of firstComA so as not to change this test
|
||||
$this->objFromFixture(Comment::class, 'firstComAChild1')->delete();
|
||||
$this->objFromFixture(Comment::class, 'firstComAChild2')->delete();
|
||||
$this->objFromFixture(Comment::class, 'firstComAChild3')->delete();
|
||||
|
||||
SecurityToken::inst()->disable();
|
||||
$this->autoFollowRedirection = false;
|
||||
$parent = $this->objFromFixture('CommentableItem', 'first');
|
||||
$parent = $this->objFromFixture(CommentableItem::class, 'first');
|
||||
|
||||
// Test posting to base comment
|
||||
$response = $this->post('CommentingController/CommentsForm',
|
||||
$response = $this->post(
|
||||
'comments/CommentsForm',
|
||||
array(
|
||||
'Name' => 'Poster',
|
||||
'Email' => 'guy@test.com',
|
||||
'Comment' => 'My Comment',
|
||||
'ParentID' => $parent->ID,
|
||||
'BaseClass' => 'CommentableItem',
|
||||
'ParentClassName' => CommentableItem::class,
|
||||
'action_doPostComment' => 'Post'
|
||||
)
|
||||
);
|
||||
$this->assertEquals(302, $response->getStatusCode());
|
||||
$this->assertStringStartsWith('CommentableItem_Controller#comment-', $response->getHeader('Location'));
|
||||
// $this->assertStringStartsWith('CommentableItemController#comment-', $response->getHeader('Location'));
|
||||
$this->assertDOSEquals(
|
||||
array(array(
|
||||
'Name' => 'Poster',
|
||||
'Email' => 'guy@test.com',
|
||||
'Comment' => 'My Comment',
|
||||
'ParentID' => $parent->ID,
|
||||
'BaseClass' => 'CommentableItem',
|
||||
)),
|
||||
array(
|
||||
array(
|
||||
'Name' => 'Poster',
|
||||
'Email' => 'guy@test.com',
|
||||
'Comment' => 'My Comment',
|
||||
'ParentID' => $parent->ID,
|
||||
'ParentClass' => CommentableItem::class,
|
||||
)
|
||||
),
|
||||
Comment::get()->filter('Email', 'guy@test.com')
|
||||
);
|
||||
|
||||
// Test posting to parent comment
|
||||
$parentComment = $this->objFromFixture('Comment', 'firstComA');
|
||||
$parentComment = $this->objFromFixture(Comment::class, 'firstComA');
|
||||
$this->assertEquals(0, $parentComment->ChildComments()->count());
|
||||
|
||||
$response = $this->post(
|
||||
'CommentingController/reply/'.$parentComment->ID,
|
||||
'comments/reply/' . $parentComment->ID,
|
||||
array(
|
||||
'Name' => 'Test Author',
|
||||
'Email' => 'test@test.com',
|
||||
'Comment' => 'Making a reply to firstComA',
|
||||
'ParentID' => $parent->ID,
|
||||
'BaseClass' => 'CommentableItem',
|
||||
'ParentClassName' => CommentableItem::class,
|
||||
'ParentCommentID' => $parentComment->ID,
|
||||
'action_doPostComment' => 'Post'
|
||||
)
|
||||
);
|
||||
$this->assertEquals(302, $response->getStatusCode());
|
||||
$this->assertStringStartsWith('CommentableItem_Controller#comment-', $response->getHeader('Location'));
|
||||
$this->assertDOSEquals(array(array(
|
||||
'Name' => 'Test Author',
|
||||
'Email' => 'test@test.com',
|
||||
'Comment' => 'Making a reply to firstComA',
|
||||
'ParentID' => $parent->ID,
|
||||
'BaseClass' => 'CommentableItem',
|
||||
'ParentCommentID' => $parentComment->ID
|
||||
)), $parentComment->ChildComments());
|
||||
// $this->assertStringStartsWith('CommentableItemController#comment-', $response->getHeader('Location'));
|
||||
$this->assertDOSEquals(
|
||||
array(
|
||||
array(
|
||||
'Name' => 'Test Author',
|
||||
'Email' => 'test@test.com',
|
||||
'Comment' => 'Making a reply to firstComA',
|
||||
'ParentID' => $parent->ID,
|
||||
'ParentClass' => CommentableItem::class,
|
||||
'ParentCommentID' => $parentComment->ID
|
||||
)
|
||||
),
|
||||
$parentComment->ChildComments()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* SS4 introduces namespaces. They don't work in URLs, so we encode and decode them here.
|
||||
*/
|
||||
public function testEncodeClassName()
|
||||
{
|
||||
$controller = new CommentingController;
|
||||
$this->assertSame('SilverStripe-Comments-Model-Comment', $controller->encodeClassName(Comment::class));
|
||||
}
|
||||
|
||||
public function testDecodeClassName()
|
||||
{
|
||||
$controller = new CommentingController;
|
||||
$this->assertSame(Comment::class, $controller->decodeClassName('SilverStripe-Comments-Model-Comment'));
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,17 @@
|
||||
<?php
|
||||
|
||||
namespace SilverStripe\Comments\Tests;
|
||||
|
||||
use PHPUnit_Framework_Error_Deprecated;
|
||||
use SilverStripe\Comments\Commenting;
|
||||
use SilverStripe\Comments\Extensions\CommentsExtension;
|
||||
use SilverStripe\Comments\Tests\Stubs\CommentableItem;
|
||||
use SilverStripe\Core\Config\Config;
|
||||
use SilverStripe\Dev\SapphireTest;
|
||||
use SilverStripe\Security\Member;
|
||||
|
||||
class CommentingTest extends SapphireTest
|
||||
{
|
||||
|
||||
public function setUpOnce()
|
||||
{
|
||||
parent::setUpOnce();
|
||||
@ -13,7 +22,7 @@ class CommentingTest extends SapphireTest
|
||||
$methods = array('add', 'remove', 'has_commenting');
|
||||
foreach ($methods as $methodName) {
|
||||
try {
|
||||
Commenting::$methodName('Member');
|
||||
Commenting::$methodName(Member::class);
|
||||
} catch (PHPUnit_Framework_Error_Deprecated $e) {
|
||||
$expected = 'Using Commenting:' . $methodName .' is deprecated.'
|
||||
. ' Please use the config API instead';
|
||||
@ -22,18 +31,17 @@ class CommentingTest extends SapphireTest
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function test_set_config_value()
|
||||
public function testSetConfigValue()
|
||||
{
|
||||
// public static function set_config_value($class, $key, $value = false) {
|
||||
Commenting::set_config_value(
|
||||
'CommentableItem',
|
||||
CommentableItem::class,
|
||||
'comments_holder_id',
|
||||
'commentable_item'
|
||||
);
|
||||
|
||||
$config = Config::inst()->get(
|
||||
'CommentableItem',
|
||||
CommentableItem::class,
|
||||
'comments'
|
||||
);
|
||||
$actual = $config['comments_holder_id'];
|
||||
@ -49,7 +57,7 @@ class CommentingTest extends SapphireTest
|
||||
);
|
||||
|
||||
$config = Config::inst()->get(
|
||||
'CommentsExtension',
|
||||
CommentsExtension::class,
|
||||
'comments'
|
||||
);
|
||||
$actual = $config['comments_holder_id'];
|
||||
@ -59,19 +67,23 @@ class CommentingTest extends SapphireTest
|
||||
);
|
||||
}
|
||||
|
||||
public function test_get_config_value()
|
||||
public function testGetConfigValue()
|
||||
{
|
||||
Config::inst()->update('CommentableItem', 'comments',
|
||||
Config::inst()->update(
|
||||
CommentableItem::class,
|
||||
'comments',
|
||||
array(
|
||||
'comments_holder_id' => 'commentable_item'
|
||||
)
|
||||
);
|
||||
$this->assertEquals(
|
||||
'commentable_item',
|
||||
Commenting::get_config_value('CommentableItem', 'comments_holder_id')
|
||||
Commenting::get_config_value(CommentableItem::class, 'comments_holder_id')
|
||||
);
|
||||
|
||||
Config::inst()->update('CommentsExtension', 'comments',
|
||||
Config::inst()->update(
|
||||
CommentsExtension::class,
|
||||
'comments',
|
||||
array(
|
||||
'comments_holder_id' => 'comments_extension'
|
||||
)
|
||||
@ -86,12 +98,14 @@ class CommentingTest extends SapphireTest
|
||||
'InvalidArgumentException',
|
||||
'Member does not have commenting enabled'
|
||||
);
|
||||
Commenting::get_config_value('Member', 'comments_holder_id');
|
||||
Commenting::get_config_value(Member::class, 'comments_holder_id');
|
||||
}
|
||||
|
||||
public function test_config_value_equals()
|
||||
public function testConfigValueEquals()
|
||||
{
|
||||
Config::inst()->update('CommentableItem', 'comments',
|
||||
Config::inst()->update(
|
||||
CommentableItem::class,
|
||||
'comments',
|
||||
array(
|
||||
'comments_holder_id' => 'some_value'
|
||||
)
|
||||
@ -99,7 +113,7 @@ class CommentingTest extends SapphireTest
|
||||
|
||||
$this->assertTrue(
|
||||
Commenting::config_value_equals(
|
||||
'CommentableItem',
|
||||
CommentableItem::class,
|
||||
'comments_holder_id',
|
||||
'some_value'
|
||||
)
|
||||
@ -107,33 +121,33 @@ class CommentingTest extends SapphireTest
|
||||
|
||||
$this->assertNull(
|
||||
Commenting::config_value_equals(
|
||||
'CommentableItem',
|
||||
CommentableItem::class,
|
||||
'comments_holder_id',
|
||||
'not_some_value'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
public function test_add()
|
||||
public function testAdd()
|
||||
{
|
||||
Commenting::add('Member', array('comments_holder_id' => 'test_add_value'));
|
||||
Commenting::add(Member::class, array('comments_holder_id' => 'test_add_value'));
|
||||
|
||||
$config = Config::inst()->get(
|
||||
'Member',
|
||||
'comments'
|
||||
);
|
||||
Member::class,
|
||||
'comments'
|
||||
);
|
||||
$actual = $config['comments_holder_id'];
|
||||
$this->assertEquals(
|
||||
'test_add_value',
|
||||
$actual
|
||||
);
|
||||
|
||||
Commenting::add('Member');
|
||||
Commenting::add(Member::class);
|
||||
|
||||
$config = Config::inst()->get(
|
||||
'Member',
|
||||
'comments'
|
||||
);
|
||||
Member::class,
|
||||
'comments'
|
||||
);
|
||||
$actual = $config['comments_holder_id'];
|
||||
// no settings updated
|
||||
$this->assertEquals(
|
||||
@ -142,39 +156,45 @@ class CommentingTest extends SapphireTest
|
||||
);
|
||||
|
||||
$this->setExpectedException('InvalidArgumentException', "\$settings needs to be an array or null");
|
||||
Commenting::add('Member', 'illegal format, not an array');
|
||||
Commenting::add(Member::class, 'illegal format, not an array');
|
||||
}
|
||||
|
||||
public function test_can_member_post()
|
||||
public function testCanMemberPost()
|
||||
{
|
||||
// logout
|
||||
if ($member = Member::currentUser()) {
|
||||
$member->logOut();
|
||||
}
|
||||
|
||||
Config::inst()->update('CommentableItem', 'comments',
|
||||
Config::inst()->update(
|
||||
CommentableItem::class,
|
||||
'comments',
|
||||
array(
|
||||
'require_login' => false
|
||||
'require_login' => false
|
||||
)
|
||||
);
|
||||
$this->assertTrue(Commenting::can_member_post('CommentableItem'));
|
||||
$this->assertTrue(Commenting::can_member_post(CommentableItem::class));
|
||||
|
||||
Config::inst()->update('CommentableItem', 'comments',
|
||||
Config::inst()->update(
|
||||
CommentableItem::class,
|
||||
'comments',
|
||||
array(
|
||||
'require_login' => true
|
||||
'require_login' => true
|
||||
)
|
||||
);
|
||||
$this->assertFalse(Commenting::can_member_post('CommentableItem'));
|
||||
$this->assertFalse(Commenting::can_member_post(CommentableItem::class));
|
||||
|
||||
$this->logInWithPermission('CMS_ACCESS_CommentAdmin');
|
||||
$this->assertTrue(Commenting::can_member_post('CommentableItem'));
|
||||
$this->assertTrue(Commenting::can_member_post(CommentableItem::class));
|
||||
|
||||
Config::inst()->update('CommentableItem', 'comments',
|
||||
Config::inst()->update(
|
||||
CommentableItem::class,
|
||||
'comments',
|
||||
array(
|
||||
'require_login' => false
|
||||
'require_login' => false
|
||||
)
|
||||
);
|
||||
|
||||
$this->assertTrue(Commenting::can_member_post('CommentableItem'));
|
||||
$this->assertTrue(Commenting::can_member_post(CommentableItem::class));
|
||||
}
|
||||
}
|
||||
|
@ -1,14 +1,33 @@
|
||||
<?php
|
||||
|
||||
namespace SilverStripe\Comments\Tests;
|
||||
|
||||
use PHPUnit_Framework_Error_Deprecated;
|
||||
use SilverStripe\Comments\Extensions\CommentsExtension;
|
||||
use SilverStripe\Comments\Model\Comment;
|
||||
use SilverStripe\Comments\Tests\CommentTestHelper;
|
||||
use SilverStripe\Comments\Tests\Stubs\CommentableItem;
|
||||
use SilverStripe\Comments\Tests\Stubs\CommentableItemDisabled;
|
||||
use SilverStripe\Comments\Tests\Stubs\CommentableItemEnabled;
|
||||
use SilverStripe\Core\Config\Config;
|
||||
use SilverStripe\Dev\SapphireTest;
|
||||
use SilverStripe\Security\Member;
|
||||
use SilverStripe\View\Requirements;
|
||||
|
||||
class CommentsExtensionTest extends SapphireTest
|
||||
{
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public static $fixture_file = 'comments/tests/CommentsTest.yml';
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
protected $extraDataObjects = array(
|
||||
'CommentableItem',
|
||||
'CommentableItemEnabled',
|
||||
'CommentableItemDisabled'
|
||||
CommentableItem::class,
|
||||
CommentableItemEnabled::class,
|
||||
CommentableItemDisabled::class
|
||||
);
|
||||
|
||||
public function setUp()
|
||||
@ -17,7 +36,7 @@ class CommentsExtensionTest extends SapphireTest
|
||||
Config::nest();
|
||||
|
||||
// Set good default values
|
||||
Config::inst()->update('CommentsExtension', 'comments', array(
|
||||
Config::inst()->update(CommentsExtension::class, 'comments', array(
|
||||
'enabled' => true,
|
||||
'enabled_cms' => false,
|
||||
'require_login' => false,
|
||||
@ -31,11 +50,11 @@ class CommentsExtensionTest extends SapphireTest
|
||||
));
|
||||
|
||||
$this->requiredExtensions = array(
|
||||
'CommentableItem' => 'CommentsExtension'
|
||||
'CommentableItem' => CommentsExtension::class
|
||||
);
|
||||
|
||||
// Configure this dataobject
|
||||
Config::inst()->update('CommentableItem', 'comments', array(
|
||||
Config::inst()->update(CommentableItem::class, 'comments', array(
|
||||
'enabled_cms' => true
|
||||
));
|
||||
}
|
||||
@ -60,7 +79,7 @@ class CommentsExtensionTest extends SapphireTest
|
||||
{
|
||||
|
||||
// the 3 options take precedence in this order, executed if true
|
||||
Config::inst()->update('CommentableItem', 'comments', array(
|
||||
Config::inst()->update(CommentableItem::class, 'comments', array(
|
||||
'require_moderation_cms' => true,
|
||||
'require_moderation' => true,
|
||||
'require_moderation_nonmembers' => true
|
||||
@ -68,7 +87,7 @@ class CommentsExtensionTest extends SapphireTest
|
||||
|
||||
// With require moderation CMS set to true, the value of the field
|
||||
// 'ModerationRequired' is returned
|
||||
$item = $this->objFromFixture('CommentableItem', 'first');
|
||||
$item = $this->objFromFixture(CommentableItem::class, 'first');
|
||||
$item->ModerationRequired = 'None';
|
||||
$this->assertEquals('None', $item->getModerationRequired());
|
||||
$item->ModerationRequired = 'Required';
|
||||
@ -76,21 +95,21 @@ class CommentsExtensionTest extends SapphireTest
|
||||
$item->ModerationRequired = 'NonMembersOnly';
|
||||
$this->assertEquals('NonMembersOnly', $item->getModerationRequired());
|
||||
|
||||
Config::inst()->update('CommentableItem', 'comments', array(
|
||||
Config::inst()->update(CommentableItem::class, 'comments', array(
|
||||
'require_moderation_cms' => false,
|
||||
'require_moderation' => true,
|
||||
'require_moderation_nonmembers' => true
|
||||
));
|
||||
$this->assertEquals('Required', $item->getModerationRequired());
|
||||
|
||||
Config::inst()->update('CommentableItem', 'comments', array(
|
||||
Config::inst()->update(CommentableItem::class, 'comments', array(
|
||||
'require_moderation_cms' => false,
|
||||
'require_moderation' => false,
|
||||
'require_moderation_nonmembers' => true
|
||||
));
|
||||
$this->assertEquals('NonMembersOnly', $item->getModerationRequired());
|
||||
|
||||
Config::inst()->update('CommentableItem', 'comments', array(
|
||||
Config::inst()->update(CommentableItem::class, 'comments', array(
|
||||
'require_moderation_cms' => false,
|
||||
'require_moderation' => false,
|
||||
'require_moderation_nonmembers' => false
|
||||
@ -100,24 +119,24 @@ class CommentsExtensionTest extends SapphireTest
|
||||
|
||||
public function testGetCommentsRequireLogin()
|
||||
{
|
||||
Config::inst()->update('CommentableItem', 'comments', array(
|
||||
Config::inst()->update(CommentableItem::class, 'comments', array(
|
||||
'require_login_cms' => true
|
||||
));
|
||||
|
||||
// With require moderation CMS set to true, the value of the field
|
||||
// 'ModerationRequired' is returned
|
||||
$item = $this->objFromFixture('CommentableItem', 'first');
|
||||
$item = $this->objFromFixture(CommentableItem::class, 'first');
|
||||
$item->CommentsRequireLogin = true;
|
||||
$this->assertTrue($item->getCommentsRequireLogin());
|
||||
$item->CommentsRequireLogin = false;
|
||||
$this->assertFalse($item->getCommentsRequireLogin());
|
||||
|
||||
Config::inst()->update('CommentableItem', 'comments', array(
|
||||
Config::inst()->update(CommentableItem::class, 'comments', array(
|
||||
'require_login_cms' => false,
|
||||
'require_login' => false
|
||||
));
|
||||
$this->assertFalse($item->getCommentsRequireLogin());
|
||||
Config::inst()->update('CommentableItem', 'comments', array(
|
||||
Config::inst()->update(CommentableItem::class, 'comments', array(
|
||||
'require_login_cms' => false,
|
||||
'require_login' => true
|
||||
));
|
||||
@ -146,13 +165,13 @@ class CommentsExtensionTest extends SapphireTest
|
||||
|
||||
public function testGetCommentHolderID()
|
||||
{
|
||||
$item = $this->objFromFixture('CommentableItem', 'first');
|
||||
Config::inst()->update('CommentableItem', 'comments', array(
|
||||
$item = $this->objFromFixture(CommentableItem::class, 'first');
|
||||
Config::inst()->update(CommentableItem::class, 'comments', array(
|
||||
'comments_holder_id' => 'commentid_test1',
|
||||
));
|
||||
$this->assertEquals('commentid_test1', $item->getCommentHolderID());
|
||||
|
||||
Config::inst()->update('CommentableItem', 'comments', array(
|
||||
Config::inst()->update(CommentableItem::class, 'comments', array(
|
||||
'comments_holder_id' => 'commtentid_test_another',
|
||||
));
|
||||
$this->assertEquals('commtentid_test_another', $item->getCommentHolderID());
|
||||
@ -171,7 +190,7 @@ class CommentsExtensionTest extends SapphireTest
|
||||
Member::currentUser()->logOut();
|
||||
}
|
||||
|
||||
$item = $this->objFromFixture('CommentableItem', 'first');
|
||||
$item = $this->objFromFixture(CommentableItem::class, 'first');
|
||||
$this->assertFalse($item->canModerateComments());
|
||||
|
||||
$this->logInWithPermission('CMS_ACCESS_CommentAdmin');
|
||||
@ -180,33 +199,36 @@ class CommentsExtensionTest extends SapphireTest
|
||||
|
||||
public function testGetCommentRSSLink()
|
||||
{
|
||||
$item = $this->objFromFixture('CommentableItem', 'first');
|
||||
$item = $this->objFromFixture(CommentableItem::class, 'first');
|
||||
$link = $item->getCommentRSSLink();
|
||||
$this->assertEquals('/CommentingController/rss', $link);
|
||||
$this->assertEquals('/comments/rss', $link);
|
||||
}
|
||||
|
||||
|
||||
public function testGetCommentRSSLinkPage()
|
||||
{
|
||||
$item = $this->objFromFixture('CommentableItem', 'first');
|
||||
$item = $this->objFromFixture(CommentableItem::class, 'first');
|
||||
$page = $item->getCommentRSSLinkPage();
|
||||
$this->assertEquals(
|
||||
'/CommentingController/rss/CommentableItem/' . $item->ID,
|
||||
'/comments/rss/SilverStripe-Comments-Tests-Stubs-CommentableItem/' . $item->ID,
|
||||
$page
|
||||
);
|
||||
}
|
||||
|
||||
public function testCommentsForm()
|
||||
{
|
||||
Config::inst()->update('CommentableItem', 'comments', array(
|
||||
'include_js' => false
|
||||
Config::inst()->update(
|
||||
CommentableItem::class,
|
||||
'comments',
|
||||
array(
|
||||
'include_js' => false
|
||||
)
|
||||
);
|
||||
$item = $this->objFromFixture('CommentableItem', 'first');
|
||||
$item = $this->objFromFixture(CommentableItem::class, 'first');
|
||||
|
||||
// The comments form is HTML to do assertions by contains
|
||||
$cf = $item->CommentsForm();
|
||||
$expected = '<form id="Form_CommentsForm" action="/CommentingController'
|
||||
$expected = '<form id="Form_CommentsForm" action="/comments'
|
||||
. '/CommentsForm" method="post" enctype="application/x-www-form-urlenco'
|
||||
. 'ded">';
|
||||
$this->assertContains($expected, $cf);
|
||||
@ -231,13 +253,13 @@ class CommentsExtensionTest extends SapphireTest
|
||||
$expected = '<input type="submit" name="action_doPostComment" value="Post" class="action" id="Form_CommentsForm_action_doPostComment"';
|
||||
$this->assertContains($expected, $cf);
|
||||
|
||||
$expected = '<a href="/CommentingController/spam/';
|
||||
$expected = '<a href="/comments/spam/';
|
||||
$this->assertContains($expected, $cf);
|
||||
|
||||
$expected = '<p>Reply to firstComA 1</p>';
|
||||
$this->assertContains($expected, $cf);
|
||||
|
||||
$expected = '<a href="/CommentingController/delete';
|
||||
$expected = '<a href="/comments/delete';
|
||||
$this->assertContains($expected, $cf);
|
||||
|
||||
$expected = '<p>Reply to firstComA 2</p>';
|
||||
@ -250,28 +272,36 @@ class CommentsExtensionTest extends SapphireTest
|
||||
$backend = Requirements::backend();
|
||||
$this->assertEquals(
|
||||
array(),
|
||||
$backend->get_javascript()
|
||||
$backend->getJavascript()
|
||||
);
|
||||
|
||||
Config::inst()->update('CommentableItem', 'comments', array(
|
||||
'include_js' => true
|
||||
Config::inst()->update(
|
||||
CommentableItem::class,
|
||||
'comments',
|
||||
array(
|
||||
'include_js' => true
|
||||
)
|
||||
);
|
||||
$cf = $item->CommentsForm();
|
||||
|
||||
$backend = Requirements::backend();
|
||||
$this->assertEquals(
|
||||
array(
|
||||
'framework/thirdparty/jquery/jquery.js',
|
||||
'framework/thirdparty/jquery-entwine/dist/jquery.entwine-dist.js',
|
||||
'framework/thirdparty/jquery-validate/lib/jquery.form.js',
|
||||
'comments/thirdparty/jquery-validate/jquery.validate.min.js',
|
||||
'framework/javascript/i18n.js',
|
||||
'comments/javascript/lang/en.js',
|
||||
'comments/javascript/CommentsInterface.js'
|
||||
),
|
||||
$backend->get_javascript()
|
||||
$javascriptRequirements = $backend->getJavascript();
|
||||
$expected = array(
|
||||
'framework/admin/thirdparty/jquery/jquery.js',
|
||||
'framework/admin/thirdparty/jquery-entwine/dist/jquery.entwine-dist.js',
|
||||
'framework/admin/thirdparty/jquery-form/jquery.form.js',
|
||||
'comments/thirdparty/jquery-validate/jquery.validate.min.js',
|
||||
/**
|
||||
* @todo: Is there a replacement for this? The docs are unclear
|
||||
*/
|
||||
// 'framework/admin/client/src/i18n.js',
|
||||
'comments/javascript/lang/en.js',
|
||||
'comments/javascript/CommentsInterface.js'
|
||||
);
|
||||
|
||||
foreach ($expected as $javascript) {
|
||||
$this->assertArrayHasKey($javascript, $javascriptRequirements);
|
||||
};
|
||||
}
|
||||
|
||||
public function testAttachedToSiteTree()
|
||||
@ -281,7 +311,7 @@ class CommentsExtensionTest extends SapphireTest
|
||||
|
||||
public function testPagedComments()
|
||||
{
|
||||
$item = $this->objFromFixture('CommentableItem', 'first');
|
||||
$item = $this->objFromFixture(CommentableItem::class, 'first');
|
||||
// Ensure Created times are set, as order not guaranteed if all set to 0
|
||||
$comments = $item->PagedComments()->sort('ID');
|
||||
$ctr = 0;
|
||||
@ -299,19 +329,19 @@ class CommentsExtensionTest extends SapphireTest
|
||||
}
|
||||
|
||||
$this->assertEquals(
|
||||
$this->objFromFixture('Comment', 'firstComA')->Comment,
|
||||
$this->objFromFixture(Comment::class, 'firstComA')->Comment,
|
||||
$results[3]->Comment
|
||||
);
|
||||
$this->assertEquals(
|
||||
$this->objFromFixture('Comment', 'firstComAChild1')->Comment,
|
||||
$this->objFromFixture(Comment::class, 'firstComAChild1')->Comment,
|
||||
$results[2]->Comment
|
||||
);
|
||||
$this->assertEquals(
|
||||
$this->objFromFixture('Comment', 'firstComAChild2')->Comment,
|
||||
$this->objFromFixture(Comment::class, 'firstComAChild2')->Comment,
|
||||
$results[1]->Comment
|
||||
);
|
||||
$this->assertEquals(
|
||||
$this->objFromFixture('Comment', 'firstComAChild3')->Comment,
|
||||
$this->objFromFixture(Comment::class, 'firstComAChild3')->Comment,
|
||||
$results[0]->Comment
|
||||
);
|
||||
|
||||
@ -330,37 +360,51 @@ class CommentsExtensionTest extends SapphireTest
|
||||
|
||||
public function testUpdateCMSFields()
|
||||
{
|
||||
Config::inst()->update('CommentableItem', 'comments', array(
|
||||
'require_login_cms' => false
|
||||
Config::inst()->update(
|
||||
CommentableItem::class,
|
||||
'comments',
|
||||
array(
|
||||
'require_login_cms' => false
|
||||
)
|
||||
);
|
||||
$this->logInWithPermission('ADMIN');
|
||||
$item = $this->objFromFixture('CommentableItem', 'first');
|
||||
$item = $this->objFromFixture(CommentableItem::class, 'first');
|
||||
$item->ProvideComments = true;
|
||||
$item->write();
|
||||
$fields = $item->getCMSFields();
|
||||
CommentTestHelper::assertFieldsForTab($this, 'Root.Comments',
|
||||
CommentTestHelper::assertFieldsForTab(
|
||||
$this,
|
||||
'Root.Comments',
|
||||
array('CommentsNewCommentsTab', 'CommentsCommentsTab', 'CommentsSpamCommentsTab'),
|
||||
$fields
|
||||
);
|
||||
|
||||
CommentTestHelper::assertFieldsForTab($this, 'Root.Comments.CommentsNewCommentsTab',
|
||||
CommentTestHelper::assertFieldsForTab(
|
||||
$this,
|
||||
'Root.Comments.CommentsNewCommentsTab',
|
||||
array('NewComments'),
|
||||
$fields
|
||||
);
|
||||
|
||||
CommentTestHelper::assertFieldsForTab($this, 'Root.Comments.CommentsCommentsTab',
|
||||
CommentTestHelper::assertFieldsForTab(
|
||||
$this,
|
||||
'Root.Comments.CommentsCommentsTab',
|
||||
array('ApprovedComments'),
|
||||
$fields
|
||||
);
|
||||
|
||||
CommentTestHelper::assertFieldsForTab($this, 'Root.Comments.CommentsSpamCommentsTab',
|
||||
CommentTestHelper::assertFieldsForTab(
|
||||
$this,
|
||||
'Root.Comments.CommentsSpamCommentsTab',
|
||||
array('SpamComments'),
|
||||
$fields
|
||||
);
|
||||
|
||||
Config::inst()->update('CommentableItem', 'comments', array(
|
||||
'require_login_cms' => true
|
||||
Config::inst()->update(
|
||||
CommentableItem::class,
|
||||
'comments',
|
||||
array(
|
||||
'require_login_cms' => true
|
||||
)
|
||||
);
|
||||
$fields = $item->getCMSFields();
|
||||
@ -376,9 +420,12 @@ class CommentsExtensionTest extends SapphireTest
|
||||
$fields
|
||||
);
|
||||
|
||||
Config::inst()->update('CommentableItem', 'comments', array(
|
||||
'require_login_cms' => true,
|
||||
'require_moderation_cms' => true
|
||||
Config::inst()->update(
|
||||
CommentableItem::class,
|
||||
'comments',
|
||||
array(
|
||||
'require_login_cms' => true,
|
||||
'require_moderation_cms' => true
|
||||
)
|
||||
);
|
||||
|
||||
@ -386,7 +433,8 @@ class CommentsExtensionTest extends SapphireTest
|
||||
CommentTestHelper::assertFieldsForTab(
|
||||
$this,
|
||||
'Root.Settings',
|
||||
array('Comments', 'ModerationRequired'), $fields
|
||||
array('Comments', 'ModerationRequired'),
|
||||
$fields
|
||||
);
|
||||
$settingsTab = $fields->findOrMakeTab('Root.Settings');
|
||||
$settingsChildren = $settingsTab->getChildren();
|
||||
@ -400,11 +448,9 @@ class CommentsExtensionTest extends SapphireTest
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public function testDeprecatedMethods()
|
||||
{
|
||||
$item = $this->objFromFixture('CommentableItem', 'first');
|
||||
$item = $this->objFromFixture(CommentableItem::class, 'first');
|
||||
$methodNames = array(
|
||||
'getRssLinkPage',
|
||||
'getRssLink',
|
||||
@ -419,8 +465,8 @@ class CommentsExtensionTest extends SapphireTest
|
||||
$item->$methodName();
|
||||
$this->fail('Method ' . $methodName .' should be depracated');
|
||||
} catch (PHPUnit_Framework_Error_Deprecated $e) {
|
||||
$expected = 'CommentsExtension->' . $methodName . ' is '.
|
||||
'deprecated.';
|
||||
$expected = 'SilverStripe\\Comments\\Extensions\\CommentsExtension->' . $methodName . ' is '
|
||||
. 'deprecated.';
|
||||
$this->assertStringStartsWith($expected, $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,22 @@
|
||||
<?php
|
||||
|
||||
namespace SilverStripe\Comments\Tests;
|
||||
|
||||
use SilverStripe\Comments\Admin\CommentsGridField;
|
||||
use SilverStripe\Comments\Admin\CommentsGridFieldAction;
|
||||
use SilverStripe\Comments\Admin\CommentsGridFieldConfig;
|
||||
use SilverStripe\Comments\Model\Comment;
|
||||
use SilverStripe\Control\Controller;
|
||||
use SilverStripe\Dev\SapphireTest;
|
||||
use SilverStripe\Forms\FieldList;
|
||||
use SilverStripe\Forms\Form;
|
||||
use SilverStripe\Forms\GridField\GridFieldDeleteAction;
|
||||
use SilverStripe\Forms\Tests\GridField\GridFieldTest\Team;
|
||||
use SilverStripe\ORM\DataList;
|
||||
use SilverStripe\ORM\DataObject;
|
||||
|
||||
class CommentsGridFieldActionTest extends SapphireTest
|
||||
{
|
||||
|
||||
/** @var ArrayList */
|
||||
protected $list;
|
||||
|
||||
@ -15,7 +29,7 @@ class CommentsGridFieldActionTest extends SapphireTest
|
||||
public function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
$this->list = new DataList('GridFieldAction_Delete_Team');
|
||||
$this->list = new DataList(Team::class);
|
||||
$config = CommentsGridFieldConfig::create()->addComponent(new GridFieldDeleteAction());
|
||||
$this->gridField = new CommentsGridField('testfield', 'testfield', $this->list, $config);
|
||||
$this->form = new Form(new Controller(), 'mockform', new FieldList(array($this->gridField)), new FieldList());
|
||||
@ -41,7 +55,7 @@ class CommentsGridFieldActionTest extends SapphireTest
|
||||
{
|
||||
$action = new CommentsGridFieldAction();
|
||||
$record = new Comment();
|
||||
$attrs = $action->getColumnAttributes($this->gridField, $record, 'Comment');
|
||||
$attrs = $action->getColumnAttributes($this->gridField, $record, Comment::class);
|
||||
$this->assertEquals(array('class' => 'col-buttons'), $attrs);
|
||||
}
|
||||
|
||||
@ -70,28 +84,25 @@ class CommentsGridFieldActionTest extends SapphireTest
|
||||
$record->Comment = 'This is a comment';
|
||||
$record->write();
|
||||
$recordID = $record->ID;
|
||||
$html = $action->getColumnContent($this->gridField, $record, 'Comment');
|
||||
$this->assertContains('data-url="Controller/mockform/field/testfield',
|
||||
$html);
|
||||
$spamAction = 'value="Spam" class="action" id="action_CustomAction' .
|
||||
$recordID . 'Spam"';
|
||||
$html = $action->getColumnContent($this->gridField, $record, Comment::class);
|
||||
$this->assertContains('data-url="Controller/mockform/field/testfield', $html);
|
||||
$spamAction = 'value="Spam" class="action" id="action_CustomAction' . $recordID . 'Spam"';
|
||||
$this->assertContains($spamAction, $html);
|
||||
|
||||
$approveAction = 'value="Approve" class="action" id="action_CustomAction' .
|
||||
$recordID . 'Approve"';
|
||||
$approveAction = 'value="Approve" class="action" id="action_CustomAction' . $recordID . 'Approve"';
|
||||
$this->assertContains($approveAction, $html);
|
||||
|
||||
// If marked as spam, only the approve button should be available
|
||||
$record->markSpam();
|
||||
$record->write();
|
||||
$html = $action->getColumnContent($this->gridField, $record, 'Comment');
|
||||
$html = $action->getColumnContent($this->gridField, $record, Comment::class);
|
||||
$this->assertContains($approveAction, $html);
|
||||
$this->assertNotContains($spamAction, $html);
|
||||
|
||||
// If marked as spam, only the approve button should be available
|
||||
$record->markApproved();
|
||||
$record->write();
|
||||
$html = $action->getColumnContent($this->gridField, $record, 'Comment');
|
||||
$html = $action->getColumnContent($this->gridField, $record, Comment::class);
|
||||
$this->assertNotContains($approveAction, $html);
|
||||
$this->assertContains($spamAction, $html);
|
||||
}
|
||||
@ -103,12 +114,11 @@ class CommentsGridFieldActionTest extends SapphireTest
|
||||
$this->assertEquals(array('spam', 'approve'), $result);
|
||||
}
|
||||
|
||||
|
||||
public function testHandleAction()
|
||||
{
|
||||
$action = new CommentsGridFieldAction();
|
||||
$record = new Comment();
|
||||
$record->Name = 'Name of commeter';
|
||||
$record->Name = 'Name of commenter';
|
||||
$record->Comment = 'This is a comment';
|
||||
$record->write();
|
||||
$recordID = $record->ID;
|
||||
@ -120,11 +130,11 @@ class CommentsGridFieldActionTest extends SapphireTest
|
||||
'Comment marked as spam.',
|
||||
Controller::curr()->getResponse()->getStatusDescription()
|
||||
);
|
||||
$record = DataObject::get_by_id('Comment', $recordID);
|
||||
$record = DataObject::get_by_id(Comment::class, $recordID);
|
||||
$this->assertEquals(1, $record->Moderated);
|
||||
$this->assertEquals(1, $record->IsSpam);
|
||||
|
||||
//getStatusDescription
|
||||
//getStatusDescription
|
||||
$result = $action->handleAction($this->gridField, 'approve', $arguments, $data);
|
||||
$this->assertEquals(200, Controller::curr()->getResponse()->getStatusCode());
|
||||
$this->assertEquals(
|
||||
@ -132,10 +142,8 @@ class CommentsGridFieldActionTest extends SapphireTest
|
||||
Controller::curr()->getResponse()->getStatusDescription()
|
||||
);
|
||||
|
||||
$record = DataObject::get_by_id('Comment', $recordID);
|
||||
$record = DataObject::get_by_id(Comment::class, $recordID);
|
||||
$this->assertEquals(1, $record->Moderated);
|
||||
$this->assertEquals(0, $record->IsSpam);
|
||||
|
||||
error_log(Controller::curr()->getResponse()->getStatusCode());
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,9 @@
|
||||
<?php
|
||||
|
||||
namespace SilverStripe\Comments\Tests;
|
||||
|
||||
use SilverStripe\Dev\SapphireTest;
|
||||
|
||||
class CommentsGridFieldBulkActionTest extends SapphireTest
|
||||
{
|
||||
public function testSpam()
|
||||
|
@ -1,10 +1,14 @@
|
||||
<?php
|
||||
|
||||
namespace SilverStripe\Comments\Tests;
|
||||
|
||||
use SilverStripe\Dev\SapphireTest;
|
||||
|
||||
class CommentsGridFieldConfigTest extends SapphireTest
|
||||
{
|
||||
public function test__construct()
|
||||
public function testConstruct()
|
||||
{
|
||||
$config = new CommentsGridFieldConfigTest();
|
||||
// $config = new CommentsGridFieldConfigTest();
|
||||
$this->markTestSkipped('TODO');
|
||||
}
|
||||
}
|
||||
|
@ -1,17 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace SilverStripe\Comments\Tests;
|
||||
|
||||
use ReflectionClass;
|
||||
use ReflectionException;
|
||||
use SilverStripe\Comments\Model\Comment;
|
||||
use SilverStripe\Comments\Admin\CommentsGridField;
|
||||
use SilverStripe\Dev\SapphireTest;
|
||||
|
||||
class CommentsGridFieldTest extends SapphireTest
|
||||
{
|
||||
public function testNewRow()
|
||||
{
|
||||
$gridfield = new CommentsGridField('testfield', 'testfield');
|
||||
// protected function newRow($total, $index, $record, $attributes, $content) {
|
||||
$comment = new Comment();
|
||||
// protected function newRow($total, $index, $record, $attributes, $content) {
|
||||
$comment = new Comment();
|
||||
$comment->Name = 'Fred Bloggs';
|
||||
$comment->Comment = 'This is a comment';
|
||||
$attr = array();
|
||||
|
||||
|
||||
try {
|
||||
$class = new ReflectionClass($gridfield);
|
||||
$method = $class->getMethod('newRow');
|
||||
|
@ -1,17 +1,41 @@
|
||||
<?php
|
||||
|
||||
namespace SilverStripe\Comments\Tests;
|
||||
|
||||
use ReflectionClass;
|
||||
use SilverStripe\Comments\Extensions\CommentsExtension;
|
||||
use SilverStripe\Comments\Model\Comment;
|
||||
use SilverStripe\Comments\Tests\Stubs\CommentableItem;
|
||||
use SilverStripe\Comments\Tests\Stubs\CommentableItemDisabled;
|
||||
use SilverStripe\Comments\Tests\Stubs\CommentableItemEnabled;
|
||||
use SilverStripe\Control\Controller;
|
||||
use SilverStripe\Control\Director;
|
||||
use SilverStripe\Core\Config\Config;
|
||||
use SilverStripe\Core\Email\Email;
|
||||
use SilverStripe\Dev\FunctionalTest;
|
||||
use SilverStripe\Dev\TestOnly;
|
||||
use SilverStripe\i18n\i18n;
|
||||
use SilverStripe\ORM\DataObject;
|
||||
use SilverStripe\Security\Member;
|
||||
use SilverStripe\Security\Permission;
|
||||
|
||||
/**
|
||||
* @package comments
|
||||
*/
|
||||
class CommentsTest extends FunctionalTest
|
||||
{
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public static $fixture_file = 'comments/tests/CommentsTest.yml';
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
protected $extraDataObjects = array(
|
||||
'CommentableItem',
|
||||
'CommentableItemEnabled',
|
||||
'CommentableItemDisabled'
|
||||
CommentableItem::class,
|
||||
CommentableItemEnabled::class,
|
||||
CommentableItemDisabled::class
|
||||
);
|
||||
|
||||
public function setUp()
|
||||
@ -20,7 +44,7 @@ class CommentsTest extends FunctionalTest
|
||||
Config::nest();
|
||||
|
||||
// Set good default values
|
||||
Config::inst()->update('CommentsExtension', 'comments', array(
|
||||
Config::inst()->update(CommentsExtension::class, 'comments', array(
|
||||
'enabled' => true,
|
||||
'enabled_cms' => false,
|
||||
'require_login' => false,
|
||||
@ -34,7 +58,7 @@ class CommentsTest extends FunctionalTest
|
||||
));
|
||||
|
||||
// Configure this dataobject
|
||||
Config::inst()->update('CommentableItem', 'comments', array(
|
||||
Config::inst()->update(CommentableItem::class, 'comments', array(
|
||||
'enabled_cms' => true
|
||||
));
|
||||
}
|
||||
@ -49,13 +73,13 @@ class CommentsTest extends FunctionalTest
|
||||
{
|
||||
// comments don't require moderation so unmoderated comments can be
|
||||
// shown but not spam posts
|
||||
Config::inst()->update('CommentableItem', 'comments', array(
|
||||
Config::inst()->update(CommentableItem::class, 'comments', array(
|
||||
'require_moderation_nonmembers' => false,
|
||||
'require_moderation' => false,
|
||||
'require_moderation_cms' => false,
|
||||
));
|
||||
|
||||
$item = $this->objFromFixture('CommentableItem', 'spammed');
|
||||
$item = $this->objFromFixture(CommentableItem::class, 'spammed');
|
||||
$this->assertEquals('None', $item->ModerationRequired);
|
||||
|
||||
$this->assertDOSEquals(array(
|
||||
@ -64,11 +88,11 @@ class CommentsTest extends FunctionalTest
|
||||
), $item->Comments(), 'Only 2 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::class, 'comments', array('require_moderation_nonmembers' => true));
|
||||
$this->assertEquals('NonMembersOnly', $item->ModerationRequired);
|
||||
|
||||
// Check that require_moderation overrides this option
|
||||
Config::inst()->update('CommentableItem', 'comments', array('require_moderation' => true));
|
||||
Config::inst()->update(CommentableItem::class, 'comments', array('require_moderation' => true));
|
||||
$this->assertEquals('Required', $item->ModerationRequired);
|
||||
|
||||
$this->assertDOSEquals(array(
|
||||
@ -77,14 +101,14 @@ class CommentsTest extends FunctionalTest
|
||||
$this->assertEquals(1, $item->Comments()->Count());
|
||||
|
||||
// require_moderation_nonmembers still filters out unmoderated comments
|
||||
Config::inst()->update('CommentableItem', 'comments', array('require_moderation' => false));
|
||||
Config::inst()->update(CommentableItem::class, 'comments', array('require_moderation' => false));
|
||||
$this->assertEquals(1, $item->Comments()->Count());
|
||||
|
||||
Config::inst()->update('CommentableItem', 'comments', array('require_moderation_nonmembers' => false));
|
||||
Config::inst()->update(CommentableItem::class, 'comments', array('require_moderation_nonmembers' => false));
|
||||
$this->assertEquals(2, $item->Comments()->Count());
|
||||
|
||||
// With unmoderated comments set to display in frontend
|
||||
Config::inst()->update('CommentableItem', 'comments', array(
|
||||
Config::inst()->update(CommentableItem::class, 'comments', array(
|
||||
'require_moderation' => true,
|
||||
'frontend_moderation' => true
|
||||
));
|
||||
@ -94,7 +118,7 @@ class CommentsTest extends FunctionalTest
|
||||
$this->assertEquals(2, $item->Comments()->Count());
|
||||
|
||||
// With spam comments set to display in frontend
|
||||
Config::inst()->update('CommentableItem', 'comments', array(
|
||||
Config::inst()->update(CommentableItem::class, 'comments', array(
|
||||
'require_moderation' => true,
|
||||
'frontend_moderation' => false,
|
||||
'frontend_spam' => true,
|
||||
@ -109,7 +133,7 @@ class CommentsTest extends FunctionalTest
|
||||
|
||||
|
||||
// With spam and unmoderated comments set to display in frontend
|
||||
Config::inst()->update('CommentableItem', 'comments', array(
|
||||
Config::inst()->update(CommentableItem::class, 'comments', array(
|
||||
'require_moderation' => true,
|
||||
'frontend_moderation' => true,
|
||||
'frontend_spam' => true,
|
||||
@ -130,12 +154,12 @@ class CommentsTest extends FunctionalTest
|
||||
{
|
||||
// comments don't require moderation so unmoderated comments can be
|
||||
// shown but not spam posts
|
||||
Config::inst()->update('CommentableItem', 'comments', array(
|
||||
Config::inst()->update(CommentableItem::class, 'comments', array(
|
||||
'require_moderation' => true,
|
||||
'require_moderation_cms' => true,
|
||||
));
|
||||
|
||||
$item = $this->objFromFixture('CommentableItem', 'spammed');
|
||||
$item = $this->objFromFixture(CommentableItem::class, 'spammed');
|
||||
$this->assertEquals('None', $item->ModerationRequired);
|
||||
|
||||
$this->assertDOSEquals(array(
|
||||
@ -170,13 +194,13 @@ class CommentsTest extends FunctionalTest
|
||||
|
||||
public function testCanPostComment()
|
||||
{
|
||||
Config::inst()->update('CommentableItem', 'comments', array(
|
||||
Config::inst()->update(CommentableItem::class, 'comments', array(
|
||||
'require_login' => false,
|
||||
'require_login_cms' => false,
|
||||
'required_permission' => false,
|
||||
));
|
||||
$item = $this->objFromFixture('CommentableItem', 'first');
|
||||
$item2 = $this->objFromFixture('CommentableItem', 'second');
|
||||
$item = $this->objFromFixture(CommentableItem::class, 'first');
|
||||
$item2 = $this->objFromFixture(CommentableItem::class, 'second');
|
||||
|
||||
// Test restriction free commenting
|
||||
if ($member = Member::currentUser()) {
|
||||
@ -186,7 +210,7 @@ class CommentsTest extends FunctionalTest
|
||||
$this->assertTrue($item->canPostComment());
|
||||
|
||||
// Test permission required to post
|
||||
Config::inst()->update('CommentableItem', 'comments', array(
|
||||
Config::inst()->update(CommentableItem::class, 'comments', array(
|
||||
'require_login' => true,
|
||||
'required_permission' => 'POSTING_PERMISSION',
|
||||
));
|
||||
@ -200,7 +224,7 @@ class CommentsTest extends FunctionalTest
|
||||
$this->assertTrue($item->canPostComment());
|
||||
|
||||
// Test require login to post, but not any permissions
|
||||
Config::inst()->update('CommentableItem', 'comments', array(
|
||||
Config::inst()->update(CommentableItem::class, 'comments', array(
|
||||
'required_permission' => false,
|
||||
));
|
||||
$this->assertTrue($item->CommentsRequireLogin);
|
||||
@ -212,7 +236,7 @@ class CommentsTest extends FunctionalTest
|
||||
$this->assertTrue($item->canPostComment());
|
||||
|
||||
// Test options set via CMS
|
||||
Config::inst()->update('CommentableItem', 'comments', array(
|
||||
Config::inst()->update(CommentableItem::class, 'comments', array(
|
||||
'require_login' => true,
|
||||
'require_login_cms' => true,
|
||||
));
|
||||
@ -235,12 +259,12 @@ class CommentsTest extends FunctionalTest
|
||||
if ($member = Member::currentUser()) {
|
||||
$member->logOut();
|
||||
}
|
||||
$comment = $this->objFromFixture('Comment', 'firstComA');
|
||||
$comment = $this->objFromFixture(Comment::class, 'firstComA');
|
||||
$commentID = $comment->ID;
|
||||
$this->assertNull($comment->DeleteLink(), 'No permission to see delete link');
|
||||
$delete = $this->get('CommentingController/delete/'.$comment->ID.'?ajax=1');
|
||||
$delete = $this->get('comments/delete/' . $comment->ID . '?ajax=1');
|
||||
$this->assertEquals(403, $delete->getStatusCode());
|
||||
$check = DataObject::get_by_id('Comment', $commentID);
|
||||
$check = DataObject::get_by_id(Comment::class, $commentID);
|
||||
$this->assertTrue($check && $check->exists());
|
||||
|
||||
// Test non-authenticated user
|
||||
@ -249,16 +273,16 @@ class CommentsTest extends FunctionalTest
|
||||
|
||||
// Test authenticated user
|
||||
$this->logInAs('commentadmin');
|
||||
$comment = $this->objFromFixture('Comment', 'firstComA');
|
||||
$comment = $this->objFromFixture(Comment::class, 'firstComA');
|
||||
$commentID = $comment->ID;
|
||||
$adminComment1Link = $comment->DeleteLink();
|
||||
$this->assertContains('CommentingController/delete/'.$commentID.'?t=', $adminComment1Link);
|
||||
$this->assertContains('comments/delete/' . $commentID . '?t=', $adminComment1Link);
|
||||
|
||||
// Test that this link can't be shared / XSS exploited
|
||||
$this->logInAs('commentadmin2');
|
||||
$delete = $this->get($adminComment1Link);
|
||||
$this->assertEquals(400, $delete->getStatusCode());
|
||||
$check = DataObject::get_by_id('Comment', $commentID);
|
||||
$check = DataObject::get_by_id(Comment::class, $commentID);
|
||||
$this->assertTrue($check && $check->exists());
|
||||
|
||||
// Test that this other admin can delete the comment with their own link
|
||||
@ -267,7 +291,7 @@ class CommentsTest extends FunctionalTest
|
||||
$this->autoFollowRedirection = false;
|
||||
$delete = $this->get($adminComment2Link);
|
||||
$this->assertEquals(302, $delete->getStatusCode());
|
||||
$check = DataObject::get_by_id('Comment', $commentID);
|
||||
$check = DataObject::get_by_id(Comment::class, $commentID);
|
||||
$this->assertFalse($check && $check->exists());
|
||||
}
|
||||
|
||||
@ -277,12 +301,12 @@ class CommentsTest extends FunctionalTest
|
||||
if ($member = Member::currentUser()) {
|
||||
$member->logOut();
|
||||
}
|
||||
$comment = $this->objFromFixture('Comment', 'firstComA');
|
||||
$comment = $this->objFromFixture(Comment::class, 'firstComA');
|
||||
$commentID = $comment->ID;
|
||||
$this->assertNull($comment->SpamLink(), 'No permission to see mark as spam link');
|
||||
$spam = $this->get('CommentingController/spam/'.$comment->ID.'?ajax=1');
|
||||
$spam = $this->get('comments/spam/'.$comment->ID.'?ajax=1');
|
||||
$this->assertEquals(403, $spam->getStatusCode());
|
||||
$check = DataObject::get_by_id('Comment', $commentID);
|
||||
$check = DataObject::get_by_id(Comment::class, $commentID);
|
||||
$this->assertEquals(0, $check->IsSpam, 'No permission to mark as spam');
|
||||
|
||||
// Test non-authenticated user
|
||||
@ -291,16 +315,16 @@ class CommentsTest extends FunctionalTest
|
||||
|
||||
// Test authenticated user
|
||||
$this->logInAs('commentadmin');
|
||||
$comment = $this->objFromFixture('Comment', 'firstComA');
|
||||
$comment = $this->objFromFixture(Comment::class, 'firstComA');
|
||||
$commentID = $comment->ID;
|
||||
$adminComment1Link = $comment->SpamLink();
|
||||
$this->assertContains('CommentingController/spam/'.$commentID.'?t=', $adminComment1Link);
|
||||
$this->assertContains('comments/spam/' . $commentID . '?t=', $adminComment1Link);
|
||||
|
||||
// Test that this link can't be shared / XSS exploited
|
||||
$this->logInAs('commentadmin2');
|
||||
$spam = $this->get($adminComment1Link);
|
||||
$this->assertEquals(400, $spam->getStatusCode());
|
||||
$check = DataObject::get_by_id('Comment', $comment->ID);
|
||||
$check = DataObject::get_by_id(Comment::class, $comment->ID);
|
||||
$this->assertEquals(0, $check->IsSpam, 'No permission to mark as spam');
|
||||
|
||||
// Test that this other admin can spam the comment with their own link
|
||||
@ -309,7 +333,7 @@ class CommentsTest extends FunctionalTest
|
||||
$this->autoFollowRedirection = false;
|
||||
$spam = $this->get($adminComment2Link);
|
||||
$this->assertEquals(302, $spam->getStatusCode());
|
||||
$check = DataObject::get_by_id('Comment', $commentID);
|
||||
$check = DataObject::get_by_id(Comment::class, $commentID);
|
||||
$this->assertEquals(1, $check->IsSpam);
|
||||
|
||||
// Cannot re-spam spammed comment
|
||||
@ -322,12 +346,12 @@ class CommentsTest extends FunctionalTest
|
||||
if ($member = Member::currentUser()) {
|
||||
$member->logOut();
|
||||
}
|
||||
$comment = $this->objFromFixture('Comment', 'secondComC');
|
||||
$comment = $this->objFromFixture(Comment::class, 'secondComC');
|
||||
$commentID = $comment->ID;
|
||||
$this->assertNull($comment->HamLink(), 'No permission to see mark as ham link');
|
||||
$ham = $this->get('CommentingController/ham/'.$comment->ID.'?ajax=1');
|
||||
$ham = $this->get('comments/ham/' . $comment->ID . '?ajax=1');
|
||||
$this->assertEquals(403, $ham->getStatusCode());
|
||||
$check = DataObject::get_by_id('Comment', $commentID);
|
||||
$check = DataObject::get_by_id(Comment::class, $commentID);
|
||||
$this->assertEquals(1, $check->IsSpam, 'No permission to mark as ham');
|
||||
|
||||
// Test non-authenticated user
|
||||
@ -336,16 +360,16 @@ class CommentsTest extends FunctionalTest
|
||||
|
||||
// Test authenticated user
|
||||
$this->logInAs('commentadmin');
|
||||
$comment = $this->objFromFixture('Comment', 'secondComC');
|
||||
$comment = $this->objFromFixture(Comment::class, 'secondComC');
|
||||
$commentID = $comment->ID;
|
||||
$adminComment1Link = $comment->HamLink();
|
||||
$this->assertContains('CommentingController/ham/'.$commentID.'?t=', $adminComment1Link);
|
||||
$this->assertContains('comments/ham/' . $commentID . '?t=', $adminComment1Link);
|
||||
|
||||
// Test that this link can't be shared / XSS exploited
|
||||
$this->logInAs('commentadmin2');
|
||||
$ham = $this->get($adminComment1Link);
|
||||
$this->assertEquals(400, $ham->getStatusCode());
|
||||
$check = DataObject::get_by_id('Comment', $comment->ID);
|
||||
$check = DataObject::get_by_id(Comment::class, $comment->ID);
|
||||
$this->assertEquals(1, $check->IsSpam, 'No permission to mark as ham');
|
||||
|
||||
// Test that this other admin can ham the comment with their own link
|
||||
@ -354,7 +378,7 @@ class CommentsTest extends FunctionalTest
|
||||
$this->autoFollowRedirection = false;
|
||||
$ham = $this->get($adminComment2Link);
|
||||
$this->assertEquals(302, $ham->getStatusCode());
|
||||
$check = DataObject::get_by_id('Comment', $commentID);
|
||||
$check = DataObject::get_by_id(Comment::class, $commentID);
|
||||
$this->assertEquals(0, $check->IsSpam);
|
||||
|
||||
// Cannot re-ham hammed comment
|
||||
@ -367,12 +391,12 @@ class CommentsTest extends FunctionalTest
|
||||
if ($member = Member::currentUser()) {
|
||||
$member->logOut();
|
||||
}
|
||||
$comment = $this->objFromFixture('Comment', 'secondComB');
|
||||
$comment = $this->objFromFixture(Comment::class, 'secondComB');
|
||||
$commentID = $comment->ID;
|
||||
$this->assertNull($comment->ApproveLink(), 'No permission to see approve link');
|
||||
$approve = $this->get('CommentingController/approve/'.$comment->ID.'?ajax=1');
|
||||
$approve = $this->get('comments/approve/' . $comment->ID . '?ajax=1');
|
||||
$this->assertEquals(403, $approve->getStatusCode());
|
||||
$check = DataObject::get_by_id('Comment', $commentID);
|
||||
$check = DataObject::get_by_id(Comment::class, $commentID);
|
||||
$this->assertEquals(0, $check->Moderated, 'No permission to approve');
|
||||
|
||||
// Test non-authenticated user
|
||||
@ -381,16 +405,16 @@ class CommentsTest extends FunctionalTest
|
||||
|
||||
// Test authenticated user
|
||||
$this->logInAs('commentadmin');
|
||||
$comment = $this->objFromFixture('Comment', 'secondComB');
|
||||
$comment = $this->objFromFixture(Comment::class, 'secondComB');
|
||||
$commentID = $comment->ID;
|
||||
$adminComment1Link = $comment->ApproveLink();
|
||||
$this->assertContains('CommentingController/approve/'.$commentID.'?t=', $adminComment1Link);
|
||||
$this->assertContains('comments/approve/' . $commentID . '?t=', $adminComment1Link);
|
||||
|
||||
// Test that this link can't be shared / XSS exploited
|
||||
$this->logInAs('commentadmin2');
|
||||
$approve = $this->get($adminComment1Link);
|
||||
$this->assertEquals(400, $approve->getStatusCode());
|
||||
$check = DataObject::get_by_id('Comment', $comment->ID);
|
||||
$check = DataObject::get_by_id(Comment::class, $comment->ID);
|
||||
$this->assertEquals(0, $check->Moderated, 'No permission to approve');
|
||||
|
||||
// Test that this other admin can approve the comment with their own link
|
||||
@ -399,7 +423,7 @@ class CommentsTest extends FunctionalTest
|
||||
$this->autoFollowRedirection = false;
|
||||
$approve = $this->get($adminComment2Link);
|
||||
$this->assertEquals(302, $approve->getStatusCode());
|
||||
$check = DataObject::get_by_id('Comment', $commentID);
|
||||
$check = DataObject::get_by_id(Comment::class, $commentID);
|
||||
$this->assertEquals(1, $check->Moderated);
|
||||
|
||||
// Cannot re-approve approved comment
|
||||
@ -427,21 +451,21 @@ class CommentsTest extends FunctionalTest
|
||||
|
||||
public function testSanitizesWithAllowHtml()
|
||||
{
|
||||
if (!class_exists('HTMLPurifier')) {
|
||||
if (!class_exists('\\HTMLPurifier')) {
|
||||
$this->markTestSkipped('HTMLPurifier class not found');
|
||||
return;
|
||||
}
|
||||
|
||||
// Add p for paragraph
|
||||
// NOTE: The config method appears to append to the existing array
|
||||
Config::inst()->update('CommentableItem', 'comments', array(
|
||||
Config::inst()->update(CommentableItem::class, 'comments', array(
|
||||
'html_allowed_elements' => array('p'),
|
||||
));
|
||||
|
||||
// Without HTML allowed
|
||||
$comment1 = new Comment();
|
||||
$comment1->AllowHtml = false;
|
||||
$comment1->BaseClass = 'CommentableItem';
|
||||
$comment1->BaseClass = CommentableItem::class;
|
||||
$comment1->Comment = '<p><script>alert("w00t")</script>my comment</p>';
|
||||
$comment1->write();
|
||||
$this->assertEquals(
|
||||
@ -454,7 +478,7 @@ class CommentsTest extends FunctionalTest
|
||||
// With HTML allowed
|
||||
$comment2 = new Comment();
|
||||
$comment2->AllowHtml = true;
|
||||
$comment2->BaseClass = 'CommentableItem';
|
||||
$comment2->ParentClass = CommentableItem::class;
|
||||
$comment2->Comment = '<p><script>alert("w00t")</script>my comment</p>';
|
||||
$comment2->write();
|
||||
$this->assertEquals(
|
||||
@ -466,11 +490,11 @@ class CommentsTest extends FunctionalTest
|
||||
|
||||
public function testDefaultTemplateRendersHtmlWithAllowHtml()
|
||||
{
|
||||
if (!class_exists('HTMLPurifier')) {
|
||||
if (!class_exists('\\HTMLPurifier')) {
|
||||
$this->markTestSkipped('HTMLPurifier class not found');
|
||||
}
|
||||
|
||||
Config::inst()->update('CommentableItem', 'comments', array(
|
||||
Config::inst()->update(CommentableItem::class, 'comments', array(
|
||||
'html_allowed_elements' => array('p'),
|
||||
));
|
||||
|
||||
@ -482,7 +506,7 @@ class CommentsTest extends FunctionalTest
|
||||
$comment->Comment = '<p>my comment</p>';
|
||||
$comment->AllowHtml = false;
|
||||
$comment->ParentID = $item->ID;
|
||||
$comment->BaseClass = 'CommentableItem';
|
||||
$comment->BaseClass = CommentableItem::class;
|
||||
$comment->write();
|
||||
|
||||
$html = $item->customise(array('CommentsEnabled' => true))->renderWith('CommentsInterface');
|
||||
@ -507,7 +531,7 @@ class CommentsTest extends FunctionalTest
|
||||
public function testDefaultEnabled()
|
||||
{
|
||||
// Ensure values are set via cms (not via config)
|
||||
Config::inst()->update('CommentableItem', 'comments', array(
|
||||
Config::inst()->update(CommentableItem::class, 'comments', array(
|
||||
'enabled_cms' => true,
|
||||
'require_moderation_cms' => true,
|
||||
'require_login_cms' => true
|
||||
@ -532,13 +556,13 @@ class CommentsTest extends FunctionalTest
|
||||
|
||||
// With default = false
|
||||
// Because of config rules about falsey values, apply config to object directly
|
||||
Config::inst()->update('CommentableItem', 'comments', array(
|
||||
Config::inst()->update(CommentableItem::class, 'comments', array(
|
||||
'enabled' => false,
|
||||
'require_login' => true,
|
||||
'require_moderation' => true
|
||||
));
|
||||
$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->assertEquals('Required', $obj->ModerationRequired);
|
||||
$this->assertTrue((bool)$obj->CommentsRequireLogin);
|
||||
@ -559,7 +583,7 @@ class CommentsTest extends FunctionalTest
|
||||
*/
|
||||
public function testOnBeforeDelete()
|
||||
{
|
||||
$comment = $this->objFromFixture('Comment', 'firstComA');
|
||||
$comment = $this->objFromFixture(Comment::class, 'firstComA');
|
||||
|
||||
$child = new Comment();
|
||||
$child->Name = 'Fred Bloggs';
|
||||
@ -574,8 +598,8 @@ class CommentsTest extends FunctionalTest
|
||||
$comment->delete();
|
||||
|
||||
// assert that the new child been deleted
|
||||
$this->assertFalse(DataObject::get_by_id('Comment', $commentID));
|
||||
$this->assertFalse(DataObject::get_by_id('Comment', $childCommentID));
|
||||
$this->assertFalse(DataObject::get_by_id(Comment::class, $commentID));
|
||||
$this->assertFalse(DataObject::get_by_id(Comment::class, $childCommentID));
|
||||
}
|
||||
|
||||
public function testRequireDefaultRecords()
|
||||
@ -585,41 +609,42 @@ class CommentsTest extends FunctionalTest
|
||||
|
||||
public function testLink()
|
||||
{
|
||||
$comment = $this->objFromFixture('Comment', 'thirdComD');
|
||||
$this->assertEquals('CommentableItem_Controller#comment-'.$comment->ID,
|
||||
$comment->Link());
|
||||
$comment = $this->objFromFixture(Comment::class, 'thirdComD');
|
||||
$this->assertEquals(
|
||||
'CommentableItemController#comment-' . $comment->ID,
|
||||
$comment->Link()
|
||||
);
|
||||
$this->assertEquals($comment->ID, $comment->ID);
|
||||
|
||||
// An orphan comment has no link
|
||||
$comment->ParentID = 0;
|
||||
$comment->ParentClass = null;
|
||||
$comment->write();
|
||||
$this->assertEquals('', $comment->Link());
|
||||
}
|
||||
|
||||
public function testPermalink()
|
||||
{
|
||||
$comment = $this->objFromFixture('Comment', 'thirdComD');
|
||||
$comment = $this->objFromFixture(Comment::class, 'thirdComD');
|
||||
$this->assertEquals('comment-' . $comment->ID, $comment->Permalink());
|
||||
}
|
||||
|
||||
/*
|
||||
Test field labels in 2 languages
|
||||
/**
|
||||
* Test field labels in 2 languages
|
||||
*/
|
||||
public function testFieldLabels()
|
||||
{
|
||||
$locale = i18n::get_locale();
|
||||
i18n::set_locale('fr');
|
||||
$comment = $this->objFromFixture('Comment', 'firstComA');
|
||||
$comment = $this->objFromFixture(Comment::class, 'firstComA');
|
||||
$labels = $comment->FieldLabels();
|
||||
$expected = array(
|
||||
'Name' => 'Nom de l\'Auteur',
|
||||
'Comment' => 'Commentaire',
|
||||
'Email' => 'Email',
|
||||
'URL' => 'URL',
|
||||
'BaseClass' => 'Base Class',
|
||||
'Moderated' => 'Modéré?',
|
||||
'IsSpam' => 'Spam?',
|
||||
'ParentID' => 'Parent ID',
|
||||
'AllowHtml' => 'Allow Html',
|
||||
'SecretToken' => 'Secret Token',
|
||||
'Depth' => 'Depth',
|
||||
@ -627,7 +652,8 @@ class CommentsTest extends FunctionalTest
|
||||
'ParentComment' => 'Parent Comment',
|
||||
'ChildComments' => 'Child Comments',
|
||||
'ParentTitle' => 'Parent',
|
||||
'Created' => 'Date de publication'
|
||||
'Created' => 'Date de publication',
|
||||
'Parent' => 'Parent'
|
||||
);
|
||||
i18n::set_locale($locale);
|
||||
$this->assertEquals($expected, $labels);
|
||||
@ -637,10 +663,8 @@ class CommentsTest extends FunctionalTest
|
||||
'Comment' => 'Comment',
|
||||
'Email' => 'Email',
|
||||
'URL' => 'URL',
|
||||
'BaseClass' => 'Base Class',
|
||||
'Moderated' => 'Moderated?',
|
||||
'IsSpam' => 'Spam?',
|
||||
'ParentID' => 'Parent ID',
|
||||
'AllowHtml' => 'Allow Html',
|
||||
'SecretToken' => 'Secret Token',
|
||||
'Depth' => 'Depth',
|
||||
@ -648,8 +672,8 @@ class CommentsTest extends FunctionalTest
|
||||
'ParentComment' => 'Parent Comment',
|
||||
'ChildComments' => 'Child Comments',
|
||||
'ParentTitle' => 'Parent',
|
||||
'Created' => 'Date posted'
|
||||
|
||||
'Created' => 'Date posted',
|
||||
'Parent' => 'Parent'
|
||||
);
|
||||
$this->assertEquals($expected, $labels);
|
||||
}
|
||||
@ -661,29 +685,31 @@ class CommentsTest extends FunctionalTest
|
||||
|
||||
public function testGetParent()
|
||||
{
|
||||
$comment = $this->objFromFixture('Comment', 'firstComA');
|
||||
$item = $this->objFromFixture('CommentableItem', 'first');
|
||||
$parent = $comment->getParent();
|
||||
$this->assertEquals($item, $parent);
|
||||
$comment = $this->objFromFixture(Comment::class, 'firstComA');
|
||||
$item = $this->objFromFixture(CommentableItem::class, 'first');
|
||||
$parent = $comment->Parent();
|
||||
$this->assertSame($item->getClassName(), $parent->getClassName());
|
||||
$this->assertSame($item->ID, $parent->ID);
|
||||
}
|
||||
|
||||
public function testGetParentTitle()
|
||||
{
|
||||
$comment = $this->objFromFixture('Comment', 'firstComA');
|
||||
$comment = $this->objFromFixture(Comment::class, 'firstComA');
|
||||
$title = $comment->getParentTitle();
|
||||
$this->assertEquals('First', $title);
|
||||
|
||||
// Title from a comment with no parent is blank
|
||||
$comment->ParentID = 0;
|
||||
$comment->ParentClass = null;
|
||||
$comment->write();
|
||||
$this->assertEquals('', $comment->getParentTitle());
|
||||
}
|
||||
|
||||
public function testGetParentClassName()
|
||||
{
|
||||
$comment = $this->objFromFixture('Comment', 'firstComA');
|
||||
$comment = $this->objFromFixture(Comment::class, 'firstComA');
|
||||
$className = $comment->getParentClassName();
|
||||
$this->assertEquals('CommentableItem', $className);
|
||||
$this->assertEquals(CommentableItem::class, $className);
|
||||
}
|
||||
|
||||
public function testCastingHelper()
|
||||
@ -708,7 +734,7 @@ class CommentsTest extends FunctionalTest
|
||||
|
||||
public function testCanCreate()
|
||||
{
|
||||
$comment = $this->objFromFixture('Comment', 'firstComA');
|
||||
$comment = $this->objFromFixture(Comment::class, 'firstComA');
|
||||
|
||||
// admin can create - this is always false
|
||||
$this->logInAs('commentadmin');
|
||||
@ -721,7 +747,7 @@ class CommentsTest extends FunctionalTest
|
||||
|
||||
public function testCanView()
|
||||
{
|
||||
$comment = $this->objFromFixture('Comment', 'firstComA');
|
||||
$comment = $this->objFromFixture(Comment::class, 'firstComA');
|
||||
|
||||
// admin can view
|
||||
$this->logInAs('commentadmin');
|
||||
@ -738,7 +764,7 @@ class CommentsTest extends FunctionalTest
|
||||
|
||||
public function testCanEdit()
|
||||
{
|
||||
$comment = $this->objFromFixture('Comment', 'firstComA');
|
||||
$comment = $this->objFromFixture(Comment::class, 'firstComA');
|
||||
|
||||
// admin can edit
|
||||
$this->logInAs('commentadmin');
|
||||
@ -755,7 +781,7 @@ class CommentsTest extends FunctionalTest
|
||||
|
||||
public function testCanDelete()
|
||||
{
|
||||
$comment = $this->objFromFixture('Comment', 'firstComA');
|
||||
$comment = $this->objFromFixture(Comment::class, 'firstComA');
|
||||
|
||||
// admin can delete
|
||||
$this->logInAs('commentadmin');
|
||||
@ -774,7 +800,7 @@ class CommentsTest extends FunctionalTest
|
||||
{
|
||||
$this->logInAs('visitor');
|
||||
$current = Member::currentUser();
|
||||
$comment = $this->objFromFixture('Comment', 'firstComA');
|
||||
$comment = $this->objFromFixture(Comment::class, 'firstComA');
|
||||
$method = $this->getMethod('getMember');
|
||||
|
||||
// null case
|
||||
@ -792,7 +818,7 @@ class CommentsTest extends FunctionalTest
|
||||
|
||||
public function testGetAuthorName()
|
||||
{
|
||||
$comment = $this->objFromFixture('Comment', 'firstComA');
|
||||
$comment = $this->objFromFixture(Comment::class, 'firstComA');
|
||||
$this->assertEquals(
|
||||
'FA',
|
||||
$comment->getAuthorName()
|
||||
@ -804,7 +830,7 @@ class CommentsTest extends FunctionalTest
|
||||
$comment->getAuthorName()
|
||||
);
|
||||
|
||||
$author = $this->objFromFixture('Member', 'visitor');
|
||||
$author = $this->objFromFixture(Member::class, 'visitor');
|
||||
$comment->AuthorID = $author->ID;
|
||||
$comment->write();
|
||||
$this->assertEquals(
|
||||
@ -821,44 +847,44 @@ class CommentsTest extends FunctionalTest
|
||||
|
||||
public function testLinks()
|
||||
{
|
||||
$comment = $this->objFromFixture('Comment', 'firstComA');
|
||||
$comment = $this->objFromFixture(Comment::class, 'firstComA');
|
||||
$this->logInAs('commentadmin');
|
||||
|
||||
$method = $this->getMethod('ActionLink');
|
||||
|
||||
// test with starts of strings and tokens and salts change each time
|
||||
$this->assertStringStartsWith(
|
||||
'/CommentingController/theaction/'.$comment->ID,
|
||||
'/comments/theaction/' . $comment->ID,
|
||||
$method->invokeArgs($comment, array('theaction'))
|
||||
);
|
||||
|
||||
$this->assertStringStartsWith(
|
||||
'/CommentingController/delete/'.$comment->ID,
|
||||
'/comments/delete/' . $comment->ID,
|
||||
$comment->DeleteLink()
|
||||
);
|
||||
|
||||
$this->assertStringStartsWith(
|
||||
'/CommentingController/spam/'.$comment->ID,
|
||||
'/comments/spam/' . $comment->ID,
|
||||
$comment->SpamLink()
|
||||
);
|
||||
|
||||
$comment->markSpam();
|
||||
$this->assertStringStartsWith(
|
||||
'/CommentingController/ham/'.$comment->ID,
|
||||
'/comments/ham/' . $comment->ID,
|
||||
$comment->HamLink()
|
||||
);
|
||||
|
||||
//markApproved
|
||||
$comment->markUnapproved();
|
||||
$this->assertStringStartsWith(
|
||||
'/CommentingController/approve/'.$comment->ID,
|
||||
'/comments/approve/' . $comment->ID,
|
||||
$comment->ApproveLink()
|
||||
);
|
||||
}
|
||||
|
||||
public function testMarkSpam()
|
||||
{
|
||||
$comment = $this->objFromFixture('Comment', 'firstComA');
|
||||
$comment = $this->objFromFixture(Comment::class, 'firstComA');
|
||||
$comment->markSpam();
|
||||
$this->assertTrue($comment->Moderated);
|
||||
$this->assertTrue($comment->IsSpam);
|
||||
@ -866,7 +892,7 @@ class CommentsTest extends FunctionalTest
|
||||
|
||||
public function testMarkApproved()
|
||||
{
|
||||
$comment = $this->objFromFixture('Comment', 'firstComA');
|
||||
$comment = $this->objFromFixture(Comment::class, 'firstComA');
|
||||
$comment->markApproved();
|
||||
$this->assertTrue($comment->Moderated);
|
||||
$this->assertFalse($comment->IsSpam);
|
||||
@ -874,14 +900,14 @@ class CommentsTest extends FunctionalTest
|
||||
|
||||
public function testMarkUnapproved()
|
||||
{
|
||||
$comment = $this->objFromFixture('Comment', 'firstComA');
|
||||
$comment = $this->objFromFixture(Comment::class, 'firstComA');
|
||||
$comment->markApproved();
|
||||
$this->assertTrue($comment->Moderated);
|
||||
}
|
||||
|
||||
public function testSpamClass()
|
||||
{
|
||||
$comment = $this->objFromFixture('Comment', 'firstComA');
|
||||
$comment = $this->objFromFixture(Comment::class, 'firstComA');
|
||||
$this->assertEquals('notspam', $comment->spamClass());
|
||||
$comment->Moderated = false;
|
||||
$this->assertEquals('unmoderated', $comment->spamClass());
|
||||
@ -891,7 +917,7 @@ class CommentsTest extends FunctionalTest
|
||||
|
||||
public function testGetTitle()
|
||||
{
|
||||
$comment = $this->objFromFixture('Comment', 'firstComA');
|
||||
$comment = $this->objFromFixture(Comment::class, 'firstComA');
|
||||
$this->assertEquals(
|
||||
'Comment by FA on First',
|
||||
$comment->getTitle()
|
||||
@ -900,7 +926,7 @@ class CommentsTest extends FunctionalTest
|
||||
|
||||
public function testGetCMSFields()
|
||||
{
|
||||
$comment = $this->objFromFixture('Comment', 'firstComA');
|
||||
$comment = $this->objFromFixture(Comment::class, 'firstComA');
|
||||
$fields = $comment->getCMSFields();
|
||||
$names = array();
|
||||
foreach ($fields as $field) {
|
||||
@ -912,7 +938,7 @@ class CommentsTest extends FunctionalTest
|
||||
'Comment',
|
||||
'Email',
|
||||
'URL',
|
||||
null #FIXME this is suspicious
|
||||
'Options'
|
||||
);
|
||||
$this->assertEquals($expected, $names);
|
||||
}
|
||||
@ -920,7 +946,7 @@ class CommentsTest extends FunctionalTest
|
||||
public function testGetCMSFieldsCommentHasAuthor()
|
||||
{
|
||||
$member = Member::get()->filter('FirstName', 'visitor')->first();
|
||||
$comment = $this->objFromFixture('Comment', 'firstComA');
|
||||
$comment = $this->objFromFixture(Comment::class, 'firstComA');
|
||||
$comment->AuthorID = $member->ID;
|
||||
$comment->write();
|
||||
|
||||
@ -936,14 +962,14 @@ class CommentsTest extends FunctionalTest
|
||||
'Comment',
|
||||
'Email',
|
||||
'URL',
|
||||
null #FIXME this is suspicious
|
||||
'Options'
|
||||
);
|
||||
$this->assertEquals($expected, $names);
|
||||
}
|
||||
|
||||
public function testGetCMSFieldsWithParentComment()
|
||||
{
|
||||
$comment = $this->objFromFixture('Comment', 'firstComA');
|
||||
$comment = $this->objFromFixture(Comment::class, 'firstComA');
|
||||
|
||||
$child = new Comment();
|
||||
$child->Name = 'John Smith';
|
||||
@ -962,7 +988,7 @@ class CommentsTest extends FunctionalTest
|
||||
'Comment',
|
||||
'Email',
|
||||
'URL',
|
||||
null, #FIXME this is suspicious
|
||||
'Options',
|
||||
'ParentComment_Title',
|
||||
'ParentComment_Created',
|
||||
'ParentComment_AuthorName',
|
||||
@ -971,10 +997,9 @@ class CommentsTest extends FunctionalTest
|
||||
$this->assertEquals($expected, $names);
|
||||
}
|
||||
|
||||
|
||||
public function testPurifyHtml()
|
||||
{
|
||||
$comment = $this->objFromFixture('Comment', 'firstComA');
|
||||
$comment = $this->objFromFixture(Comment::class, 'firstComA');
|
||||
|
||||
$dirtyHTML = '<p><script>alert("w00t")</script>my comment</p>';
|
||||
$this->assertEquals(
|
||||
@ -986,22 +1011,22 @@ class CommentsTest extends FunctionalTest
|
||||
public function testGravatar()
|
||||
{
|
||||
// Turn gravatars on
|
||||
Config::inst()->update('CommentableItem', 'comments', array(
|
||||
Config::inst()->update(CommentableItem::class, 'comments', array(
|
||||
'use_gravatar' => true
|
||||
));
|
||||
$comment = $this->objFromFixture('Comment', 'firstComA');
|
||||
$comment = $this->objFromFixture(Comment::class, 'firstComA');
|
||||
|
||||
$this->assertEquals(
|
||||
'http://www.gravatar.com/avatar/d41d8cd98f00b204e9800998ecf8427e?s'.
|
||||
'=80&d=identicon&r=g',
|
||||
'http://www.gravatar.com/avatar/d41d8cd98f00b204e9800998ecf8427e?s'
|
||||
. '=80&d=identicon&r=g',
|
||||
$comment->gravatar()
|
||||
);
|
||||
|
||||
// Turn gravatars off
|
||||
Config::inst()->update('CommentableItem', 'comments', array(
|
||||
Config::inst()->update(CommentableItem::class, 'comments', array(
|
||||
'use_gravatar' => false
|
||||
));
|
||||
$comment = $this->objFromFixture('Comment', 'firstComA');
|
||||
$comment = $this->objFromFixture(Comment::class, 'firstComA');
|
||||
|
||||
$this->assertEquals(
|
||||
'',
|
||||
@ -1011,13 +1036,13 @@ class CommentsTest extends FunctionalTest
|
||||
|
||||
public function testGetRepliesEnabled()
|
||||
{
|
||||
$comment = $this->objFromFixture('Comment', 'firstComA');
|
||||
Config::inst()->update('CommentableItem', 'comments', array(
|
||||
$comment = $this->objFromFixture(Comment::class, 'firstComA');
|
||||
Config::inst()->update(CommentableItem::class, 'comments', array(
|
||||
'nested_comments' => false
|
||||
));
|
||||
$this->assertFalse($comment->getRepliesEnabled());
|
||||
|
||||
Config::inst()->update('CommentableItem', 'comments', array(
|
||||
Config::inst()->update(CommentableItem::class, 'comments', array(
|
||||
'nested_comments' => true,
|
||||
'nested_depth' => 4
|
||||
));
|
||||
@ -1028,7 +1053,7 @@ class CommentsTest extends FunctionalTest
|
||||
|
||||
|
||||
// 0 indicates no limit for nested_depth
|
||||
Config::inst()->update('CommentableItem', 'comments', array(
|
||||
Config::inst()->update(CommentableItem::class, 'comments', array(
|
||||
'nested_comments' => true,
|
||||
'nested_depth' => 0
|
||||
));
|
||||
@ -1046,11 +1071,11 @@ class CommentsTest extends FunctionalTest
|
||||
|
||||
public function testAllReplies()
|
||||
{
|
||||
Config::inst()->update('CommentableItem', 'comments', array(
|
||||
Config::inst()->update(CommentableItem::class, 'comments', array(
|
||||
'nested_comments' => true,
|
||||
'nested_depth' => 4
|
||||
));
|
||||
$comment = $this->objFromFixture('Comment', 'firstComA');
|
||||
$comment = $this->objFromFixture(Comment::class, 'firstComA');
|
||||
$this->assertEquals(
|
||||
3,
|
||||
$comment->allReplies()->count()
|
||||
@ -1069,7 +1094,7 @@ class CommentsTest extends FunctionalTest
|
||||
$comment->allReplies()->count()
|
||||
);
|
||||
|
||||
Config::inst()->update('CommentableItem', 'comments', array(
|
||||
Config::inst()->update(CommentableItem::class, 'comments', array(
|
||||
'nested_comments' => false
|
||||
));
|
||||
|
||||
@ -1078,13 +1103,13 @@ class CommentsTest extends FunctionalTest
|
||||
|
||||
public function testReplies()
|
||||
{
|
||||
CommentableItem::add_extension('CommentsExtension');
|
||||
CommentableItem::add_extension(CommentsExtension::class);
|
||||
$this->logInWithPermission('ADMIN');
|
||||
Config::inst()->update('CommentableItem', 'comments', array(
|
||||
Config::inst()->update(CommentableItem::class, 'comments', array(
|
||||
'nested_comments' => true,
|
||||
'nested_depth' => 4
|
||||
));
|
||||
$comment = $this->objFromFixture('Comment', 'firstComA');
|
||||
$comment = $this->objFromFixture(Comment::class, 'firstComA');
|
||||
$this->assertEquals(
|
||||
3,
|
||||
$comment->Replies()->count()
|
||||
@ -1114,17 +1139,17 @@ class CommentsTest extends FunctionalTest
|
||||
|
||||
|
||||
// Test moderation required on the front end
|
||||
$item = $this->objFromFixture('CommentableItem', 'first');
|
||||
$item = $this->objFromFixture(CommentableItem::class, 'first');
|
||||
$item->ModerationRequired = 'Required';
|
||||
$item->write();
|
||||
|
||||
Config::inst()->update('CommentableItemDisabled', 'comments', array(
|
||||
Config::inst()->update(CommentableItemDisabled::class, 'comments', array(
|
||||
'nested_comments' => true,
|
||||
'nested_depth' => 4,
|
||||
'frontend_moderation' => true
|
||||
));
|
||||
|
||||
$comment = DataObject::get_by_id('Comment', $comment->ID);
|
||||
$comment = DataObject::get_by_id(Comment::class, $comment->ID);
|
||||
|
||||
$this->assertEquals(
|
||||
2,
|
||||
@ -1132,7 +1157,7 @@ class CommentsTest extends FunctionalTest
|
||||
);
|
||||
|
||||
// Turn off nesting, empty array should be returned
|
||||
Config::inst()->update('CommentableItem', 'comments', array(
|
||||
Config::inst()->update(CommentableItem::class, 'comments', array(
|
||||
'nested_comments' => false
|
||||
));
|
||||
|
||||
@ -1141,18 +1166,18 @@ class CommentsTest extends FunctionalTest
|
||||
$comment->Replies()->count()
|
||||
);
|
||||
|
||||
CommentableItem::remove_extension('CommentsExtension');
|
||||
CommentableItem::remove_extension(CommentsExtension::class);
|
||||
}
|
||||
|
||||
public function testPagedReplies()
|
||||
{
|
||||
Config::inst()->update('CommentableItem', 'comments', array(
|
||||
Config::inst()->update(CommentableItem::class, 'comments', array(
|
||||
'nested_comments' => true,
|
||||
'nested_depth' => 4,
|
||||
'comments_per_page' => 2 #Force 2nd page for 3 items
|
||||
));
|
||||
|
||||
$comment = $this->objFromFixture('Comment', 'firstComA');
|
||||
$comment = $this->objFromFixture(Comment::class, 'firstComA');
|
||||
$pagedList = $comment->pagedReplies();
|
||||
$this->assertEquals(
|
||||
2,
|
||||
@ -1164,7 +1189,7 @@ class CommentsTest extends FunctionalTest
|
||||
);
|
||||
//TODO - 2nd page requires controller
|
||||
//
|
||||
Config::inst()->update('CommentableItem', 'comments', array(
|
||||
Config::inst()->update(CommentableItem::class, 'comments', array(
|
||||
'nested_comments' => false
|
||||
));
|
||||
|
||||
@ -1173,19 +1198,19 @@ class CommentsTest extends FunctionalTest
|
||||
|
||||
public function testReplyForm()
|
||||
{
|
||||
Config::inst()->update('CommentableItem', 'comments', array(
|
||||
Config::inst()->update(CommentableItem::class, 'comments', array(
|
||||
'nested_comments' => false,
|
||||
'nested_depth' => 4
|
||||
));
|
||||
|
||||
$comment = $this->objFromFixture('Comment', 'firstComA');
|
||||
$comment = $this->objFromFixture(Comment::class, 'firstComA');
|
||||
|
||||
// No nesting, no reply form
|
||||
$form = $comment->replyForm();
|
||||
$this->assertNull($form);
|
||||
|
||||
// parent item so show form
|
||||
Config::inst()->update('CommentableItem', 'comments', array(
|
||||
Config::inst()->update(CommentableItem::class, 'comments', array(
|
||||
'nested_comments' => true,
|
||||
'nested_depth' => 4
|
||||
));
|
||||
@ -1198,11 +1223,11 @@ class CommentsTest extends FunctionalTest
|
||||
|
||||
$this->assertEquals(
|
||||
array(
|
||||
null, #FIXME suspicious
|
||||
'NameEmailURLComment', // The CompositeField name?
|
||||
'ParentID',
|
||||
'ParentClassName',
|
||||
'ReturnURL',
|
||||
'ParentCommentID',
|
||||
'BaseClass'
|
||||
'ParentCommentID'
|
||||
),
|
||||
$names
|
||||
);
|
||||
@ -1210,6 +1235,7 @@ class CommentsTest extends FunctionalTest
|
||||
// no parent, no reply form
|
||||
|
||||
$comment->ParentID = 0;
|
||||
$comment->ParentClass = null;
|
||||
$comment->write();
|
||||
$form = $comment->replyForm();
|
||||
$this->assertNull($form);
|
||||
@ -1217,12 +1243,12 @@ class CommentsTest extends FunctionalTest
|
||||
|
||||
public function testUpdateDepth()
|
||||
{
|
||||
Config::inst()->update('CommentableItem', 'comments', array(
|
||||
Config::inst()->update(CommentableItem::class, 'comments', array(
|
||||
'nested_comments' => true,
|
||||
'nested_depth' => 4
|
||||
));
|
||||
|
||||
$comment = $this->objFromFixture('Comment', 'firstComA');
|
||||
$comment = $this->objFromFixture(Comment::class, 'firstComA');
|
||||
$children = $comment->allReplies()->toArray();
|
||||
// Make the second child a child of the first
|
||||
// Make the third child a child of the second
|
||||
@ -1262,98 +1288,11 @@ class CommentsTest extends FunctionalTest
|
||||
$this->markTestSkipped('TODO');
|
||||
}
|
||||
|
||||
|
||||
protected static function getMethod($name)
|
||||
{
|
||||
$class = new ReflectionClass('Comment');
|
||||
$class = new ReflectionClass(Comment::class);
|
||||
$method = $class->getMethod($name);
|
||||
$method->setAccessible(true);
|
||||
return $method;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @package comments
|
||||
* @subpackage tests
|
||||
*/
|
||||
class CommentableItem extends DataObject implements TestOnly
|
||||
{
|
||||
|
||||
private static $db = array(
|
||||
'Title' => 'Varchar'
|
||||
);
|
||||
|
||||
private static $extensions = array(
|
||||
'CommentsExtension'
|
||||
);
|
||||
|
||||
public function RelativeLink()
|
||||
{
|
||||
return "CommentableItem_Controller";
|
||||
}
|
||||
|
||||
public function canView($member = null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// This is needed for canModerateComments
|
||||
public function canEdit($member = null)
|
||||
{
|
||||
if ($member instanceof Member) {
|
||||
$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;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public function Link()
|
||||
{
|
||||
return $this->RelativeLink();
|
||||
}
|
||||
|
||||
public function AbsoluteLink()
|
||||
{
|
||||
return Director::absoluteURL($this->RelativeLink());
|
||||
}
|
||||
}
|
||||
|
||||
class CommentableItemEnabled extends CommentableItem
|
||||
{
|
||||
private static $defaults = array(
|
||||
'ProvideComments' => true,
|
||||
'ModerationRequired' => 'Required',
|
||||
'CommentsRequireLogin' => true
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
class CommentableItemDisabled extends CommentableItem
|
||||
{
|
||||
private static $defaults = array(
|
||||
'ProvideComments' => false,
|
||||
'ModerationRequired' => 'None',
|
||||
'CommentsRequireLogin' => false
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @package comments
|
||||
* @subpackage tests
|
||||
*/
|
||||
class CommentableItem_Controller extends Controller implements TestOnly
|
||||
{
|
||||
|
||||
public function index()
|
||||
{
|
||||
return CommentableItem::get()->first()->CommentsForm();
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
Member:
|
||||
SilverStripe\Security\Member:
|
||||
commentadmin:
|
||||
FirstName: admin
|
||||
commentadmin2:
|
||||
@ -6,17 +6,17 @@ Member:
|
||||
visitor:
|
||||
FirstName: visitor
|
||||
|
||||
Group:
|
||||
SilverStripe\Security\Group:
|
||||
commentadmins:
|
||||
Title: Admin
|
||||
Members: =>Member.commentadmin, =>Member.commentadmin2
|
||||
Members: =>SilverStripe\Security\Member.commentadmin, =>SilverStripe\Security\Member.commentadmin2
|
||||
|
||||
Permission:
|
||||
SilverStripe\Security\Permission:
|
||||
admin:
|
||||
Code: CMS_ACCESS_CommentAdmin
|
||||
Group: =>Group.commentadmins
|
||||
Group: =>SilverStripe\Security\Group.commentadmins
|
||||
|
||||
CommentableItem:
|
||||
SilverStripe\Comments\Tests\Stubs\CommentableItem:
|
||||
first:
|
||||
Title: First
|
||||
ProvideComments: 1
|
||||
@ -35,166 +35,158 @@ CommentableItem:
|
||||
ProvideComments: 1
|
||||
Title: spammed
|
||||
ModerationRequired: 'None'
|
||||
moderated:
|
||||
ProvideComments: 1
|
||||
Title: Moderate everything
|
||||
ModerationRequired: Required
|
||||
CommentsRequireLogin: 0
|
||||
|
||||
Comment:
|
||||
SilverStripe\Comments\Model\Comment:
|
||||
firstComA:
|
||||
ParentID: =>CommentableItem.first
|
||||
Parent: =>SilverStripe\Comments\Tests\Stubs\CommentableItem.first
|
||||
Name: FA
|
||||
Comment: textFA
|
||||
BaseClass: CommentableItem
|
||||
Moderated: 1
|
||||
IsSpam:
|
||||
Depth: 1
|
||||
firstComAChild1:
|
||||
ParentID: =>CommentableItem.first
|
||||
ParentCommentID: =>Comment.firstComA
|
||||
Parent: =>SilverStripe\Comments\Tests\Stubs\CommentableItem.first
|
||||
ParentComment: =>SilverStripe\Comments\Model\Comment.firstComA
|
||||
Name: John Smith
|
||||
Comment: Reply to firstComA 1
|
||||
BaseClass: CommentableItem
|
||||
Moderated: 1
|
||||
IsSpam: 0
|
||||
Depth: 2
|
||||
firstComAChild2:
|
||||
ParentID: =>CommentableItem.first
|
||||
ParentCommentID: =>Comment.firstComA
|
||||
Parent: =>SilverStripe\Comments\Tests\Stubs\CommentableItem.first
|
||||
ParentComment: =>SilverStripe\Comments\Model\Comment.firstComA
|
||||
Name: John Smith
|
||||
Comment: Reply to firstComA 2
|
||||
BaseClass: CommentableItem
|
||||
Moderated: 1
|
||||
IsSpam: 0
|
||||
Depth: 2
|
||||
firstComAChild3:
|
||||
ParentID: =>CommentableItem.first
|
||||
ParentCommentID: =>Comment.firstComA
|
||||
Parent: =>SilverStripe\Comments\Tests\Stubs\CommentableItem.first
|
||||
ParentComment: =>SilverStripe\Comments\Model\Comment.firstComA
|
||||
Name: John Smith
|
||||
Comment: Reply to firstComA 3
|
||||
BaseClass: CommentableItem
|
||||
Moderated: 1
|
||||
IsSpam: 0
|
||||
Depth: 2
|
||||
secondComA:
|
||||
ParentID: =>CommentableItem.second
|
||||
Parent: =>SilverStripe\Comments\Tests\Stubs\CommentableItem.second
|
||||
Name: SA
|
||||
Comment: textSA
|
||||
Moderated: 1
|
||||
IsSpam: 0
|
||||
BaseClass: CommentableItem
|
||||
secondComB:
|
||||
ParentID: =>CommentableItem.second
|
||||
Parent: =>SilverStripe\Comments\Tests\Stubs\CommentableItem.second
|
||||
Name: SB
|
||||
Comment: textSB
|
||||
Moderated: 0
|
||||
IsSpam: 0
|
||||
BaseClass: CommentableItem
|
||||
secondComC:
|
||||
ParentID: =>CommentableItem.second
|
||||
Parent: =>SilverStripe\Comments\Tests\Stubs\CommentableItem.second
|
||||
Name: SB
|
||||
Comment: textSB
|
||||
Moderated: 1
|
||||
IsSpam: 1
|
||||
BaseClass: CommentableItem
|
||||
thirdComA:
|
||||
ParentID: =>CommentableItem.third
|
||||
Parent: =>SilverStripe\Comments\Tests\Stubs\CommentableItem.third
|
||||
Name: TA
|
||||
Comment: textTA
|
||||
Moderated: 1
|
||||
IsSpam: 0
|
||||
BaseClass: CommentableItem
|
||||
thirdComB:
|
||||
ParentID: =>CommentableItem.third
|
||||
Parent: =>SilverStripe\Comments\Tests\Stubs\CommentableItem.third
|
||||
Name: TB
|
||||
Comment: textTB
|
||||
Moderated: 1
|
||||
IsSpam: 0
|
||||
BaseClass: CommentableItem
|
||||
thirdComC:
|
||||
ParentID: =>CommentableItem.third
|
||||
Parent: =>SilverStripe\Comments\Tests\Stubs\CommentableItem.third
|
||||
Name: TC
|
||||
Comment: textTC
|
||||
Moderated: 1
|
||||
IsSpam: 0
|
||||
BaseClass: CommentableItem
|
||||
thirdComD:
|
||||
ParentID: =>CommentableItem.third
|
||||
Parent: =>SilverStripe\Comments\Tests\Stubs\CommentableItem.third
|
||||
Name: TC
|
||||
Comment: textTC
|
||||
Moderated: 1
|
||||
BaseClass: CommentableItem
|
||||
thirdComE:
|
||||
ParentID: =>CommentableItem.third
|
||||
Parent: =>SilverStripe\Comments\Tests\Stubs\CommentableItem.third
|
||||
Name: TC
|
||||
Comment: textTC
|
||||
Moderated: 1
|
||||
BaseClass: CommentableItem
|
||||
thirdComF:
|
||||
ParentID: =>CommentableItem.third
|
||||
Parent: =>SilverStripe\Comments\Tests\Stubs\CommentableItem.third
|
||||
Name: TC
|
||||
Comment: textTC
|
||||
Moderated: 1
|
||||
IsSpam: 0
|
||||
BaseClass: CommentableItem
|
||||
thirdComG:
|
||||
ParentID: =>CommentableItem.third
|
||||
Parent: =>SilverStripe\Comments\Tests\Stubs\CommentableItem.third
|
||||
Name: TC
|
||||
Comment: textTC
|
||||
Moderated: 1
|
||||
IsSpam: 0
|
||||
BaseClass: CommentableItem
|
||||
thirdComH:
|
||||
ParentID: =>CommentableItem.third
|
||||
Parent: =>SilverStripe\Comments\Tests\Stubs\CommentableItem.third
|
||||
Name: TC
|
||||
Comment: textTC
|
||||
Moderated: 1
|
||||
IsSpam: 0
|
||||
BaseClass: CommentableItem
|
||||
thirdComI:
|
||||
ParentID: =>CommentableItem.third
|
||||
Parent: =>SilverStripe\Comments\Tests\Stubs\CommentableItem.third
|
||||
Name: TC
|
||||
Comment: textTC
|
||||
Moderated: 1
|
||||
IsSpam: 0
|
||||
BaseClass: CommentableItem
|
||||
thirdComJ:
|
||||
ParentID: =>CommentableItem.third
|
||||
Parent: =>SilverStripe\Comments\Tests\Stubs\CommentableItem.third
|
||||
Name: TC
|
||||
Comment: textTC
|
||||
Moderated: 1
|
||||
IsSpam: 0
|
||||
BaseClass: CommentableItem
|
||||
thirdComK:
|
||||
ParentID: =>CommentableItem.third
|
||||
Parent: =>SilverStripe\Comments\Tests\Stubs\CommentableItem.third
|
||||
Name: TC
|
||||
Comment: textTC
|
||||
Moderated: 1
|
||||
IsSpam: 0
|
||||
BaseClass: CommentableItem
|
||||
disabledCom:
|
||||
ParentID: =>CommentableItem.nocomments
|
||||
Parent: =>SilverStripe\Comments\Tests\Stubs\CommentableItem.nocomments
|
||||
Name: Disabled
|
||||
Moderated: 0
|
||||
IsSpam: 1
|
||||
BaseClass: CommentableItem
|
||||
testCommentList1:
|
||||
ParentID: =>CommentableItem.spammed
|
||||
Parent: =>SilverStripe\Comments\Tests\Stubs\CommentableItem.spammed
|
||||
Name: Comment 1
|
||||
Moderated: 0
|
||||
IsSpam: 0
|
||||
BaseClass: CommentableItem
|
||||
testCommentList2:
|
||||
ParentID: =>CommentableItem.spammed
|
||||
Parent: =>SilverStripe\Comments\Tests\Stubs\CommentableItem.spammed
|
||||
Name: Comment 2
|
||||
Moderated: 1
|
||||
IsSpam: 1
|
||||
BaseClass: CommentableItem
|
||||
testCommentList3:
|
||||
ParentID: =>CommentableItem.spammed
|
||||
Parent: =>SilverStripe\Comments\Tests\Stubs\CommentableItem.spammed
|
||||
Name: Comment 3
|
||||
Moderated: 1
|
||||
IsSpam: 0
|
||||
BaseClass: CommentableItem
|
||||
testCommentList4:
|
||||
ParentID: =>CommentableItem.spammed
|
||||
Parent: =>SilverStripe\Comments\Tests\Stubs\CommentableItem.spammed
|
||||
Name: Comment 4
|
||||
Moderated: 0
|
||||
IsSpam: 1
|
||||
BaseClass: CommentableItem
|
||||
testModeratedComment1:
|
||||
Parent: =>SilverStripe\Comments\Tests\Stubs\CommentableItem.moderated
|
||||
Name: Moderated comment 1
|
||||
Moderated: 0
|
||||
IsSpam: 0
|
||||
testModeratedComment2:
|
||||
Parent: =>SilverStripe\Comments\Tests\Stubs\CommentableItem.moderated
|
||||
Name: Moderated comment 2
|
||||
Moderated: 0
|
||||
IsSpam: 1
|
||||
|
62
tests/Stubs/CommentableItem.php
Normal file
62
tests/Stubs/CommentableItem.php
Normal file
@ -0,0 +1,62 @@
|
||||
<?php
|
||||
|
||||
namespace SilverStripe\Comments\Tests\Stubs;
|
||||
|
||||
use SilverStripe\Comments\Extensions\CommentsExtension;
|
||||
use SilverStripe\Control\Director;
|
||||
use SilverStripe\Dev\TestOnly;
|
||||
use SilverStripe\ORM\DataObject;
|
||||
use SilverStripe\Security\Member;
|
||||
use SilverStripe\Security\Permission;
|
||||
|
||||
/**
|
||||
* @package comments
|
||||
* @subpackage tests
|
||||
*/
|
||||
class CommentableItem extends DataObject implements TestOnly
|
||||
{
|
||||
private static $db = array(
|
||||
'Title' => 'Varchar'
|
||||
);
|
||||
|
||||
private static $extensions = array(
|
||||
CommentsExtension::class
|
||||
);
|
||||
|
||||
public function RelativeLink()
|
||||
{
|
||||
return 'CommentableItemController';
|
||||
}
|
||||
|
||||
public function canView($member = null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// This is needed for canModerateComments
|
||||
public function canEdit($member = null)
|
||||
{
|
||||
if ($member instanceof Member) {
|
||||
$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;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public function Link()
|
||||
{
|
||||
return $this->RelativeLink();
|
||||
}
|
||||
|
||||
public function AbsoluteLink()
|
||||
{
|
||||
return Director::absoluteURL($this->RelativeLink());
|
||||
}
|
||||
}
|
19
tests/Stubs/CommentableItemController.php
Normal file
19
tests/Stubs/CommentableItemController.php
Normal file
@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace SilverStripe\Comments\Tests\Stubs;
|
||||
|
||||
use SilverStripe\Comments\Tests\Stubs\CommentableItem;
|
||||
use SilverStripe\Control\Controller;
|
||||
use SilverStripe\Dev\TestOnly;
|
||||
|
||||
/**
|
||||
* @package comments
|
||||
* @subpackage tests
|
||||
*/
|
||||
class CommentableItemController extends Controller implements TestOnly
|
||||
{
|
||||
public function index()
|
||||
{
|
||||
return CommentableItem::get()->first()->CommentsForm();
|
||||
}
|
||||
}
|
14
tests/Stubs/CommentableItemDisabled.php
Normal file
14
tests/Stubs/CommentableItemDisabled.php
Normal file
@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
namespace SilverStripe\Comments\Tests\Stubs;
|
||||
|
||||
use SilverStripe\Comments\Tests\Stubs\CommentableItem;
|
||||
|
||||
class CommentableItemDisabled extends CommentableItem
|
||||
{
|
||||
private static $defaults = array(
|
||||
'ProvideComments' => false,
|
||||
'ModerationRequired' => 'None',
|
||||
'CommentsRequireLogin' => false
|
||||
);
|
||||
}
|
14
tests/Stubs/CommentableItemEnabled.php
Normal file
14
tests/Stubs/CommentableItemEnabled.php
Normal file
@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
namespace SilverStripe\Comments\Tests\Stubs;
|
||||
|
||||
use SilverStripe\Comments\Tests\Stubs\CommentableItem;
|
||||
|
||||
class CommentableItemEnabled extends CommentableItem
|
||||
{
|
||||
private static $defaults = array(
|
||||
'ProvideComments' => true,
|
||||
'ModerationRequired' => 'Required',
|
||||
'CommentsRequireLogin' => true
|
||||
);
|
||||
}
|
Loading…
Reference in New Issue
Block a user