Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
83.58% |
56 / 67 |
|
71.43% |
5 / 7 |
CRAP | |
0.00% |
0 / 1 |
Validator | |
83.58% |
56 / 67 |
|
71.43% |
5 / 7 |
32.72 | |
0.00% |
0 / 1 |
getValidConstraints | |
83.33% |
10 / 12 |
|
0.00% |
0 / 1 |
7.23 | |||
validate | |
72.73% |
24 / 33 |
|
0.00% |
0 / 1 |
12.03 | |||
isValidString | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
2 | |||
isValidArray | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
2 | |||
isValidVersion | |
100.00% |
4 / 4 |
|
100.00% |
1 / 1 |
3 | |||
isValidSemVer | |
100.00% |
6 / 6 |
|
100.00% |
1 / 1 |
2 | |||
isTypeIdentifier | |
100.00% |
6 / 6 |
|
100.00% |
1 / 1 |
3 |
1 | <?php |
2 | |
3 | /** |
4 | * This program is free software; you can redistribute it and/or |
5 | * modify it under the terms of the GNU General Public License |
6 | * as published by the Free Software Foundation; under version 2 |
7 | * of the License (non-upgradable). |
8 | * |
9 | * This program is distributed in the hope that it will be useful, |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
12 | * GNU General Public License for more details. |
13 | * |
14 | * You should have received a copy of the GNU General Public License |
15 | * along with this program; if not, write to the Free Software |
16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
17 | * |
18 | * Copyright (c) 2016 (original work) Open Assessment Technologies SA; |
19 | * |
20 | */ |
21 | |
22 | namespace oat\taoQtiItem\model\portableElement\validator; |
23 | |
24 | use Naneau\SemVer\Regex; |
25 | use oat\taoQtiItem\model\portableElement\exception\PortableElementInconsistencyModelException; |
26 | use oat\taoQtiItem\model\portableElement\exception\PortableElementInvalidFieldException; |
27 | use oat\taoQtiItem\model\portableElement\exception\PortableElementInvalidModelException; |
28 | use oat\taoQtiItem\model\portableElement\element\PortableElementObject; |
29 | |
30 | class Validator |
31 | { |
32 | // phpcs:disable Generic.NamingConventions.UpperCaseConstantName |
33 | public const NotEmpty = 'NotEmpty'; |
34 | public const AlphaNum = 'AlphaNum'; |
35 | public const Callback = 'Callback'; |
36 | public const DateTime = 'DateTime'; |
37 | public const Email = 'Email'; |
38 | public const Equals = 'Equals'; |
39 | public const FileMimeType = 'FileMimeType'; |
40 | public const FileName = 'FileName'; |
41 | public const FileSize = 'FileSize'; |
42 | public const IndexIdentifier = 'IndexIdentifier'; |
43 | public const Integer = 'Integer'; |
44 | public const Length = 'Length'; |
45 | public const Numeric = 'Numeric'; |
46 | public const Password = 'Password'; |
47 | public const PasswordStrength = 'PasswordStrength'; |
48 | public const Regex = 'Regex'; |
49 | public const Unique = 'Unique'; |
50 | public const Url = 'Url'; |
51 | public const isArray = 'isArray'; |
52 | public const isString = 'isString'; |
53 | public const isVersion = 'isVersion'; |
54 | public const isTypeIdentifier = 'isTypeIdentifier'; |
55 | public const isSemVer = 'isValidSemVer'; |
56 | // phpcs:enable Generic.NamingConventions.UpperCaseConstantName |
57 | |
58 | protected static $customValidators = [ |
59 | self::isTypeIdentifier => 'isTypeIdentifier', |
60 | self::isArray => 'isValidArray', |
61 | self::isString => 'isValidString', |
62 | self::isVersion => 'isValidVersion', |
63 | self::isSemVer => 'isValidSemVer' |
64 | ]; |
65 | |
66 | protected static function getValidConstraints(array $requirements, $validationGroup = []) |
67 | { |
68 | $validConstraints = []; |
69 | |
70 | foreach ($requirements as $field => $constraints) { |
71 | if (!empty($validationGroup) && !in_array($field, $validationGroup)) { |
72 | continue; |
73 | } |
74 | |
75 | if (is_array($constraints)) { |
76 | $validators = $constraints; |
77 | } else { |
78 | $validators = explode(',', $constraints); |
79 | } |
80 | |
81 | foreach ($validators as $validator) { |
82 | if (array_key_exists($validator, self::$customValidators)) { |
83 | $validConstraints[$field][] = $validator; |
84 | } else { |
85 | $validConstraints[$field][] = \tao_helpers_form_FormFactory::getValidator($validator); |
86 | } |
87 | } |
88 | } |
89 | |
90 | return $validConstraints; |
91 | } |
92 | |
93 | /** |
94 | * @param PortableElementObject $object |
95 | * @param Validatable $validatable |
96 | * @param array $validationGroup |
97 | * @return bool |
98 | * @throws PortableElementInconsistencyModelException |
99 | * @throws PortableElementInvalidModelException |
100 | * @throws \common_exception_Error |
101 | */ |
102 | public static function validate(PortableElementObject $object, Validatable $validatable, $validationGroup = []) |
103 | { |
104 | $constraints = self::getValidConstraints($validatable->getConstraints(), $validationGroup); |
105 | $errorReport = \common_report_Report::createFailure('Portable element validation has failed.'); |
106 | |
107 | foreach ($constraints as $field => $constraint) { |
108 | foreach ($constraint as $validator) { |
109 | $getter = 'get' . ucfirst($field); |
110 | if (! method_exists($object, $getter)) { |
111 | throw new PortableElementInconsistencyModelException( |
112 | 'Validator is not correctly set for model ' . get_class($object) |
113 | ); |
114 | } |
115 | $value = $object->$getter(); |
116 | |
117 | if ($validator instanceof \tao_helpers_form_Validator) { |
118 | if (! $validator->evaluate($value)) { |
119 | $subReport = \common_report_Report::createFailure( |
120 | __("Unable to validate %s: %s", $field, $validator->getMessage()) |
121 | ); |
122 | $errorReport->add($subReport); |
123 | } |
124 | continue; |
125 | } |
126 | |
127 | if (is_string($validator)) { |
128 | if (array_key_exists($validator, self::$customValidators)) { |
129 | $callable = self::$customValidators[$validator]; |
130 | try { |
131 | self::$callable($value); |
132 | } catch (PortableElementInvalidFieldException $e) { |
133 | $subReport = \common_report_Report::createFailure( |
134 | __("Unable to validate %s: %s", $field, $e->getMessage()) |
135 | ); |
136 | $errorReport->add($subReport); |
137 | } |
138 | } |
139 | continue; |
140 | } |
141 | |
142 | return false; |
143 | } |
144 | } |
145 | if ($errorReport->containsError()) { |
146 | $exception = new PortableElementInvalidModelException(); |
147 | $exception->setReport($errorReport); |
148 | throw $exception; |
149 | } |
150 | return true; |
151 | } |
152 | |
153 | /** |
154 | * @param $value |
155 | * @return bool |
156 | * @throws PortableElementInvalidFieldException |
157 | */ |
158 | public static function isValidString($value) |
159 | { |
160 | if (! is_string($value)) { |
161 | throw new PortableElementInvalidFieldException('Unable to validate the given value as valid string.'); |
162 | } |
163 | return true; |
164 | } |
165 | |
166 | /** |
167 | * @param $value |
168 | * @return bool |
169 | * @throws PortableElementInvalidFieldException |
170 | */ |
171 | public static function isValidArray($value) |
172 | { |
173 | if (! is_array($value)) { |
174 | throw new PortableElementInvalidFieldException('Unable to validate the given value as valid array.'); |
175 | } |
176 | return true; |
177 | } |
178 | |
179 | /** |
180 | * @param $value |
181 | * @return bool |
182 | * @throws PortableElementInvalidFieldException |
183 | */ |
184 | public static function isValidVersion($value) |
185 | { |
186 | $validator = \tao_helpers_form_FormFactory::getValidator(self::Regex, ['format' => '/\d+(?:\.\d+)+/']); |
187 | if (! is_null($value) && ! $validator->evaluate($value)) { |
188 | throw new PortableElementInvalidFieldException('Unable to validate the given value as valid version.'); |
189 | } |
190 | return true; |
191 | } |
192 | |
193 | /** |
194 | * @param $value |
195 | * @return bool |
196 | * @throws PortableElementInvalidFieldException |
197 | */ |
198 | public static function isValidSemVer($value) |
199 | { |
200 | try { |
201 | Regex::matchSemVer($value); |
202 | } catch (\InvalidArgumentException $exception) { |
203 | throw new PortableElementInvalidFieldException( |
204 | 'Unable to validate the given value as valid SemVer version.' |
205 | ); |
206 | } |
207 | |
208 | return true; |
209 | } |
210 | |
211 | /** |
212 | * @param $value |
213 | * @return bool |
214 | * @throws PortableElementInvalidFieldException |
215 | */ |
216 | public static function isTypeIdentifier($value) |
217 | { |
218 | //the IMS PCI standard recommends using the URN https://tools.ietf.org/html/rfc4198 |
219 | $validator = \tao_helpers_form_FormFactory::getValidator(self::Regex, ['format' => '/[a-z0-9-_:]+/i']); |
220 | if (! is_null($value) && ! $validator->evaluate($value)) { |
221 | throw new PortableElementInvalidFieldException( |
222 | 'Unable to validate the given value as valid type identifier.' |
223 | ); |
224 | } |
225 | return true; |
226 | } |
227 | } |