Open-Source PHP Framework - Designed for rapid development of performance-oriented scalable applications

/packages/validator

[return to app]
1 <?php
2
/**
3  * This comes from the May 2007 php|architect article:
4  * Unifying Server-Side and Client-Side Input Validation
5  */
6
class ValidatedField {
7     protected 
$_label$_validation;
8
9     public function 
__construct($label$validation) {
10         
$this->_label $label;
11         
$this->_validation $validation;
12     }
13
14     public function 
__call($name$val) {
15         if (
strpos($name'get') === 0) {
16         
$property '_' strtolower($name[3]) . substr($name4);
17             if (isset(
$this->$property)) {
18                 return 
$this->$property;
19             } else {
20             
$error_message 'There is no property defined as ' $property
21                            
' or method called ' $name
22                            
' in the ' __CLASS__ ' class';
23             }
24         } else {
25             
$error_message 'Call to undefined method ' __CLASS__ '::' $name '()';
26         }
27
28         if (isset(
$error_message)) {
29             
trigger_error($error_messageE_USER_ERROR);
30         }
31     }
32 }
33
34 class 
Validator {
35     protected 
$_validatedFields = array();
36
37     protected 
$_commonRegex = array(
38         
'match' => array(
39             
'HexColor' => '/^#?([\dA-F]{3}){1,2}$/i',
40             
'UsTelephone' =>
 
'/^\(?([2-9]\d{2})\)?[\.\s-]?([2-4|6-9]\d\d|5([0-4|6-9]\d|\d[0-4|6-9]))[\.\s-]?(\d{4})$/',
41             
'Email' => '/(^[\w\.!#$%"*+\/=?`{}|~^-]+)@(([-\w]+\.)+[A-Za-z]{2,})$/',
42             
'Url' => '/^(https?|ftp):\/\/([-\w]+\.)+[A-Za-z]{2,}(:\d+)?([\\\\\/]\S+)*?[\\\\\/]?(\?\S*)?$/i',
43             
'Integer' => '/^-?\d+$/',
44             
'Numeric' => '/^-?(\d*\.)?\d+$/',
45             
'AlphaNumeric' => '/^[\w\s]+$/i'),
46         
'get' => array(
47             
'Integer' => '/\d+/',
48             
'Numeric' => '/\d+(\.\d+)?/',
49             
'Trim' => '/^\s*(.*?)\s*$/')
50     );
51
52     protected 
$_validCssColors = array(
53         
'aqua' => '00FFFF',
54         
'black' => '000000',
55         
'blue' => '0000FF',
56         
'fuchsia' => 'FF00FF',
57         
'gray' => '808080',
58         
'green' => '008000',
59         
'lime' => '00FF00',
60         
'maroon' => '800000',
61         
'navy' => '000080',
62         
'olive' => '808000',
63         
'purple' => '800080',
64         
'red' => 'FF0000',
65         
'silver' => 'C0C0C0',
66         
'teal' => '008080',
67         
'white' => 'FFFFFF',
68         
'yellow' => 'FFFF00'
69     
);
70
71     public function 
getCommonData($dataType) {
72         switch (
$dataType) {
73             case 
'commonRegex':
74                 
$x = -1;
75                 
$return '{';
76                 foreach (
$this->_commonRegex as $matchType => $regexArray) {
77                     
$y = -1;
78                     if (++
$x) {
79                         
$return .= ', ' PHP_EOL;
80                     }
81                     
$return .= "'" $matchType "': {" PHP_EOL;
82                     foreach (
$regexArray as $key => $regexString) {
83                         if (++
$y) {
84                             
$return .= ', ' PHP_EOL;
85                         }
86                         
$return .= "'" $key "': " $regexString;
87                         if (
$matchType == 'get') {
88                             
$return .=  'g';
89                         }
90                     }
91                     
$return .= "}";
92                 }
93                 
$return .= '}';
94                 break;
95             case 
'validations':
96                 
$return = array();
97                 foreach (
$this->_validatedFields as $formId => $validatedArray) {
98                     foreach (
$validatedArray as $inputId => $obj) {
99                         
$return[$formId][$inputId] = $obj->getValidation();
100                     }
101                 }
102                 
$return json_encode($return);
103                 break;
104         }
105         return 
$return;
106     }
107
108     public function 
isValidNumeric($val) {
109         return 
is_numeric($val);
110     }
111
112     public function 
isValidInteger($val) {
113         return (
is_numeric($val) && $val == intval($val));
114     }
115
116     public function 
getNumbersOnly($val$integerOnly 0) {
117         
$regexType = ($integerOnly 'Integer' 'Numeric');
118         
preg_match_all($this->_commonRegex['get'][$regexType], $val$matches);
119         return 
implode($matches[0]);
120     }
121
122     public function 
isValidTelephone($val$country 'US') {
123         if (
strtoupper($country) == 'US') {
124             
$return = (preg_match($this->_commonRegex['match']['UsTelephone'], $val));
125         } else {
126             
$return = (strlen($this->getNumbersOnly($val)) > 6);
127         }
128         return 
$return;
129     }
130
131     public function 
isValidHexColor($val) {
132         if (isset(
$this->_validCssColors[$val])) {
133             
$val '#' $this->_validCssColors[$val];
134         }
135         return 
$this->__call('isValidHexColor', array($val));
136     }
137
138     public function 
setValidatedField($formId$inputId$label$validation) {
139         
$this->_validatedFields[$formId][$inputId] = new ValidatedField($label$validation);
140     }
141
142     public function 
getClosingJs() {
143         return 
'var validations = ' $this->getCommonData('validations') . ';
144 var thisFormId;
145 for (var formId in validations) {
146     thisFormId = Validator.dom(formId);
147     if (thisFormId) {
148         thisFormId.onsubmit = function() {
149             return Validator.validateForm(formId);
150         }
151     }
152 }'
;
153     }
154
155     public static 
$errors = array();
156
157     public function 
getErrorsFromPost($formId) {
158         
self::$errors[$formId] = array();
159         if (isset(
$_POST[key($this->_validatedFields[$formId])])) {
160             foreach (
$this->_validatedFields[$formId] as $inputId => $obj) {
161                 
$_POST[$inputId] = trim($_POST[$inputId]);
162                 if (!
$this->{$obj->getValidation()}($_POST[$inputId])) {
163                     
self::$errors[$formId][$inputId] = $obj->getLabel() . ' is not valid';
164                 }
165             }
166         }
167     }
168
169     public function 
__call($name$val) {
170         
$triggerError true;
171         if (
strpos($name'isValid') === 0) {
172             
$regexType substr($name7);
173             if (isset(
$this->_commonRegex['match'][$regexType])) {
174                 return 
preg_match($this->_commonRegex['match'][$regexType], current($val));
175                 
$triggerError false;
176             }
177         } else if (
strpos($name'set') === 0) {
178             
$this->{'_' strtolower($name[3]) . substr($name4)} = current($val);
179             
$triggerError false;
180         } else if (
strpos($name'get') === 0) {
181             
$property '_' strtolower($name[3]) . substr($name4);
182             if (isset(
$this->$property)) {
183                 return 
$this->$property;
184                 
$triggerError false;
185             }
186         }
187
188         if (
$triggerError) {
189             
trigger_error('Call to undefined method ' __CLASS__ '::' $name '()'E_USER_ERROR);
190         }
191     }
192 }