DecimalType.php 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  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.3.4
  13. * @license http://www.opensource.org/licenses/mit-license.php MIT License
  14. */
  15. namespace Cake\Database\Type;
  16. use Cake\Database\Driver;
  17. use Cake\Database\Type;
  18. use Cake\Database\TypeInterface;
  19. use InvalidArgumentException;
  20. use PDO;
  21. use RuntimeException;
  22. /**
  23. * Decimal type converter.
  24. *
  25. * Use to convert decimal data between PHP and the database types.
  26. */
  27. class DecimalType extends Type implements TypeInterface
  28. {
  29. /**
  30. * Identifier name for this type
  31. *
  32. * @var string|null
  33. */
  34. protected $_name = null;
  35. /**
  36. * Constructor
  37. *
  38. * @param string|null $name The name identifying this type
  39. */
  40. public function __construct($name = null)
  41. {
  42. $this->_name = $name;
  43. }
  44. /**
  45. * The class to use for representing number objects
  46. *
  47. * @var string
  48. */
  49. public static $numberClass = 'Cake\I18n\Number';
  50. /**
  51. * Whether numbers should be parsed using a locale aware parser
  52. * when marshalling string inputs.
  53. *
  54. * @var bool
  55. */
  56. protected $_useLocaleParser = false;
  57. /**
  58. * Convert integer data into the database format.
  59. *
  60. * @param string|int|float $value The value to convert.
  61. * @param \Cake\Database\Driver $driver The driver instance to convert with.
  62. * @return string|null
  63. * @throws \InvalidArgumentException
  64. */
  65. public function toDatabase($value, Driver $driver)
  66. {
  67. if ($value === null || $value === '') {
  68. return null;
  69. }
  70. if (!is_scalar($value)) {
  71. throw new InvalidArgumentException('Cannot convert value to a decimal.');
  72. }
  73. if (is_string($value) && is_numeric($value)) {
  74. return $value;
  75. }
  76. return sprintf('%F', $value);
  77. }
  78. /**
  79. * Convert float values to PHP integers
  80. *
  81. * @param null|string|resource $value The value to convert.
  82. * @param \Cake\Database\Driver $driver The driver instance to convert with.
  83. * @return resource
  84. * @throws \Cake\Core\Exception\Exception
  85. */
  86. public function toPHP($value, Driver $driver)
  87. {
  88. if ($value === null) {
  89. return null;
  90. }
  91. return (float)$value;
  92. }
  93. /**
  94. * Get the correct PDO binding type for integer data.
  95. *
  96. * @param mixed $value The value being bound.
  97. * @param \Cake\Database\Driver $driver The driver.
  98. * @return int
  99. */
  100. public function toStatement($value, Driver $driver)
  101. {
  102. return PDO::PARAM_STR;
  103. }
  104. /**
  105. * Marshalls request data into PHP floats.
  106. *
  107. * @param mixed $value The value to convert.
  108. * @return mixed Converted value.
  109. */
  110. public function marshal($value)
  111. {
  112. if ($value === null || $value === '') {
  113. return null;
  114. }
  115. if (is_numeric($value)) {
  116. return (float)$value;
  117. }
  118. if (is_string($value) && $this->_useLocaleParser) {
  119. return $this->_parseValue($value);
  120. }
  121. if (is_array($value)) {
  122. return 1;
  123. }
  124. return $value;
  125. }
  126. /**
  127. * Sets whether or not to parse numbers passed to the marshal() function
  128. * by using a locale aware parser.
  129. *
  130. * @param bool $enable Whether or not to enable
  131. * @return $this
  132. */
  133. public function useLocaleParser($enable = true)
  134. {
  135. if ($enable === false) {
  136. $this->_useLocaleParser = $enable;
  137. return $this;
  138. }
  139. if (static::$numberClass === 'Cake\I18n\Number' ||
  140. is_subclass_of(static::$numberClass, 'Cake\I18n\Number')
  141. ) {
  142. $this->_useLocaleParser = $enable;
  143. return $this;
  144. }
  145. throw new RuntimeException(
  146. sprintf('Cannot use locale parsing with the %s class', static::$numberClass)
  147. );
  148. }
  149. /**
  150. * Converts a string into a float point after parseing it using the locale
  151. * aware parser.
  152. *
  153. * @param string $value The value to parse and convert to an float.
  154. * @return float
  155. */
  156. protected function _parseValue($value)
  157. {
  158. $class = static::$numberClass;
  159. return $class::parseFloat($value);
  160. }
  161. }