Skip to content

Commit f2dc965

Browse files
committed
Adds server side validation
1 parent f8bd369 commit f2dc965

28 files changed

+740
-7
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
<?php
2+
3+
namespace Ubiquity\annotations;
4+
5+
use Ubiquity\contents\validation\ValidatorsManager;
6+
7+
/**
8+
* Validator annotation
9+
* @author jc
10+
* @version 1.0.0.1
11+
* @package annotations
12+
* @usage('property'=>true, 'inherited'=>true, 'multiple'=>true)
13+
*/
14+
class ValidatorAnnotation extends BaseAnnotation {
15+
public $type;
16+
public $message;
17+
public $severity;
18+
public $constraints=[];
19+
20+
/**
21+
* Initialize the annotation.
22+
*/
23+
public function initAnnotation(array $properties){
24+
if (isset($properties[0])) {
25+
$this->type = $properties[0];
26+
unset($properties[0]);
27+
if(isset($properties[1])){
28+
if(!is_array($properties[1])){
29+
$this->constraints=["ref"=>$properties[1]];
30+
}else{
31+
$this->constraints=$properties[1];
32+
}
33+
unset($properties[1]);
34+
}
35+
}else{
36+
throw new \Exception('Validator annotation must have a type');
37+
}
38+
parent::initAnnotation($properties);
39+
if (!isset(ValidatorsManager::$validatorTypes[$this->type])) {
40+
throw new \Exception('This type of annotation does not exists : '.$this->type);
41+
}
42+
}
43+
}

Ubiquity/cache/CacheManager.php

+4-2
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,8 @@ public static function getCacheDirectories(&$config, $silent = false) {
9090
$viewsCacheDir = ROOT . DS . $cacheDirectory . DS . "views";
9191
$seoCacheDir = ROOT . DS . $cacheDirectory . DS . "seo";
9292
$gitCacheDir = ROOT . DS . $cacheDirectory . DS . "git";
93-
return [ "annotations" => $annotationCacheDir,"models" => $modelsCacheDir,"controllers" => $controllersCacheDir,"queries" => $queriesCacheDir,"views" => $viewsCacheDir,"seo" => $seoCacheDir,"git" => $gitCacheDir ];
93+
$contentsCacheDir = ROOT . DS . $cacheDirectory . DS . "contents";
94+
return [ "annotations" => $annotationCacheDir,"models" => $modelsCacheDir,"controllers" => $controllersCacheDir,"queries" => $queriesCacheDir,"views" => $viewsCacheDir,"seo" => $seoCacheDir,"git" => $gitCacheDir,"contents"=>$contentsCacheDir ];
9495
}
9596

