RegistrationValidator   A
last analyzed

Complexity

Total Complexity 34

Size/Duplication

Total Lines 203
Duplicated Lines 0 %

Importance

Changes 3
Bugs 0 Features 0
Metric Value
eloc 92
c 3
b 0
f 0
dl 0
loc 203
rs 9.68
wmc 34

9 Methods

Rating   Name   Duplication   Size   Complexity  
A getValidator() 0 17 3
A __construct() 0 4 1
A isSpamCheckFailed() 0 14 1
B isValid() 0 40 8
A getNotEmptyValidator() 0 9 1
A validateDefaultFields() 0 18 6
A isInvalidPriceOption() 0 10 3
A validatePriceOption() 0 26 6
A validatePaymentMethod() 0 13 5
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->validatePaymentMethod($value);
63
        $this->validatePriceOption($value);
64
65
        $requiredFields = array_map('trim', explode(',', $settings['registration']['requiredFields'] ?? ''));
66
        foreach ($requiredFields as $requiredField) {
67
            if ($requiredField !== '' && $value->_hasProperty($requiredField)) {
68
                $validator = $this->getValidator(gettype($value->_getProperty($requiredField)), $requiredField);
69
                $validationResult = $validator->validate($value->_getProperty($requiredField));
70
                if ($validationResult->hasErrors()) {
71
                    foreach ($validationResult->getErrors() as $error) {
72
                        $this->result->forProperty($requiredField)->addError($error);
73
                    }
74
                }
75
            }
76
        }
77
78
        $event = new ModifyRegistrationValidatorResultEvent(
79
            $value,
80
            $settings,
81
            $this->result,
82
            $this->getRequest()
83
        );
84
        $this->eventDispatcher->dispatch($event);
85
    }
86
87
    /**
88
     * Validates the default fields of a registration, that must be filled out. Since domain object validation
89
     * did not work as expected with registration fields (domain object validation results completely ignored)
90
     * this own validation is done
91
     *
92
     * Checks:
93
     * - firstname: NotEmpty
94
     * - lastname: NotEmpty
95
     * - email: NotEmpty, EmailAddress
96
     */
97
    protected function validateDefaultFields(Registration $value): void
98
    {
99
        $defaultFields = ['firstname', 'lastname', 'email'];
100
        foreach ($defaultFields as $defaultField) {
101
            $validator = $this->getNotEmptyValidator();
102
            $validationResult = $validator->validate($value->_getProperty($defaultField));
103
            if ($validationResult->hasErrors()) {
104
                foreach ($validationResult->getErrors() as $error) {
105
                    $this->result->forProperty($defaultField)->addError($error);
106
                }
107
            }
108
        }
109
110
        $validator = new EmailAddressValidator();
111
        $validationResult = $validator->validate($value->_getProperty('email'));
112
        if ($validationResult->hasErrors()) {
113
            foreach ($validationResult->getErrors() as $error) {
114
                $this->result->forProperty('email')->addError($error);
115
            }
116
        }
117
    }
118
119
    /**
120
     * Processes the spam check and returns, if it failed or not
121
     *
122
     * @throws SpamCheckNotFoundException
123
     */
124
    protected function isSpamCheckFailed(Registration $registration, array $settings): bool
125
    {
126
        $pluginKey = 'tx_sfeventmgt_pieventregistration';
127
        $getMergedWithPost = $this->getRequest()->getQueryParams()[$pluginKey] ?? [];
128
        $parsedBody = (array)$this->getRequest()->getParsedBody();
129
        ArrayUtility::mergeRecursiveWithOverrule($getMergedWithPost, $parsedBody[$pluginKey] ?? []);
130
131
        $spamCheckService = new SpamCheckService(
132
            $registration,
133
            $settings,
134
            $getMergedWithPost
135
        );
136
137
        return $spamCheckService->isSpamCheckFailed();
138
    }
139
140
    /**
141
     * Returns a validator object depending on the given type of the property
142
     */
143
    protected function getValidator(string $type, string $field): AbstractValidator
144
    {
145
        switch ($type) {
146
            case 'boolean':
147
                $validator = new BooleanValidator();
148
                $validator->setOptions(['is' => true]);
149
                break;
150
            default:
151
                if ($field === 'captcha') {
152
                    $validator = new CaptchaValidator($this->configurationManager);
153
                    $validator->setRequest($this->getRequest());
154
                } else {
155
                    $validator = $this->getNotEmptyValidator();
156
                }
157
        }
158
159
        return $validator;
160
    }
161
162
    protected function getNotEmptyValidator(): NotEmptyValidator
163
    {
164
        $validator = new NotEmptyValidator();
165
        $validator->setOptions([
166
            'nullMessage' => 'LLL:EXT:sf_event_mgt/Resources/Private/Language/locallang.xlf:validation.required_field',
167
            'emptyMessage' => 'LLL:EXT:sf_event_mgt/Resources/Private/Language/locallang.xlf:validation.required_field',
168
        ]);
169
170
        return $validator;
171
    }
172
173
    protected function validatePaymentMethod(Registration $registration): void
174
    {
175
        $event = $registration->getEvent();
176
        if ($event === null || $event->getEnablePayment() === false) {
177
            // Payment is not enablled for event
178
            return;
179
        }
180
181
        $validator = $this->getNotEmptyValidator();
182
        $validationResult = $validator->validate($registration->getPaymentmethod());
183
        if ($validationResult->hasErrors()) {
184
            foreach ($validationResult->getErrors() as $error) {
185
                $this->result->forProperty('paymentmethod')->addError($error);
186
            }
187
        }
188
    }
189
190
    protected function validatePriceOption(Registration $registration): void
191
    {
192
        $event = $registration->getEvent();
193
        if ($event === null || $event->getActivePriceOptions() === []) {
194
            // No price option check, since event has no price options
195
            return;
196
        }
197
198
        $validator = $this->getNotEmptyValidator();
199
        $validationResult = $validator->validate($registration->getPriceOption());
200
        if ($validationResult->hasErrors()) {
201
            foreach ($validationResult->getErrors() as $error) {
202
                $this->result->forProperty('priceOption')->addError($error);
203
            }
204
205
            // No further checks required, since the price option is empty
206
            return;
207
        }
208
209
        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

209
        if ($this->isInvalidPriceOption(/** @scrutinizer ignore-type */ $registration->getPriceOption(), $event)) {
Loading history...
210
            $message = LocalizationUtility::translate('validation.invalid_priceoption', 'SfEventMgt');
211
            $error = new Error(
212
                $message ?? 'Invalid price option selected.',
213
                1727776820
214
            );
215
            $this->result->forProperty('priceOption')->addError($error);
216
        }
217
    }
218
219
    /**
220
     * Checks, if the given price option is an active price option of the event. Returns
221
     * true, if the price option is valid, else false is returned.
222
     */
223
    protected function isInvalidPriceOption(PriceOption $priceOption, Event $event): bool
224
    {
225
        foreach ($event->getActivePriceOptions() as $eventPriceOption) {
226
            if ($eventPriceOption->getUid() === $priceOption->getUid()) {
227
                // The price option is valid
228
                return false;
229
            }
230
        }
231
232
        return true;
233
    }
234
}
235