-
Notifications
You must be signed in to change notification settings - Fork 195
/
Copy pathValidationRouteData.php
149 lines (126 loc) · 3.93 KB
/
ValidationRouteData.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
<?php
namespace Give\DonationForms\DataTransferObjects;
use Give\DonationForms\Exceptions\DonationFormFieldErrorsException;
use Give\DonationForms\Exceptions\DonationFormForbidden;
use Give\DonationForms\Models\DonationForm;
use Give\Framework\FieldsAPI\Actions\CreateValidatorFromFormFields;
use Give\Framework\FieldsAPI\Exceptions\NameCollisionException;
use Give\Framework\FieldsAPI\Field;
use Give\Framework\FieldsAPI\SecurityChallenge;
use Give\Framework\Http\Response\Types\JsonResponse;
use Give\Framework\Support\Contracts\Arrayable;
use WP_Error;
/**
* @since 3.0.0
*/
class ValidationRouteData implements Arrayable
{
/**
* @var array
*/
private $requestData;
/**
* @var int
*/
public $formId;
/**
* Convert data from request into DTO
*
* @since 3.0.0
*/
public static function fromRequest(array $requestData): self
{
$self = new self();
$self->formId = (int)$requestData['formId'];
$self->requestData = $requestData;
return $self;
}
/**
* This method loops over the form schema to
* compares the request against the individual fields,
* their types and validation rules.
*
* @unreleased updated to exclude security challenge fields during pre-validation
* @since 3.22.0 added additional validation for form validity, added givewp_donation_form_fields_validated action
* @since 3.0.0
*
* @throws DonationFormFieldErrorsException|NameCollisionException|DonationFormForbidden
*/
public function validate(): JsonResponse
{
$request = $this->getRequestData();
/** @var DonationForm $form */
$form = DonationForm::find($this->formId);
if (!$form || !$this->isValidForm($form)) {
throw new DonationFormForbidden();
}
$formFields = array_filter($form->schema()->getFields(), function ($field) use ($request) {
return array_key_exists($field->getName(), $request) && !$this->isSecurityChallengeField($field);
});
$validator = (new CreateValidatorFromFormFields())($formFields, $request);
if ($validator->fails()) {
$this->throwDonationFormFieldErrorsException($validator->errors());
}
$validatedValues = $validator->validated();
/**
* @since 3.22.0
/**
* @param array $validatedValues validated values in key value pairs
*/
do_action('givewp_donation_form_fields_validated', $validatedValues);
return new JsonResponse(['valid' => true]);
}
/**
* @since 3.0.0
*/
public function getRequestData(): array
{
return $this->requestData;
}
/**
* This loops over an array of errors in the specific FieldAPI format,
* and converts them into a WP_Error object that is attached to the
* exception and delivered back to the client via JSON.
*
* @since 3.0.0
*
* @param array<string, string> $errors
*
* @throws DonationFormFieldErrorsException
*/
private function throwDonationFormFieldErrorsException(array $errors): void
{
$wpError = new WP_Error();
foreach ($errors as $id => $error) {
$wpError->add($id, $error);
}
throw new DonationFormFieldErrorsException($wpError);
}
/**
* @since 3.22.0
*/
private function isValidForm(DonationForm $form): bool
{
if ($form->status->isTrash()) {
return false;
}
if (!$form->status->isPublished() && !current_user_can('edit_give_forms')) {
return false;
}
return true;
}
/**
* @since 3.0.0
*/
public function toArray(): array
{
return get_object_vars($this);
}
/**
* @unreleased
*/
protected function isSecurityChallengeField(Field $field): bool
{
return is_subclass_of($field, SecurityChallenge::class);
}
}