Merge pull request #51 from Firesphere/master

SilverStripe 4 and Namespacing
This commit is contained in:
Franco Springveldt 2017-09-05 09:29:33 +12:00 committed by GitHub
commit 42c733061d
32 changed files with 558 additions and 395 deletions

1
.gitattributes vendored
View File

@ -4,3 +4,4 @@
/.gitignore export-ignore
/.travis.yml export-ignore
/.scrutinizer.yml export-ignore
/codecov.yml export-ignore

View File

@ -1,33 +1,31 @@
# See https://github.com/silverstripe/silverstripe-travis-support for setup details
sudo: false
language: php
php:
- 5.3
- 5.4
- 5.5
env:
- DB=MYSQL CORE_RELEASE=3.5
global:
- COMPOSER_ROOT_VERSION="4.0.x-dev"
matrix:
include:
- php: 5.6
env: DB=MYSQL CORE_RELEASE=3
- php: 5.6
env: DB=MYSQL CORE_RELEASE=3.1
- php: 5.6
env: DB=PGSQL CORE_RELEASE=3.2
env: DB=MYSQL PHPCS_TEST=1 PHPUNIT_TEST=1
- php: 7.0
env: DB=PGSQL PHPUNIT_TEST=1
- php: 7.1
env: DB=MYSQL CORE_RELEASE=3.6
env: DB=MYSQL PHPUNIT_COVERAGE_TEST=1
before_script:
- composer self-update || true
- git clone git://github.com/silverstripe/silverstripe-travis-support.git ~/travis-support
- php ~/travis-support/travis_setup.php --source `pwd` --target ~/builds/ss --require silverstripe/userforms
- cd ~/builds/ss
- phpenv rehash
- phpenv config-rm xdebug.ini
- composer install --prefer-dist
- composer require --prefer-dist --no-update silverstripe/framework:4.0.x-dev
- if [[ $DB == PGSQL ]]; then composer require --prefer-dist --no-update silverstripe/postgresql:2.0.x-dev; fi
- composer update
script:
- vendor/bin/phpunit spamprotection/tests
- if [[ $PHPUNIT_TEST ]]; then vendor/bin/phpunit tests/; fi
- if [[ $PHPUNIT_COVERAGE_TEST ]]; then phpdbg -qrr vendor/bin/phpunit --coverage-clover=coverage.xml; fi
- if [[ $PHPCS_TEST ]]; then vendor/bin/phpcs --standard=framework/phpcs.xml.dist code/ tests/ ; fi
after_success:
- if [[ $PHPUNIT_COVERAGE_TEST ]]; then bash <(curl -s https://codecov.io/bash) -f coverage.xml; fi

11
.upgrade.yml Normal file
View File

@ -0,0 +1,11 @@
mappings:
SpamProtector: SilverStripe\SpamProtection\SpamProtector
CommentSpamProtection: SilverStripe\SpamProtection\Extension\CommentSpamProtection
EditableSpamProtectionField: SilverStripe\SpamProtection\EditableSpamProtectionField
FormSpamProtectionExtension: SilverStripe\SpamProtection\Extension\FormSpamProtectionExtension
EditableSpamProtectionFieldTest: SilverStripe\SpamProtection\Tests\EditableSpamProtectionFieldTest
EditableSpamProtectionFieldTest_Protector: SilverStripe\SpamProtection\Tests\Stub\Protector
FormSpamProtectionExtensionTest: SilverStripe\SpamProtection\Tests\FormSpamProtectionExtensionTest
FormSpamProtectionExtensionTest_BarProtector: SilverStripe\SpamProtection\Tests\Stub\BarProtector
FormSpamProtectionExtensionTest_BazProtector: SilverStripe\SpamProtection\Tests\Stub\BazProtector
FormSpamProtectionExtensionTest_FooProtector: SilverStripe\SpamProtection\Tests\Stub\FooProtector

127
README.md
View File

@ -1,8 +1,7 @@
# SpamProtection Module
[![Build Status](https://secure.travis-ci.org/silverstripe/silverstripe-spamprotection.png?branch=master)](http://travis-ci.org/silverstripe/silverstripe-spamprotection)
![helpfulrobot](https://helpfulrobot.io/silverstripe/spamprotection/badge)
[![Code Coverage](https://codecov.io/gh/silverstripe/silverstripe-spamprotection/branch/master/graph/badge.svg)](https://codecov.io/gh/silverstripe/silverstripe-spamprotection)
## Maintainer Contact
@ -14,13 +13,13 @@
## Requirements
SilverStripe 3.0.0 or greater
SilverStripe 4.0 or greater
## Documentation
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
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:
* [Mollom](https://github.com/silverstripe/silverstripe-mollom)
@ -33,95 +32,113 @@ implements the `SpamProtector` interface. More on that below.
## Configuring
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
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
```yaml
---
name: spamprotection
---
SilverStripe\SpamProtection\Extension\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
```php
// 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.
`enableSpamProtection` takes a hash of optional configuration values.
$form->enableSpamProtection(array(
'protector' => 'MathSpamProtector',
'name' => 'Captcha'
));
```php
$form->enableSpamProtection(array(
'protector' => MathSpamProtector::class,
'name' => 'Captcha'
));
```
Options to configure are:
*`protector`* a class name string or class instance which implements
`SpamProtector`. Defaults to your
*`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 `''`
*`insertBefore`* name of existing field to insert the spam protection field prior to
*`mapping`* an array mapping of the Form fields to the standardized list of
*`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
```
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
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
```php
<?php
class CustomSpamProtector implements SpamProtector {
use CaptchaField;
use SilverStripe\SpamProtection\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);
}
class CustomSpamProtector implements SpamProtector
{
public function getFormField($name = null, $title = null, $value = null)
{
// CaptchaField is an 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
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
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(..);
```php
use SilverStripe\Forms\Form;
use SilverStripe\SpamProtection\Extension\FormSpamProtectionExtension;
if($form->hasExtension('FormSpamProtectionExtension')) {
$form->enableSpamProtection();
}
$form = new Form(/* .. */);
if ($form->hasExtension(FormSpamProtectionExtension::class)) {
$form->enableSpamProtection();
}
```

View File

@ -8,4 +8,7 @@
*
* @package spamprotection
*/
Deprecation::notification_version('1.1', 'spamprotection');
use SilverStripe\Dev\Deprecation;
Deprecation::notification_version('3.0', 'spamprotection');

View File

@ -1,6 +1,6 @@
---
name: spamprotection
Name: spamprotection
---
Form:
SilverStripe\Forms\Form:
extensions:
- FormSpamProtectionExtension
- SilverStripe\SpamProtection\Extension\FormSpamProtectionExtension

View File

@ -1,258 +1,273 @@
<?php
namespace SilverStripe\SpamProtection;
use SilverStripe\Core\ClassInfo;
use SilverStripe\Core\Convert;
use SilverStripe\Forms\DropdownField;
use SilverStripe\Forms\FieldGroup;
use SilverStripe\Forms\FieldList;
use SilverStripe\Forms\FormField;
use SilverStripe\ORM\UnsavedRelationList;
use SilverStripe\SpamProtection\Extension\FormSpamProtectionExtension;
use SilverStripe\UserForms\Model\EditableFormField;
use SilverStripe\UserForms\Model\EditableFormField\EditableEmailField;
use SilverStripe\UserForms\Model\EditableFormField\EditableNumericField;
use SilverStripe\UserForms\Model\EditableFormField\EditableTextField;
/**
* @todo The userforms namespaces may still change, as the branch is not merged in yet
*/
if (!class_exists(EditableFormField::class)) {
return;
}
/**
* Editable Spam Protecter Field. Used with the User Defined Forms module (if
* installed) to allow the user to have captcha fields with their custom forms
*
* @package spamprotection
*/
if (class_exists('EditableFormField')) {
class EditableSpamProtectionField extends EditableFormField
class EditableSpamProtectionField extends EditableFormField
{
private static $singular_name = 'Spam Protection Field';
private static $plural_name = 'Spam Protection Fields';
private static $table_name = 'EditableSpamProtectionField';
/**
* Fields to include spam detection for
*
* @var array
* @config
*/
private static $check_fields = array(
EditableEmailField::class,
EditableTextField::class,
EditableNumericField::class
);
private static $db = array(
'SpamFieldSettings' => 'Text'
);
/**
* @var FormField
*/
protected $formField = null;
public function getFormField()
{
private static $singular_name = 'Spam Protection Field';
private static $plural_name = 'Spam Protection Fields';
/**
* Fields to include spam detection for
*
* @var array
* @config
*/
private static $check_fields = array(
'EditableEmailField',
'EditableTextField',
'EditableNumericField'
);
private static $db = array(
'SpamFieldSettings' => 'Text'
);
/**
* @var FormField
*/
protected $formField = null;
public function getFormField()
{
if ($this->formField) {
return $this->formField;
}
// Get protector
$protector = FormSpamProtectionExtension::get_protector();
if (!$protector) {
return false;
}
// Extract saved field mappings and update this field.
$fieldMapping = array();
foreach ($this->getCandidateFields() as $otherField) {
$mapSetting = "Map-{$otherField->Name}";
$spamField = $this->spamMapValue($mapSetting);
$fieldMapping[$otherField->Name] = $spamField;
}
$protector->setFieldMapping($fieldMapping);
// Generate field
return $protector->getFormField($this->Name, $this->Title, null);
if ($this->formField) {
return $this->formField;
}
/**
* @param FormField $field
* @return self
*/
public function setFormField(FormField $field)
{
$this->formField = $field;
return $this;
// Get protector
$protector = FormSpamProtectionExtension::get_protector();
if (!$protector) {
return false;
}
/**
* Gets the list of all candidate spam detectable fields on this field's form
*
* @return DataList
*/
protected function getCandidateFields()
{
// Extract saved field mappings and update this field.
$fieldMapping = array();
foreach ($this->getCandidateFields() as $otherField) {
$mapSetting = "Map-{$otherField->Name}";
$spamField = $this->spamMapValue($mapSetting);
$fieldMapping[$otherField->Name] = $spamField;
}
$protector->setFieldMapping($fieldMapping);
// Get list of all configured classes available for spam detection
$types = self::config()->check_fields;
$typesInherit = array();
foreach ($types as $type) {
$subTypes = ClassInfo::subclassesFor($type);
$typesInherit = array_merge($typesInherit, $subTypes);
}
// Generate field
return $protector->getFormField($this->Name, $this->Title, null);
}
// Get all candidates of the above types
return $this
->Parent()
->Fields()
->filter('ClassName', $typesInherit)
->exclude('Title', ''); // Ignore this field and those without titles
/**
* @param FormField $field
* @return self
*/
public function setFormField(FormField $field)
{
$this->formField = $field;
return $this;
}
/**
* Gets the list of all candidate spam detectable fields on this field's form
*
* @return DataList
*/
protected function getCandidateFields()
{
// Get list of all configured classes available for spam detection
$types = $this->config()->get('check_fields');
$typesInherit = array();
foreach ($types as $type) {
$subTypes = ClassInfo::subclassesFor($type);
$typesInherit = array_merge($typesInherit, $subTypes);
}
/**
* This method is in place for userforms 2.x
*
* @deprecated 3.0 Please use {@link getCMSFields()} instead
*/
public function getFieldConfiguration()
{
return $this->getCMSFields();
// Get all candidates of the above types
return $this
->Parent()
->Fields()
->filter('ClassName', $typesInherit)
->exclude('Title', ''); // Ignore this field and those without titles
}
/**
* Write the spam field mapping values to a serialised DB field
*
* {@inheritDoc}
*/
public function onBeforeWrite()
{
$fieldMap = Convert::json2array($this->SpamFieldSettings);
if (empty($fieldMap)) {
$fieldMap = array();
}
/**
* Write the spam field mapping values to a serialised DB field
*
* {@inheritDoc}
*/
public function onBeforeWrite()
{
$fieldMap = Convert::json2array($this->SpamFieldSettings);
if (empty($fieldMap)) {
$fieldMap = array();
foreach ($this->record as $key => $value) {
if (substr($key, 0, 8) === 'spammap-') {
$fieldMap[substr($key, 8)] = $value;
}
foreach ($this->record as $key => $value) {
if (substr($key, 0, 8) === 'spammap-') {
$fieldMap[substr($key, 8)] = $value;
}
}
$this->setField('SpamFieldSettings', Convert::raw2json($fieldMap));
return parent::onBeforeWrite();
}
$this->setField('SpamFieldSettings', Convert::raw2json($fieldMap));
/**
* Used in userforms 3.x and above
*
* {@inheritDoc}
*/
public function getCMSFields()
{
/** @var FieldList $fields */
$fields = parent::getCMSFields();
return parent::onBeforeWrite();
}
// Get protector
$protector = FormSpamProtectionExtension::get_protector();
if (!$protector) {
return $fields;
}
if ($this->Parent()->Fields() instanceof UnsavedRelationList) {
return $fields;
}
// Each other text field in this group can be assigned a field mapping
$mapGroup = FieldGroup::create()
->setTitle(_t('EditableSpamProtectionField.SPAMFIELDMAPPING', 'Spam Field Mapping'))
->setName('SpamFieldMapping')
->setDescription(_t(
'EditableSpamProtectionField.SPAMFIELDMAPPINGDESCRIPTION',
'Select the form fields that correspond to any relevant spam protection identifiers'
));
// Generate field specific settings
$mappableFields = Config::inst()->get('FormSpamProtectionExtension', 'mappable_fields');
$mappableFieldsMerged = array_combine($mappableFields, $mappableFields);
foreach ($this->getCandidateFields() as $otherField) {
$mapSetting = "Map-{$otherField->Name}";
$fieldOption = DropdownField::create(
'spammap-' . $mapSetting,
$otherField->Title,
$mappableFieldsMerged,
$this->spamMapValue($mapSetting)
)->setEmptyString('');
$mapGroup->push($fieldOption);
}
$fields->addFieldToTab('Root.Main', $mapGroup);
/**
* Used in userforms 3.x and above
*
* {@inheritDoc}
*/
public function getCMSFields()
{
/** @var FieldList $fields */
$fields = parent::getCMSFields();
// Get protector
$protector = FormSpamProtectionExtension::get_protector();
if (!$protector) {
var_dump('a');
return $fields;
}
/**
* Try to retrieve a value for the given spam field map name from the serialised data
*
* @param string $mapSetting
* @return string
*/
public function spamMapValue($mapSetting)
{
$map = Convert::json2array($this->SpamFieldSettings);
if (empty($map)) {
$map = array();
}
if (array_key_exists($mapSetting, $map)) {
return $map[$mapSetting];
}
return '';
if ($this->Parent()->Fields() instanceof UnsavedRelationList) {
var_dump('b');
return $fields;
}
/**
* Using custom validateField method
* as Spam Protection Field implementations may have their own error messages
* and may not be based on the field being required, e.g. Honeypot Field
*
* @param array $data
* @param Form $form
* @return void
*/
public function validateField($data, $form)
{
$formField = $this->getFormField();
$formField->setForm($form);
// Each other text field in this group can be assigned a field mapping
$mapGroup = FieldGroup::create()
->setTitle(_t(__CLASS__.'.SPAMFIELDMAPPING', 'Spam Field Mapping'))
->setName('SpamFieldMapping')
->setDescription(_t(
__CLASS__.'.SPAMFIELDMAPPINGDESCRIPTION',
'Select the form fields that correspond to any relevant spam protection identifiers'
));
if (isset($data[$this->Name])) {
$formField->setValue($data[$this->Name]);
}
// Generate field specific settings
$mappableFields = FormSpamProtectionExtension::config()->get('mappable_fields');
$mappableFieldsMerged = array_combine($mappableFields, $mappableFields);
foreach ($this->getCandidateFields() as $otherField) {
$mapSetting = "Map-{$otherField->Name}";
$fieldOption = DropdownField::create(
'spammap-' . $mapSetting,
$otherField->Title,
$mappableFieldsMerged,
$this->spamMapValue($mapSetting)
)->setEmptyString('');
$mapGroup->push($fieldOption);
}
$fields->addFieldToTab('Root.Main', $mapGroup);
$validator = $form->getValidator();
if (!$formField->validate($validator)) {
$errors = $validator->getErrors();
$foundError = false;
return $fields;
}
// field validate implementation may not add error to validator
if (count($errors) > 0) {
// check if error already added from fields' validate method
foreach ($errors as $error) {
if ($error['fieldName'] == $this->Name) {
$foundError = $error;
break;
}
/**
* Try to retrieve a value for the given spam field map name from the serialised data
*
* @param string $mapSetting
* @return string
*/
public function spamMapValue($mapSetting)
{
$map = Convert::json2array($this->SpamFieldSettings);
if (empty($map)) {
$map = array();
}
if (array_key_exists($mapSetting, $map)) {
return $map[$mapSetting];
}
return '';
}
/**
* Using custom validateField method
* as Spam Protection Field implementations may have their own error messages
* and may not be based on the field being required, e.g. Honeypot Field
*
* @param array $data
* @param Form $form
* @return void
*/
public function validateField($data, $form)
{
$formField = $this->getFormField();
$formField->setForm($form);
if (isset($data[$this->Name])) {
$formField->setValue($data[$this->Name]);
}
$validator = $form->getValidator();
if (!$formField->validate($validator)) {
$errors = $validator->getErrors();
$foundError = false;
// field validate implementation may not add error to validator
if (count($errors) > 0) {
// check if error already added from fields' validate method
foreach ($errors as $error) {
if ($error['fieldName'] == $this->Name) {
$foundError = $error;
break;
}
}
}
if ($foundError !== false) {
// use error messaging already set from validate method
$form->addErrorMessage($this->Name, $foundError['message'], $foundError['messageType'], false);
} else {
// fallback to custom message set in CMS or default message if none set
$form->addErrorMessage($this->Name, $this->getErrorMessage()->HTML(), 'error', false);
}
if ($foundError !== false) {
// use error messaging already set from validate method
$form->sessionMessage($foundError['message'], $foundError['messageType']);
} else {
// fallback to custom message set in CMS or default message if none set
$form->sessionError($this->getErrorMessage()->HTML());
}
}
}
public function getFieldValidationOptions()
{
return new FieldList();
}
public function getFieldValidationOptions()
{
return FieldList::create();
}
public function getRequired()
{
return false;
}
public function getRequired()
{
return false;
}
public function getIcon()
{
return 'spamprotection/images/' . strtolower($this->class) . '.png';
}
public function getIcon()
{
return 'spamprotection/images/' . strtolower($this->class) . '.png';
}
public function showInReports()
{
return false;
}
public function showInReports()
{
return false;
}
}

View File

@ -1,5 +1,9 @@
<?php
namespace SilverStripe\SpamProtection\Extension;
use SilverStripe\Core\Extension;
/**
* Apply the spam protection to the comments module if it is installed.
*

View File

@ -1,5 +1,12 @@
<?php
namespace SilverStripe\SpamProtection\Extension;
use SilverStripe\Core\Config\Config;
use SilverStripe\Core\Config\Configurable;
use SilverStripe\Core\Extension;
use SilverStripe\Core\Injector\Injector;
/**
* An extension to the {@link Form} class which provides the method
* {@link enableSpamProtection()} helper.
@ -9,6 +16,8 @@
class FormSpamProtectionExtension extends Extension
{
use Configurable;
/**
* @config
*
@ -40,7 +49,7 @@ class FormSpamProtectionExtension extends Extension
'authorIp',
'authorId'
);
/**
* @config
*
@ -49,12 +58,12 @@ class FormSpamProtectionExtension extends Extension
* @var string $spam_protector
*/
private static $field_name = "Captcha";
/**
* Instantiate a SpamProtector instance
*
* @param array $options Configuration options
* @return SpamProtector
* @return SpamProtector|null
*/
public static function get_protector($options = null)
{
@ -62,7 +71,7 @@ class FormSpamProtectionExtension extends Extension
if (isset($options['protector'])) {
$protector = $options['protector'];
} else {
$protector = Config::inst()->get('FormSpamProtectionExtension', 'default_spam_protector');
$protector = Config::inst()->get(self::class, 'default_spam_protector');
}
if ($protector && class_exists($protector)) {
@ -76,15 +85,16 @@ class FormSpamProtectionExtension extends Extension
* Activates the spam protection module.
*
* @param array $options
* @return Object
*/
public function enableSpamProtection($options = array())
{
// captcha form field name (must be unique)
if (isset($options['name'])) {
$name = $options['name'];
} else {
$name = Config::inst()->get('FormSpamProtectionExtension', 'field_name');
$name = Config::inst()->get(self::class, 'field_name');
}
// captcha field title
@ -105,7 +115,7 @@ class FormSpamProtectionExtension extends Extension
// add the form field
if ($field = $protector->getFormField($name, $title)) {
$field->setForm($this->owner);
// Add before field specified by insertBefore
$inserted = false;
if (!empty($options['insertBefore'])) {
@ -117,7 +127,7 @@ class FormSpamProtectionExtension extends Extension
}
}
}
return $this->owner;
}
}

View File

@ -1,5 +1,9 @@
<?php
namespace SilverStripe\SpamProtection;
use SilverStripe\Forms\FormField;
/**
* SpamProtector base interface.
*

View File

@ -1,45 +0,0 @@
<?php
/**
* @package spamprotection
*
* @deprecated 1.0
*/
class SpamProtectorManager
{
private static $spam_protector = null;
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;
}
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;
}
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
codecov.yml Normal file
View File

@ -0,0 +1 @@
comment: false

View File

@ -11,15 +11,25 @@
"email": "will@fullscreen.io"
}],
"require": {
"silverstripe/framework": "~3.1"
"silverstripe/framework": "^4@dev"
},
"require-dev": {
"phpunit/PHPUnit": "~3.7@stable"
"phpunit/phpunit": "^5.7",
"silverstripe/versioned": "^1@dev",
"squizlabs/php_codesniffer": "^3.0"
},
"extra": {
"branch-alias": {
"dev-master": "3.0.x-dev"
}
},
"license": "BSD-3-Clause"
"autoload": {
"psr-4": {
"SilverStripe\\SpamProtection\\": "code/",
"SilverStripe\\SpamProtection\\Tests\\": "tests/"
}
},
"license": "BSD-3-Clause",
"minimum-stability": "dev",
"prefer-stable": true
}

View File

@ -1,5 +1,5 @@
de:
EditableSpamProtectionField:
SilverStripe\SpamProtection\EditableSpamProtectionField:
PLURALNAME: Spamschutzfelder
SINGULARNAME: Spamschutzfeld
SPAMFIELDMAPPING: 'Spamschutzfeld Zuordnung'

View File

@ -1,5 +1,5 @@
en:
EditableSpamProtectionField:
SilverStripe\SpamProtection\EditableSpamProtectionField:
PLURALNAME: 'Spam Protection Fields'
SINGULARNAME: 'Spam Protection Field'
SPAMFIELDMAPPING: 'Spam Field Mapping'

View File

@ -1,5 +1,5 @@
eo:
EditableSpamProtectionField:
SilverStripe\SpamProtection\EditableSpamProtectionField:
PLURALNAME: 'Spamprotektaj kampoj'
SINGULARNAME: 'Spamprotekta kampo'
SPAMFIELDMAPPING: 'Spamkampa mapigo'

View File

@ -1,5 +1,5 @@
es:
EditableSpamProtectionField:
SilverStripe\SpamProtection\EditableSpamProtectionField:
PLURALNAME: 'Campos de protección de spam'
SINGULARNAME: 'Campo de protección de spam'
SPAMFIELDMAPPING: 'Mapeo del campo spam'

View File

@ -1,5 +1,5 @@
fa_IR:
EditableSpamProtectionField:
SilverStripe\SpamProtection\EditableSpamProtectionField:
PLURALNAME: 'فیلدهای محافظت از هرزنوشته'
SINGULARNAME: 'فیلد محافظت از هرزنوشته'
SPAMFIELDMAPPING: 'نقشه‌برداری فیلد هرزنوشته'

View File

@ -1,5 +1,5 @@
hr:
EditableSpamProtectionField:
SilverStripe\SpamProtection\EditableSpamProtectionField:
PLURALNAME: 'Polja Spam zaštite'
SINGULARNAME: 'Polje Spam zaštite'
SPAMFIELDMAPPING: 'Mapiranje polja Spama'

View File

@ -1,5 +1,5 @@
ru:
EditableSpamProtectionField:
SilverStripe\SpamProtection\EditableSpamProtectionField:
PLURALNAME: 'Поля защиты от спама'
SINGULARNAME: 'Поле защиты от спама'
SPAMFIELDMAPPING: 'Привязка полей для защиты от спама'

View File

@ -1,5 +1,5 @@
sk:
EditableSpamProtectionField:
SilverStripe\SpamProtection\EditableSpamProtectionField:
PLURALNAME: 'Polia ochrany proti spamu'
SINGULARNAME: 'Pole ochrany proti spamu'
SPAMFIELDMAPPING: 'Mapovanie spamového poľa'

View File

@ -1,4 +1,4 @@
Copyright (c) 2016, SilverStripe Limited
Copyright (c) 2017, SilverStripe Limited
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

14
phpunit.xml.dist Normal file
View File

@ -0,0 +1,14 @@
<phpunit bootstrap="framework/tests/bootstrap.php" colors="true">
<testsuite name="Default">
<directory>tests</directory>
</testsuite>
<filter>
<whitelist addUncoveredFilesFromWhitelist="true">
<directory suffix=".php">code/</directory>
<exclude>
<directory suffix=".php">tests/</directory>
</exclude>
</whitelist>
</filter>
</phpunit>

View File

@ -1,22 +1,34 @@
<?php
namespace SilverStripe\SpamProtection\Tests;
use SilverStripe\UserForms\Model\UserDefinedForm;
use SilverStripe\Core\Config\Config;
use SilverStripe\Dev\SapphireTest;
use SilverStripe\Forms\FieldGroup;
use SilverStripe\Forms\Form;
use SilverStripe\Forms\RequiredFields;
use SilverStripe\Forms\TextField;
use SilverStripe\SpamProtection\EditableSpamProtectionField;
use SilverStripe\SpamProtection\Extension\FormSpamProtectionExtension;
use SilverStripe\SpamProtection\Tests\Stub\Protector;
class EditableSpamProtectionFieldTest extends SapphireTest
{
protected $usesDatabase = true;
public function setUp()
protected function setUp()
{
parent::setUp();
if (!class_exists('EditableSpamProtectionField')) {
if (!class_exists(EditableSpamProtectionField::class)) {
$this->markTestSkipped('"userforms" module not installed');
}
Config::inst()->update(
'FormSpamProtectionExtension',
Config::modify()->set(
FormSpamProtectionExtension::class,
'default_spam_protector',
'EditableSpamProtectionFieldTest_Protector'
Protector::class
);
}
@ -33,7 +45,7 @@ class EditableSpamProtectionFieldTest extends SapphireTest
$formMock
->expects($this->never())
->method('addErrorMessage');
->method('sessionMessage');
$formFieldMock->validateField(array('MyField' => null), $formMock);
}
@ -53,9 +65,8 @@ class EditableSpamProtectionFieldTest extends SapphireTest
$formMock
->expects($this->once())
->method('addErrorMessage')
->with($this->anything(), $this->stringContains('some field message'), $this->anything(), $this->anything());
;
->method('sessionMessage')
->with($this->stringContains('some field message'), $this->anything());
$formFieldMock->validateField(array('MyField' => null), $formMock);
}
@ -75,8 +86,8 @@ class EditableSpamProtectionFieldTest extends SapphireTest
$formMock
->expects($this->once())
->method('addErrorMessage')
->with($this->anything(), $this->stringContains('default error message'), $this->anything(), $this->anything());
->method('sessionError')
->with($this->stringContains('default error message'));
$formFieldMock->validateField(array('MyField' => null), $formMock);
}
@ -86,7 +97,7 @@ class EditableSpamProtectionFieldTest extends SapphireTest
$field = $this->getEditableFormFieldMock();
$fields = $field->getCMSFields();
$this->assertInstanceOf('FieldGroup', $fields->fieldByName('Root.Main.SpamFieldMapping'));
$this->assertInstanceOf(FieldGroup::class, $fields->fieldByName('Root.Main.SpamFieldMapping'));
}
public function testSpamMapSettingsAreSerialised()
@ -102,9 +113,11 @@ class EditableSpamProtectionFieldTest extends SapphireTest
protected function getFormMock()
{
$formMock = $this->getMockBuilder('Form', array('addErrorMessage'))
$formMock = $this->getMockBuilder(Form::class)
->setMethods(['sessionMessage', 'sessionError', 'getValidator'])
->disableOriginalConstructor()
->getMock();
$formMock
->expects($this->any())
->method('getValidator')
@ -118,7 +131,7 @@ class EditableSpamProtectionFieldTest extends SapphireTest
$page = new UserDefinedForm();
$page->write();
$formFieldMock = $this->getMockBuilder('TextField')
$formFieldMock = $this->getMockBuilder(TextField::class)
->disableOriginalConstructor()
->getMock();

View File

@ -1,5 +1,18 @@
<?php
namespace SilverStripe\SpamProtection\Tests;
use SilverStripe\Control\Controller;
use SilverStripe\Core\Config\Config;
use SilverStripe\Dev\SapphireTest;
use SilverStripe\Forms\FieldList;
use SilverStripe\Forms\Form;
use SilverStripe\Forms\TextField;
use SilverStripe\SpamProtection\Extension\FormSpamProtectionExtension;
use SilverStripe\SpamProtection\Tests\Stub\FooProtector;
use SilverStripe\SpamProtection\Tests\Stub\BarProtector;
use SilverStripe\SpamProtection\Tests\Stub\BazProtector;
/**
* @package spamprotection
*/
@ -12,24 +25,25 @@ class FormSpamProtectionExtensionTest extends SapphireTest
*/
protected $form = null;
public function setUp()
protected function setUp()
{
parent::setUp();
$this->form = new Form($this, 'Form', new FieldList(
$this->form = new Form(new Controller, 'Form', new FieldList(
new TextField('Title'),
new TextField('Comment'),
new TextField('URL')
), new FieldList());
$this->form->disableSecurityToken();
}
public function testEnableSpamProtection()
{
Config::inst()->update(
'FormSpamProtectionExtension',
Config::modify()->set(
FormSpamProtectionExtension::class,
'default_spam_protector',
'FormSpamProtectionExtensionTest_FooProtector'
FooProtector::class
);
$form = $this->form->enableSpamProtection();
@ -40,7 +54,7 @@ class FormSpamProtectionExtensionTest extends SapphireTest
public function testEnableSpamProtectionCustomProtector()
{
$form = $this->form->enableSpamProtection(array(
'protector' => 'FormSpamProtectionExtensionTest_BarProtector'
'protector' => BarProtector::class
));
$this->assertEquals('Bar', $form->Fields()->fieldByName('Captcha')->Title());
@ -49,7 +63,7 @@ class FormSpamProtectionExtensionTest extends SapphireTest
public function testEnableSpamProtectionCustomTitle()
{
$form = $this->form->enableSpamProtection(array(
'protector' => 'FormSpamProtectionExtensionTest_BarProtector',
'protector' => BarProtector::class,
'title' => 'Baz',
));
@ -59,7 +73,7 @@ class FormSpamProtectionExtensionTest extends SapphireTest
public function testCustomOptions()
{
$form = $this->form->enableSpamProtection(array(
'protector' => 'FormSpamProtectionExtensionTest_BazProtector',
'protector' => BazProtector::class,
'title' => 'Qux',
'name' => 'Borris'
));
@ -70,17 +84,19 @@ class FormSpamProtectionExtensionTest extends SapphireTest
public function testConfigurableName()
{
$field_name = "test_configurable_name";
Config::inst()->update(
'FormSpamProtectionExtension', 'default_spam_protector',
'FormSpamProtectionExtensionTest_FooProtector'
Config::modify()->set(
FormSpamProtectionExtension::class,
'default_spam_protector',
FooProtector::class
);
Config::inst()->update(
'FormSpamProtectionExtension', 'field_name',
Config::modify()->set(
FormSpamProtectionExtension::class,
'field_name',
$field_name
);
$form = $this->form->enableSpamProtection();
// remove for subsequent tests
Config::inst()->remove('FormSpamProtectionExtension', 'field_name');
Config::modify()->remove(FormSpamProtectionExtension::class, 'field_name');
// field should take up configured name
$this->assertEquals('Foo', $form->Fields()->fieldByName($field_name)->Title());
}
@ -88,7 +104,7 @@ class FormSpamProtectionExtensionTest extends SapphireTest
public function testInsertBefore()
{
$form = $this->form->enableSpamProtection(array(
'protector' => 'FormSpamProtectionExtensionTest_FooProtector',
'protector' => FooProtector::class,
'insertBefore' => 'URL'
));
@ -102,7 +118,7 @@ class FormSpamProtectionExtensionTest extends SapphireTest
public function testInsertBeforeMissing()
{
$form = $this->form->enableSpamProtection(array(
'protector' => 'FormSpamProtectionExtensionTest_FooProtector',
'protector' => FooProtector::class,
'insertBefore' => 'NotAField'
));

View File

@ -0,0 +1,23 @@
<?php
namespace SilverStripe\SpamProtection\Tests\FormSpamProtectionExtensionTest;
use SilverStripe\Dev\TestOnly;
use SilverStripe\Forms\TextField;
use SilverStripe\SpamProtection\SpamProtector;
/**
* @package spamprotection
*/
class BarProtector implements SpamProtector, TestOnly
{
public function getFormField($name = null, $title = null, $value = null)
{
$title = $title ?: 'Bar';
return new TextField($name, $title, $value);
}
public function setFieldMapping($fieldMapping)
{
}
}

View File

@ -0,0 +1,22 @@
<?php
namespace SilverStripe\SpamProtection\Tests\FormSpamProtectionExtensionTest;
use SilverStripe\Dev\TestOnly;
use SilverStripe\Forms\TextField;
use SilverStripe\SpamProtection\SpamProtector;
/**
* @package spamprotection
*/
class BazProtector implements SpamProtector, TestOnly
{
public function getFormField($name = null, $title = null, $value = null)
{
return new TextField($name, $title, $value);
}
public function setFieldMapping($fieldMapping)
{
}
}

View File

@ -0,0 +1,22 @@
<?php
namespace SilverStripe\SpamProtection\Tests\FormSpamProtectionExtensionTest;
use SilverStripe\Dev\TestOnly;
use SilverStripe\Forms\TextField;
use SilverStripe\SpamProtection\SpamProtector;
/**
* @package spamprotection
*/
class FooProtector implements SpamProtector, TestOnly
{
public function getFormField($name = null, $title = null, $value = null)
{
return new TextField($name, 'Foo', $value);
}
public function setFieldMapping($fieldMapping)
{
}
}

View File

@ -1,9 +1,15 @@
<?php
namespace SilverStripe\SpamProtection\Tests\Stub;
use SilverStripe\Dev\TestOnly;
use SilverStripe\Forms\TextField;
use SilverStripe\SpamProtection\SpamProtector;
/**
* @package spamprotection
*/
class FormSpamProtectionExtensionTest_BarProtector implements SpamProtector, TestOnly
class BarProtector implements SpamProtector, TestOnly
{
public function getFormField($name = null, $title = null, $value = null)
{

View File

@ -1,9 +1,15 @@
<?php
namespace SilverStripe\SpamProtection\Tests\Stub;
use SilverStripe\Dev\TestOnly;
use SilverStripe\Forms\TextField;
use SilverStripe\SpamProtection\SpamProtector;
/**
* @package spamprotection
*/
class FormSpamProtectionExtensionTest_BazProtector implements SpamProtector, TestOnly
class BazProtector implements SpamProtector, TestOnly
{
public function getFormField($name = null, $title = null, $value = null)
{

View File

@ -1,9 +1,15 @@
<?php
namespace SilverStripe\SpamProtection\Tests\Stub;
use SilverStripe\Dev\TestOnly;
use SilverStripe\Forms\TextField;
use SilverStripe\SpamProtection\SpamProtector;
/**
* @package spamprotection
*/
class FormSpamProtectionExtensionTest_FooProtector implements SpamProtector, TestOnly
class FooProtector implements SpamProtector, TestOnly
{
public function getFormField($name = null, $title = null, $value = null)
{

View File

@ -1,6 +1,12 @@
<?php
class EditableSpamProtectionFieldTest_Protector implements SpamProtector, TestOnly
namespace SilverStripe\SpamProtection\Tests\Stub;
use SilverStripe\Dev\TestOnly;
use SilverStripe\Forms\TextField;
use SilverStripe\SpamProtection\SpamProtector;
class Protector implements SpamProtector, TestOnly
{
public function getFormField($name = null, $title = null, $value = null)
{