From 680411e2acff6aee4469431e6c5f246fd8f6f2a7 Mon Sep 17 00:00:00 2001 From: Robbie Averill Date: Mon, 28 Aug 2017 13:44:53 +1200 Subject: [PATCH] FIX Missing syntax opening in readme, and tweaks for pre-emptive userforms compatibility --- README.md | 1 + code/EditableSpamProtectionField.php | 447 +++++++++--------- .../Extension/FormSpamProtectionExtension.php | 3 + tests/EditableSpamProtectionFieldTest.php | 32 +- 4 files changed, 239 insertions(+), 244 deletions(-) diff --git a/README.md b/README.md index bbb8047..394ac28 100644 --- a/README.md +++ b/README.md @@ -101,6 +101,7 @@ 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 'Text' + ); + + /** + * @var FormField + */ + protected $formField = null; + + public function getFormField() { - 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() - { - 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(__CLASS__.'.SPAMFIELDMAPPING', 'Spam Field Mapping')) - ->setName('SpamFieldMapping') - ->setDescription(_t( - __CLASS__.'.SPAMFIELDMAPPINGDESCRIPTION', - 'Select the form fields that correspond to any relevant spam protection identifiers' - )); - - // Generate field specific settings - $mappableFields = Config::inst()->get(FormSpamProtectionExtension::class, '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->sessionMessage($foundError['message'], $foundError['messageType']); - } else { - // fallback to custom message set in CMS or default message if none set - $form->sessionError($this->getErrorMessage()->HTML()); - } + 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; } } diff --git a/code/Extension/FormSpamProtectionExtension.php b/code/Extension/FormSpamProtectionExtension.php index ad26df3..a07b3e2 100644 --- a/code/Extension/FormSpamProtectionExtension.php +++ b/code/Extension/FormSpamProtectionExtension.php @@ -3,6 +3,7 @@ namespace SilverStripe\SpamProtection\Extension; use SilverStripe\Core\Config\Config; +use SilverStripe\Core\Config\Configurable; use SilverStripe\Core\Extension; use SilverStripe\Core\Injector\Injector; @@ -15,6 +16,8 @@ use SilverStripe\Core\Injector\Injector; class FormSpamProtectionExtension extends Extension { + use Configurable; + /** * @config * diff --git a/tests/EditableSpamProtectionFieldTest.php b/tests/EditableSpamProtectionFieldTest.php index 2e35a06..fdb7452 100644 --- a/tests/EditableSpamProtectionFieldTest.php +++ b/tests/EditableSpamProtectionFieldTest.php @@ -2,14 +2,16 @@ namespace SilverStripe\SpamProtection\Tests; -use UserDefinedForm; +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\EditableSpamProtectionFieldTest\Protector; +use SilverStripe\SpamProtection\Tests\Stub\Protector; class EditableSpamProtectionFieldTest extends SapphireTest { @@ -19,7 +21,7 @@ class EditableSpamProtectionFieldTest extends SapphireTest { parent::setUp(); - if (!class_exists('EditableSpamProtectionField')) { + if (!class_exists(EditableSpamProtectionField::class)) { $this->markTestSkipped('"userforms" module not installed'); } @@ -64,12 +66,7 @@ class EditableSpamProtectionFieldTest extends SapphireTest $formMock ->expects($this->once()) ->method('sessionMessage') - ->with( - $this->anything(), - $this->stringContains('some field message'), - $this->anything(), - $this->anything() - ); + ->with($this->stringContains('some field message'), $this->anything()); $formFieldMock->validateField(array('MyField' => null), $formMock); } @@ -89,13 +86,8 @@ class EditableSpamProtectionFieldTest extends SapphireTest $formMock ->expects($this->once()) - ->method('sessionMessage') - ->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); } @@ -105,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() @@ -121,9 +113,11 @@ class EditableSpamProtectionFieldTest extends SapphireTest protected function getFormMock() { - $formMock = $this->getMockBuilder(Form::class, array('sessionMessage')) + $formMock = $this->getMockBuilder(Form::class) + ->setMethods(['sessionMessage', 'sessionError', 'getValidator']) ->disableOriginalConstructor() ->getMock(); + $formMock ->expects($this->any()) ->method('getValidator') @@ -137,7 +131,7 @@ class EditableSpamProtectionFieldTest extends SapphireTest $page = new UserDefinedForm(); $page->write(); - $formFieldMock = $this->getMockBuilder('TextField') + $formFieldMock = $this->getMockBuilder(TextField::class) ->disableOriginalConstructor() ->getMock();