Passed
Push — typo3-v13 ( ba73f3...83a476 )
by Torben
02:10
created

RegistrationValidator::validatePriceOption()   A

Complexity

Conditions 6
Paths 5

Size

Total Lines 26
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 6
eloc 15
nc 5
nop 1
dl 0
loc 26
rs 9.2222
c 0
b 0
f 0
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\Core\Utility\GeneralUtility;
23
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...
24
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...
25
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...
26
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...
27
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...
28
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...
29
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...
30
31
/**
32
 * RegistrationValidator
33
 */
34
class RegistrationValidator extends AbstractValidator
35
{
36
    protected ConfigurationManagerInterface $configurationManager;
37
    protected EventDispatcherInterface $eventDispatcher;
38
    protected array $settings;
39
40
    public function __construct()
41
    {
42
        // @todo Use CPP in sf_event_mgt v8 (breaking change)
43
        $this->configurationManager = GeneralUtility::makeInstance(ConfigurationManagerInterface::class);
44
        $this->eventDispatcher = GeneralUtility::makeInstance(EventDispatcherInterface::class);
45
46
        $this->settings = $this->configurationManager->getConfiguration(
47
            ConfigurationManagerInterface::CONFIGURATION_TYPE_SETTINGS,
48
            'SfEventMgt',
49
            'Pieventregistration'
50
        );
51
    }
52
53
    /**
54
     * Validates the given registration according to required fields set in plugin
55
     * settings. For boolean fields, the booleanValidator is used and it is assumed,
56
     * that boolean fields must have the value "TRUE" (for checkboxes)
57
     *
58
     * @param Registration $value Registration
59
     */
60
    protected function isValid(mixed $value): void
61
    {
62
        $spamSettings = $this->settings['registration']['spamCheck'] ?? [];
63
        if ((bool)($spamSettings['enabled'] ?? false) && $this->isSpamCheckFailed($value, $spamSettings)) {
64
            $message = $this->translateErrorMessage('registration.spamCheckFailed', 'SfEventMgt');
65
            $this->addErrorForProperty('spamCheck', $message, 1578855253);
66
67
            return;
68
        }
69
70
        $this->validateDefaultFields($value);
71
        $this->validatePriceOption($value);
72
73
        $requiredFields = array_map('trim', explode(',', $this->settings['registration']['requiredFields'] ?? ''));
74
        foreach ($requiredFields as $requiredField) {
75
            if ($requiredField !== '' && $value->_hasProperty($requiredField)) {
76
                $validator = $this->getValidator(gettype($value->_getProperty($requiredField)), $requiredField);
77
                $validationResult = $validator->validate($value->_getProperty($requiredField));
78
                if ($validationResult->hasErrors()) {
79
                    foreach ($validationResult->getErrors() as $error) {
80
                        $this->result->forProperty($requiredField)->addError($error);
81
                    }
82
                }
83
            }
84
        }
85
86
        $event = new ModifyRegistrationValidatorResultEvent(
87
            $value,
88
            $this->settings,
89
            $this->result,
90
            $this->getRequest()
91
        );
92
        $this->eventDispatcher->dispatch($event);
93
    }
94
95
    /**
96
     * Validates the default fields of a registration, that must be filled out. Since domain object validation
97
     * did not work as expected with registration fields (domain object validation results completely ignored)
98
     * this own validation is done
99
     *
100
     * Checks:
101
     * - firstname: NotEmpty
102
     * - lastname: NotEmpty
103
     * - email: NotEmpty, EmailAddress
104
     */
105
    protected function validateDefaultFields(Registration $value): bool
106
    {
107
        $result = true;
108
109
        $defaultFields = ['firstname', 'lastname', 'email'];
110
        foreach ($defaultFields as $defaultField) {
111
            $validator = new NotEmptyValidator();
112
            $validationResult = $validator->validate($value->_getProperty($defaultField));
113
            if ($validationResult->hasErrors()) {
114
                $result = false;
115
                foreach ($validationResult->getErrors() as $error) {
116
                    $this->result->forProperty($defaultField)->addError($error);
117
                }
118
            }
119
        }
120
121
        $validator = new EmailAddressValidator();
122
        $validationResult = $validator->validate($value->_getProperty('email'));
123
        if ($validationResult->hasErrors()) {
124
            $result = false;
125
            foreach ($validationResult->getErrors() as $error) {
126
                $this->result->forProperty('email')->addError($error);
127
            }
128
        }
129
130
        return $result;
131
    }
132
133
    /**
134
     * Processes the spam check and returns, if it failed or not
135
     *
136
     * @throws SpamCheckNotFoundException
137
     */
138
    protected function isSpamCheckFailed(Registration $registration, array $settings): bool
139
    {
140
        $pluginKey = 'tx_sfeventmgt_pieventregistration';
141
        $getMergedWithPost = $this->getRequest()->getQueryParams()[$pluginKey];
142
        ArrayUtility::mergeRecursiveWithOverrule($getMergedWithPost, $this->getRequest()->getParsedBody()[$pluginKey] ?? []);
143
144
        $spamCheckService = new SpamCheckService(
145
            $registration,
146
            $settings,
147
            $getMergedWithPost
148
        );
149
150
        return $spamCheckService->isSpamCheckFailed();
151
    }
152
153
    /**
154
     * Returns a validator object depending on the given type of the property
155
     */
156
    protected function getValidator(string $type, string $field): AbstractValidator
157
    {
158
        switch ($type) {
159
            case 'boolean':
160
                $validator = new BooleanValidator();
161
                $validator->setOptions(['is' => true]);
162
                break;
163
            default:
164
                if ($field === 'captcha') {
165
                    $validator = new CaptchaValidator();
166
                } else {
167
                    $validator = new NotEmptyValidator();
168
                }
169
        }
170
171
        return $validator;
172
    }
173
174
    protected function validatePriceOption(Registration $registration): void
175
    {
176
        $event = $registration->getEvent();
177
        if ($event === null || $event->getActivePriceOptions() === []) {
178
            // No price option check, since event has no price options
179
            return;
180
        }
181
182
        $validator = new NotEmptyValidator();
183
        $validationResult = $validator->validate($registration->getPriceOption());
184
        if ($validationResult->hasErrors()) {
185
            foreach ($validationResult->getErrors() as $error) {
186
                $this->result->forProperty('priceOption')->addError($error);
187
            }
188
189
            // No further checks required, since the price option is empty
190
            return;
191
        }
192
193
        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

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