Passed
Push — master ( f21277...f08cc9 )
by Aimeos
04:50
created

SQL::getConnection()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * @license LGPLv3, http://opensource.org/licenses/LGPL-3.0
5
 * @copyright Metaways Infosystems GmbH, 2011
6
 * @copyright Aimeos (aimeos.org), 2015-2018
7
 * @package MW
8
 * @subpackage Common
9
 */
10
11
12
namespace Aimeos\MW\Criteria\Expression\Compare;
13
14
15
/**
16
 * SQL implementation for comparing objects.
17
 *
18
 * @package MW
19
 * @subpackage Common
20
 */
21
class SQL extends \Aimeos\MW\Criteria\Expression\Compare\Base
22
{
23
	private static $operators = array( '=~' => 'LIKE', '~=' => 'LIKE', '==' => '=', '!=' => '<>', '>' => '>', '>=' => '>=', '<' => '<', '<=' => '<=' );
24
	private $conn;
25
26
27
	/**
28
	 * Initializes the object.
29
	 *
30
	 * @param \Aimeos\MW\DB\Connection\Iface $conn Database connection object
31
	 * @param string $operator Operator used for the expression
32
	 * @param string $name Name of variable or column that should be compared.
33
	 * @param mixed $value Value that the variable or column should be compared to
34
	 */
35
	public function __construct( \Aimeos\MW\DB\Connection\Iface $conn, $operator, $name, $value )
36
	{
37
		if( !isset( self::$operators[$operator] ) ) {
38
			throw new \Aimeos\MW\Common\Exception( sprintf( 'Invalid operator "%1$s"', $operator ) );
39
		}
40
41
		parent::__construct( $operator, $name, $value );
42
		$this->conn = $conn;
43
	}
44
45
46
	/**
47
	 * Returns the available operators for the expression.
48
	 *
49
	 * @return array List of available operators
50
	 */
51
	public static function getOperators()
52
	{
53
		return array_keys( self::$operators );
54
	}
55
56
57
	/**
58
	 * Creates a term string from the given parameters.
59
	 *
60
	 * @param string $name Translated name of variable or column that should be compared
61
	 * @param integer $type Type constant
62
	 * @param mixed $value Value that the variable or column should be compared to
63
	 * @return string Created term string (name operator value)
64
	 */
65
	protected function createTerm( $name, $type, $value )
66
	{
67
		$term = $name . ' ' . self::$operators[$this->getOperator()] . ' ' . $this->escape( $this->getOperator(), $type, $value );
68
69
		if( in_array( $this->getOperator(), array( '=~', '~=' ), true ) ) {
70
			$term .= ' ESCAPE \'#\'';
71
		}
72
73
		return $term;
74
	}
75
76
77
	/**
78
	 * Creates a term which contains a null value.
79
	 *
80
	 * @param string|array $name Translated name of the variable or column
81
	 * @return string String that can be inserted into a SQL statement
82
	 */
83
	protected function createNullTerm( $name )
84
	{
85
		if( is_array( $name ) ) {
86
			return '';
87
		}
88
89
		switch( $this->getOperator() )
90
		{
91
			case '==':
92
				return $name . ' IS NULL';
93
			case '!=':
94
				return $name . ' IS NOT NULL';
95
			default:
96
				throw new \Aimeos\MW\Common\Exception( sprintf( 'NULL value not allowed for operator "%1$s"', $this->getOperator() ) );
97
		}
98
	}
99
100
101
	/**
102
	 * Creates a term from a list of values.
103
	 *
104
	 * @param string $name Translated name of the variable or column
105
	 * @param integer $type Type constant
106
	 * @return string String that can be inserted into a SQL statement
107
	 */
108
	protected function createListTerm( $name, $type )
109
	{
110
		switch( $this->getOperator() )
111
		{
112
			case '==':
113
				return $name . ' IN ' . $this->createValueList( $type, (array) $this->getValue() );
114
			case '!=':
115
				return $name . ' NOT IN ' . $this->createValueList( $type, (array) $this->getValue() );
116
			default:
117
				$terms = [];
118
119
				foreach( (array) $this->getValue() as $val ) {
120
					$terms[] = $this->createTerm( $name, $type, $val );
121
				}
122
123
				return '(' . implode( ' OR ', $terms ) . ')';
124
		}
125
	}
126
127
128
	/**
129
	 * Creates a list of search values.
130
	 *
131
	 * @param integer $type Type constant
132
	 * @param string[] $values Value list for the variable or column name
133
	 * @return string String of comma separated values in parenthesis
134
	 */
135
	protected function createValueList( $type, array $values )
136
	{
137
		if( empty( $values ) ) {
138
			return '(NULL)';
139
		}
140
141
		$operator = $this->getOperator();
142
143
		foreach( $values as $key => $value ) {
144
			$values[$key] = $this->escape( $operator, $type, $value );
145
		}
146
147
		return '(' . implode(',', $values) . ')';
148
	}
149
150
151
	/**
152
	 * Escapes the value so it can be inserted into a SQL statement
153
	 *
154
	 * @param string $operator Operator used for the expression
155
	 * @param integer $type Type constant
156
	 * @param mixed $value Value that the variable or column should be compared to
157
	 * @return double|string|integer Escaped value
158
	 */
159
	protected function escape( $operator, $type, $value )
160
	{
161
		$value = $this->translateValue( $this->getName(), $value );
162
163
		switch( $type )
164
		{
165
			case \Aimeos\MW\DB\Statement\Base::PARAM_NULL:
166
				$value = 'null'; break;
167
			case \Aimeos\MW\DB\Statement\Base::PARAM_BOOL:
168
				$value = (int) (bool) $value; break;
169
			case \Aimeos\MW\DB\Statement\Base::PARAM_INT:
170
				$value = (int) $value; break;
171
			case \Aimeos\MW\DB\Statement\Base::PARAM_FLOAT:
172
				$value = (double) $value; break;
173
			case \Aimeos\MW\DB\Statement\Base::PARAM_STR:
174
				if( $operator === '~=' ) {
175
					$value = '\'%' . str_replace( ['#', '%', '_', '['], ['##', '#%', '#_', '#['], $this->conn->escape( $value ) ) . '%\''; break;
176
				}
177
				if( $operator === '=~' ) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment if this fall-through is intended.
Loading history...
178
					$value = '\'' . str_replace( ['#', '%', '_', '['], ['##', '#%', '#_', '#['], $this->conn->escape( $value ) ) . '%\''; break;
179
				}
180
			default:
181
				$value = '\'' . $this->conn->escape( $value ) . '\'';
182
		}
183
184
		return $value;
185
	}
186
187
188
	/**
189
	 * Returns the connection object.
190
	 *
191
	 * return \Aimeos\MW\DB\Connection\Iface Connection object
192
	 */
193
	public function getConnection()
194
	{
195
		return $this->conn;
196
	}
197
198
199
	/**
200
	 * Returns the internal type of the function parameter.
201
	 *
202
	 * @param string &$item Reference to parameter value (will be updated if necessary)
203
	 * @return integer Internal parameter type
204
	 * @throws \Aimeos\MW\Common\Exception If an error occurs
205
	 */
206
	protected function getParamType( &$item )
207
	{
208
		if( $item[0] == '"' )
209
		{
210
			if( ( $item = substr( $item, 1, strlen( $item ) - 2 ) ) === false ) {
211
				throw new \Aimeos\MW\Common\Exception( sprintf( 'Unable to extract string parameter from >%1$s<', $item ) );
212
			}
213
214
			return \Aimeos\MW\DB\Statement\Base::PARAM_STR;
215
		}
216
		elseif( strpos( $item, '.' ) !== false )
217
		{
218
			return \Aimeos\MW\DB\Statement\Base::PARAM_FLOAT;
219
		}
220
		elseif( ctype_digit( $item ) !== false )
221
		{
222
			return \Aimeos\MW\DB\Statement\Base::PARAM_INT;
223
		}
224
		elseif( $item === 'null' )
225
		{
226
			return \Aimeos\MW\DB\Statement\Base::PARAM_NULL;
227
		}
228
229
		return \Aimeos\MW\DB\Statement\Base::PARAM_STR;
230
	}
231
}
232