Passed
Push — main ( 52a7ec...5410b3 )
by Torben
03:32
created

RegistrationValidator   A

Complexity

Total Complexity 29

Size/Duplication

Total Lines 184
Duplicated Lines 0 %

Importance

Changes 5
Bugs 0 Features 0
Metric Value
eloc 82
c 5
b 0
f 0
dl 0
loc 184
rs 10
wmc 29

8 Methods

Rating   Name   Duplication   Size   Complexity  
A getNotEmptyValidator() 0 9 1
A isInvalidPriceOption() 0 10 3
A validatePriceOption() 0 26 6
A getValidator() 0 17 3
A isSpamCheckFailed() 0 13 1
B isValid() 0 39 8
A validateDefaultFields() 0 18 6
A __construct() 0 4 1
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of the Extension "sf_event_mgt" for TYPO3 CMS.
7
 *
8
 * For the full copyright and license information, please read the
9
 * LICENSE.txt file that was distributed with this source code.
10
 */
11
12
namespace DERHANSEN\SfEventMgt\Validation\Validator;
13
14
use DERHANSEN\SfEventMgt\Domain\Model\Event;
15
use DERHANSEN\SfEventMgt\Domain\Model\PriceOption;
16
use DERHANSEN\SfEventMgt\Domain\Model\Registration;
17
use DERHANSEN\SfEventMgt\Event\ModifyRegistrationValidatorResultEvent;
0 ignored issues
show
Bug introduced by
The type DERHANSEN\SfEventMgt\Eve...ionValidatorResultEvent 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...
18
use DERHANSEN\SfEventMgt\Service\SpamCheckService;
19
use DERHANSEN\SfEventMgt\SpamChecks\Exceptions\SpamCheckNotFoundException;
20
use Psr\EventDispatcher\EventDispatcherInterface;
21
use TYPO3\CMS\Core\Utility\ArrayUtility;
22
use TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface;
0 ignored issues
show
Bug introduced by
The type TYPO3\CMS\Extbase\Config...urationManagerInterface 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...
23
use TYPO3\CMS\Extbase\Utility\LocalizationUtility;
0 ignored issues
show
Bug introduced by
The type TYPO3\CMS\Extbase\Utility\LocalizationUtility 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...
24
use TYPO3\CMS\Extbase\Validation\Error;
0 ignored issues
show
Bug introduced by
The type TYPO3\CMS\Extbase\Validation\Error 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...
25
use TYPO3\CMS\Extbase\Validation\Validator\AbstractValidator;
0 ignored issues
show
Bug introduced by
The type TYPO3\CMS\Extbase\Valida...dator\AbstractValidator 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...
26
use TYPO3\CMS\Extbase\Validation\Validator\BooleanValidator;
0 ignored issues
show
Bug introduced by
The type TYPO3\CMS\Extbase\Valida...idator\BooleanValidator 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...
27
use TYPO3\CMS\Extbase\Validation\Validator\EmailAddressValidator;
0 ignored issues
show
Bug introduced by
The type TYPO3\CMS\Extbase\Valida...r\EmailAddressValidator 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...
28
use TYPO3\CMS\Extbase\Validation\Validator\NotEmptyValidator;
0 ignored issues
show
Bug introduced by
The type TYPO3\CMS\Extbase\Valida...dator\NotEmptyValidator 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...
29
30
class RegistrationValidator extends AbstractValidator
31
{
32
    public function __construct(
33
        protected readonly ConfigurationManagerInterface $configurationManager,
34
        protected readonly EventDispatcherInterface $eventDispatcher
35
    ) {
36
    }
37
38
    /**
39
     * Validates the given registration according to required fields set in plugin
40
     * settings. For boolean fields, the booleanValidator is used and it is assumed,
41
     * that boolean fields must have the value "TRUE" (for checkboxes)
42
     *
43
     * @param Registration $value Registration
44
     */
45
    protected function isValid(mixed $value): void
46
    {
47
        $settings = $this->configurationManager->getConfiguration(
48
            ConfigurationManagerInterface::CONFIGURATION_TYPE_SETTINGS,
49
            'SfEventMgt',
50
            'Pieventregistration'
51
        );
52
53
        $spamSettings = $settings['registration']['spamCheck'] ?? [];
54
        if ((bool)($spamSettings['enabled'] ?? false) && $this->isSpamCheckFailed($value, $spamSettings)) {
55
            $message = $this->translateErrorMessage('LLL:EXT:sf_event_mgt/Resources/Private/Language/locallang.xlf:registration.spamCheckFailed');
56
            $this->addErrorForProperty('spamCheck', $message, 1578855253);
57
58
            return;
59
        }
60
61
        $this->validateDefaultFields($value);
62
        $this->validatePriceOption($value);
63
64
        $requiredFields = array_map('trim', explode(',', $settings['registration']['requiredFields'] ?? ''));
65
        foreach ($requiredFields as $requiredField) {
66
            if ($requiredField !== '' && $value->_hasProperty($requiredField)) {
67
                $validator = $this->getValidator(gettype($value->_getProperty($requiredField)), $requiredField);
68
                $validationResult = $validator->validate($value->_getProperty($requiredField));
69
                if ($validationResult->hasErrors()) {
70
                    foreach ($validationResult->getErrors() as $error) {
71
                        $this->result->forProperty($requiredField)->addError($error);
72
                    }
73
                }
74
            }
75
        }
76
77
        $event = new ModifyRegistrationValidatorResultEvent(
78
            $value,
79
            $settings,
80
            $this->result,
81
            $this->getRequest()
82
        );
83
        $this->eventDispatcher->dispatch($event);
84
    }
85
86
    /**
87
     * Validates the default fields of a registration, that must be filled out. Since domain object validation
88
     * did not work as expected with registration fields (domain object validation results completely ignored)
89
     * this own validation is done
90
     *
91
     * Checks:
92
     * - firstname: NotEmpty
93
     * - lastname: NotEmpty
94
     * - email: NotEmpty, EmailAddress
95
     */
96
    protected function validateDefaultFields(Registration $value): void
97
    {
98
        $defaultFields = ['firstname', 'lastname', 'email'];
99
        foreach ($defaultFields as $defaultField) {
100
            $validator = $this->getNotEmptyValidator();
101
            $validationResult = $validator->validate($value->_getProperty($defaultField));
102
            if ($validationResult->hasErrors()) {
103
                foreach ($validationResult->getErrors() as $error) {
104
                    $this->result->forProperty($defaultField)->addError($error);
105
                }
106
            }
107
        }
108
109
        $validator = new EmailAddressValidator();
110
        $validationResult = $validator->validate($value->_getProperty('email'));
111
        if ($validationResult->hasErrors()) {
112
            foreach ($validationResult->getErrors() as $error) {
113
                $this->result->forProperty('email')->addError($error);
114
            }
115
        }
116
    }
117
118
    /**
119
     * Processes the spam check and returns, if it failed or not
120
     *
121
     * @throws SpamCheckNotFoundException
122
     */
123
    protected function isSpamCheckFailed(Registration $registration, array $settings): bool
124
    {
125
        $pluginKey = 'tx_sfeventmgt_pieventregistration';
126
        $getMergedWithPost = $this->getRequest()->getQueryParams()[$pluginKey];
127
        ArrayUtility::mergeRecursiveWithOverrule($getMergedWithPost, $this->getRequest()->getParsedBody()[$pluginKey] ?? []);
128
129
        $spamCheckService = new SpamCheckService(
130
            $registration,
131
            $settings,
132
            $getMergedWithPost
133
        );
134
135
        return $spamCheckService->isSpamCheckFailed();
136
    }
137
138
    /**
139
     * Returns a validator object depending on the given type of the property
140
     */
141
    protected function getValidator(string $type, string $field): AbstractValidator
142
    {
143
        switch ($type) {
144
            case 'boolean':
145
                $validator = new BooleanValidator();
146
                $validator->setOptions(['is' => true]);
147
                break;
148
            default:
149
                if ($field === 'captcha') {
150
                    $validator = new CaptchaValidator($this->configurationManager);
151
                    $validator->setRequest($this->getRequest());
152
                } else {
153
                    $validator = $this->getNotEmptyValidator();
154
                }
155
        }
156
157
        return $validator;
158
    }
159
160
    protected function getNotEmptyValidator(): NotEmptyValidator
161
    {
162
        $validator = new NotEmptyValidator();
163
        $validator->setOptions([
164
            'nullMessage' => 'LLL:EXT:sf_event_mgt/Resources/Private/Language/locallang.xlf:validation.required_field',
165
            'emptyMessage' => 'LLL:EXT:sf_event_mgt/Resources/Private/Language/locallang.xlf:validation.required_field',
166
        ]);
167
168
        return $validator;
169
    }
170
171
    protected function validatePriceOption(Registration $registration): void
172
    {
173
        $event = $registration->getEvent();
174
        if ($event === null || $event->getActivePriceOptions() === []) {
175
            // No price option check, since event has no price options
176
            return;
177
        }
178
179
        $validator = $this->getNotEmptyValidator();
180
        $validationResult = $validator->validate($registration->getPriceOption());
181
        if ($validationResult->hasErrors()) {
182
            foreach ($validationResult->getErrors() as $error) {
183
                $this->result->forProperty('priceOption')->addError($error);
184
            }
185
186
            // No further checks required, since the price option is empty
187
            return;
188
        }
189
190
        if ($this->isInvalidPriceOption($registration->getPriceOption(), $event)) {
0 ignored issues
show
Bug introduced by
It seems like $registration->getPriceOption() can also be of type null; however, parameter $priceOption of DERHANSEN\SfEventMgt\Val...:isInvalidPriceOption() does only seem to accept DERHANSEN\SfEventMgt\Domain\Model\PriceOption, maybe add an additional type check? ( Ignorable by Annotation )

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

190
        if ($this->isInvalidPriceOption(/** @scrutinizer ignore-type */ $registration->getPriceOption(), $event)) {
Loading history...
191
            $message = LocalizationUtility::translate('validation.invalid_priceoption', 'SfEventMgt');
192
            $error = new Error(
193
                $message ?? 'Invalid price option selected.',
194
                1727776820
195
            );
196
            $this->result->forProperty('priceOption')->addError($error);
197
        }
198
    }
199
200
    /**
201
     * Checks, if the given price option is an active price option of the event. Returns
202
     * true, if the price option is valid, else false is returned.
203
     */
204
    protected function isInvalidPriceOption(PriceOption $priceOption, Event $event): bool
205
    {
206
        foreach ($event->getActivePriceOptions() as $eventPriceOption) {
207
            if ($eventPriceOption->getUid() === $priceOption->getUid()) {
208
                // The price option is valid
209
                return false;
210
            }
211
        }
212
213
        return true;
214
    }
215
}
216