1+ <?php
2+
3+ namespace PhpPlatform \RESTFul ;
4+
5+ use PhpPlatform \Errors \Exceptions \Http \_4XX \BadRequest ;
6+
7+ /**
8+ * Provides utilities to validate and sanitize the input data from rest clients
9+ *
10+ * All of the methods can be chained to validate for multiple conditions
11+ *
12+ * Example
13+ *
14+ * $validation = new Validation('data',['a','b','c']);
15+ * $validation->isArray()->hasCount(2,3); // success
16+ * $validation->key(2)->isString()->hasLength(2,4);
17+ *
18+ */
19+ class Validation {
20+
21+ private $ key = null ;
22+ private $ data = null ;
23+ private $ validationErrors = null ;
24+ private $ continue = true ; // continue to next validation or skip it
25+
26+ /**
27+ * @var Validation
28+ */
29+ private $ parentValidation = null ;
30+
31+ /**
32+ * @var Validation[]
33+ */
34+ private $ childValidations = [];
35+
36+ function __construct ($ key , $ data ){
37+ $ this ->key = $ key ;
38+ $ this ->data = $ data ;
39+ }
40+
41+ function containsOnly ($ keys ){
42+ if ($ this ->continue ){
43+ if (!is_array ($ this ->data ) || count (array_diff (array_keys ($ this ->data ), $ keys )) > 0 ){
44+ $ this ->validationErrors = 'invalid ' ;
45+ $ this ->continue = false ;
46+ }
47+ }
48+ return $ this ;
49+ }
50+
51+ function containsAll ($ keys ){
52+ if ($ this ->continue ){
53+ if (!is_array ($ this ->data ) || count (array_diff ($ keys ,array_keys ($ this ->data ))) > 0 ){
54+ $ this ->validationErrors = 'invalid ' ;
55+ $ this ->continue = false ;
56+ }
57+ }
58+ return $ this ;
59+ }
60+
61+ function containsExactly ($ keys ){
62+ if ($ this ->continue ){
63+ $ this ->containsOnly ($ keys );
64+ $ this ->containsAll ($ keys );
65+ }
66+ return $ this ;
67+ }
68+
69+ function key ($ key ){
70+ $ subValidation = new Validation ($ key ,$ this ->data [$ key ]);
71+ $ subValidation ->continue = $ this ->continue ;
72+ $ subValidation ->parentValidation = $ this ;
73+ $ this ->childValidations [] = $ subValidation ;
74+ return $ subValidation ;
75+ }
76+
77+ function required (){
78+ if ($ this ->continue ){
79+ if (!isset ($ this ->data )){
80+ $ this ->validationErrors = 'missing ' ;
81+ $ this ->continue = false ;
82+ }
83+ }
84+ return $ this ;
85+ }
86+
87+ function defaultValue ($ value ){
88+ if ($ this ->continue ){
89+ if (!isset ($ this ->data )){
90+ $ this ->parentValidation ->data [$ this ->key ] = $ value ;
91+ }
92+ }
93+ return $ this ;
94+ }
95+
96+ function isNumeric (){
97+ if ($ this ->continue ){
98+ if (!is_numeric ($ this ->data )){
99+ $ this ->validationErrors = 'invalid ' ;
100+ $ this ->continue = false ;
101+ }
102+ }
103+ return $ this ;
104+ }
105+
106+ function isInt (){
107+ $ this ->isNumeric ();
108+ if ($ this ->continue ){
109+ if (intval ($ this ->data ) != $ this ->data ){
110+ $ this ->validationErrors = 'invalid ' ;
111+ $ this ->continue = false ;
112+ }
113+ }
114+ return $ this ;
115+ }
116+
117+ function inRange ($ min = null ,$ max = null ){
118+ if ($ this ->continue ){
119+ if ($ min !== null && $ this ->data < $ min ){
120+ $ this ->validationErrors = 'invalid ' ;
121+ $ this ->continue = false ;
122+ }
123+ if ($ max !== null && $ this ->data > $ max ){
124+ $ this ->validationErrors = 'invalid ' ;
125+ $ this ->continue = false ;
126+ }
127+ }
128+ }
129+
130+ function isTimestamp (){
131+ if ($ this ->continue ){
132+ if (strtotime ($ this ->data ) === false ){
133+ $ this ->validationErrors = 'invalid ' ;
134+ $ this ->continue = false ;
135+ }
136+ }
137+ return $ this ;
138+ }
139+
140+ function isString (){
141+ if ($ this ->continue ){
142+ if (is_string ($ this ->data ) === false ){
143+ $ this ->validationErrors = 'invalid ' ;
144+ $ this ->continue = false ;
145+ }
146+ }
147+ return $ this ;
148+ }
149+
150+ function isArray (){
151+ if ($ this ->continue ){
152+ if (is_array ($ this ->data ) === false ){
153+ $ this ->validationErrors = 'invalid ' ;
154+ $ this ->continue = false ;
155+ }
156+ }
157+ return $ this ;
158+ }
159+
160+ function isBoolean (){
161+ if ($ this ->continue ){
162+ if (is_bool ($ this ->data ) === false ){
163+ $ this ->validationErrors = 'invalid ' ;
164+ $ this ->continue = false ;
165+ }
166+ }
167+ return $ this ;
168+ }
169+
170+ function match ($ regExpr ){
171+ if ($ this ->continue ){
172+ if (preg_match ($ regExpr ,$ this ->data ) === false ){
173+ $ this ->validationErrors = 'invalid ' ;
174+ $ this ->continue = false ;
175+ }
176+ }
177+ return $ this ;
178+ }
179+
180+ function hasLength ($ min = null , $ max = null ){
181+ if ($ this ->continue ){
182+ if ($ min !== null && strlen ($ this ->data ) < $ min ){
183+ $ this ->validationErrors = 'invalid ' ;
184+ $ this ->continue = false ;
185+ }
186+ if ($ max !== null && strlen ($ this ->data ) > $ max ){
187+ $ this ->validationErrors = 'invalid ' ;
188+ $ this ->continue = false ;
189+ }
190+ }
191+ return $ this ;
192+ }
193+
194+ function hasCount ($ min = null , $ max = null ){
195+ if ($ this ->continue ){
196+ if ($ min !== null && count ($ this ->data ) < $ min ){
197+ $ this ->validationErrors = 'invalid ' ;
198+ $ this ->continue = false ;
199+ }
200+ if ($ max !== null && count ($ this ->data ) > $ max ){
201+ $ this ->validationErrors = 'invalid ' ;
202+ $ this ->continue = false ;
203+ }
204+ }
205+ return $ this ;
206+ }
207+
208+ function in ($ range ){
209+ if ($ this ->continue ){
210+ if (in_array ($ this ->data ,$ range ) === false ){
211+ $ this ->validationErrors = 'invalid ' ;
212+ $ this ->continue = false ;
213+ }
214+ }
215+ return $ this ;
216+ }
217+
218+ function getValidationErrors (){
219+ if (isset ($ this ->validationErrors )){
220+ return $ this ->validationErrors ;
221+ }
222+ $ validationErrors = [];
223+ foreach ($ this ->childValidations as $ childValidation ){
224+ $ childValidationErrors = $ childValidation ->getValidationErrors ();
225+ if (is_string ($ childValidationErrors ) || (is_array ($ childValidationErrors ) && count ($ childValidationErrors ) > 0 )){
226+ $ validationErrors [$ childValidation ->key ] = $ childValidationErrors ;
227+ }
228+ }
229+ return $ validationErrors ;
230+ }
231+
232+ function generateBadRequestOnError (){
233+ $ validationErrors = $ this ->getValidationErrors ();
234+ if (is_string ($ validationErrors ) || (is_array ($ validationErrors ) && count ($ validationErrors ) > 0 )){
235+ // there is validation error
236+ throw new BadRequest ($ validationErrors );
237+ }
238+ }
239+ }
0 commit comments