9697
private static function safeMkdir($dir) {
@@ -100,7 +101,7 @@ private static function safeMkdir($dir) {
100101

101102
public static function clearCache(&$config, $type = "all") {
102103
$cacheDirectories = self::checkCache ( $config );
103-
$cacheDirs = [ "annotations","controllers","models","queries","views" ];
104+
$cacheDirs = [ "annotations","controllers","models","queries","views","contents" ];
104105
foreach ( $cacheDirs as $typeRef ) {
105106
self::_clearCache ( $cacheDirectories, $type, $typeRef );
106107
}
@@ -140,6 +141,7 @@ private static function register(AnnotationManager $annotationManager) {
140141
'table' => 'Ubiquity\annotations\TableAnnotation',
141142
'transient' => 'Ubiquity\annotations\TransientAnnotation',
142143
'column' => 'Ubiquity\annotations\ColumnAnnotation',
144+
'validator' => 'Ubiquity\annotations\ValidatorAnnotation',
143145
'joinTable' => 'Ubiquity\annotations\JoinTableAnnotation',
144146
'requestMapping' => 'Ubiquity\annotations\router\RouteAnnotation',
145147
'route' => 'Ubiquity\annotations\router\RouteAnnotation',

Ubiquity/cache/traits/ModelsCacheTrait.php

+3-1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
use Ubiquity\orm\parser\ModelParser;
55
use Ubiquity\cache\ClassUtils;
6+
use Ubiquity\contents\validation\ValidatorsManager;
67

78
/**
89
* @author jc
@@ -35,7 +36,7 @@ public static function modelCacheExists($classname){
3536
$key=self::getModelCacheKey($classname);
3637
if(isset(self::$cache))
3738
return self::$cache->exists($key);
38-
return false;
39+
return false;
3940
}
4041

4142
public static function initModelsCache(&$config,$forChecking=false,$silent=false) {
@@ -48,6 +49,7 @@ public static function initModelsCache(&$config,$forChecking=false,$silent=false
4849
}
4950
}
5051
}
52+
ValidatorsManager::initModelsValidators($config);
5153
if(!$silent){
5254
echo "Models cache reset\n";
5355
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
<?php
2+
3+
namespace Ubiquity\contents\validation;
4+
5+
use Ubiquity\orm\parser\Reflexion;
6+
use Ubiquity\utils\base\UArray;
7+
8+
/**
9+
* @author jc
10+
*
11+
*/
12+
class ValidationModelParser {
13+
14+
protected $validators=[];
15+
16+
public function parse($modelClass) {
17+
$instance=new $modelClass();
18+
$properties=Reflexion::getProperties($instance);
19+
foreach ( $properties as $property ) {
20+
$propName=$property->getName();
21+
$annots=Reflexion::getAnnotationsMember($modelClass, $propName, "@validator");
22+
if(sizeof($annots)>0){
23+
$this->validators[$propName]=[];
24+
foreach ($annots as $annotation){
25+
$this->validators[$propName][]=$annotation->getPropertiesAndValues();
26+
}
27+
}
28+
}
29+
30+
}
31+
32+
public function getValidators(){
33+
return $this->validators;
34+
}
35+
36+
public function __toString() {
37+
return "return " . UArray::asPhpArray($this->validators, "array") . ";";
38+
}
39+
}
40+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
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+
20+
/**
21+
* @author jc
22+
*
23+
*/
24+
class ValidatorsManager {
25+
26+
protected static $validatorInstances=[];
27+
public static $validatorTypes=[
28+
"notNull"=>NotNullValidator::class,
29+
"isNull"=>IsNullValidator::class,
30+
"notEmpty"=>NotEmptyValidator::class,
31+
"isEmpty"=>IsEmptyValidator::class,
32+
"isTrue"=>IsTrueValidator::class,
33+
"isFalse"=>IsFalseValidator::class,
34+
"equals"=>EqualsValidator::class,
35+
"type"=>TypeValidator::class,
36+
"greaterThan"=>GreaterThanValidator::class,
37+
"lessThan"=>LessThanValidator::class,
38+
"length"=>LengthValidator::class,
39+
"id"=>IdValidator::class
40+
41+
];
42+
protected static $key="contents/validators/";
43+
44+
public static function registerType($type,$validatorClass){
45+
self::$validatorTypes[$type]=$validatorClass;
46+
}
47+
48+
public static function initModelsValidators(&$config){
49+
$models=CacheManager::getModels($config,true);
50+
foreach ($models as $model){
51+
$parser=new ValidationModelParser();
52+
$parser->parse($model);
53+
$validators=$parser->getValidators();
54+
if(sizeof($validators)>0){
55+
self::store($model, $parser->__toString());
56+
}
57+
}
58+
}
59+
60+
protected static function store($model,$validators){
61+
CacheManager::$cache->store(self::getModelCacheKey($model), $validators);
62+
}
63+
64+
protected static function fetch($model){
65+
$key=self::getModelCacheKey($model);
66+
if(CacheManager::$cache->exists($key)){
67+
return CacheManager::$cache->fetch($key);
68+
}
69+
return [];
70+
}
71+
72+
public static function validate($instance){
73+
$result=[];
74+
$members=self::fetch(get_class($instance));
75+
foreach ($members as $member=>$validators){
76+
$accessor="get".ucfirst($member);
77+
if(method_exists($instance, $accessor)){
78+
foreach ($validators as $validator){
79+
$validatorInstance=self::getValidatorInstance($validator["type"]);
80+
if($validatorInstance!==false){
81+
$valid=$validatorInstance->validate_($instance->$accessor(),$member,$instance,$validator["constraints"],@$validator["severity"],@$validator["message"]);
82+
if($valid!==true){
83+
$result[]=$valid;
84+
}
85+
}
86+
}
87+
}
88+
}
89+
return $result;
90+
}
91+
92+
protected static function getModelCacheKey($classname){
93+
return self::$key.\str_replace("\\", DIRECTORY_SEPARATOR, $classname);
94+
}
95+
96+
protected static function getValidatorInstance($type){
97+
if(!isset(self::$validatorInstances[$type])){
98+
if(isset(self::$validatorTypes[$type])){
99+
$class=self::$validatorTypes[$type];
100+
self::$validatorInstances[$type]=new $class();
101+
}else{
102+
Logger::warn("validation", "Validator ".$type." does not exists!");
103+
return false;
104+
}
105+
}
106+
return self::$validatorInstances[$type];
107+
}
108+
}
109+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<?php
2+
3+
namespace Ubiquity\contents\validation\validators;
4+
5+
class ConstraintViolation {
6+
protected $message;
7+
protected $value;
8+
protected $member;
9+
protected $validatorType;
10+
protected $severity;
11+
12+
public function __construct($message,$value,$member,$validatorType,$severity){
13+
$this->message=$message;
14+
$this->severity=$severity;
15+
$this->value=$value;
16+
$this->member=$member;
17+
$this->validatorType=$validatorType;
18+
}
19+
}
20+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
<?php
2+
3+
namespace Ubiquity\contents\validation\validators;
4+
5+
abstract class Validator implements ValidatorInterface{
6+
protected $modifiedMessage;
7+
protected $message;
8+
protected $member;
9+
protected $value;
10+
11+
public function validate_($value,$member,$instance,$params,$severity='warning',$message=null){
12+
$this->value=$value;
13+
$this->setParams($params);
14+
if(!$this->validate($value)){
15+
$this->modifiedMessage=$message;
16+
return new ConstraintViolation($this->_getMessage(), $value, $member, get_class($this),$severity);
17+
}
18+
return true;
19+
}
20+
21+
protected function setParams(array $params){
22+
foreach ($params as $member=>$value){
23+
$this->$member=$value;
24+
}
25+
}
26+
/**
27+
* @return mixed
28+
*/
29+
public function getMember() {
30+
return $this->member;
31+
}
32+
33+
/**
34+
* @param mixed $member
35+
*/
36+
public function setMember($member) {
37+
$this->member = $member;
38+
}
39+
40+
/**
41+
* {@inheritDoc}
42+
* @see \Ubiquity\contents\validation\validators\ValidatorInterface::getParameters()
43+
*/
44+
public function getParameters(): array {
45+
return [];
46+
47+
}
48+
49+
protected function mergeMessages(){
50+
if(!isset($this->modifiedMessage)){
51+
return $this->message;
52+
}else{
53+
return $this->modifiedMessage;
54+
}
55+
}
56+
57+
protected function _getMessage(){
58+
$parameters=$this->getParameters();
59+
$message=$this->mergeMessages();
60+
foreach ($parameters as $param){
61+
$message=str_replace("{".$param."}", $this->$param, $message);
62+
}
63+
return $message;
64+
}
65+
66+
}
67+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?php
2+
3+
namespace Ubiquity\contents\validation\validators;
4+
5+
interface ValidatorInterface {
6+
/**
7+
* @param mixed $value
8+
* @return boolean
9+
*/
10+
public function validate($value);
11+
12+
public function getParameters():array;
13+
}
14+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<?php
2+
3+
namespace Ubiquity\contents\validation\validators\basic;
4+
5+
use Ubiquity\contents\validation\validators\Validator;
6+
7+
class IsEmptyValidator extends Validator {
8+
9+
public function __construct(){
10+
$this->message="This value should be empty";
11+
}
12+
public function validate($value) {
13+
return $value==null;
14+
}
15+
16+
/**
17+
* {@inheritDoc}
18+
* @see \Ubiquity\contents\validation\validators\Validator::getParameters()
19+
*/
20+
public function getParameters(): array {
21+
return ["value"];
22+
}
23+
}
24+

0 commit comments

Comments
 (0)