Type.php 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. <?php
  2. /**
  3. * PHP Version 5.4
  4. *
  5. * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
  6. * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
  7. *
  8. * Licensed under The MIT License
  9. * For full copyright and license information, please see the LICENSE.txt
  10. * Redistributions of files must retain the above copyright notice.
  11. *
  12. * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
  13. * @link http://cakephp.org CakePHP(tm) Project
  14. * @since CakePHP(tm) v 3.0.0
  15. * @license MIT License (http://www.opensource.org/licenses/mit-license.php)
  16. */
  17. namespace Cake\Database;
  18. use Cake\Database\Driver;
  19. use Exception;
  20. use PDO;
  21. /**
  22. * Encapsulates all conversion functions for values coming from database into PHP and
  23. * going from PHP into database.
  24. */
  25. class Type {
  26. /**
  27. * List of supported database types. A human readable
  28. * identifier is used as key and a complete namespaced class name as value
  29. * representing the class that will do actual type conversions.
  30. *
  31. * @var array
  32. */
  33. protected static $_types = [
  34. 'binary' => 'Cake\Database\Type\BinaryType',
  35. 'date' => 'Cake\Database\Type\DateType',
  36. 'datetime' => 'Cake\Database\Type\DateTimeType',
  37. 'timestamp' => 'Cake\Database\Type\DateTimeType',
  38. 'time' => 'Cake\Database\Type\TimeType'
  39. ];
  40. /**
  41. * List of basic type mappings, used to avoid having to instantiate a class
  42. * for doing conversion on these
  43. *
  44. * @var array
  45. */
  46. protected static $_basicTypes = [
  47. 'float' => ['callback' => 'floatval'],
  48. 'decimal' => ['callback' => 'floatval'],
  49. 'integer' => ['callback' => 'intval', 'pdo' => PDO::PARAM_INT],
  50. 'biginteger' => ['callback' => 'intval', 'pdo' => PDO::PARAM_INT],
  51. 'string' => ['callback' => 'strval'],
  52. 'uuid' => ['callback' => 'strval'],
  53. 'text' => ['callback' => 'strval'],
  54. 'boolean' => [
  55. 'callback' => ['\Cake\Database\Type', 'boolval'],
  56. 'pdo' => PDO::PARAM_BOOL
  57. ],
  58. ];
  59. /**
  60. * Contains a map of type object instances to be reused if needed
  61. *
  62. * @var array
  63. */
  64. protected static $_builtTypes = [];
  65. /**
  66. * Identifier name for this type
  67. *
  68. * @var string
  69. */
  70. protected $_name = null;
  71. /**
  72. * Constructor
  73. *
  74. * @param string $name The name identifying this type
  75. * @return void
  76. */
  77. public function __construct($name = null) {
  78. $this->_name = $name;
  79. }
  80. /**
  81. * Returns a Type object capable of converting a type identified by $name
  82. *
  83. * @param string $name type identifier
  84. * @throws \InvalidArgumentException If type identifier is unknown
  85. * @return Type
  86. */
  87. public static function build($name) {
  88. if (isset(static::$_builtTypes[$name])) {
  89. return static::$_builtTypes[$name];
  90. }
  91. if (isset(static::$_basicTypes[$name])) {
  92. return static::$_builtTypes[$name] = new static($name);
  93. }
  94. if (!isset(static::$_types[$name])) {
  95. throw new \InvalidArgumentException(__d('cake_dev', 'Unknown type "%s"', $name));
  96. }
  97. return static::$_builtTypes[$name] = new static::$_types[$name]($name);
  98. }
  99. /**
  100. * Registers a new type identifier and maps it to a fully namespaced classname,
  101. * If called with no arguments it will return current types map array
  102. * If $className is omitted it will return mapped class for $type
  103. *
  104. * @param string|array $type if string name of type to map, if array list of arrays to be mapped
  105. * @param string $className
  106. * @return array|string|null if $type is null then array with current map, if $className is null string
  107. * configured class name for give $type, null otherwise
  108. */
  109. public static function map($type = null, $className = null) {
  110. if ($type === null) {
  111. return self::$_types;
  112. }
  113. if (!is_string($type)) {
  114. self::$_types = $type;
  115. return;
  116. }
  117. if ($className === null) {
  118. return isset(self::$_types[$type]) ? self::$_types[$type] : null;
  119. }
  120. self::$_types[$type] = $className;
  121. }
  122. /**
  123. * Clears out all created instances and mapped types classes, useful for testing
  124. *
  125. * @return void
  126. */
  127. public static function clear() {
  128. self::$_types = [];
  129. self::$_builtTypes = [];
  130. }
  131. /**
  132. * Returns type identifier name for this object
  133. *
  134. * @return string
  135. */
  136. public function getName() {
  137. return $this->_name;
  138. }
  139. /**
  140. * Casts given value from a PHP type to one acceptable by database
  141. *
  142. * @param mixed $value value to be converted to database equivalent
  143. * @param Driver $driver object from which database preferences and configuration will be extracted
  144. * @return mixed
  145. */
  146. public function toDatabase($value, Driver $driver) {
  147. return $this->_basicTypeCast($value, $driver);
  148. }
  149. /**
  150. * Casts given value from a database type to PHP equivalent
  151. *
  152. * @param mixed $value value to be converted to PHP equivalent
  153. * @param Driver $driver object from which database preferences and configuration will be extracted
  154. * @return mixed
  155. */
  156. public function toPHP($value, Driver $driver) {
  157. return $this->_basicTypeCast($value, $driver);
  158. }
  159. /**
  160. * Checks whether this type is a basic one and can be converted using a callback
  161. * If it is, returns converted value
  162. *
  163. * @param mixed $value value to be converted to PHP equivalent
  164. * @param Driver $driver object from which database preferences and configuration will be extracted
  165. * @return mixed
  166. */
  167. protected function _basicTypeCast($value, Driver $driver) {
  168. if (is_null($value)) {
  169. return null;
  170. }
  171. if (!empty(self::$_basicTypes[$this->_name])) {
  172. $typeInfo = self::$_basicTypes[$this->_name];
  173. if (isset($typeInfo['callback'])) {
  174. return $typeInfo['callback']($value);
  175. }
  176. }
  177. return $value;
  178. }
  179. /**
  180. * Casts give value to Statement equivalent
  181. *
  182. * @param mixed $value value to be converted to PHP equivalent
  183. * @param Driver $driver object from which database preferences and configuration will be extracted
  184. * @return mixed
  185. */
  186. public function toStatement($value, Driver $driver) {
  187. if (is_null($value)) {
  188. return PDO::PARAM_NULL;
  189. }
  190. if (!empty(self::$_basicTypes[$this->_name])) {
  191. $typeInfo = self::$_basicTypes[$this->_name];
  192. return isset($typeInfo['pdo']) ? $typeInfo['pdo'] : PDO::PARAM_STR;
  193. }
  194. return PDO::PARAM_STR;
  195. }
  196. /**
  197. * Type converter for boolean values.
  198. *
  199. * Will convert string true/false into booleans.
  200. *
  201. * @param mixed $value The value to convert to a boolean.
  202. * @return boolean
  203. */
  204. public static function boolval($value) {
  205. if (is_string($value)) {
  206. return strtolower($value) === 'true' ? true : false;
  207. }
  208. return !empty($value);
  209. }
  210. }