Completed
Pull Request — master (#51)
by Robbie
02:02 queued 51s
created

getFieldConfiguration()   B

Complexity

Conditions 4
Paths 4

Size

Total Lines 40
Code Lines 26

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 40
rs 8.5806
c 0
b 0
f 0
cc 4
eloc 26
nc 4
nop 0
1
<?php
2
3
namespace SilverStripe\SpamProtection;
4
5
use SilverStripe\Forms\DropdownField;
6
use SilverStripe\Forms\FieldGroup;
7
use SilverStripe\Forms\FieldList;
8
use SilverStripe\SpamProtection\Extension\FormSpamProtectionExtension;
9
use SilverStripe\ORM\UnsavedRelationList;
10
11
// @todo
12
use EditableEmailField;
13
use EditableFormField;
14
use EditableNumericField;
15
use EditableTextField;
16
17
/**
18
 * Editable Spam Protecter Field. Used with the User Defined Forms module (if
19
 * installed) to allow the user to have captcha fields with their custom forms
20
 *
21
 * @package spamprotection
22
 */
23
// @todo update namespaced for userforms when it is 4.0 compatible
24
if (class_exists('EditableFormField')) {
25
    class EditableSpamProtectionField extends EditableFormField
26
    {
27
        private static $singular_name = 'Spam Protection Field';
0 ignored issues
show
Unused Code introduced by
The property $singular_name is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
28
29
        private static $plural_name = 'Spam Protection Fields';
0 ignored issues
show
Unused Code introduced by
The property $plural_name is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
30
31
        private static $table_name = 'EditableSpamProtectionField';
0 ignored issues
show
Unused Code introduced by
The property $table_name is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
32
33
        /**
34
         * Fields to include spam detection for
35
         *
36
         * @var array
37
         * @config
38
         */
39
        private static $check_fields = array(
0 ignored issues
show
Unused Code introduced by
The property $check_fields is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
40
            EditableEmailField::class,
41
            EditableTextField::class,
42
            EditableNumericField::class
43
        );
44
45
        /**
46
         * @var FormField
47
         */
48
        protected $formField = null;
49
50
        public function getFormField()
51
        {
52
            if ($this->formField) {
53
                return $this->formField;
54
            }
55
56
            // Get protector
57
            $protector = FormSpamProtectionExtension::get_protector();
58
            if (!$protector) {
59
                return false;
60
            }
61
62
            // Extract saved field mappings and update this field.
63
            $fieldMapping = array();
64
            foreach ($this->getCandidateFields() as $otherField) {
65
                $mapSetting = "Map-{$otherField->Name}";
66
                $spamField = $this->getSetting($mapSetting);
67
                $fieldMapping[$otherField->Name] = $spamField;
68
            }
69
            $protector->setFieldMapping($fieldMapping);
70
71
            // Generate field
72
            return $protector->getFormField($this->Name, $this->Title, null);
73
        }
74
75
        /**
76
         * @param FormField $field
77
         * @return self
78
         */
79
        public function setFormField(FormField $field)
80
        {
81
            $this->formField = $field;
82
83
            return $this;
84
        }
85
86
        /**
87
         * Gets the list of all candidate spam detectable fields on this field's form
88
         *
89
         * @return DataList
90
         */
91
        protected function getCandidateFields()
92
        {
93
94
            // Get list of all configured classes available for spam detection
95
            $types = self::config()->check_fields;
96
            $typesInherit = array();
97
            foreach ($types as $type) {
98
                $subTypes = ClassInfo::subclassesFor($type);
99
                $typesInherit = array_merge($typesInherit, $subTypes);
100
            }
101
102
            // Get all candidates of the above types
103
            return $this
104
                ->Parent()
105
                ->Fields()
106
                ->filter('ClassName', $typesInherit)
107
                ->exclude('Title', ''); // Ignore this field and those without titles
108
        }
109
110
        public function getFieldConfiguration()
111
        {
112
            $fields = parent::getFieldConfiguration();
113
114
            // Get protector
115
            $protector = FormSpamProtectionExtension::get_protector();
116
            if (!$protector) {
117
                return $fields;
118
            }
119
120
            if ($this->Parent()->Fields() instanceof UnsavedRelationList) {
121
                return $fields;
122
            }
123
124
            // Each other text field in this group can be assigned a field mapping
125
            $mapGroup = FieldGroup::create(_t(
126
                __CLASS__.'.SPAMFIELDMAPPING',
127
                'Spam Field Mapping'
128
            ))->setDescription(_t(
129
                __CLASS__.'.SPAMFIELDMAPPINGDESCRIPTION',
130
                'Select the form fields that correspond to any relevant spam protection identifiers'
131
            ));
132
133
            // Generate field specific settings
134
            $mappableFields = Config::inst()->get(FormSpamProtectionExtension::class, 'mappable_fields');
135
            $mappableFieldsMerged = array_combine($mappableFields, $mappableFields);
136
            foreach ($this->getCandidateFields() as $otherField) {
137
                $mapSetting = "Map-{$otherField->Name}";
138
                $fieldOption = DropdownField::create(
139
                    $this->getSettingName($mapSetting),
140
                    $otherField->Title,
141
                    $mappableFieldsMerged,
142
                    $this->getSetting($mapSetting)
143
                )->setEmptyString('');
144
                $mapGroup->push($fieldOption);
145
            }
146
            $fields->insertBefore($mapGroup, $this->getSettingName('ExtraClass'));
147
148
            return $fields;
149
        }
150
151
        /**
152
         * Using custom validateField method
153
         * as Spam Protection Field implementations may have their own error messages
154
         * and may not be based on the field being required, e.g. Honeypot Field
155
         *
156
         * @param array $data
157
         * @param Form $form
158
         * @return void
159
         */
160
        public function validateField($data, $form)
161
        {
162
            $formField = $this->getFormField();
163
            $formField->setForm($form);
164
165
            if (isset($data[$this->Name])) {
166
                $formField->setValue($data[$this->Name]);
167
            }
168
169
            $validator = $form->getValidator();
170
            if (!$formField->validate($validator)) {
171
                $errors = $validator->getErrors();
172
                $foundError = false;
173
174
                // field validate implementation may not add error to validator
175
                if (count($errors) > 0) {
176
                    // check if error already added from fields' validate method
177
                    foreach ($errors as $error) {
178
                        if ($error['fieldName'] == $this->Name) {
179
                            $foundError = $error;
180
                            break;
181
                        }
182
                    }
183
                }
184
185
                if ($foundError !== false) {
186
                    // use error messaging already set from validate method
187
                    $form->sessionMessage($foundError['message'], $foundError['messageType']);
188
                } else {
189
                    // fallback to custom message set in CMS or default message if none set
190
                    $form->sessionError($this->getErrorMessage()->HTML());
191
                }
192
            }
193
        }
194
195
        public function getFieldValidationOptions()
196
        {
197
            return new FieldList();
198
        }
199
200
        public function getRequired()
201
        {
202
            return false;
203
        }
204
205
        public function getIcon()
206
        {
207
            return 'spamprotection/images/' . strtolower($this->class) . '.png';
208
        }
209
210
        public function showInReports()
211
        {
212
            return false;
213
        }
214
    }
215
}
216