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\Expression;
16:
17: use Cake\Database\ExpressionInterface;
18: use Cake\Database\Type\ExpressionTypeCasterTrait;
19: use Cake\Database\ValueBinder;
20:
21: /**
22: * An expression object that represents a SQL BETWEEN snippet
23: */
24: class BetweenExpression implements ExpressionInterface, FieldInterface
25: {
26: use ExpressionTypeCasterTrait;
27: use FieldTrait;
28:
29: /**
30: * The first value in the expression
31: *
32: * @var mixed
33: */
34: protected $_from;
35:
36: /**
37: * The second value in the expression
38: *
39: * @var mixed
40: */
41: protected $_to;
42:
43: /**
44: * The data type for the from and to arguments
45: *
46: * @var mixed
47: */
48: protected $_type;
49:
50: /**
51: * Constructor
52: *
53: * @param string|\Cake\Database\ExpressionInterface $field The field name to compare for values in between the range.
54: * @param mixed $from The initial value of the range.
55: * @param mixed $to The ending value in the comparison range.
56: * @param string|null $type The data type name to bind the values with.
57: */
58: public function __construct($field, $from, $to, $type = null)
59: {
60: if ($type !== null) {
61: $from = $this->_castToExpression($from, $type);
62: $to = $this->_castToExpression($to, $type);
63: }
64:
65: $this->_field = $field;
66: $this->_from = $from;
67: $this->_to = $to;
68: $this->_type = $type;
69: }
70:
71: /**
72: * Converts the expression to its string representation
73: *
74: * @param \Cake\Database\ValueBinder $generator Placeholder generator object
75: * @return string
76: */
77: public function sql(ValueBinder $generator)
78: {
79: $parts = [
80: 'from' => $this->_from,
81: 'to' => $this->_to
82: ];
83:
84: $field = $this->_field;
85: if ($field instanceof ExpressionInterface) {
86: $field = $field->sql($generator);
87: }
88:
89: foreach ($parts as $name => $part) {
90: if ($part instanceof ExpressionInterface) {
91: $parts[$name] = $part->sql($generator);
92: continue;
93: }
94: $parts[$name] = $this->_bindValue($part, $generator, $this->_type);
95: }
96:
97: return sprintf('%s BETWEEN %s AND %s', $field, $parts['from'], $parts['to']);
98: }
99:
100: /**
101: * {@inheritDoc}
102: *
103: */
104: public function traverse(callable $callable)
105: {
106: foreach ([$this->_field, $this->_from, $this->_to] as $part) {
107: if ($part instanceof ExpressionInterface) {
108: $callable($part);
109: }
110: }
111: }
112:
113: /**
114: * Registers a value in the placeholder generator and returns the generated placeholder
115: *
116: * @param mixed $value The value to bind
117: * @param \Cake\Database\ValueBinder $generator The value binder to use
118: * @param string $type The type of $value
119: * @return string generated placeholder
120: */
121: protected function _bindValue($value, $generator, $type)
122: {
123: $placeholder = $generator->placeholder('c');
124: $generator->bind($placeholder, $value, $type);
125:
126: return $placeholder;
127: }
128:
129: /**
130: * Do a deep clone of this expression.
131: *
132: * @return void
133: */
134: public function __clone()
135: {
136: foreach (['_field', '_from', '_to'] as $part) {
137: if ($this->{$part} instanceof ExpressionInterface) {
138: $this->{$part} = clone $this->{$part};
139: }
140: }
141: }
142: }
143: