Completed
Push — master ( 3a0750...56d871 )
by Jean-Christophe
01:41
created

ValidatorsManager::validateInstancesGroup()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 11
rs 9.9
c 0
b 0
f 0
cc 2
nc 2
nop 2
1
<?php
2
3
namespace Ubiquity\contents\validation;
4
5
use Ubiquity\cache\CacheManager;
6
use Ubiquity\log\Logger;
7
use Ubiquity\contents\validation\validators\multiples\LengthValidator;
8
use Ubiquity\contents\validation\validators\multiples\IdValidator;
9
use Ubiquity\contents\validation\validators\basic\NotNullValidator;
10
use Ubiquity\contents\validation\validators\basic\NotEmptyValidator;
11
use Ubiquity\contents\validation\validators\comparison\EqualsValidator;
12
use Ubiquity\contents\validation\validators\basic\TypeValidator;
13
use Ubiquity\contents\validation\validators\comparison\GreaterThanValidator;
14
use Ubiquity\contents\validation\validators\comparison\LessThanValidator;
15
use Ubiquity\contents\validation\validators\basic\IsNullValidator;
16
use Ubiquity\contents\validation\validators\basic\IsEmptyValidator;
17
use Ubiquity\contents\validation\validators\basic\IsTrueValidator;
18
use Ubiquity\contents\validation\validators\basic\IsFalseValidator;
19
use Ubiquity\contents\validation\validators\strings\RegexValidator;
20
use Ubiquity\contents\validation\validators\strings\EmailValidator;
21
use Ubiquity\contents\validation\validators\strings\UrlValidator;
22
use Ubiquity\contents\validation\validators\strings\IpValidator;
23
use Ubiquity\contents\validation\validators\comparison\RangeValidator;
24
use Ubiquity\contents\validation\validators\comparison\GreaterThanOrEqualValidator;
25
use Ubiquity\contents\validation\validators\comparison\LessThanOrEqualValidator;
26
use Ubiquity\contents\validation\validators\dates\DateValidator;
27
use Ubiquity\contents\validation\validators\dates\DateTimeValidator;
28
use Ubiquity\contents\validation\validators\dates\TimeValidator;
29
use Ubiquity\contents\validation\validators\basic\IsBooleanValidator;
30
use Ubiquity\cache\objects\SessionCache;
31
32
/**
33
 * Validators manager
34
 * @author jcheron <[email protected]>
35
 * @version 1.0.0
36
 */
