commiting uncommited changes on live site
[weblabels.fsf.org.git] / crm.fsf.org / 20131203 / files / sites / all / modules-new / civicrm / CRM / Utils / Type.php
1 <?php
2 /*
3 +--------------------------------------------------------------------+
4 | CiviCRM version 4.6 |
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 * $Id: $
33 *
34 */
35 class CRM_Utils_Type {
36 const
37 T_INT = 1,
38 T_STRING = 2,
39 T_ENUM = 2,
40 T_DATE = 4,
41 T_TIME = 8,
42 T_BOOLEAN = 16,
43 T_TEXT = 32,
44 T_LONGTEXT = 32,
45 T_BLOB = 64,
46 T_TIMESTAMP = 256,
47 T_FLOAT = 512,
48 T_MONEY = 1024,
49 T_EMAIL = 2048,
50 T_URL = 4096,
51 T_CCNUM = 8192,
52 T_MEDIUMBLOB = 16384;
53
54 // @todo What's the point of these constants? Backwards compatibility?
55 const
56 TWO = 2,
57 FOUR = 4,
58 SIX = 6,
59 EIGHT = 8,
60 TWELVE = 12,
61 SIXTEEN = 16,
62 TWENTY = 20,
63 MEDIUM = 20,
64 THIRTY = 30,
65 BIG = 30,
66 FORTYFIVE = 45,
67 HUGE = 45;
68
69 /**
70 * Gets the string representation for a data type.
71 *
72 * @param int $type
73 * Integer number identifying the data type.
74 *
75 * @return string
76 * String identifying the data type, e.g. 'Int' or 'String'.
77 */
78 public static function typeToString($type) {
79 // @todo Use constants in the case statements, e.g. "case T_INT:".
80 // @todo return directly, instead of assigning a value.
81 // @todo Use a lookup array, as a property or as a local variable.
82 switch ($type) {
83 case 1:
84 $string = 'Int';
85 break;
86
87 case 2:
88 $string = 'String';
89 break;
90
91 case 3:
92 $string = 'Enum';
93 break;
94
95 case 4:
96 $string = 'Date';
97 break;
98
99 case 8:
100 $string = 'Time';
101 break;
102
103 case 16:
104 $string = 'Boolean';
105 break;
106
107 case 32:
108 $string = 'Text';
109 break;
110
111 case 64:
112 $string = 'Blob';
113 break;
114
115 // CRM-10404
116 case 12:
117 case 256:
118 $string = 'Timestamp';
119 break;
120
121 case 512:
122 $string = 'Float';
123 break;
124
125 case 1024:
126 $string = 'Money';
127 break;
128
129 case 2048:
130 $string = 'Date';
131 break;
132
133 case 4096:
134 $string = 'Email';
135 break;
136
137 case 16384:
138 $string = 'Mediumblob';
139 break;
140 }
141
142 return (isset($string)) ? $string : "";
143 }
144
145 /**
146 * Helper function to call escape on arrays
147 *
148 * @see escape
149 */
150 public static function escapeAll($data, $type, $abort = TRUE) {
151 foreach ($data as $key => $value) {
152 $data[$key] = CRM_Utils_Type::escape($value, $type, $abort);
153 }
154 return $data;
155 }
156
157 /**
158 * Verify that a variable is of a given type, and apply a bit of processing.
159 *
160 * @param mixed $data
161 * The value to be verified/escaped.
162 * @param string $type
163 * The type to verify against.
164 * @param bool $abort
165 * If TRUE, the operation will CRM_Core_Error::fatal() on invalid data.
166 *
167 * @return mixed
168 * The data, escaped if necessary.
169 */
170 public static function escape($data, $type, $abort = TRUE) {
171 switch ($type) {
172 case 'Integer':
173 case 'Int':
174 if (CRM_Utils_Rule::integer($data)) {
175 return (int) $data;
176 }
177 break;
178
179 case 'Positive':
180 if (CRM_Utils_Rule::positiveInteger($data)) {
181 return (int) $data;
182 }
183 break;
184
185 // CRM-8925 for custom fields of this type
186 case 'Country':
187 case 'StateProvince':
188 // Handle multivalued data in delimited or array format
189 if (is_array($data) || (strpos($data, CRM_Core_DAO::VALUE_SEPARATOR) !== FALSE)) {
190 $valid = TRUE;
191 foreach (CRM_Utils_Array::explodePadded($data) as $item) {
192 if (!CRM_Utils_Rule::positiveInteger($item)) {
193 $valid = FALSE;
194 }
195 }
196 if ($valid) {
197 return $data;
198 }
199 }
200 elseif (CRM_Utils_Rule::positiveInteger($data)) {
201 return (int) $data;
202 }
203 break;
204
205 case 'File':
206 if (CRM_Utils_Rule::positiveInteger($data)) {
207 return (int) $data;
208 }
209 break;
210
211 case 'Link':
212 if (CRM_Utils_Rule::url($data = trim($data))) {
213 return $data;
214 }
215 break;
216
217 case 'Boolean':
218 if (CRM_Utils_Rule::boolean($data)) {
219 return $data;
220 }
221 break;
222
223 case 'Float':
224 case 'Money':
225 if (CRM_Utils_Rule::numeric($data)) {
226 return $data;
227 }
228 break;
229
230 case 'String':
231 case 'Memo':
232 case 'Text':
233 return CRM_Core_DAO::escapeString($data);
234
235 case 'Date':
236 case 'Timestamp':
237 // a null date or timestamp is valid
238 if (strlen(trim($data)) == 0) {
239 return trim($data);
240 }
241
242 if ((preg_match('/^\d{8}$/', $data) ||
243 preg_match('/^\d{14}$/', $data)
244 ) &&
245 CRM_Utils_Rule::mysqlDate($data)
246 ) {
247 return $data;
248 }
249 break;
250
251 case 'ContactReference':
252 if (strlen(trim($data)) == 0) {
253 return trim($data);
254 }
255
256 if (CRM_Utils_Rule::validContact($data)) {
257 return (int) $data;
258 }
259 break;
260
261 case 'MysqlColumnNameOrAlias':
262 if (CRM_Utils_Rule::mysqlColumnNameOrAlias($data)) {
263 $data = str_replace('`', '', $data);
264 $parts = explode('.', $data);
265 $data = '`' . implode('`.`', $parts) . '`';
266
267 return $data;
268 }
269 break;
270
271 case 'MysqlOrderByDirection':
272 if (CRM_Utils_Rule::mysqlOrderByDirection($data)) {
273 return strtolower($data);
274 }
275 break;
276
277 case 'MysqlOrderBy':
278 if (CRM_Utils_Rule::mysqlOrderBy($data)) {
279 $parts = explode(',', $data);
280 foreach ($parts as &$part) {
281 $part = preg_replace_callback('/^(?:(?:((?:`[\w-]{1,64}`|[\w-]{1,64}))(?:\.))?(`[\w-]{1,64}`|[\w-]{1,64})(?: (asc|desc))?)$/i', array('CRM_Utils_Type', 'mysqlOrderByCallback'), trim($part));
282 }
283 return implode(', ', $parts);
284 }
285 break;
286
287 default:
288 CRM_Core_Error::fatal(
289 $type . " is not a recognised (camel cased) data type."
290 );
291 break;
292 }
293
294 // @todo Use exceptions instead of CRM_Core_Error::fatal().
295 if ($abort) {
296 $data = htmlentities($data);
297 CRM_Core_Error::fatal("$data is not of the type $type");
298 }
299 return NULL;
300 }
301
302 /**
303 * Helper function to call validate on arrays
304 *
305 * @see validate
306 */
307 public static function validateAll($data, $type, $abort = TRUE) {
308 foreach ($data as $key => $value) {
309 $data[$key] = CRM_Utils_Type::validate($value, $type, $abort);
310 }
311 return $data;
312 }
313
314 /**
315 * Verify that a variable is of a given type.
316 *
317 * @param mixed $data
318 * The value to validate.
319 * @param string $type
320 * The type to validate against.
321 * @param bool $abort
322 * If TRUE, the operation will CRM_Core_Error::fatal() on invalid data.
323 * @name string $name
324 * The name of the attribute
325 *
326 * @return mixed
327 * The data, escaped if necessary
328 */
329 public static function validate($data, $type, $abort = TRUE, $name = 'One of parameters ') {
330 switch ($type) {
331 case 'Integer':
332 case 'Int':
333 if (CRM_Utils_Rule::integer($data)) {
334 return (int) $data;
335 }
336 break;
337
338 case 'Positive':
339 if (CRM_Utils_Rule::positiveInteger($data)) {
340 return (int) $data;
341 }
342 break;
343
344 case 'Boolean':
345 if (CRM_Utils_Rule::boolean($data)) {
346 return $data;
347 }
348 break;
349
350 case 'Float':
351 case 'Money':
352 if (CRM_Utils_Rule::numeric($data)) {
353 return $data;
354 }
355 break;
356
357 case 'Text':
358 case 'String':
359 case 'Link':
360 case 'Memo':
361 return $data;
362
363 case 'Date':
364 // a null date is valid
365 if (strlen(trim($data)) == 0) {
366 return trim($data);
367 }
368
369 if (preg_match('/^\d{8}$/', $data) &&
370 CRM_Utils_Rule::mysqlDate($data)
371 ) {
372 return $data;
373 }
374 break;
375
376 case 'Timestamp':
377 // a null timestamp is valid
378 if (strlen(trim($data)) == 0) {
379 return trim($data);
380 }
381
382 if ((preg_match('/^\d{14}$/', $data) ||
383 preg_match('/^\d{8}$/', $data)
384 ) &&
385 CRM_Utils_Rule::mysqlDate($data)
386 ) {
387 return $data;
388 }
389 break;
390
391 case 'ContactReference':
392 // null is valid
393 if (strlen(trim($data)) == 0) {
394 return trim($data);
395 }
396
397 if (CRM_Utils_Rule::validContact($data)) {
398 return $data;
399 }
400 break;
401
402 case 'MysqlColumnNameOrAlias':
403 if (CRM_Utils_Rule::mysqlColumnNameOrAlias($data)) {
404 return $data;
405 }
406 break;
407
408 case 'MysqlOrderByDirection':
409 if (CRM_Utils_Rule::mysqlOrderByDirection($data)) {
410 return strtolower($data);
411 }
412 break;
413
414 case 'MysqlOrderBy':
415 if (CRM_Utils_Rule::mysqlOrderBy($data)) {
416 return $data;
417 }
418 break;
419
420 default:
421 CRM_Core_Error::fatal("Cannot recognize $type for $data");
422 break;
423 }
424
425 if ($abort) {
426 $data = htmlentities($data);
427 CRM_Core_Error::fatal("$name (value: $data) is not of the type $type");
428 }
429
430 return NULL;
431 }
432
433 /**
434 * preg_replace_callback for MysqlOrderBy escape.
435 */
436 public static function mysqlOrderByCallback($matches) {
437 $output = '';
438 $matches = str_replace('`', '', $matches);
439 // Table name.
440 if (isset($matches[1]) && $matches[1]) {
441 $output .= '`' . $matches[1] . '`.';
442 }
443 // Column name.
444 if (isset($matches[2]) && $matches[2]) {
445 $output .= '`' . $matches[2] . '`';
446 }
447 // Sort order.
448 if (isset($matches[3]) && $matches[3]) {
449 $output .= ' ' . $matches[3];
450 }
451 return $output;
452 }
453
454 }