mirror of
https://github.com/silverstripe/silverstripe-spamprotection.git
synced 2024-10-22 14:05:59 +02:00
API: Use config / extension APIs
Overhaul of spam protection to use an extension on Form rather than the SpamProtectorManager. More fluent interface and easier to replace the built in spam protection api with an alternative.
This commit is contained in:
parent
28b57beb37
commit
440e30b611
@ -1,8 +0,0 @@
|
||||
0.1:
|
||||
- initial release
|
||||
|
||||
0.2
|
||||
- Renamed 'SpamProtecterManager' to 'SpamProtectorManager'. Note the typo with the 'er'
|
||||
|
||||
0.3 (trunk)
|
||||
- Updated Error Reporting to be a bit more verbose
|
106
README.md
106
README.md
@ -14,12 +14,108 @@ SilverStripe 3.0.0 or greater
|
||||
|
||||
## Documentation
|
||||
|
||||
See docs/
|
||||
This module provides a generic, consistent API for adding spam protection to
|
||||
your SilverStripe Forms. This does not provide any spam protection out of the
|
||||
box, for that, you must also download one of the spam protection
|
||||
implementations. Currently available options are:
|
||||
|
||||
## Installation Instructions
|
||||
* [Mollom](https://github.com/silverstripe/silverstripe-mollom)
|
||||
* [Recaptcha](https://github.com/chillu/silverstripe-recaptcha)
|
||||
* [MathSpamProtection](https://github.com/silverstripe/silverstripe-mathspamprotection)
|
||||
|
||||
See docs/Install
|
||||
As a developer you can also provide your own protector by creating a class which
|
||||
implements the `SpamProtector` interface. More on that below.
|
||||
|
||||
## Usage Overview
|
||||
## Configuring
|
||||
|
||||
See docs/Install
|
||||
After installing this module and a protector of your choice (i.e mollom) you'll
|
||||
need to rebuild your database through `dev/build` and set the default protector
|
||||
via SilverStripe's config system. This will update any Form instances that have
|
||||
spam protection hooks with that protector.
|
||||
|
||||
*mysite/_config/spamprotection.yml*
|
||||
|
||||
---
|
||||
name: spamprotection
|
||||
---
|
||||
FormSpamProtectionExtension:
|
||||
default_spam_protector: MollomSpamProtector
|
||||
|
||||
To add spam protection to your form instance call `enableSpamProtection`.
|
||||
|
||||
// your existing form code
|
||||
$form = new Form( .. );
|
||||
$form->enableSpamProtection();
|
||||
|
||||
The logic to perform the actual spam validation is controlled by each of the
|
||||
individual `SpamProtector` implementation since they each require a different
|
||||
implementation client side or server side.
|
||||
|
||||
### Options
|
||||
|
||||
`enableSpamProtection` takes a hash of optional configuration values.
|
||||
|
||||
$form->enableSpamProtection(array(
|
||||
'protector' => 'MathSpamProtector',
|
||||
'name' => 'Captcha'
|
||||
));
|
||||
|
||||
Options to configure are:
|
||||
|
||||
*`protector`* a class name string or class instance which implements
|
||||
`SpamProtector`. Defaults to your
|
||||
`FormSpamProtectionExtension.default_spam_protector` value.
|
||||
|
||||
*`name`* the form field name argument for the Captcha. Defaults to `Catcha`.
|
||||
*`title`* title of the Captcha form field. Defaults to `''`
|
||||
*`mapping`* an array mapping of the Form fields to the standardized list of
|
||||
field names. The list of standardized fields to pass to the spam protector are:
|
||||
|
||||
title
|
||||
body
|
||||
contextUrl
|
||||
contextTitle
|
||||
authorName
|
||||
authorMail
|
||||
authorUrl
|
||||
authorIp
|
||||
authorId
|
||||
|
||||
## Defining your own `SpamProtector`
|
||||
|
||||
Any class that implements `SpamProtector` and the `getFormField()` method can
|
||||
be set as the spam protector. The `getFormField()` method returns the
|
||||
`FormField` to be inserted into the `Form`. The `FormField` returned should be
|
||||
in charge of the validation process.
|
||||
|
||||
<?php
|
||||
|
||||
class CustomSpamProtector implements SpamProtector {
|
||||
|
||||
public function getFormField($name = null, $title = null, $value = null) {
|
||||
// CaptchaField is a imagined class which has some functionality.
|
||||
// See silverstripe-mollom module for an example.
|
||||
return new CaptchaField($name, $title, $value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
## Using Spam Protection with User Forms
|
||||
|
||||
This module provides an EditableSpamProtectionField wrapper which you can add
|
||||
to your UserForm instances. After installing this module and running /dev/build
|
||||
to rebuild the database, your Form Builder interface will have an option for
|
||||
`Spam Protection Field`. The type of spam protection used will be based on your
|
||||
currently selected SpamProtector instance.
|
||||
|
||||
## Releasing code with Spam Protection support
|
||||
|
||||
Spam protection is useful to provide but in some cases we do not want to require
|
||||
the developer to use spam protection. In that case, modules can provide the
|
||||
following pattern
|
||||
|
||||
$form = new Form(..);
|
||||
|
||||
if($form->hasExtension('FormSpamProtectionExtension')) {
|
||||
$form->enableSpamProtection();
|
||||
}
|
||||
|
10
_config.php
10
_config.php
@ -8,12 +8,4 @@
|
||||
*
|
||||
* @package spamprotection
|
||||
*/
|
||||
|
||||
/**
|
||||
* If the comments module is installed then add the spam protection module
|
||||
* to the comments form via this extension.
|
||||
*
|
||||
* Place this line in your mysite/_config.php
|
||||
*/
|
||||
|
||||
// CommentingController::add_extension('CommentSpamProtection');
|
||||
Deprecation::notification_version('1.1', 'spamprotection');
|
6
_config/spamprotection.yml
Normal file
6
_config/spamprotection.yml
Normal file
@ -0,0 +1,6 @@
|
||||
---
|
||||
name: spamprotection
|
||||
---
|
||||
Form:
|
||||
extensions:
|
||||
- FormSpamProtectionExtension
|
@ -6,30 +6,29 @@
|
||||
*
|
||||
* @package spamprotection
|
||||
*/
|
||||
if(class_exists('EditableFormField')){
|
||||
if(class_exists('EditableFormField')) {
|
||||
|
||||
class EditableSpamProtectionField extends EditableFormField {
|
||||
|
||||
static $singular_name = 'Spam Protection Field';
|
||||
|
||||
static $plural_name = 'Spam Protection Fields';
|
||||
|
||||
function getFormField() {
|
||||
if($protector = SpamProtectorManager::get_spam_protector()) {
|
||||
if($protector) {
|
||||
$protector = new $protector();
|
||||
public function getFormField() {
|
||||
if($protector = Config::inst()->get('FormSpamProtectionExtension', 'default_spam_protector')) {
|
||||
$protector = Injector::inst()->create($protector);
|
||||
|
||||
return $protector->getFormField($this->Name, $this->Title, null);
|
||||
}
|
||||
return $protector->getFormField($this->Name, $this->Title, null);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function getFieldValidationOptions() {
|
||||
public function getFieldValidationOptions() {
|
||||
return new FieldList();
|
||||
}
|
||||
|
||||
function getRequired() {
|
||||
public function getRequired() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -37,7 +36,7 @@ if(class_exists('EditableFormField')){
|
||||
return 'spamprotection/images/' . strtolower($this->class) . '.png';
|
||||
}
|
||||
|
||||
function showInReports() {
|
||||
public function showInReports() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -1,23 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Spam Protector base interface. All Protectors should implement this interface
|
||||
* to ensure that they contain all the correct methods.
|
||||
*
|
||||
* @package spamprotection
|
||||
*/
|
||||
|
||||
interface SpamProtector {
|
||||
|
||||
/**
|
||||
* Return the Field Associated with this protector
|
||||
*/
|
||||
public function getFormField($name = null, $title = null, $value = null, $form = null, $rightTitle = null);
|
||||
|
||||
/**
|
||||
* Function required to handle dynamic feedback of the system.
|
||||
* if unneeded just return true
|
||||
*/
|
||||
public function sendFeedback($object = null, $feedback = "");
|
||||
|
||||
}
|
@ -1,34 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* This class acts as a template for spam protecting form field, for instance MollomField.
|
||||
*
|
||||
* @package spamprotection
|
||||
*/
|
||||
abstract class SpamProtectorField extends FormField {
|
||||
|
||||
/**
|
||||
* Fields to map spam protection too.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $spamFieldMapping = array();
|
||||
|
||||
|
||||
/**
|
||||
* Set the fields to map spam protection too
|
||||
*
|
||||
* @param Array array of Field Names, where the indexes of the array are the field names of the form and the values are the field names of the spam/captcha service
|
||||
*/
|
||||
public function setFieldMapping($array) {
|
||||
$this->spamFieldMapping = $array;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the fields that are mapped via spam protection
|
||||
*
|
||||
* @return Array
|
||||
*/
|
||||
public function getFieldMapping() {
|
||||
return $this->spamFieldMapping;
|
||||
}
|
||||
}
|
@ -1,97 +1,38 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This class is responsible for setting an system-wide spam protector field
|
||||
* and add the protecter field to a form.
|
||||
*
|
||||
* @package spamprotection
|
||||
*
|
||||
* @deprecated 1.0
|
||||
*/
|
||||
|
||||
class SpamProtectorManager {
|
||||
|
||||
/**
|
||||
* Current Spam Protector used on the site
|
||||
*
|
||||
* @var SpamProtector
|
||||
*/
|
||||
private static $spam_protector = null;
|
||||
|
||||
/**
|
||||
* Set the name of the spam protecter class
|
||||
*
|
||||
* @param String the name of protecter field class
|
||||
*/
|
||||
|
||||
public static function set_spam_protector($protector) {
|
||||
Deprecation::notice('1.1',
|
||||
'SpamProtectorManager::set_spam_protector() is deprecated. '.
|
||||
'Use the new config system. FormSpamProtectorExtension.default_spam_protector'
|
||||
);
|
||||
|
||||
self::$spam_protector = $protector;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the name of the spam protector class
|
||||
*/
|
||||
|
||||
public static function get_spam_protector() {
|
||||
Deprecation::notice('1.1',
|
||||
'SpamProtectorManager::get_spam_protector() is deprecated'.
|
||||
'Use the new config system. FormSpamProtectorExtension.default_spam_protector');
|
||||
|
||||
return self::$spam_protector;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the spam protector field to a form
|
||||
* @param Form the form that the protecter field added into
|
||||
* @param string the name of the field that the protecter field will be added in front of
|
||||
* @param array an associative array
|
||||
* with the name of the spam web service's field, for example post_title, post_body, author_name
|
||||
* and a string of field names
|
||||
* @param String Title for the captcha field
|
||||
* @param String RightTitle for the captcha field
|
||||
* @return SpamProtector object on success or null if the spamprotector class is not found
|
||||
* also null if spamprotectorfield creation fails.
|
||||
*/
|
||||
static function update_form($form, $before = null, $fieldsToSpamServiceMapping = array(), $title = null, $rightTitle = null) {
|
||||
$protectorClass = self::get_spam_protector();
|
||||
|
||||
// Don't update if no protector is set
|
||||
if(!$protectorClass) return false;
|
||||
|
||||
if(!class_exists($protectorClass)) {
|
||||
return user_error("Spam Protector class '$protectorClass' does not exist. Please define a valid Spam Protector", E_USER_WARNING);
|
||||
}
|
||||
|
||||
try {
|
||||
$protector = new $protectorClass();
|
||||
$field = $protector->getFormField("Captcha", $title, null);
|
||||
$field->setForm($form);
|
||||
if ($rightTitle) $field->setRightTitle($rightTitle);
|
||||
|
||||
if($field) {
|
||||
// update the mapping
|
||||
$field->setFieldMapping($fieldsToSpamServiceMapping);
|
||||
|
||||
// add the form field
|
||||
if($before && $form->Fields()->fieldByName($before)) {
|
||||
$form->Fields()->insertBefore($field, $before);
|
||||
}
|
||||
else {
|
||||
$form->Fields()->push($field);
|
||||
}
|
||||
}
|
||||
|
||||
} catch (Exception $e) {
|
||||
return user_error("SpamProtectorManager::update_form(): '$protectorClass' is not correctly set up. " . $e, E_USER_WARNING);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Send Feedback to the Spam Protection. The level of feedback
|
||||
* will depend on the Protector class.
|
||||
*
|
||||
* @param DataObject The Object which you want to send feedback about. Must have a
|
||||
* SessionID field.
|
||||
* @param String Feedback on the $object usually 'spam' or 'ham' for non spam entries
|
||||
*/
|
||||
static function send_feedback($object, $feedback) {
|
||||
$protectorClass = self::get_spam_protector();
|
||||
|
||||
if(!$protectorClass) return false;
|
||||
|
||||
$protector = new $protectorClass();
|
||||
return $protector->sendFeedback($object, $feedback);
|
||||
public static function update_form($form, $before = null, $fieldsToSpamServiceMapping = array(), $title = null, $rightTitle = null) {
|
||||
Deprecation::notice('1.1',
|
||||
'SpamProtectorManager::update_form is deprecated'.
|
||||
'Please use $form->enableSpamProtection() for adding spamprotection'
|
||||
);
|
||||
|
||||
return $form->enableSpamProtection();
|
||||
}
|
||||
}
|
@ -1,23 +1,26 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Apply the spam protection to the comments module if it is installed
|
||||
* Apply the spam protection to the comments module if it is installed.
|
||||
*
|
||||
* @package spamprotection
|
||||
*/
|
||||
|
||||
class CommentSpamProtection extends Extension {
|
||||
|
||||
/**
|
||||
* Disable the AJAX commenting and update the form
|
||||
* with the {@link SpamProtectorField} which is enabled
|
||||
*/
|
||||
public function alterCommentForm(&$form) {
|
||||
SpamProtectorManager::update_form($form, null, array(
|
||||
'Name' => 'author_name',
|
||||
'URL' => 'author_url',
|
||||
'Comment' => 'post_body',
|
||||
'Email' => 'author_mail'
|
||||
$form->enableSpamProtection(array(
|
||||
'mapping' => array(
|
||||
'Name' => 'authorName',
|
||||
'Email' => 'authorEmail',
|
||||
'URL' => 'authorUrl',
|
||||
'Comment' => 'body',
|
||||
'ReturnURL' => 'contextUrl'
|
||||
),
|
||||
'checks' => array(
|
||||
'spam',
|
||||
'profanity'
|
||||
)
|
||||
));
|
||||
}
|
||||
}
|
||||
|
117
code/extensions/FormSpamProtectionExtension.php
Normal file
117
code/extensions/FormSpamProtectionExtension.php
Normal file
@ -0,0 +1,117 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* An extension to the {@link Form} class which provides the method
|
||||
* {@link enableSpamProtection()} helper.
|
||||
*
|
||||
* @package spamprotection
|
||||
*/
|
||||
|
||||
class FormSpamProtectionExtension extends Extension {
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $fieldMapping = array();
|
||||
|
||||
/**
|
||||
* @config
|
||||
*
|
||||
* The default spam protector class name to use. Class should implement the
|
||||
* {@link SpamProtector} interface.
|
||||
*
|
||||
* @var string $spam_protector
|
||||
*/
|
||||
private static $default_spam_protector;
|
||||
|
||||
/**
|
||||
* @config
|
||||
*
|
||||
* The {@link enableSpamProtection} method will define which of the form
|
||||
* values correlates to this form mapped fields list. Totally custom forms
|
||||
* and subclassed SpamProtector instances are define their own mapping
|
||||
*
|
||||
* @var array $mappable_fields
|
||||
*/
|
||||
private static $mappable_fields = array(
|
||||
'title',
|
||||
'body',
|
||||
'contextUrl',
|
||||
'contextTitle',
|
||||
'authorName',
|
||||
'authorMail',
|
||||
'authorUrl',
|
||||
'authorIp',
|
||||
'authorId'
|
||||
);
|
||||
|
||||
/**
|
||||
* Activates the spam protection module.
|
||||
*
|
||||
* @param array $options
|
||||
*/
|
||||
public function enableSpamProtection($options = array()) {
|
||||
// generate the spam protector
|
||||
if(isset($options['protector'])) {
|
||||
$protector = $options['protector'];
|
||||
|
||||
if(is_string($protector)) {
|
||||
$protector = Injector::inst()->create($protector);
|
||||
}
|
||||
} else {
|
||||
$protector = Config::inst()->get('FormSpamProtectionExtension', 'default_spam_protector');
|
||||
$protector = Injector::inst()->create($protector);
|
||||
}
|
||||
|
||||
// captcha form field name (must be unique)
|
||||
if(isset($options['name'])) {
|
||||
$name = $options['name'];
|
||||
} else {
|
||||
$name = 'Captcha';
|
||||
}
|
||||
|
||||
// captcha field title
|
||||
if(isset($options['title'])) {
|
||||
$title = $options['title'];
|
||||
} else {
|
||||
$title = '';
|
||||
}
|
||||
|
||||
// set custom mapping on this form
|
||||
if(isset($options['mapping'])) {
|
||||
$this->fieldMapping = $options['mapping'];
|
||||
}
|
||||
|
||||
// add the form field
|
||||
if($field = $protector->getFormField($name, $title)) {
|
||||
$this->owner->Fields()->push($field);
|
||||
}
|
||||
|
||||
return $this->owner;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function hasSpamProtectionMapping() {
|
||||
return ($this->fieldMapping);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getSpamMappedData() {
|
||||
if($this->fieldMapping) {
|
||||
$result = array();
|
||||
$data = $this->owner->getData();
|
||||
|
||||
foreach($this->fieldMapping as $fieldName => $mappedName) {
|
||||
$result[$mappedName] = (isset($data[$fieldName])) ? $data[$fieldName] : null;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
30
code/interfaces/SpamProtector.php
Normal file
30
code/interfaces/SpamProtector.php
Normal file
@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* SpamProtector base interface.
|
||||
*
|
||||
* All Protectors are required implement this interface if they want to appear
|
||||
* on the form.
|
||||
*
|
||||
* Classes with this interface are used to generate helper lists to allow the
|
||||
* user to select the protector.
|
||||
*
|
||||
* @package spamprotection
|
||||
*/
|
||||
|
||||
interface SpamProtector {
|
||||
|
||||
/**
|
||||
* Return the {@link FormField} associated with this protector.
|
||||
*
|
||||
* Most spam methods will simply return a piece of HTML to be injected at
|
||||
* the end of the form. If a spam method needs to inject more than one
|
||||
* form field (i.e a hidden field and a text field) then return a
|
||||
* {@link FieldGroup} from this method to include both.
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $title
|
||||
* @param mixed $value
|
||||
*/
|
||||
public function getFormField($name = null, $title = null, $value = null);
|
||||
}
|
@ -1,41 +0,0 @@
|
||||
# Spam Protection Module Installation
|
||||
|
||||
## Install
|
||||
|
||||
1. Unzip this file (spamprotection-0.3.tar.gz) inside your SilverStripe installation directory.
|
||||
It should be at the same level as the 'cms' and 'framework' modules.
|
||||
|
||||
2. Ensure the directory name for the module is 'spamprotection'.
|
||||
|
||||
3. Visit your SilverStripe site in a webbrowser and run www.yoursite.com/dev/build
|
||||
|
||||
5. We now need to setup some basic features to get the module up and running. Open up _config.php
|
||||
inside project directory (typically 'mysite/_config.php') with your favourite text editor.
|
||||
Read the instructions below to setup the initial configuration of the module.
|
||||
|
||||
|
||||
## Configuring
|
||||
|
||||
Before putting the following code in '_config.php', make sure you have a additional protector class installed.
|
||||
The SpamProtector module only provides the backbone. To make use of the module you have to have an additional protector
|
||||
such as Mollom or Recaptcha. Both of these modules can be downloaded off the SilverStripe.org website.
|
||||
|
||||
SpamProtectorManager::set_spam_protector('MollomSpamProtector');
|
||||
|
||||
|
||||
## Updating a form to include Spam Protection
|
||||
|
||||
This following code should appear after the form creation.
|
||||
|
||||
// your existing form code here...
|
||||
$form = new Form( .. );
|
||||
|
||||
// add this line
|
||||
$protector = SpamProtectorManager::update_form($form, 'Message');
|
||||
|
||||
This code add an instance of a 'SpamProtectorField' class specified in SETTING UP THE MODULE section. The newly created field will have
|
||||
MollomField field. The first parameter is a Form object in which the field will be added into and the second parameter tells
|
||||
SpamProtectorManagor to place the new field before a field named 'Message'.
|
||||
|
||||
|
||||
## Using Spam Protection with User Forms
|
@ -1,16 +0,0 @@
|
||||
<?php
|
||||
|
||||
global $lang;
|
||||
|
||||
$lang['en_US']['EditableSpamProtectionField']['PLURALNAME'] = array(
|
||||
'Spam Protection Fields',
|
||||
50,
|
||||
'Pural name of the object, used in dropdowns and to generally identify a collection of this object in the interface'
|
||||
);
|
||||
$lang['en_US']['EditableSpamProtectionField']['SINGULARNAME'] = array(
|
||||
'Spam Protection Field',
|
||||
50,
|
||||
'Singular name of the object, used in dropdowns and to generally identify a single object in the interface'
|
||||
);
|
||||
|
||||
?>
|
Loading…
Reference in New Issue
Block a user