37
class ValidatorsManager {
38
	protected static $instanceValidators=[];
39
	protected static $cache;
40
	
41
	public static function start(){
42
		self::$cache=new SessionCache();
43
	}
44
	
45
	public static $validatorTypes=[
46
			"notNull"=>NotNullValidator::class,
47
			"isNull"=>IsNullValidator::class,
48
			"notEmpty"=>NotEmptyValidator::class,
49
			"isEmpty"=>IsEmptyValidator::class,
50
			"isTrue"=>IsTrueValidator::class,
51
			"isFalse"=>IsFalseValidator::class,
52
			"isBool"=>IsBooleanValidator::class,
53
			"equals"=>EqualsValidator::class,
54
			"type"=>TypeValidator::class,
55
			"greaterThan"=>GreaterThanValidator::class,
56
			"greaterThanOrEqual"=>GreaterThanOrEqualValidator::class,
57
			"lessThan"=>LessThanValidator::class,
58
			"lessThanOrEqual"=>LessThanOrEqualValidator::class,
59
			"length"=>LengthValidator::class,
60
			"id"=>IdValidator::class,
61
			"regex"=>RegexValidator::class,
62
			"email"=>EmailValidator::class,
63
			"url"=>UrlValidator::class,
64
			"ip"=>IpValidator::class,
65
			"range"=>RangeValidator::class,
66
			"date"=>DateValidator::class,
67
			"dateTime"=>DateTimeValidator::class,
68
			"time"=>TimeValidator::class
69
			
70
	];
71
	
72
	protected static $key="contents/validators/";
73
	
74
	/**
75
	 * Registers a validator type for using with @validator annotation
76
	 * @param string $type
77
	 * @param string $validatorClass
78
	 */
79
	public static function registerType($type,$validatorClass){
80
		self::$validatorTypes[$type]=$validatorClass;
81
	}
82
	
83
	/**
84
	 * Parses models and save validators in cache
85
	 * to use in dev only
86
	 * @param array $config
87
	 */
88
	public static function initModelsValidators(&$config){
89
		$models=CacheManager::getModels($config,true);
90
		foreach ($models as $model){
91
			$parser=new ValidationModelParser();
92
			$parser->parse($model);
93
			$validators=$parser->getValidators();
94
			if(sizeof($validators)>0){
95
				self::store($model, $parser->__toString());
96
			}
97
		}
98
	}
99
	
100
	protected static function store($model,$validators){
101
		CacheManager::$cache->store(self::getModelCacheKey($model), $validators);
102
	}
103
	
104
	protected static function fetch($model){
105
		$key=self::getModelCacheKey($model);
106
		if(CacheManager::$cache->exists($key)){
107
			return CacheManager::$cache->fetch($key);
108
		}
109
		return [];
110
	}
111
	
112
	protected static function getGroupArrayValidators(array $validators,$group){
113
		$result=[];
114
		foreach ($validators as $member=>$validators){
115
			$filteredValidators=self::getGroupMemberValidators($validators, $group);
116
			if(sizeof($filteredValidators)){
117
				$result[$member]=$filteredValidators;
118
			}
119
		}
120
		return $result;
121
	}
122
	
123
	protected static function getGroupMemberValidators(array $validators,$group){
124
		$result=[];
125
		foreach ($validators as $validator){
126
			if(isset($validator["group"]) && $validator["group"]===$group){
127
				$result[]=$validator;
128
			}
129
		}
130
		return $result;
131
	}
132
	
133
	private static function getCacheValidators($instance,$group=""){
134
		if(isset(self::$cache)){
135
			$key=self::getHash(get_class($instance).$group);
136
			if(self::$cache->exists($key)){
137
				return self::$cache->fetch($key);
138
			}
139
		}
140
		return false;
141
	}
142
	
143
	/**
144
	 * Validates an instance
145
	 * @param object $instance
146
	 * @param string $group
147
	 * @return \Ubiquity\contents\validation\validators\ConstraintViolation[]
148
	 */
149
	public static function validate($instance,$group=""){
150
		$cache=self::getCacheValidators($instance,$group);
151
		if($cache!==false){
152
			return self::validateFromCache_($instance,$cache);
153
		}
154
		$members=self::fetch(get_class($instance));
155
		if($group!==""){
156
			$members=self::getGroupArrayValidators($members, $group);
157
		}
158
		return self::validate_($instance,$members);
159
	}
160
	
161
	/**
162
	 * Validates an array of objects
163
	 * @param array $instances
164
	 * @param string $group
165
	 * @return \Ubiquity\contents\validation\validators\ConstraintViolation[]
166
	 */
167
	public static function validateInstances($instances,$group=""){
168
		if(sizeof($instances)>0){
169
			$instance=reset($instances);
170
			$cache=self::getCacheValidators($instance,$group);
171
			if($cache===false){
172
				$class=get_class($instance);
173
				$members=self::fetch($class);
174
				self::initInstancesValidators($instance, $members,$group);
175
				$cache=self::$instanceValidators[$class];
176
			}
177
			return self::validateInstances_($instances,$cache);
178
		}
179
		return [];
180
	}
181
	
182
	public static function clearCache($model=null,$group=""){
183
		if(isset(self::$cache)){
184
			if(isset($model)){
185
				$key=self::getHash($model.$group);
186
				self::$cache->remove($key);
187
			}else{
188
				self::$cache->clear();
189
			}
190
		}
191
	}
192
	
193 View Code Duplication
	protected static function validateInstances_($instances,$members){
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
194
		$result=[];
195
		foreach ($instances as $instance){
196
			foreach ($members as $accessor=>$validators){
197
				foreach ($validators as $validator){
198
					$valid=$validator->validate_($instance->$accessor());
199
					if($valid!==true){
200
						$result[]=$valid;
201
					}
202
				}
203
			}
204
		}
205
		return $result;
206
	}
207
	
208
	protected static function validate_($instance,$members){
209
		$result=[];
210
		foreach ($members as $member=>$validators){
211
			$accessor="get".ucfirst($member);
212
			if(method_exists($instance, $accessor)){
213
				foreach ($validators as $validator){
214
					$validatorInstance=self::getValidatorInstance($validator["type"]);
215
					if($validatorInstance!==false){
216
						$validatorInstance->setValidationParameters($member,$validator["constraints"],@$validator["severity"],@$validator["message"]);
217
						$valid=$validatorInstance->validate_($instance->$accessor());
218
						if($valid!==true){
219
							$result[]=$valid;
220
						}
221
					}
222
				}
223
			}
224
		}
225
		return $result;
226
	}
227
	
228 View Code Duplication
	protected static function validateFromCache_($instance,$members){
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
229
		$result=[];
230
		foreach ($members as $accessor=>$validators){
231
			foreach ($validators as $validatorInstance){
232
				$valid=$validatorInstance->validate_($instance->$accessor());
233
				if($valid!==true){
234
					$result[]=$valid;
235
				}
236
			}
237
		}
238
		return $result;
239
	}
240
	
241
	/**
242
	 * Initializes the cache (SessionCache) for the class of înstance
243
	 * @param object $instance
244
	 * @param string $group
245
	 */
246
	public static function initCacheInstanceValidators($instance,$group=""){
247
		$class=get_class($instance);
248
		$members=self::fetch($class);
249
		self::initInstancesValidators($instance, $members,$group);
250
	}
251
	
252
	protected static function initInstancesValidators($instance,$members,$group=""){
253
		$class=get_class($instance);
254
		$result=[];
255
		foreach ($members as $member=>$validators){
256
			$accessor="get".ucfirst($member);
257
			if(method_exists($instance, $accessor)){
258
				foreach ($validators as $validator){
259
					$validatorInstance=self::getValidatorInstance($validator["type"]);
260
					if($validatorInstance!==false){
261
						$validatorInstance->setValidationParameters($member,$validator["constraints"],@$validator["severity"],@$validator["message"]);
262
						if($group==="" || (isset($validator["group"]) && $validator["group"]===$group)){
263
							self::$instanceValidators[$class][$accessor][]=$validatorInstance;
264
							$result[$accessor][]=$validatorInstance;
265
						}
266
					}
267
				}
268
			}
269
		}
270
		self::$cache->store(self::getHash($class.$group), $result);
271
	}
272
	
273
	protected static function getHash($class){
274
		return hash("sha1", $class);
275
	}
276
	
277
	protected static function getModelCacheKey($classname){
278
		return self::$key.\str_replace("\\", DIRECTORY_SEPARATOR, $classname);
279
	}
280
	
281
	protected static function getValidatorInstance($type){
282
		if(isset(self::$validatorTypes[$type])){
283
			$class=self::$validatorTypes[$type];
284
			return new $class();
285
		}else{
286
			Logger::warn("validation", "Validator ".$type." does not exists!");
287
			return false;
288
		}
289
	}
290
}
291
292