Type.php 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320
  1. <?php
  2. /**
  3. * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
  4. * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
  5. *
  6. * Licensed under The MIT License
  7. * For full copyright and license information, please see the LICENSE.txt
  8. * Redistributions of files must retain the above copyright notice.
  9. *
  10. * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
  11. * @link http://cakephp.org CakePHP(tm) Project
  12. * @since 3.0.0
  13. * @license http://www.opensource.org/licenses/mit-license.php MIT License
  14. */
  15. namespace Cake\Database;
  16. use InvalidArgumentException;
  17. use PDO;
  18. /**
  19. * Encapsulates all conversion functions for values coming from database into PHP and
  20. * going from PHP into database.
  21. */
  22. class Type
  23. {
  24. /**
  25. * List of supported database types. A human readable
  26. * identifier is used as key and a complete namespaced class name as value
  27. * representing the class that will do actual type conversions.
  28. *
  29. * @var array
  30. */
  31. protected static $_types = [
  32. 'biginteger' => 'Cake\Database\Type\IntegerType',
  33. 'binary' => 'Cake\Database\Type\BinaryType',
  34. 'boolean' => 'Cake\Database\Type\BoolType',
  35. 'date' => 'Cake\Database\Type\DateType',
  36. 'datetime' => 'Cake\Database\Type\DateTimeType',
  37. 'decimal' => 'Cake\Database\Type\FloatType',
  38. 'float' => 'Cake\Database\Type\FloatType',
  39. 'integer' => 'Cake\Database\Type\IntegerType',
  40. 'string' => 'Cake\Database\Type\StringType',
  41. 'text' => 'Cake\Database\Type\StringType',
  42. 'time' => 'Cake\Database\Type\TimeType',
  43. 'timestamp' => 'Cake\Database\Type\DateTimeType',
  44. 'uuid' => 'Cake\Database\Type\UuidType',
  45. ];
  46. /**
  47. * List of basic type mappings, used to avoid having to instantiate a class
  48. * for doing conversion on these
  49. *
  50. * @var array
  51. * @deprecated 3.1 All types will now use a specific class
  52. */
  53. protected static $_basicTypes = [
  54. 'string' => ['callback' => ['\Cake\Database\Type', 'strval']],
  55. 'text' => ['callback' => ['\Cake\Database\Type', 'strval']],
  56. 'boolean' => [
  57. 'callback' => ['\Cake\Database\Type', 'boolval'],
  58. 'pdo' => PDO::PARAM_BOOL
  59. ],
  60. ];
  61. /**
  62. * Contains a map of type object instances to be reused if needed
  63. *
  64. * @var array
  65. */
  66. protected static $_builtTypes = [];
  67. /**
  68. * Identifier name for this type
  69. *
  70. * @var string
  71. */
  72. protected $_name = null;
  73. /**
  74. * Constructor
  75. *
  76. * @param string $name The name identifying this type
  77. */
  78. public function __construct($name = null)
  79. {
  80. $this->_name = $name;
  81. }
  82. /**
  83. * Returns a Type object capable of converting a type identified by $name
  84. *
  85. * @param string $name type identifier
  86. * @throws \InvalidArgumentException If type identifier is unknown
  87. * @return Type
  88. */
  89. public static function build($name)
  90. {
  91. if (isset(static::$_builtTypes[$name])) {
  92. return static::$_builtTypes[$name];
  93. }
  94. if (!isset(static::$_types[$name])) {
  95. throw new InvalidArgumentException(sprintf('Unknown type "%s"', $name));
  96. }
  97. if (is_string(static::$_types[$name])) {
  98. return static::$_builtTypes[$name] = new static::$_types[$name]($name);
  99. }
  100. return static::$_builtTypes[$name] = static::$_types[$name];
  101. }
  102. /**
  103. * Returns an arrays with all the mapped type objects, indexed by name
  104. *
  105. * @return array
  106. */
  107. public static function buildAll()
  108. {
  109. $result = [];
  110. foreach (self::$_types as $name => $type) {
  111. $result[$name] = isset(static::$_builtTypes[$name]) ? static::$_builtTypes[$name] : static::build($name);
  112. }
  113. return $result;
  114. }
  115. /**
  116. * Returns a Type object capable of converting a type identified by $name
  117. *
  118. * @param string $name The type identifier you want to set.
  119. * @param \Cake\Database\Type $instance The type instance you want to set.
  120. * @return void
  121. */
  122. public static function set($name, Type $instance)
  123. {
  124. static::$_builtTypes[$name] = $instance;
  125. }
  126. /**
  127. * Registers a new type identifier and maps it to a fully namespaced classname,
  128. * If called with no arguments it will return current types map array
  129. * If $className is omitted it will return mapped class for $type
  130. *
  131. * @param string|array|\Cake\Database\Type|null $type if string name of type to map, if array list of arrays to be mapped
  132. * @param string|null $className The classname to register.
  133. * @return array|string|null if $type is null then array with current map, if $className is null string
  134. * configured class name for give $type, null otherwise
  135. */
  136. public static function map($type = null, $className = null)
  137. {
  138. if ($type === null) {
  139. return self::$_types;
  140. }
  141. if (is_array($type)) {
  142. self::$_types = $type;
  143. return null;
  144. }
  145. if ($className === null) {
  146. return isset(self::$_types[$type]) ? self::$_types[$type] : null;
  147. }
  148. self::$_types[$type] = $className;
  149. }
  150. /**
  151. * Clears out all created instances and mapped types classes, useful for testing
  152. *
  153. * @return void
  154. */
  155. public static function clear()
  156. {
  157. self::$_types = [];
  158. self::$_builtTypes = [];
  159. }
  160. /**
  161. * Returns type identifier name for this object
  162. *
  163. * @return string
  164. */
  165. public function getName()
  166. {
  167. return $this->_name;
  168. }
  169. /**
  170. * Returns the base type name that this class is inheriting.
  171. * This is useful when extending base type for adding extra functionality
  172. * but still want the rest of the framework to use the same assumptions it would
  173. * do about the base type it inherits from.
  174. *
  175. * @return string
  176. */
  177. public function getBaseType()
  178. {
  179. return $this->_name;
  180. }
  181. /**
  182. * Casts given value from a PHP type to one acceptable by database
  183. *
  184. * @param mixed $value value to be converted to database equivalent
  185. * @param Driver $driver object from which database preferences and configuration will be extracted
  186. * @return mixed
  187. */
  188. public function toDatabase($value, Driver $driver)
  189. {
  190. return $this->_basicTypeCast($value);
  191. }
  192. /**
  193. * Casts given value from a database type to PHP equivalent
  194. *
  195. * @param mixed $value value to be converted to PHP equivalent
  196. * @param Driver $driver object from which database preferences and configuration will be extracted
  197. * @return mixed
  198. */
  199. public function toPHP($value, Driver $driver)
  200. {
  201. return $this->_basicTypeCast($value);
  202. }
  203. /**
  204. * Checks whether this type is a basic one and can be converted using a callback
  205. * If it is, returns converted value
  206. *
  207. * @param mixed $value value to be converted to PHP equivalent
  208. * @return mixed
  209. * @deprecated 3.1 All types should now be a specific class
  210. */
  211. protected function _basicTypeCast($value)
  212. {
  213. if ($value === null) {
  214. return null;
  215. }
  216. if (!empty(self::$_basicTypes[$this->_name])) {
  217. $typeInfo = self::$_basicTypes[$this->_name];
  218. if (isset($typeInfo['callback'])) {
  219. return $typeInfo['callback']($value);
  220. }
  221. }
  222. return $value;
  223. }
  224. /**
  225. * Casts give value to Statement equivalent
  226. *
  227. * @param mixed $value value to be converted to PHP equivalent
  228. * @param Driver $driver object from which database preferences and configuration will be extracted
  229. * @return mixed
  230. */
  231. public function toStatement($value, Driver $driver)
  232. {
  233. if ($value === null) {
  234. return PDO::PARAM_NULL;
  235. }
  236. return PDO::PARAM_STR;
  237. }
  238. /**
  239. * Type converter for boolean values.
  240. *
  241. * Will convert string true/false into booleans.
  242. *
  243. * @param mixed $value The value to convert to a boolean.
  244. * @return bool
  245. * @deprecated 3.1.8 This method is now unused.
  246. */
  247. public static function boolval($value)
  248. {
  249. if (is_string($value) && !is_numeric($value)) {
  250. return strtolower($value) === 'true' ? true : false;
  251. }
  252. return !empty($value);
  253. }
  254. /**
  255. * Type converter for string values.
  256. *
  257. * Will convert values into strings
  258. *
  259. * @param mixed $value The value to convert to a string.
  260. * @return bool
  261. * @deprecated 3.1.8 This method is now unused.
  262. */
  263. public static function strval($value)
  264. {
  265. if (is_array($value)) {
  266. $value = '';
  267. }
  268. return strval($value);
  269. }
  270. /**
  271. * Generate a new primary key value for a given type.
  272. *
  273. * This method can be used by types to create new primary key values
  274. * when entities are inserted.
  275. *
  276. * @return mixed A new primary key value.
  277. * @see \Cake\Database\Type\UuidType
  278. */
  279. public function newId()
  280. {
  281. return null;
  282. }
  283. /**
  284. * Marshalls flat data into PHP objects.
  285. *
  286. * Most useful for converting request data into PHP objects
  287. * that make sense for the rest of the ORM/Database layers.
  288. *
  289. * @param mixed $value The value to convert.
  290. * @return mixed Converted value.
  291. */
  292. public function marshal($value)
  293. {
  294. return $this->_basicTypeCast($value);
  295. }
  296. }