diff --git a/code/EditableSpamProtectionField.php b/code/EditableSpamProtectionField.php index 1d591b0..faa8729 100644 --- a/code/EditableSpamProtectionField.php +++ b/code/EditableSpamProtectionField.php @@ -13,17 +13,95 @@ if(class_exists('EditableFormField')) { static $singular_name = 'Spam Protection Field'; static $plural_name = 'Spam Protection Fields'; + + /** + * Fields to include spam detection for + * + * @var array + * @config + */ + private static $check_fields = array( + 'EditableEmailField', + 'EditableTextField', + 'EditableNumericField' + ); 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 false; + // Get protector + $protector = FormSpamProtectionExtension::get_protector(); + if(empty($protector)) return false; + + // Extract saved field mappings and update this field. + $fieldMapping = array(); + foreach($this->getCandidateFields() as $otherField) { + $mapSetting = "Map-{$otherField->Name}"; + $spamField = $this->getSetting($mapSetting); + $fieldMapping[$otherField->Name] = $spamField; + } + $protector->setFieldMapping($fieldMapping); + + // Generate field + return $protector->getFormField($this->Name, $this->Title, null); } - + + /** + * 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 = self::config()->check_fields; + $typesInherit = array(); + foreach ($types as $type) { + $subTypes = ClassInfo::subclassesFor($type); + $typesInherit = array_merge($typesInherit, $subTypes); + } + + // Get all candidates of the above types + return $this + ->Parent() + ->Fields() + ->filter('ClassName', $typesInherit) + ->exclude('Title', ''); // Ignore this field and those without titles + } + + public function getFieldConfiguration() { + $fields = parent::getFieldConfiguration(); + + // Get protector + $protector = FormSpamProtectionExtension::get_protector(); + if (empty($protector)) return fields; + + // Each other text field in this group can be assigned a field mapping + $mapGroup = FieldGroup::create(_t( + 'EditableSpamProtectionField.SPAMFIELDMAPPING', + 'Spam Field Mapping' + ))->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( + $this->getSettingName($mapSetting), + $otherField->Title, + $mappableFieldsMerged, + $this->getSetting($mapSetting) + )->setEmptyString(''); + $mapGroup->push($fieldOption); + } + $fields->insertBefore($mapGroup, $this->getSettingName('ExtraClass')); + + return $fields; + } + public function getFieldValidationOptions() { return new FieldList(); } @@ -32,7 +110,7 @@ if(class_exists('EditableFormField')) { return false; } - public function Icon() { + public function getIcon() { return 'spamprotection/images/' . strtolower($this->class) . '.png'; } @@ -40,4 +118,4 @@ if(class_exists('EditableFormField')) { return false; } } -} \ No newline at end of file +} diff --git a/code/extensions/FormSpamProtectionExtension.php b/code/extensions/FormSpamProtectionExtension.php index 946b9de..49f555e 100644 --- a/code/extensions/FormSpamProtectionExtension.php +++ b/code/extensions/FormSpamProtectionExtension.php @@ -8,11 +8,6 @@ */ class FormSpamProtectionExtension extends Extension { - - /** - * @var array - */ - private $fieldMapping = array(); /** * @config @@ -45,13 +40,14 @@ class FormSpamProtectionExtension extends Extension { 'authorIp', 'authorId' ); - + /** - * Activates the spam protection module. - * - * @param array $options + * Instantiate a SpamProtector instance + * + * @param array $options Configuration options + * @return SpamProtector */ - public function enableSpamProtection($options = array()) { + public static function get_protector($options = null) { // generate the spam protector if(isset($options['protector'])) { $protector = $options['protector']; @@ -63,6 +59,15 @@ class FormSpamProtectionExtension extends Extension { $protector = Config::inst()->get('FormSpamProtectionExtension', 'default_spam_protector'); $protector = Injector::inst()->create($protector); } + return $protector; + } + + /** + * Activates the spam protection module. + * + * @param array $options + */ + public function enableSpamProtection($options = array()) { // captcha form field name (must be unique) if(isset($options['name'])) { @@ -79,8 +84,9 @@ class FormSpamProtectionExtension extends Extension { } // set custom mapping on this form + $protector = self::get_protector($options); if(isset($options['mapping'])) { - $this->fieldMapping = $options['mapping']; + $protector->setFieldMapping($options['mapping']); } // add the form field @@ -92,29 +98,4 @@ class FormSpamProtectionExtension extends Extension { 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; - } -} \ No newline at end of file +} diff --git a/code/interfaces/SpamProtector.php b/code/interfaces/SpamProtector.php index 945e3c3..b19dd74 100644 --- a/code/interfaces/SpamProtector.php +++ b/code/interfaces/SpamProtector.php @@ -25,6 +25,16 @@ interface SpamProtector { * @param string $name * @param string $title * @param mixed $value + * @return FormField The resulting field */ public function getFormField($name = null, $title = null, $value = null); -} \ No newline at end of file + + /** + * Set the fields to map spam protection too + * + * @param array $fieldMapping array of Field Names, where the indexes of the array are + * the field names of the form and the values are the standard spamprotection + * fields used by the protector + */ + public function setFieldMapping($fieldMapping); +} diff --git a/lang/_manifest_exclude b/lang/_manifest_exclude new file mode 100644 index 0000000..e69de29 diff --git a/lang/en.yml b/lang/en.yml new file mode 100644 index 0000000..7eefe0a --- /dev/null +++ b/lang/en.yml @@ -0,0 +1,6 @@ +en: + EditableSpamProtectionField: + SINGULARNAME: 'Spam Protection Field' + PLURALNAME: 'Spam Protection Fields' + SPAMFIELDMAPPING: 'Spam Field Mapping' + SPAMFIELDMAPPINGDESCRIPTION: 'Select the form fields that correspond to any relevant spam protection identifiers' diff --git a/tests/FormSpamProtectionExtensionTest.php b/tests/FormSpamProtectionExtensionTest.php index 2848afb..d078121 100644 --- a/tests/FormSpamProtectionExtensionTest.php +++ b/tests/FormSpamProtectionExtensionTest.php @@ -64,6 +64,9 @@ class FormSpamProtectionExtensionTest_BazProtector implements SpamProtector, Tes public function getFormField($name = null, $title = null, $value = null) { return new TextField($name, $title, $value); } + + public function setFieldMapping($fieldMapping) {} + } /** @@ -76,6 +79,9 @@ class FormSpamProtectionExtensionTest_BarProtector implements SpamProtector, Tes public function getFormField($name = null, $title = null, $value = null) { return new TextField($name, $this->title, $value); } + + public function setFieldMapping($fieldMapping) {} + } /** @@ -86,4 +92,7 @@ class FormSpamProtectionExtensionTest_FooProtector implements SpamProtector, Tes public function getFormField($name = null, $title = null, $value = null) { return new TextField($name, 'Foo', $value); } + + public function setFieldMapping($fieldMapping) {} + } \ No newline at end of file