Passed
Push — master ( f5da16...2e3bf1 )
by Jean-Christophe
12:28
created

ValidatorsManager::getHash()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 2
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
eloc 1
dl 0
loc 2
ccs 2
cts 2
cp 1
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
crap 1
1
<?php
2
3
namespace Ubiquity\contents\validation;
4
5
use Ubiquity\cache\CacheManager;
6
use Ubiquity\cache\objects\SessionCache;
7
use Ubiquity\contents\validation\validators\basic\IsBooleanValidator;
8
use Ubiquity\contents\validation\validators\basic\IsEmptyValidator;
9
use Ubiquity\contents\validation\validators\basic\IsFalseValidator;
10
use Ubiquity\contents\validation\validators\basic\IsNullValidator;
11
use Ubiquity\contents\validation\validators\basic\IsTrueValidator;
12
use Ubiquity\contents\validation\validators\basic\NotEmptyValidator;
13
use Ubiquity\contents\validation\validators\basic\NotNullValidator;
14
use Ubiquity\contents\validation\validators\basic\TypeValidator;
15
use Ubiquity\contents\validation\validators\comparison\EqualsValidator;
16
use Ubiquity\contents\validation\validators\comparison\GreaterThanOrEqualValidator;
17
use Ubiquity\contents\validation\validators\comparison\GreaterThanValidator;
18
use Ubiquity\contents\validation\validators\comparison\LessThanOrEqualValidator;
19
use Ubiquity\contents\validation\validators\comparison\LessThanValidator;
20
use Ubiquity\contents\validation\validators\comparison\MatchWithValidator;
21
use Ubiquity\contents\validation\validators\comparison\RangeValidator;
22
use Ubiquity\contents\validation\validators\dates\DateTimeValidator;
23
use Ubiquity\contents\validation\validators\dates\DateValidator;
24
use Ubiquity\contents\validation\validators\dates\TimeValidator;
25
use Ubiquity\contents\validation\validators\multiples\IdValidator;
26
use Ubiquity\contents\validation\validators\multiples\LengthValidator;
27
use Ubiquity\contents\validation\validators\strings\EmailValidator;
28
use Ubiquity\contents\validation\validators\strings\IpValidator;
29
use Ubiquity\contents\validation\validators\strings\RegexValidator;
30
use Ubiquity\contents\validation\validators\strings\UrlValidator;
31
use Ubiquity\log\Logger;
32
33
/**
34
 * Validators manager
35
 *
36
 * Ubiquity\contents\validation$ValidatorsManager
37
 * This class is part of Ubiquity
38
 *
39
 * @author jcheron <[email protected]>
40
 * @version 1.0.3
41
 *
42
 */
43
class ValidatorsManager {
44
	use ValidatorsManagerInitTrait;
45
	protected static $instanceValidators = [ ];
46
	protected static $cache;
47
48 6
	public static function start() {
49 6
		self::$cache = new SessionCache ();
50 6
	}
51
	public static $validatorTypes = [
52
										'notNull' => NotNullValidator::class,
53
										'isNull' => IsNullValidator::class,
54
										'notEmpty' => NotEmptyValidator::class,
55
										'isEmpty' => IsEmptyValidator::class,
56
										'isTrue' => IsTrueValidator::class,
57
										'isFalse' => IsFalseValidator::class,
58
										'isBool' => IsBooleanValidator::class,
59
										'equals' => EqualsValidator::class,
60
										'type' => TypeValidator::class,
61
										'greaterThan' => GreaterThanValidator::class,
62
										'greaterThanOrEqual' => GreaterThanOrEqualValidator::class,
63
										'lessThan' => LessThanValidator::class,
64
										'lessThanOrEqual' => LessThanOrEqualValidator::class,
65
										'length' => LengthValidator::class,
66
										'id' => IdValidator::class,
67
										'regex' => RegexValidator::class,
68
										'email' => EmailValidator::class,
69
										'url' => UrlValidator::class,
70
										'ip' => IpValidator::class,
71
										'range' => RangeValidator::class,
72
										'date' => DateValidator::class,
73
										'dateTime' => DateTimeValidator::class,
74
										'time' => TimeValidator::class,
75
										'match'=>MatchWithValidator::class
76
	];
77
	protected static $key = 'contents/validators/';
78
79 38
	protected static function store($model, $validators) {
80 38
		CacheManager::$cache->store ( self::getModelCacheKey ( $model ), $validators, 'validators' );
81 38
	}
82
83 11
	protected static function fetch($model) {
84 11
		$key = self::getModelCacheKey ( $model );
85 11
		if (CacheManager::$cache->exists ( $key )) {
86 11
			return CacheManager::$cache->fetch ( $key );
87
		}
88
		return [ ];
89
	}
90
91 1
	public static function getCacheInfo($model) {
92 1
		return self::fetch ( $model );
93
	}
94
95
	protected static function getGroupArrayValidators(array $validators, $group) {
96
		$result = [ ];
97
		foreach ( $validators as $member => $validators ) {
98
			$filteredValidators = self::getGroupMemberValidators ( $validators, $group );
99
			if (\count ( $filteredValidators ) > 0) {
100
				$result [$member] = $filteredValidators;
101
			}
102
		}
103
		return $result;
104
	}
105
106
	protected static function getGroupMemberValidators(array $validators, $group) {
107
		$result = [ ];
108
		foreach ( $validators as $validator ) {
109
			if (isset ( $validator ['group'] ) && $validator ['group'] === $group) {
110
				$result [] = $validator;
111
			}
112
		}
113
		return $result;
114
	}
115
116
	private static function getCacheValidators($instance, $group = '') {
117
		return self::getClassCacheValidators ( \get_class ( $instance ), $group );
118
	}
119
120 11
	protected static function getClassCacheValidators($class, $group = '') {
121 11
		if (isset ( self::$cache )) {
122 6
			$key = self::getHash ( $class . $group );
123 6
			if (self::$cache->exists ( $key )) {
124
				return self::$cache->fetch ( $key );
125
			}
126
		}
127 11
		return false;
128
	}
129
130
	/**
131
	 * Validates an instance
132
	 *
133
	 * @param object $instance
134
	 * @param string $group
135
	 * @param array $excludedValidators
136
	 * @return \Ubiquity\contents\validation\validators\ConstraintViolation[]
137
	 */
138 5
	public static function validate($instance, $group = '', $excludedValidators = [ ]) {
139 5
		$class = \get_class ( $instance );
140 5
		$cache = self::getClassCacheValidators ( $class, $group );
141 5
		if ($cache !== false) {
142
			return self::validateFromCache_ ( $instance, $cache, $excludedValidators );
143
		}
144 5
		$members = self::fetch ( $class );
145 5
		if ($group !== '') {
146
			$members = self::getGroupArrayValidators ( $members, $group );
147
		}
148 5
		return self::validate_ ( $instance, $members, $excludedValidators );
149
	}
150
151
	/**
152
	 * Returns an array of UI rules for Javascript validation.
153
	 * @param $instance
154
	 * @param string $group
155
	 * @param array $excludedValidators
156
	 * @return array
157
	 */
158 4
	public static function getUIConstraints($instance, $group = '', $excludedValidators = [ ]) {
159 4
		$class = \get_class ( $instance );
160 4
		$cache = self::getClassCacheValidators ( $class, $group );
161 4
		if ($cache !== false) {
162
			return self::getUIConstraintsFromCache_ ( $instance, $cache, $excludedValidators );
163
		}
164 4
		$members = self::fetch ( $class );
165 4
		if ($group !== '') {
166
			$members = self::getGroupArrayValidators ( $members, $group );
167
		}
168 4
		return self::getUIConstraints_ ( $instance, $members, $excludedValidators );
169
	}
170
171
	/**
172
	 * Validates an array of objects
173
	 *
174
	 * @param array $instances
175
	 * @param string $group
176
	 * @return \Ubiquity\contents\validation\validators\ConstraintViolation[]
177
	 */
178 2
	public static function validateInstances($instances, $group = '') {
179 2
		if (\count ( $instances ) > 0) {
180 2
			$instance = \current ( $instances );
181 2
			$class = \get_class ( $instance );
182 2
			$cache = self::getClassCacheValidators ( $class, $group );
183 2
			if ($cache === false) {
184 2
				$members = self::fetch ( $class );
185 2
				self::initInstancesValidators ( $instance, $members, $group );
186 2
				$cache = self::$instanceValidators [$class];
187
			}
188 2
			return self::validateInstances_ ( $instances, $cache );
189
		}
190
		return [ ];
191
	}
192
193
	public static function clearCache($model = null, $group = '') {
194
		if (isset ( self::$cache )) {
195
			if (isset ( $model )) {
196
				$key = self::getHash ( $model . $group );
197
				self::$cache->remove ( $key );
198
			} else {
199
				self::$cache->clear ();
200
			}
201
		}
202
	}
203
204 2
	protected static function validateInstances_($instances, $members) {
205 2
		$result = [ ];
206 2
		foreach ( $instances as $instance ) {
207 2
			foreach ( $members as $accessor => $validators ) {
208 2
				foreach ( $validators as $validator ) {
209 2
					$valid = $validator->validate_ ( $instance->$accessor () );
210 2
					if ($valid !== true) {
211 1
						$result [] = $valid;
212
					}
213
				}
214
			}
215
		}
216 2
		return $result;
217
	}
218
219 5
	protected static function validate_($instance, $members, $excludedValidators = [ ]) {
220 5
		$result = [ ];
221 5
		foreach ( $members as $member => $validators ) {
222 5
			$accessor = 'get' . \ucfirst ( $member );
223 5
			if (\method_exists ( $instance, $accessor )) {
224 5
				foreach ( $validators as $validator ) {
225 5
					$typeV = $validator ['type'];
226 5
					if (! isset ( $excludedValidators [$typeV] )) {
227 5
						$validatorInstance = self::getValidatorInstance ( $typeV );
228 5
						if ($validatorInstance !== false) {
229 5
							$validatorInstance->setValidationParameters ( $member, $validator ['constraints'] ?? [ ], $validator ['severity'] ?? null, $validator ['message'] ?? null);
230 5
							$valid = $validatorInstance->validate_ ( $instance->$accessor () );
231 5
							if ($valid !== true) {
232 4
								$result [] = $valid;
233
							}
234
						}
235
					}
236
				}
237
			}
238
		}
239 5
		return $result;
240
	}
241
242 4
	protected static function getUIConstraints_($instance, $members, $excludedValidators = [ ]) {
243 4
		$result = [ ];
244 4
		foreach ( $members as $member => $validators ) {
245 4
			$result [$member]=[];
246 4
			$accessor = 'get' . \ucfirst ( $member );
247 4
			if (\method_exists ( $instance, $accessor )) {
248 4
				foreach ( $validators as $validator ) {
249 4
					$typeV = $validator ['type'];
250 4
					if (! isset ( $excludedValidators [$typeV] )) {
251 4
						$validatorInstance = self::getValidatorInstance ( $typeV );
252 4
						if ($validatorInstance !== false) {
253 4
							$validatorInstance->setValidationParameters ( $member, $validator ['constraints'] ?? [ ], $validator ['severity'] ?? null, $validator ['message'] ?? null);
254 4
							$result [$member] = \array_merge_recursive($result[$member],$validatorInstance->asUI ());
255
						}
256
					}
257
				}
258
			}
259
		}
260 4
		return $result;
261
	}
262
263
	protected static function validateFromCache_($instance, $members, $excludedValidators = [ ]) {
264
		$result = [ ];
265
		$types = \array_flip ( self::$validatorTypes );
266
		foreach ( $members as $accessor => $validators ) {
267
			foreach ( $validators as $validatorInstance ) {
268
				$typeV = $types [get_class ( $validatorInstance )];
269
				if (! isset ( $excludedValidators [$typeV] )) {
270
					$valid = $validatorInstance->validate_ ( $instance->$accessor () );
271
					if ($valid !== true) {
272
						$result [] = $valid;
273
					}
274
				}
275
			}
276
		}
277
		return $result;
278
	}
279
280
	protected static function getUIConstraintsFromCache_($instance, $members, $excludedValidators = [ ]) {
281
		$result = [ ];
282
		$types = \array_flip ( self::$validatorTypes );
283
		foreach ( $members as $accessor => $validators ) {
284
			$member = \lcfirst ( \ltrim ( 'get', $accessor ) );
285
			foreach ( $validators as $validatorInstance ) {
286
				$typeV = $types [get_class ( $validatorInstance )];
287
				if (! isset ( $excludedValidators [$typeV] )) {
288
					$result [$member] += $validatorInstance->asUI ();
289
				}
290
			}
291
		}
292
		return $result;
293
	}
294
295
	/**
296
	 * Initializes the cache (SessionCache) for the class of instance
297
	 *
298
	 * @param object $instance
299
	 * @param string $group
300
	 */
301
	public static function initCacheInstanceValidators($instance, $group = '') {
302
		$class = \get_class ( $instance );
303
		$members = self::fetch ( $class );
304
		self::initInstancesValidators ( $instance, $members, $group );
305
	}
306
307 2
	protected static function initInstancesValidators($instance, $members, $group = '') {
308 2
		$class = \get_class ( $instance );
309 2
		$result = [ ];
310 2
		foreach ( $members as $member => $validators ) {
311 2
			$accessor = 'get' . \ucfirst ( $member );
312 2
			if (\method_exists ( $instance, $accessor )) {
313 2
				foreach ( $validators as $validator ) {
314 2
					$validatorInstance = self::getValidatorInstance ( $validator ['type'] );
315 2
					if ($validatorInstance !== false) {
316 2
						$validatorInstance->setValidationParameters ( $member, $validator ['constraints'] ?? [ ], $validator ['severity'] ?? null, $validator ['message'] ?? null);
317 2
						if ($group === '' || (isset ( $validator ['group'] ) && $validator ['group'] === $group)) {
318 2
							self::$instanceValidators [$class] [$accessor] [] = $validatorInstance;
319 2
							$result [$accessor] [] = $validatorInstance;
320
						}
321
					}
322
				}
323
			}
324
		}
325 2
		self::$cache->store ( self::getHash ( $class . $group ), $result );
326 2
	}
327
328 6
	protected static function getHash($class) {
329 6
		return \hash ( 'sha1', $class );
330
	}
331
332 45
	protected static function getModelCacheKey($classname) {
333 45
		return self::$key . \str_replace ( "\\", \DS, $classname );
334
	}
335
336 11
	protected static function getValidatorInstance($type) {
337 11
		if (isset ( self::$validatorTypes [$type] )) {
338 11
			$class = self::$validatorTypes [$type];
339 11
			return new $class ();
340
		} else {
341
			Logger::warn ( "validation", "Validator " . $type . " does not exists!" );
342
			return false;
343
		}
344
	}
345
}
346
347