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