Passed
Pull Request — master (#688)
by Robbie
03:46
created

EmailRecipient   B

Complexity

Total Complexity 49

Size/Duplication

Total Lines 562
Duplicated Lines 1.96 %

Importance

Changes 0
Metric Value
dl 11
loc 562
rs 8.5454
c 0
b 0
f 0
wmc 49

16 Methods

Rating   Name   Duplication   Size   Complexity  
A getEmailBodyContent() 0 6 2
B getEmailTemplateDropdownValues() 0 35 6
B getRulesConfig() 0 27 1
B getCMSFields() 0 210 3
A getFormParent() 0 9 3
A canDelete() 0 3 1
A canCreate() 10 10 2
A canEdit() 0 7 2
A canView() 0 7 2
C canSend() 0 23 7
A requireDefaultRecords() 0 6 1
A emailTemplateExists() 0 5 2
B validate() 0 25 6
A getTitle() 0 9 3
A getCanCreateContext() 0 13 4
A summaryFields() 0 14 4

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like EmailRecipient often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use EmailRecipient, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace SilverStripe\UserForms\Model\Recipient;
4
5
use SilverStripe\Admin\LeftAndMain;
6
use SilverStripe\Assets\FileFinder;
7
use SilverStripe\CMS\Controllers\CMSMain;
8
use SilverStripe\CMS\Controllers\CMSPageEditController;
9
use SilverStripe\Control\Controller;
10
use SilverStripe\Control\Email\Email;
11
use SilverStripe\Forms\CheckboxField;
12
use SilverStripe\Forms\DropdownField;
13
use SilverStripe\Forms\FieldGroup;
14
use SilverStripe\Forms\FieldList;
15
use SilverStripe\Forms\Form;
16
use SilverStripe\Forms\GridField\GridField;
17
use SilverStripe\Forms\GridField\GridFieldButtonRow;
18
use SilverStripe\Forms\GridField\GridFieldConfig;
19
use SilverStripe\Forms\GridField\GridFieldDeleteAction;
20
use SilverStripe\Forms\GridField\GridFieldToolbarHeader;
21
use SilverStripe\Forms\HTMLEditor\HTMLEditorField;
22
use SilverStripe\Forms\LiteralField;
23
use SilverStripe\Forms\TabSet;
24
use SilverStripe\Forms\TextareaField;
25
use SilverStripe\Forms\TextField;
26
use SilverStripe\ORM\ArrayList;
27
use SilverStripe\ORM\DataObject;
28
use SilverStripe\ORM\DB;
29
use SilverStripe\ORM\FieldType\DBField;
30
use SilverStripe\UserForms\Model\EditableFormField\EditableEmailField;
31
use SilverStripe\UserForms\Model\EditableFormField;
32
use SilverStripe\UserForms\Model\EditableFormField\EditableMultipleOptionField;
33
use SilverStripe\UserForms\Model\EditableFormField\EditableTextField;
34
use SilverStripe\UserForms\Model\Recipient\EmailRecipientCondition;
35
use SilverStripe\UserForms\Model\UserDefinedForm;
36
use SilverStripe\UserForms\UserForm;
37
use SilverStripe\View\Requirements;
38
use Symbiote\GridFieldExtensions\GridFieldAddNewInlineButton;
39
use Symbiote\GridFieldExtensions\GridFieldEditableColumns;
40
41
/**
42
 * A Form can have multiply members / emails to email the submission
43
 * to and custom subjects
44
 *
45
 * @package userforms
46
 */
47
class EmailRecipient extends DataObject
48
{
49
    private static $db = [
50
        'EmailAddress' => 'Varchar(200)',
51
        'EmailSubject' => 'Varchar(200)',
52
        'EmailFrom' => 'Varchar(200)',
53
        'EmailReplyTo' => 'Varchar(200)',
54
        'EmailBody' => 'Text',
55
        'EmailBodyHtml' => 'HTMLText',
56
        'EmailTemplate' => 'Varchar',
57
        'SendPlain' => 'Boolean',
58
        'HideFormData' => 'Boolean',
59
        'CustomRulesCondition' => 'Enum("And,Or")'
60
    ];
61
62
    private static $has_one = [
63
        'Form' => DataObject::class,
64
        'SendEmailFromField' => EditableFormField::class,
65
        'SendEmailToField' => EditableFormField::class,
66
        'SendEmailSubjectField' => EditableFormField::class
67
    ];
68
69
    private static $has_many = [
70
        'CustomRules' => EmailRecipientCondition::class,
71
    ];
72
73
    private static $owns = [
74
        'CustomRules',
75
    ];
76
77
    private static $cascade_deetes = [
78
        'CustomRules',
79
    ];
80
81
    private static $summary_fields = [
82
        'EmailAddress',
83
        'EmailSubject',
84
        'EmailFrom'
85
    ];
86
87
    private static $table_name = 'UserDefinedForm_EmailRecipient';
88
89
    /**
90
     * Setting this to true will allow you to select "risky" fields as
91
     * email recipient, such as free-text entry fields.
92
     *
93
     * It's advisable to leave this off.
94
     *
95
     * @config
96
     * @var bool
97
     */
98
    private static $allow_unbound_recipient_fields = false;
99
100
    public function requireDefaultRecords()
101
    {
102
        parent::requireDefaultRecords();
103
104
        // make sure to migrate the class across (prior to v5.x)
105
        DB::query("UPDATE UserDefinedForm_EmailRecipient SET FormClass = 'Page' WHERE FormClass IS NULL");
106
    }
107
108
    public function summaryFields()
109
    {
110
        $fields = parent::summaryFields();
111
        if (isset($fields['EmailAddress'])) {
112
            /** @skipUpgrade */
113
            $fields['EmailAddress'] = _t('SilverStripe\\UserForms\\Model\\UserDefinedForm.EMAILADDRESS', 'Email');
114
        }
115
        if (isset($fields['EmailSubject'])) {
116
            $fields['EmailSubject'] = _t('SilverStripe\\UserForms\\Model\\UserDefinedForm.EMAILSUBJECT', 'Subject');
117
        }
118
        if (isset($fields['EmailFrom'])) {
119
            $fields['EmailFrom'] = _t('SilverStripe\\UserForms\\Model\\UserDefinedForm.EMAILFROM', 'From');
120
        }
121
        return $fields;
122
    }
123
124
    /**
125
     * Get instance of UserDefinedForm when editing in getCMSFields
126
     *
127
     * @return UserDefinedFrom
0 ignored issues
show
Bug introduced by
The type SilverStripe\UserForms\M...cipient\UserDefinedFrom was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
128
     */
129
    protected function getFormParent()
130
    {
131
        // LeftAndMain::sessionNamespace is protected. @todo replace this with a non-deprecated equivalent.
132
        $sessionNamespace = $this->config()->get('session_namespace') ?: LeftAndMain::class;
133
134
        $formID = $this->FormID
0 ignored issues
show
Bug Best Practice introduced by
The property FormID does not exist on SilverStripe\UserForms\M...ecipient\EmailRecipient. Since you implemented __get, consider adding a @property annotation.
Loading history...
135
            ? $this->FormID
136
            : Controller::curr()->getRequest()->getSession()->get($sessionNamespace . '.currentPage');
137
        return UserDefinedForm::get()->byID($formID);
138
    }
139
140
    public function getTitle()
141
    {
142
        if ($this->EmailAddress) {
0 ignored issues
show
Bug Best Practice introduced by
The property EmailAddress does not exist on SilverStripe\UserForms\M...ecipient\EmailRecipient. Since you implemented __get, consider adding a @property annotation.
Loading history...
143
            return $this->EmailAddress;
144
        }
145
        if ($this->EmailSubject) {
0 ignored issues
show
Bug Best Practice introduced by
The property EmailSubject does not exist on SilverStripe\UserForms\M...ecipient\EmailRecipient. Since you implemented __get, consider adding a @property annotation.
Loading history...
146
            return $this->EmailSubject;
147
        }
148
        return parent::getTitle();
149
    }
150
151
    /**
152
     * Generate a gridfield config for editing filter rules
153
     *
154
     * @return GridFieldConfig
155
     */
156
    protected function getRulesConfig()
157
    {
158
        $formFields = $this->getFormParent()->Fields();
159
160
        $config = GridFieldConfig::create()
161
            ->addComponents(
162
                new GridFieldButtonRow('before'),
163
                new GridFieldToolbarHeader(),
164
                new GridFieldAddNewInlineButton(),
165
                new GridFieldDeleteAction(),
166
                $columns = new GridFieldEditableColumns()
167
            );
168
169
        $columns->setDisplayFields(array(
170
            'ConditionFieldID' => function ($record, $column, $grid) use ($formFields) {
0 ignored issues
show
Unused Code introduced by
The parameter $grid is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

170
            'ConditionFieldID' => function ($record, $column, /** @scrutinizer ignore-unused */ $grid) use ($formFields) {

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
171
                return DropdownField::create($column, false, $formFields->map('ID', 'Title'));
0 ignored issues
show
Bug introduced by
false of type false is incompatible with the type array expected by parameter $args of SilverStripe\View\ViewableData::create(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

171
                return DropdownField::create($column, /** @scrutinizer ignore-type */ false, $formFields->map('ID', 'Title'));
Loading history...
172
            },
173
            'ConditionOption' => function ($record, $column, $grid) {
0 ignored issues
show
Unused Code introduced by
The parameter $grid is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

173
            'ConditionOption' => function ($record, $column, /** @scrutinizer ignore-unused */ $grid) {

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
174
                $options = EmailRecipientCondition::config()->condition_options;
175
                return DropdownField::create($column, false, $options);
0 ignored issues
show
Bug introduced by
false of type false is incompatible with the type array expected by parameter $args of SilverStripe\View\ViewableData::create(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

175
                return DropdownField::create($column, /** @scrutinizer ignore-type */ false, $options);
Loading history...
176
            },
177
            'ConditionValue' => function ($record, $column, $grid) {
0 ignored issues
show
Unused Code introduced by
The parameter $grid is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

177
            'ConditionValue' => function ($record, $column, /** @scrutinizer ignore-unused */ $grid) {

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
178
                return TextField::create($column);
179
            }
180
        ));
181
182
        return $config;
183
    }
184
185
    /**
186
     * @return FieldList
187
     */
188
    public function getCMSFields()
189
    {
190
        Requirements::javascript('silverstripe/userforms:client/dist/js/userforms-cms.js');
191
192
        // Determine optional field values
193
        $form = $this->getFormParent();
194
195
        // predefined choices are also candidates
196
        $multiOptionFields = EditableMultipleOptionField::get()->filter('ParentID', $form->ID);
197
198
        // if they have email fields then we could send from it
199
        $validEmailFromFields = EditableEmailField::get()->filter('ParentID', $form->ID);
200
201
        // For the subject, only one-line entry boxes make sense
202
        $validSubjectFields = ArrayList::create(
203
            EditableTextField::get()
204
                ->filter('ParentID', $form->ID)
205
                ->exclude('Rows:GreaterThan', 1)
206
                ->toArray()
207
        );
208
        $validSubjectFields->merge($multiOptionFields);
209
210
211
        // Check valid email-recipient fields
212
        if ($this->config()->get('allow_unbound_recipient_fields')) {
213
            // To address can only be email fields or multi option fields
214
            $validEmailToFields = ArrayList::create($validEmailFromFields->toArray());
215
            $validEmailToFields->merge($multiOptionFields);
216
        } else {
217
            // To address cannot be unbound, so restrict to pre-defined lists
218
            $validEmailToFields = $multiOptionFields;
219
        }
220
221
        // Build fieldlist
222
        $fields = FieldList::create(Tabset::create('Root')->addExtraClass('EmailRecipientForm'));
0 ignored issues
show
Bug introduced by
'Root' of type string is incompatible with the type array expected by parameter $args of SilverStripe\View\ViewableData::create(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

222
        $fields = FieldList::create(Tabset::create(/** @scrutinizer ignore-type */ 'Root')->addExtraClass('EmailRecipientForm'));
Loading history...
223
224
        // Configuration fields
225
        $fields->addFieldsToTab('Root.EmailDetails', [
226
            // Subject
227
            FieldGroup::create(
228
                TextField::create(
229
                    'EmailSubject',
230
                    _t('SilverStripe\\UserForms\\Model\\UserDefinedForm.TYPESUBJECT', 'Type subject')
231
                )
232
                    ->setAttribute('style', 'min-width: 400px;'),
233
                DropdownField::create(
234
                    'SendEmailSubjectFieldID',
235
                    _t(
236
                        'SilverStripe\\UserForms\\Model\\UserDefinedForm.SELECTAFIELDTOSETSUBJECT',
237
                        '.. or select a field to use as the subject'
238
                    ),
239
                    $validSubjectFields->map('ID', 'Title')
240
                )->setEmptyString('')
241
            )
242
                ->setTitle(_t('SilverStripe\\UserForms\\Model\\UserDefinedForm.EMAILSUBJECT', 'Email subject')),
243
244
            // To
245
            FieldGroup::create(
246
                TextField::create(
247
                    'EmailAddress',
248
                    _t('SilverStripe\\UserForms\\Model\\UserDefinedForm.TYPETO', 'Type to address')
249
                )
250
                    ->setAttribute('style', 'min-width: 400px;'),
251
                DropdownField::create(
252
                    'SendEmailToFieldID',
253
                    _t(
254
                        'SilverStripe\\UserForms\\Model\\UserDefinedForm.ORSELECTAFIELDTOUSEASTO',
255
                        '.. or select a field to use as the to address'
256
                    ),
257
                    $validEmailToFields->map('ID', 'Title')
0 ignored issues
show
Bug introduced by
$validEmailToFields->map('ID', 'Title') of type SilverStripe\ORM\Map is incompatible with the type array expected by parameter $args of SilverStripe\View\ViewableData::create(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

257
                    /** @scrutinizer ignore-type */ $validEmailToFields->map('ID', 'Title')
Loading history...
258
                )->setEmptyString(' ')
259
            )
260
                ->setTitle(_t('SilverStripe\\UserForms\\Model\\UserDefinedForm.SENDEMAILTO', 'Send email to'))
261
                ->setDescription(_t(
262
                    'SilverStripe\\UserForms\\Model\\UserDefinedForm.SENDEMAILTO_DESCRIPTION',
263
                    'You may enter multiple email addresses as a comma separated list.'
264
                )),
265
266
267
            // From
268
            TextField::create(
269
                'EmailFrom',
270
                _t('SilverStripe\\UserForms\\Model\\UserDefinedForm.FROMADDRESS', 'Send email from')
271
            )
272
                ->setDescription(_t(
273
                    'SilverStripe\\UserForms\\Model\\UserDefinedForm.EmailFromContent',
274
                    "The from address allows you to set who the email comes from. On most servers this ".
275
                    "will need to be set to an email address on the same domain name as your site. ".
276
                    "For example on yoursite.com the from address may need to be [email protected]. ".
277
                    "You can however, set any email address you wish as the reply to address."
278
                )),
279
280
281
            // Reply-To
282
            FieldGroup::create(
283
                TextField::create('EmailReplyTo', _t(
284
                    'SilverStripe\\UserForms\\Model\\UserDefinedForm.TYPEREPLY',
285
                    'Type reply address'
286
                ))
287
                    ->setAttribute('style', 'min-width: 400px;'),
288
                DropdownField::create(
289
                    'SendEmailFromFieldID',
290
                    _t(
291
                        'SilverStripe\\UserForms\\Model\\UserDefinedForm.ORSELECTAFIELDTOUSEASFROM',
292
                        '.. or select a field to use as reply to address'
293
                    ),
294
                    $validEmailFromFields->map('ID', 'Title')
295
                )->setEmptyString(' ')
296
            )
297
                ->setTitle(_t(
298
                    'SilverStripe\\UserForms\\Model\\UserDefinedForm.REPLYADDRESS',
299
                    'Email for reply to'
300
                ))
301
                ->setDescription(_t(
302
                    'SilverStripe\\UserForms\\Model\\UserDefinedForm.REPLYADDRESS_DESCRIPTION',
303
                    'The email address which the recipient is able to \'reply\' to.'
304
                ))
305
        ]);
306
307
        $fields->fieldByName('Root.EmailDetails')->setTitle(_t(__CLASS__.'.EMAILDETAILSTAB', 'Email Details'));
308
309
        // Only show the preview link if the recipient has been saved.
310
        if (!empty($this->EmailTemplate)) {
0 ignored issues
show
Bug Best Practice introduced by
The property EmailTemplate does not exist on SilverStripe\UserForms\M...ecipient\EmailRecipient. Since you implemented __get, consider adding a @property annotation.
Loading history...
311
            $pageEditController = singleton(CMSPageEditController::class);
312
            $pageEditController
313
                ->getRequest()
314
                ->setSession(Controller::curr()->getRequest()->getSession());
315
316
            $preview = sprintf(
317
                '<p><a href="%s" target="_blank" class="btn btn-outline-secondary">%s</a></p><em>%s</em>',
318
                Controller::join_links(
319
                    $pageEditController->getEditForm()->FormAction(),
320
                    "field/EmailRecipients/item/{$this->ID}/preview"
321
                ),
322
                _t('SilverStripe\\UserForms\\Model\\UserDefinedForm.PREVIEW_EMAIL', 'Preview email'),
323
                _t(
324
                    'SilverStripe\\UserForms\\Model\\UserDefinedForm.PREVIEW_EMAIL_DESCRIPTION',
325
                    'Note: Unsaved changes will not appear in the preview.'
326
                )
327
            );
328
        } else {
329
            $preview = sprintf(
330
                '<em>%s</em>',
331
                _t(
332
                    'SilverStripe\\UserForms\\Model\\UserDefinedForm.PREVIEW_EMAIL_UNAVAILABLE',
333
                    'You can preview this email once you have saved the Recipient.'
334
                )
335
            );
336
        }
337
338
        // Email templates
339
        $fields->addFieldsToTab('Root.EmailContent', [
340
            CheckboxField::create(
341
                'HideFormData',
342
                _t('SilverStripe\\UserForms\\Model\\UserDefinedForm.HIDEFORMDATA', 'Hide form data from email?')
343
            ),
344
            CheckboxField::create(
345
                'SendPlain',
346
                _t(
347
                    'SilverStripe\\UserForms\\Model\\UserDefinedForm.SENDPLAIN',
348
                    'Send email as plain text? (HTML will be stripped)'
349
                )
350
            ),
351
            DropdownField::create(
352
                'EmailTemplate',
353
                _t('SilverStripe\\UserForms\\Model\\UserDefinedForm.EMAILTEMPLATE', 'Email template'),
354
                $this->getEmailTemplateDropdownValues()
355
            )->addExtraClass('toggle-html-only'),
356
            HTMLEditorField::create(
357
                'EmailBodyHtml',
358
                _t('SilverStripe\\UserForms\\Model\\UserDefinedForm.EMAILBODYHTML', 'Body')
359
            )
360
                ->addExtraClass('toggle-html-only'),
361
            TextareaField::create(
362
                'EmailBody',
363
                _t('SilverStripe\\UserForms\\Model\\UserDefinedForm.EMAILBODY', 'Body')
364
            )
365
                ->addExtraClass('toggle-plain-only'),
366
            LiteralField::create('EmailPreview', $preview)
367
        ]);
368
369
        $fields->fieldByName('Root.EmailContent')->setTitle(_t(__CLASS__.'.EMAILCONTENTTAB', 'Email Content'));
370
371
        // Custom rules for sending this field
372
        $grid = GridField::create(
373
            'CustomRules',
374
            _t('SilverStripe\\UserForms\\Model\\EditableFormField.CUSTOMRULES', 'Custom Rules'),
375
            $this->CustomRules(),
0 ignored issues
show
Bug introduced by
The method CustomRules() does not exist on SilverStripe\UserForms\M...ecipient\EmailRecipient. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

375
            $this->/** @scrutinizer ignore-call */ 
376
                   CustomRules(),
Loading history...
376
            $this->getRulesConfig()
0 ignored issues
show
Bug introduced by
$this->getRulesConfig() of type SilverStripe\Forms\GridField\GridFieldConfig is incompatible with the type array expected by parameter $args of SilverStripe\View\ViewableData::create(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

376
            /** @scrutinizer ignore-type */ $this->getRulesConfig()
Loading history...
377
        );
378
        $grid->setDescription(_t(
379
            'SilverStripe\\UserForms\\Model\\UserDefinedForm.RulesDescription',
380
            'Emails will only be sent to the recipient if the custom rules are met. If no rules are defined, this receipient will receive notifications for every submission.'
381
        ));
382
        $fields->addFieldsToTab('Root.CustomRules', [
383
            DropdownField::create(
384
                'CustomRulesCondition',
385
                _t('SilverStripe\\UserForms\\Model\\UserDefinedForm.SENDIF', 'Send condition'),
386
                [
387
                    'Or' => _t('SilverStripe\\UserForms\\Model\\UserDefinedForm.SENDIFOR', 'Any conditions are true'),
388
                    'And' => _t('SilverStripe\\UserForms\\Model\\UserDefinedForm.SENDIFAND', 'All conditions are true')
389
                ]
390
            ),
391
            $grid
392
        ]);
393
394
        $fields->fieldByName('Root.CustomRules')->setTitle(_t(__CLASS__.'.CUSTOMRULESTAB', 'Custom Rules'));
395
396
        $this->extend('updateCMSFields', $fields);
397
        return $fields;
398
    }
399
400
    /**
401
     * Return whether a user can create an object of this type
402
     *
403
     * @param Member $member
0 ignored issues
show
Bug introduced by
The type SilverStripe\UserForms\Model\Recipient\Member was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
404
     * @param array $context Virtual parameter to allow context to be passed in to check
405
     * @return bool
406
     */
407 View Code Duplication
    public function canCreate($member = null, $context = [])
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
408
    {
409
        // Check parent page
410
        $parent = $this->getCanCreateContext(func_get_args());
411
        if ($parent) {
412
            return $parent->canEdit($member);
413
        }
414
415
        // Fall back to secure admin permissions
416
        return parent::canCreate($member);
417
    }
418
419
    /**
420
     * Helper method to check the parent for this object
421
     *
422
     * @param array $args List of arguments passed to canCreate
423
     * @return SiteTree Parent page instance
0 ignored issues
show
Bug introduced by
The type SilverStripe\UserForms\Model\Recipient\SiteTree was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
424
     */
425
    protected function getCanCreateContext($args)
426
    {
427
        // Inspect second parameter to canCreate for a 'Parent' context
428
        if (isset($args[1][Form::class])) {
429
            return $args[1][Form::class];
430
        }
431
        // Hack in currently edited page if context is missing
432
        if (Controller::has_curr() && Controller::curr() instanceof CMSMain) {
433
            return Controller::curr()->currentPage();
434
        }
435
436
        // No page being edited
437
        return null;
438
    }
439
440
    /**
441
     * @param Member
442
     *
443
     * @return boolean
444
     */
445
    public function canView($member = null)
446
    {
447
        if ($form = $this->Form()) {
0 ignored issues
show
Bug introduced by
The method Form() does not exist on SilverStripe\UserForms\M...ecipient\EmailRecipient. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

447
        if ($form = $this->/** @scrutinizer ignore-call */ Form()) {
Loading history...
448
            return $form->canView($member);
449
        }
450
451
        return parent::canView($member);
452
    }
453
454
    /**
455
     * @param Member
456
     *
457
     * @return boolean
458
     */
459
    public function canEdit($member = null)
460
    {
461
        if ($form = $this->Form()) {
462
            return $form->canEdit($member);
463
        }
464
465
        return parent::canEdit($member);
466
    }
467
468
    /**
469
     * @param Member
470
     *
471
     * @return boolean
472
     */
473
    public function canDelete($member = null)
474
    {
475
        return $this->canEdit($member);
476
    }
477
478
    /**
479
     * Determine if this recipient may receive notifications for this submission
480
     *
481
     * @param array $data
482
     * @param Form $form
483
     * @return bool
484
     */
485
    public function canSend($data, $form)
0 ignored issues
show
Unused Code introduced by
The parameter $form is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

485
    public function canSend($data, /** @scrutinizer ignore-unused */ $form)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
486
    {
487
        // Skip if no rules configured
488
        $customRules = $this->CustomRules();
489
        if (!$customRules->count()) {
490
            return true;
491
        }
492
493
        // Check all rules
494
        $isAnd = $this->CustomRulesCondition === 'And';
0 ignored issues
show
Bug Best Practice introduced by
The property CustomRulesCondition does not exist on SilverStripe\UserForms\M...ecipient\EmailRecipient. Since you implemented __get, consider adding a @property annotation.
Loading history...
495
        foreach ($customRules as $customRule) {
496
            /** @var EmailRecipientCondition  $customRule */
497
            $matches = $customRule->matches($data);
498
            if ($isAnd && !$matches) {
499
                return false;
500
            }
501
            if (!$isAnd && $matches) {
502
                return true;
503
            }
504
        }
505
506
        // Once all rules are checked
507
        return $isAnd;
508
    }
509
510
    /**
511
     * Make sure the email template saved against the recipient exists on the file system.
512
     *
513
     * @param string
514
     *
515
     * @return boolean
516
     */
517
    public function emailTemplateExists($template = '')
518
    {
519
        $t = ($template ? $template : $this->EmailTemplate);
0 ignored issues
show
Bug Best Practice introduced by
The property EmailTemplate does not exist on SilverStripe\UserForms\M...ecipient\EmailRecipient. Since you implemented __get, consider adding a @property annotation.
Loading history...
520
521
        return array_key_exists($t, $this->getEmailTemplateDropdownValues());
522
    }
523
524
    /**
525
     * Get the email body for the current email format
526
     *
527
     * @return string
528
     */
529
    public function getEmailBodyContent()
530
    {
531
        if ($this->SendPlain) {
0 ignored issues
show
Bug Best Practice introduced by
The property SendPlain does not exist on SilverStripe\UserForms\M...ecipient\EmailRecipient. Since you implemented __get, consider adding a @property annotation.
Loading history...
532
            return DBField::create_field('HTMLText', $this->EmailBody)->Plain();
0 ignored issues
show
Bug Best Practice introduced by
The property EmailBody does not exist on SilverStripe\UserForms\M...ecipient\EmailRecipient. Since you implemented __get, consider adding a @property annotation.
Loading history...
533
        }
534
        return DBField::create_field('HTMLText', $this->EmailBodyHtml);
0 ignored issues
show
Bug Best Practice introduced by
The property EmailBodyHtml does not exist on SilverStripe\UserForms\M...ecipient\EmailRecipient. Since you implemented __get, consider adding a @property annotation.
Loading history...
535
    }
536
537
    /**
538
     * Gets a list of email templates suitable for populating the email template dropdown.
539
     *
540
     * @return array
541
     */
542
    public function getEmailTemplateDropdownValues()
543
    {
544
        $templates = [];
545
546
        $finder = new FileFinder();
547
        $finder->setOption('name_regex', '/^.*\.ss$/');
548
549
        $templateDirectory = UserDefinedForm::config()->get('email_template_directory');
550
        // Handle cases where "userforms" might not be the base module directory, e.g. in a Travis build
551
        if (!file_exists(BASE_PATH . DIRECTORY_SEPARATOR . $templateDirectory)
552
            && substr($templateDirectory, 0, 10) === 'userforms/'
553
        ) {
554
            $templateDirectory = substr($templateDirectory, 10);
555
        }
556
        $found = $finder->find(BASE_PATH . DIRECTORY_SEPARATOR . $templateDirectory);
557
558
        foreach ($found as $key => $value) {
559
            $template = pathinfo($value);
560
            $templatePath = substr(
561
                $template['dirname'] . DIRECTORY_SEPARATOR . $template['filename'],
562
                strlen(BASE_PATH) + 1
563
            );
564
565
            $defaultPrefixes = ['userforms/templates/', 'templates/'];
566
            foreach ($defaultPrefixes as $defaultPrefix) {
567
                // Remove default userforms folder if it's provided
568
                if (substr($templatePath, 0, strlen($defaultPrefix)) === $defaultPrefix) {
569
                    $templatePath = substr($templatePath, strlen($defaultPrefix));
570
                    break;
571
                }
572
            }
573
            $templates[$templatePath] = $template['filename'];
574
        }
575
576
        return $templates;
577
    }
578
579
    /**
580
     * Validate that valid email addresses are being used
581
     *
582
     * @return ValidationResult
0 ignored issues
show
Bug introduced by
The type SilverStripe\UserForms\M...ipient\ValidationResult was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
583
     */
584
    public function validate()
585
    {
586
        $result = parent::validate();
587
        $checkEmail = [
588
            'EmailAddress' => 'EMAILADDRESSINVALID',
589
            'EmailFrom' => 'EMAILFROMINVALID',
590
            'EmailReplyTo' => 'EMAILREPLYTOINVALID',
591
        ];
592
        foreach ($checkEmail as $check => $translation) {
593
            if ($this->$check) {
594
                //may be a comma separated list of emails
595
                $addresses = explode(',', $this->$check);
596
                foreach ($addresses as $address) {
597
                    $trimAddress = trim($address);
598
                    if ($trimAddress && !Email::is_valid_address($trimAddress)) {
599
                        $error = _t(
600
                            __CLASS__.".$translation",
601
                            "Invalid email address $trimAddress"
602
                        );
603
                        $result->addError($error . " ($trimAddress)");
604
                    }
605
                }
606
            }
607
        }
608
        return $result;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $result returns the type SilverStripe\ORM\ValidationResult which is incompatible with the documented return type SilverStripe\UserForms\M...ipient\ValidationResult.
Loading history...
609
    }
610
}
611