Merge pull request #7019 from jitendrapurohit/CRM-17395
[civicrm-core.git] / CRM / Utils / Type.php
1 <?php
2 /*
3 +--------------------------------------------------------------------+
4 | CiviCRM version 4.7 |
5 +--------------------------------------------------------------------+
6 | Copyright CiviCRM LLC (c) 2004-2015 |
7 +--------------------------------------------------------------------+
8 | This file is a part of CiviCRM. |
9 | |
10 | CiviCRM is free software; you can copy, modify, and distribute it |
11 | under the terms of the GNU Affero General Public License |
12 | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
13 | |
14 | CiviCRM is distributed in the hope that it will be useful, but |
15 | WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
17 | See the GNU Affero General Public License for more details. |
18 | |
19 | You should have received a copy of the GNU Affero General Public |
20 | License and the CiviCRM Licensing Exception along |
21 | with this program; if not, contact CiviCRM LLC |
22 | at info[AT]civicrm[DOT]org. If you have questions about the |
23 | GNU Affero General Public License or the licensing of CiviCRM, |
24 | see the CiviCRM license FAQ at http://civicrm.org/licensing |
25 +--------------------------------------------------------------------+
26 */
27
28 /**
29 *
30 * @package CRM
31 * @copyright CiviCRM LLC (c) 2004-2015
32 */
33 class CRM_Utils_Type {
34 const
35 T_INT = 1,
36 T_STRING = 2,
37 T_ENUM = 2,
38 T_DATE = 4,
39 T_TIME = 8,
40 T_BOOLEAN = 16,
41 T_TEXT = 32,
42 T_LONGTEXT = 32,
43 T_BLOB = 64,
44 T_TIMESTAMP = 256,
45 T_FLOAT = 512,
46 T_MONEY = 1024,
47 T_EMAIL = 2048,
48 T_URL = 4096,
49 T_CCNUM = 8192,
50 T_MEDIUMBLOB = 16384;
51
52 // @todo What's the point of these constants? Backwards compatibility?
53 const
54 TWO = 2,
55 FOUR = 4,
56 SIX = 6,
57 EIGHT = 8,
58 TWELVE = 12,
59 SIXTEEN = 16,
60 TWENTY = 20,
61 MEDIUM = 20,
62 THIRTY = 30,
63 BIG = 30,
64 FORTYFIVE = 45,
65 HUGE = 45;
66
67 /**
68 * Gets the string representation for a data type.
69 *
70 * @param int $type
71 * Integer number identifying the data type.
72 *
73 * @return string
74 * String identifying the data type, e.g. 'Int' or 'String'.
75 */
76 public static function typeToString($type) {
77 // @todo Use constants in the case statements, e.g. "case T_INT:".
78 // @todo return directly, instead of assigning a value.
79 // @todo Use a lookup array, as a property or as a local variable.
80 switch ($type) {
81 case 1:
82 $string = 'Int';
83 break;
84
85 case 2:
86 $string = 'String';
87 break;
88
89 case 3:
90 $string = 'Enum';
91 break;
92
93 case 4:
94 $string = 'Date';
95 break;
96
97 case 8:
98 $string = 'Time';
99 break;
100
101 case 16:
102 $string = 'Boolean';
103 break;
104
105 case 32:
106 $string = 'Text';
107 break;
108
109 case 64:
110 $string = 'Blob';
111 break;
112
113 // CRM-10404
114 case 12:
115 case 256:
116 $string = 'Timestamp';
117 break;
118
119 case 512:
120 $string = 'Float';
121 break;
122
123 case 1024:
124 $string = 'Money';
125 break;
126
127 case 2048:
128 $string = 'Date';
129 break;
130
131 case 4096:
132 $string = 'Email';
133 break;
134
135 case 16384:
136 $string = 'Mediumblob';
137 break;
138 }
139
140 return (isset($string)) ? $string : "";
141 }
142
143 /**
144 * Verify that a variable is of a given type, and apply a bit of processing.
145 *
146 * @param mixed $data
147 * The value to be verified/escaped.
148 * @param string $type
149 * The type to verify against.
150 * @param bool $abort
151 * If TRUE, the operation will CRM_Core_Error::fatal() on invalid data.
152 *
153 * @return mixed
154 * The data, escaped if necessary.
155 */
156 public static function escape($data, $type, $abort = TRUE) {
157 switch ($type) {
158 case 'Integer':
159 case 'Int':
160 if (CRM_Utils_Rule::integer($data)) {
161 return (int) $data;
162 }
163 break;
164
165 case 'Positive':
166 if (CRM_Utils_Rule::positiveInteger($data)) {
167 return (int) $data;
168 }
169 break;
170
171 // CRM-8925 for custom fields of this type
172 case 'Country':
173 case 'StateProvince':
174 // Handle multivalued data in delimited or array format
175 if (is_array($data) || (strpos($data, CRM_Core_DAO::VALUE_SEPARATOR) !== FALSE)) {
176 $valid = TRUE;
177 foreach (CRM_Utils_Array::explodePadded($data) as $item) {
178 if (!CRM_Utils_Rule::positiveInteger($item)) {
179 $valid = FALSE;
180 }
181 }
182 if ($valid) {
183 return $data;
184 }
185 }
186 elseif (CRM_Utils_Rule::positiveInteger($data)) {
187 return (int) $data;
188 }
189 break;
190
191 case 'File':
192 if (CRM_Utils_Rule::positiveInteger($data)) {
193 return (int) $data;
194 }
195 break;
196
197 case 'Link':
198 if (CRM_Utils_Rule::url($data = trim($data))) {
199 return $data;
200 }
201 break;
202
203 case 'Boolean':
204 if (CRM_Utils_Rule::boolean($data)) {
205 return $data;
206 }
207 break;
208
209 case 'Float':
210 case 'Money':
211 if (CRM_Utils_Rule::numeric($data)) {
212 return $data;
213 }
214 break;
215
216 case 'String':
217 case 'Memo':
218 case 'Text':
219 return CRM_Core_DAO::escapeString($data);
220
221 case 'Date':
222 case 'Timestamp':
223 // a null date or timestamp is valid
224 if (strlen(trim($data)) == 0) {
225 return trim($data);
226 }
227
228 if ((preg_match('/^\d{8}$/', $data) ||
229 preg_match('/^\d{14}$/', $data)
230 ) &&
231 CRM_Utils_Rule::mysqlDate($data)
232 ) {
233 return $data;
234 }
235 break;
236
237 case 'ContactReference':
238 if (strlen(trim($data)) == 0) {
239 return trim($data);
240 }
241
242 if (CRM_Utils_Rule::validContact($data)) {
243 return (int) $data;
244 }
245 break;
246
247 default:
248 CRM_Core_Error::fatal(
249 $type . " is not a recognised (camel cased) data type."
250 );
251 break;
252 }
253
254 // @todo Use exceptions instead of CRM_Core_Error::fatal().
255 if ($abort) {
256 $data = htmlentities($data);
257 CRM_Core_Error::fatal("$data is not of the type $type");
258 }
259 return NULL;
260 }
261
262 /**
263 * Verify that a variable is of a given type.
264 *
265 * @param mixed $data
266 * The value to validate.
267 * @param string $type
268 * The type to validate against.
269 * @param bool $abort
270 * If TRUE, the operation will CRM_Core_Error::fatal() on invalid data.
271 * @name string $name
272 * The name of the attribute
273 *
274 * @return mixed
275 * The data, escaped if necessary
276 */
277 public static function validate($data, $type, $abort = TRUE, $name = 'One of parameters ') {
278 switch ($type) {
279 case 'Integer':
280 case 'Int':
281 if (CRM_Utils_Rule::integer($data)) {
282 return (int) $data;
283 }
284 break;
285
286 case 'Positive':
287 if (CRM_Utils_Rule::positiveInteger($data)) {
288 return (int) $data;
289 }
290 break;
291
292 case 'Boolean':
293 if (CRM_Utils_Rule::boolean($data)) {
294 return $data;
295 }
296 break;
297
298 case 'Float':
299 case 'Money':
300 if (CRM_Utils_Rule::numeric($data)) {
301 return $data;
302 }
303 break;
304
305 case 'Text':
306 case 'String':
307 case 'Link':
308 case 'Memo':
309 return $data;
310
311 case 'Date':
312 // a null date is valid
313 if (strlen(trim($data)) == 0) {
314 return trim($data);
315 }
316
317 if (preg_match('/^\d{8}$/', $data) &&
318 CRM_Utils_Rule::mysqlDate($data)
319 ) {
320 return $data;
321 }
322 break;
323
324 case 'Timestamp':
325 // a null timestamp is valid
326 if (strlen(trim($data)) == 0) {
327 return trim($data);
328 }
329
330 if ((preg_match('/^\d{14}$/', $data) ||
331 preg_match('/^\d{8}$/', $data)
332 ) &&
333 CRM_Utils_Rule::mysqlDate($data)
334 ) {
335 return $data;
336 }
337 break;
338
339 case 'ContactReference':
340 // null is valid
341 if (strlen(trim($data)) == 0) {
342 return trim($data);
343 }
344
345 if (CRM_Utils_Rule::validContact($data)) {
346 return $data;
347 }
348 break;
349
350 default:
351 CRM_Core_Error::fatal("Cannot recognize $type for $data");
352 break;
353 }
354
355 if ($abort) {
356 $data = htmlentities($data);
357 CRM_Core_Error::fatal("$name (value: $data) is not of the type $type");
358 }
359
360 return NULL;
361 }
362
363 }