/
FunctionExpression.php
133 lines (121 loc) · 4.01 KB
/
FunctionExpression.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
<?php
/**
* PHP Version 5.4
*
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The MIT License
* For full copyright and license information, please see the LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
* @link http://cakephp.org CakePHP(tm) Project
* @package Cake.Model
* @since CakePHP(tm) v 3.0.0
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
namespace Cake\Database\Expression;
use Cake\Database\ExpressionInterface;
use Cake\Database\ValueBinder;
/**
* This class represents a function call string in a SQL statement. Calls can be
* constructed by passing the name of the function and a list of params.
* For security reasons, all params passed are quoted by default unless
* explicitly told otherwise.
*/
class FunctionExpression extends QueryExpression {
/**
* The name of the function to be constructed when generating the SQL string
*
* @var string
*/
protected $_name;
/**
* Constructor. Takes a name for the function to be invoked and a list of params
* to be passed into the function. Optionally you can pass a list of types to
* be used for each bound param.
*
* By default, all params that are passed will be quoted. If you wish to use
* literal arguments, you need to explicitly hint this function.
*
* ## Examples:
*
* ``$f = new FunctionExpression('CONCAT', ['CakePHP', ' rules']);``
*
* Previous line will generate ``CONCAT('CakePHP', ' rules')``
*
* ``$f = new FunctionExpression('CONCAT', ['name' => 'literal', ' rules']);``
*
* Will produce ``CONCAT(name, ' rules')``
*
* @param string $name the name of the function to be constructed
* @param array $params list of arguments to be passed to the function
* If associative the key would be used as argument when value is 'literal'
* @param array types associative array of types to be associated with the
* passed arguments
* @return void
*/
public function __construct($name, $params = [], $types = []) {
$this->_name = $name;
parent::__construct($params, $types, ',');
}
public function name($name = null) {
if ($name === null) {
return $this->_name;
}
$this->_name = $name;
return $this;
}
/**
* Adds one or more arguments for the function call.
*
* @param array $params list of arguments to be passed to the function
* If associative the key would be used as argument when value is 'literal'
* @param array types associative array of types to be associated with the
* passed arguments
* @see FunctionExpression::__construct() for more details.
* @return FunctionExpression
*/
public function add($params, $types = []) {
foreach ($params as $k => $p) {
if (is_string($k) && $p === 'literal') {
$this->_conditions[] = $k;
continue;
}
if ($p instanceof ExpressionInterface) {
$this->_conditions[] = $p;
continue;
}
$type = isset($types[$k]) ? $types[$k] : null;
$this->_conditions[] = ['value' => $p, 'type' => $type];
}
return $this;
}
/**
* Returns the string representation of this object so that it can be used in a
* SQL query. Note that values condition values are not included in the string,
* in their place placeholders are put and can be replaced by the quoted values
* accordingly.
*
* @param Cake\Database\ValueBinder $generator Placeholder generator object
* @return string
*/
public function sql(ValueBinder $generator) {
$parts = [];
foreach ($this->_conditions as $condition) {
if ($condition instanceof ExpressionInterface) {
$condition = $condition->sql($generator);
} elseif (is_array($condition)) {
$p = $generator->placeholder('param');
$generator->bind($p, $condition['value'], $condition['type']);
$condition = $p;
}
$parts[] = $condition;
}
return $this->_name . sprintf('(%s)', implode(
$this->_conjunction . ' ',
$parts
));
}
}