Type.php 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  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 PDO;
  20. /**
  21. * Encapsulates all conversion functions for values coming from database into PHP and
  22. * going from PHP into database.
  23. */
  24. class Type {
  25. /**
  26. * List of supported database types. A human readable
  27. * identifier is used as key and a complete namespaced class name as value
  28. * representing the class that will do actual type conversions.
  29. *
  30. * @var array
  31. */
  32. protected static $_types = [
  33. 'binary' => 'Cake\Database\Type\BinaryType',
  34. 'date' => 'Cake\Database\Type\DateType',
  35. 'datetime' => 'Cake\Database\Type\DateTimeType',
  36. 'timestamp' => 'Cake\Database\Type\DateTimeType',
  37. 'uuid' => 'Cake\Database\Type\UuidType',
  38. ];
  39. /**
  40. * List of basic type mappings, used to avoid having to instantiate a class
  41. * for doing conversion on these
  42. *
  43. * @var array
  44. */
  45. protected static $_basicTypes = [
  46. 'float' => ['callback' => 'floatval'],
  47. 'decimal' => ['callback' => 'floatval'],
  48. 'integer' => ['callback' => 'intval', 'pdo' => PDO::PARAM_INT],
  49. 'biginteger' => ['callback' => 'intval', 'pdo' => PDO::PARAM_INT],
  50. 'string' => ['callback' => 'strval'],
  51. 'text' => ['callback' => 'strval'],
  52. 'boolean' => [
  53. 'callback' => ['\Cake\Database\Type', 'boolval'],
  54. 'pdo' => PDO::PARAM_BOOL
  55. ],
  56. ];
  57. /**
  58. * Contains a map of type object instances to be reused if needed
  59. *
  60. * @var array
  61. */
  62. protected static $_builtTypes = [];
  63. /**
  64. * Identifier name for this type
  65. *
  66. * @var string
  67. */
  68. protected $_name = null;
  69. /**
  70. * Constructor
  71. *
  72. * @param string $name The name identifying this type
  73. */
  74. public function __construct($name = null) {
  75. $this->_name = $name;
  76. }
  77. /**
  78. * Returns a Type object capable of converting a type identified by $name
  79. *
  80. * @param string $name type identifier
  81. * @throws \InvalidArgumentException If type identifier is unknown
  82. * @return Type
  83. */
  84. public static function build($name) {
  85. if (isset(static::$_builtTypes[$name])) {
  86. return static::$_builtTypes[$name];
  87. }
  88. if (isset(static::$_basicTypes[$name])) {
  89. return static::$_builtTypes[$name] = new static($name);
  90. }
  91. if (!isset(static::$_types[$name])) {
  92. throw new \InvalidArgumentException(sprintf('Unknown type "%s"', $name));
  93. }
  94. return static::$_builtTypes[$name] = new static::$_types[$name]($name);
  95. }
  96. /**
  97. * Registers a new type identifier and maps it to a fully namespaced classname,
  98. * If called with no arguments it will return current types map array
  99. * If $className is omitted it will return mapped class for $type
  100. *
  101. * @param string|array $type if string name of type to map, if array list of arrays to be mapped
  102. * @param string $className
  103. * @return array|string|null if $type is null then array with current map, if $className is null string
  104. * configured class name for give $type, null otherwise
  105. */
  106. public static function map($type = null, $className = null) {
  107. if ($type === null) {
  108. return self::$_types;
  109. }
  110. if (!is_string($type)) {
  111. self::$_types = $type;
  112. return;
  113. }
  114. if ($className === null) {
  115. return isset(self::$_types[$type]) ? self::$_types[$type] : null;
  116. }
  117. self::$_types[$type] = $className;
  118. }
  119. /**
  120. * Clears out all created instances and mapped types classes, useful for testing
  121. *
  122. * @return void
  123. */
  124. public static function clear() {
  125. self::$_types = [];
  126. self::$_builtTypes = [];
  127. }
  128. /**
  129. * Returns type identifier name for this object
  130. *
  131. * @return string
  132. */
  133. public function getName() {
  134. return $this->_name;
  135. }
  136. /**
  137. * Casts given value from a PHP type to one acceptable by database
  138. *
  139. * @param mixed $value value to be converted to database equivalent
  140. * @param Driver $driver object from which database preferences and configuration will be extracted
  141. * @return mixed
  142. */
  143. public function toDatabase($value, Driver $driver) {
  144. return $this->_basicTypeCast($value, $driver);
  145. }
  146. /**
  147. * Casts given value from a database type to PHP equivalent
  148. *
  149. * @param mixed $value value to be converted to PHP equivalent
  150. * @param Driver $driver object from which database preferences and configuration will be extracted
  151. * @return mixed
  152. */
  153. public function toPHP($value, Driver $driver) {
  154. return $this->_basicTypeCast($value, $driver);
  155. }
  156. /**
  157. * Checks whether this type is a basic one and can be converted using a callback
  158. * If it is, returns converted value
  159. *
  160. * @param mixed $value value to be converted to PHP equivalent
  161. * @param Driver $driver object from which database preferences and configuration will be extracted
  162. * @return mixed
  163. */
  164. protected function _basicTypeCast($value, Driver $driver) {
  165. if (is_null($value)) {
  166. return null;
  167. }
  168. if (!empty(self::$_basicTypes[$this->_name])) {
  169. $typeInfo = self::$_basicTypes[$this->_name];
  170. if (isset($typeInfo['callback'])) {
  171. return $typeInfo['callback']($value);
  172. }
  173. }
  174. return $value;
  175. }
  176. /**
  177. * Casts give value to Statement equivalent
  178. *
  179. * @param mixed $value value to be converted to PHP equivalent
  180. * @param Driver $driver object from which database preferences and configuration will be extracted
  181. * @return mixed
  182. */
  183. public function toStatement($value, Driver $driver) {
  184. if (is_null($value)) {
  185. return PDO::PARAM_NULL;
  186. }
  187. if (!empty(self::$_basicTypes[$this->_name])) {
  188. $typeInfo = self::$_basicTypes[$this->_name];
  189. return isset($typeInfo['pdo']) ? $typeInfo['pdo'] : PDO::PARAM_STR;
  190. }
  191. return PDO::PARAM_STR;
  192. }
  193. /**
  194. * Type converter for boolean values.
  195. *
  196. * Will convert string true/false into booleans.
  197. *
  198. * @param mixed $value The value to convert to a boolean.
  199. * @return boolean
  200. */
  201. public static function boolval($value) {
  202. if (is_string($value) && !is_numeric($value)) {
  203. return strtolower($value) === 'true' ? true : false;
  204. }
  205. return !empty($value);
  206. }
  207. /**
  208. * Generate a new primary key value for a given type.
  209. *
  210. * This method can be used by types to create new primary key values
  211. * when entities are inserted.
  212. *
  213. * @return mixed A new primary key value.
  214. * @see \Cake\Database\Type\UuidType
  215. */
  216. public function newId() {
  217. return null;
  218. }
  219. /**
  220. * Marshalls flat data into PHP objects.
  221. *
  222. * Most useful for converting request data into PHP objects
  223. * that make sense for the rest of the ORM/Database layers.
  224. *
  225. * @param mixed $value The value to convert.
  226. * @return mixed Converted value.
  227. */
  228. public function marshal($value) {
  229. return $value;
  230. }
  231. }