1 <?php
  2 
  3 /**
  4  * Class for var casting.
  5  *
  6  * @author gharlan
  7  *
  8  * @package redaxo\core
  9  */
 10 class rex_type
 11 {
 12     /**
 13      * Casts the variable $var to $vartype.
 14      *
 15      * Possible types:
 16      *  - 'bool' (or 'boolean')
 17      *  - 'int' (or 'integer')
 18      *  - 'double'
 19      *  - 'string'
 20      *  - 'float'
 21      *  - 'real'
 22      *  - 'object'
 23      *  - 'array'
 24      *  - 'array[<type>]', e.g. 'array[int]'
 25      *  - '' (don't cast)
 26      *  - a callable
 27      *  - array(
 28      *      array(<key>, <vartype>, <default>),
 29      *      array(<key>, <vartype>, <default>),
 30      *      ...
 31      *    )
 32      *
 33      * @param mixed $var     Variable to cast
 34      * @param mixed $vartype Variable type
 35      *
 36      * @throws InvalidArgumentException
 37      *
 38      * @return mixed Castet value
 39      */
 40     public static function cast($var, $vartype)
 41     {
 42         if (is_string($vartype)) {
 43             $casted = true;
 44             switch ($vartype) {
 45                 // ---------------- PHP types
 46                 case 'bool':
 47                 case 'boolean':
 48                     $var = (bool) $var;
 49                     break;
 50                 case 'int':
 51                 case 'integer':
 52                     $var = (int) $var;
 53                     break;
 54                 case 'double':
 55                     $var = (float) $var;
 56                     break;
 57                 case 'float':
 58                 case 'real':
 59                     $var = (float) $var;
 60                     break;
 61                 case 'string':
 62                     $var = (string) $var;
 63                     break;
 64                 case 'object':
 65                     $var = (object) $var;
 66                     break;
 67                 case 'array':
 68                     if ('' === $var) {
 69                         $var = [];
 70                     } else {
 71                         $var = (array) $var;
 72                     }
 73                     break;
 74 
 75                     // kein Cast, nichts tun
 76                 case '': break;
 77 
 78                 default:
 79                     // check for array with generic type
 80                     if (strpos($vartype, 'array[') === 0) {
 81                         if (empty($var)) {
 82                             $var = [];
 83                         } else {
 84                             $var = (array) $var;
 85                         }
 86 
 87                         // check if every element in the array is from the generic type
 88                         $matches = [];
 89                         if (preg_match('@array\[([^\]]*)\]@', $vartype, $matches)) {
 90                             foreach ($var as $key => $value) {
 91                                 try {
 92                                     $var[$key] = self::cast($value, $matches[1]);
 93                                 } catch (InvalidArgumentException $e) {
 94                                     // Evtl Typo im vartype, mit urspr. typ als fehler melden
 95                                     throw new InvalidArgumentException('Unexpected vartype "' . $vartype . '" in cast()!');
 96                                 }
 97                             }
 98                         } else {
 99                             throw new InvalidArgumentException('Unexpected vartype "' . $vartype . '" in cast()!');
100                         }
101                     } else {
102                         $casted = false;
103                     }
104             }
105             if ($casted) {
106                 return $var;
107             }
108         }
109 
110         if (is_callable($vartype)) {
111             $var = call_user_func($vartype, $var);
112         } elseif (is_array($vartype)) {
113             $var = self::cast($var, 'array');
114             $newVar = [];
115             foreach ($vartype as $cast) {
116                 if (!is_array($cast) || !isset($cast[0])) {
117                     throw new InvalidArgumentException('Unexpected vartype in cast()!');
118                 }
119                 $key = $cast[0];
120                 $innerVartype = isset($cast[1]) ? $cast[1] : '';
121                 if (array_key_exists($key, $var)) {
122                     $newVar[$key] = self::cast($var[$key], $innerVartype);
123                 } elseif (!isset($cast[2])) {
124                     $newVar[$key] = self::cast('', $innerVartype);
125                 } else {
126                     $newVar[$key] = $cast[2];
127                 }
128             }
129             $var = $newVar;
130         } elseif (is_string($vartype)) {
131             throw new InvalidArgumentException('Unexpected vartype "' . $vartype . '" in cast()!');
132         } else {
133             throw new InvalidArgumentException('Unexpected vartype in cast()!');
134         }
135 
136         return $var;
137     }
138 }
139