1: <?php
2: /**
3: * CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
4: * Copyright (c) Cake Software Foundation, Inc. (https://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. (https://cakefoundation.org)
11: * @link https://cakephp.org CakePHP(tm) Project
12: * @since 3.0.0
13: * @license https://opensource.org/licenses/mit-license.php MIT License
14: */
15: namespace Cake\Database\Type;
16:
17: use Cake\Database\Driver;
18: use Cake\Database\Type;
19: use Cake\Database\TypeInterface;
20: use Cake\Database\Type\BatchCastingInterface;
21: use PDO;
22: use RuntimeException;
23:
24: /**
25: * Float type converter.
26: *
27: * Use to convert float/decimal data between PHP and the database types.
28: */
29: class FloatType extends Type implements TypeInterface, BatchCastingInterface
30: {
31: /**
32: * Identifier name for this type.
33: *
34: * (This property is declared here again so that the inheritance from
35: * Cake\Database\Type can be removed in the future.)
36: *
37: * @var string|null
38: */
39: protected $_name;
40:
41: /**
42: * Constructor.
43: *
44: * (This method is declared here again so that the inheritance from
45: * Cake\Database\Type can be removed in the future.)
46: *
47: * @param string|null $name The name identifying this type
48: */
49: public function __construct($name = null)
50: {
51: $this->_name = $name;
52: }
53:
54: /**
55: * The class to use for representing number objects
56: *
57: * @var string
58: */
59: public static $numberClass = 'Cake\I18n\Number';
60:
61: /**
62: * Whether numbers should be parsed using a locale aware parser
63: * when marshalling string inputs.
64: *
65: * @var bool
66: */
67: protected $_useLocaleParser = false;
68:
69: /**
70: * Convert integer data into the database format.
71: *
72: * @param string|resource $value The value to convert.
73: * @param \Cake\Database\Driver $driver The driver instance to convert with.
74: * @return float|null
75: */
76: public function toDatabase($value, Driver $driver)
77: {
78: if ($value === null || $value === '') {
79: return null;
80: }
81:
82: return (float)$value;
83: }
84:
85: /**
86: * Convert float values to PHP integers
87: *
88: * @param resource|string|null $value The value to convert.
89: * @param \Cake\Database\Driver $driver The driver instance to convert with.
90: * @return float|null
91: * @throws \Cake\Core\Exception\Exception
92: */
93: public function toPHP($value, Driver $driver)
94: {
95: if ($value === null) {
96: return null;
97: }
98:
99: return (float)$value;
100: }
101:
102: /**
103: * {@inheritDoc}
104: *
105: * @return float[]
106: */
107: public function manyToPHP(array $values, array $fields, Driver $driver)
108: {
109: foreach ($fields as $field) {
110: if (!isset($values[$field])) {
111: continue;
112: }
113:
114: $values[$field] = (float)$values[$field];
115: }
116:
117: return $values;
118: }
119:
120: /**
121: * Get the correct PDO binding type for integer data.
122: *
123: * @param mixed $value The value being bound.
124: * @param \Cake\Database\Driver $driver The driver.
125: * @return int
126: */
127: public function toStatement($value, Driver $driver)
128: {
129: return PDO::PARAM_STR;
130: }
131:
132: /**
133: * Marshals request data into PHP floats.
134: *
135: * @param mixed $value The value to convert.
136: * @return float|string|null Converted value.
137: */
138: public function marshal($value)
139: {
140: if ($value === null || $value === '') {
141: return null;
142: }
143: if (is_string($value) && $this->_useLocaleParser) {
144: return $this->_parseValue($value);
145: }
146: if (is_numeric($value)) {
147: return (float)$value;
148: }
149: if (is_string($value) && preg_match('/^[0-9,. ]+$/', $value)) {
150: return $value;
151: }
152:
153: return null;
154: }
155:
156: /**
157: * Sets whether or not to parse numbers passed to the marshal() function
158: * by using a locale aware parser.
159: *
160: * @param bool $enable Whether or not to enable
161: * @return $this
162: */
163: public function useLocaleParser($enable = true)
164: {
165: if ($enable === false) {
166: $this->_useLocaleParser = $enable;
167:
168: return $this;
169: }
170: if (static::$numberClass === 'Cake\I18n\Number' ||
171: is_subclass_of(static::$numberClass, 'Cake\I18n\Number')
172: ) {
173: $this->_useLocaleParser = $enable;
174:
175: return $this;
176: }
177: throw new RuntimeException(
178: sprintf('Cannot use locale parsing with the %s class', static::$numberClass)
179: );
180: }
181:
182: /**
183: * Converts a string into a float point after parsing it using the locale
184: * aware parser.
185: *
186: * @param string $value The value to parse and convert to an float.
187: * @return float
188: */
189: protected function _parseValue($value)
190: {
191: $class = static::$numberClass;
192:
193: return $class::parseFloat($value);
194: }
195: }
196: