Passed
Push — master ( 5e32c8...fdcb24 )
by Aimeos
07:53
created

Base::query()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 10
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 5
c 0
b 0
f 0
dl 0
loc 10
rs 10
cc 2
nc 2
nop 2
1
<?php
2
3
/**
4
 * @license LGPLv3, https://opensource.org/licenses/LGPL-3.0
5
 * @copyright Aimeos (aimeos.org), 2015-2022
6
 * @package Base
7
 * @subpackage DB
8
 */
9
10
11
namespace Aimeos\Base\DB\Connection;
12
13
14
/**
15
 * Common class for all database connection implementations.
16
 *
17
 * @package Base
18
 * @subpackage DB
19
 */
20
abstract class Base implements Iface
21
{
22
	private $params;
23
24
25
	/**
26
	 * Initializes the base class
27
	 *
28
	 * @param array $params Connection parameters
29
	 */
30
	public function __construct( array $params = [] )
31
	{
32
		$this->params = $params;
33
	}
34
35
36
	/**
37
	 * Returns the underlying connection object
38
	 *
39
	 * @return mixed Underlying connection object
40
	 */
41
	abstract public function getRawObject();
42
43
44
	/**
45
	 * Escapes the value if necessary for direct inclusion in SQL statement.
46
	 *
47
	 * @param string|null $data Value to escape or null for no value
48
	 * @return string Escaped string
49
	 */
50
	public function escape( string $data = null ) : string
51
	{
52
		$quoted = $this->getRawObject()->quote( $data );
53
54
		if( $quoted[0] === '\'' ) {
55
			$quoted = substr( $quoted, 1, strlen( $quoted ) - 2 );
56
		}
57
58
		return $quoted;
59
	}
60
61
62
	/**
63
	 * Returns the connection parameters
64
	 *
65
	 * @return array Parameters to connect to the database server
66
	 */
67
	protected function getParameters() : array
68
	{
69
		return $this->params;
70
	}
71
72
73
	/**
74
	 * Checks if a transaction is currently running
75
	 *
76
	 * @return bool True if transaction is currently running, false if not
77
	 */
78
	public function inTransaction() : bool
79
	{
80
		return true; // safe default
81
	}
82
83
84
	/**
85
	 * Deletes the records from the given table
86
	 *
87
	 * @param string $table Name of the table
88
	 * @param array $conditions Key/value pairs of column names and value to compare with
89
	 * @return \Aimeos\Base\DB\Result\Iface Result object
90
	 */
91
	public function delete( string $table, array $conditions = [] ) : \Aimeos\Base\DB\Result\Iface
92
	{
93
		$sql = 'DELETE FROM ' . $this->qi( $table );
94
95
		if( !empty( $conditions ) )
96
		{
97
			$where = [];
98
			$sql .= ' WHERE ';
99
100
			foreach( $conditions as $name => $val ) {
101
				$where[] = $this->qi( $name ) . '=?';
102
			}
103
104
			$sql .= join( ', ', $where );
105
		}
106
107
		$stmt = $this->create( $sql );
108
		$idx = 0;
109
110
		foreach( $conditions as $val ) {
111
			$stmt->bind( ++$idx, $val, $this->getType( $val ) );
112
		}
113
114
		return $stmt->execute();
115
	}
116
117
118
	/**
119
	 * Inserts a record into the given table
120
	 *
121
	 * @param string $table Name of the table
122
	 * @param array $data Key/value pairs of column name/value to insert
123
	 * @return \Aimeos\Base\DB\Result\Iface Result object
124
	 */
125
	public function insert( string $table, array $data ) : \Aimeos\Base\DB\Result\Iface
126
	{
127
		if( empty( $data ) ) {
128
			throw new \Aimeos\Base\DB\Exception( 'Inserting rows requires key/value pairs in second parameter' );
129
		}
130
131
		$cols = [];
132
		$sql = 'INSERT INTO ' . $this->qi( $table );
133
134
		foreach( $data as $name => $val ) {
135
			$cols[$this->qi( $name )] = '?';
136
		}
137
138
		$sql .= ' (' . join( ', ', array_keys( $cols ) ) . ') VALUES( ' . join( ', ', $cols ) . ')';
139
		$stmt = $this->create( $sql );
140
		$idx = 0;
141
142
		foreach( $data as $val ) {
143
			$stmt->bind( ++$idx, $val, $this->getType( $val ) );
144
		}
145
146
		return $stmt->execute();
147
	}
148
149
150
	/**
151
	 * Executes a custom SQL query
152
	 *
153
	 * @param string $sql Custom SQL statement
154
	 * @param array $params List of positional parameters
155
	 * @return \Aimeos\Base\DB\Result\Iface Result object
156
	 */
157
	public function query( string $sql, array $params = [] ) : \Aimeos\Base\DB\Result\Iface
158
	{
159
		$stmt = $this->create( $sql );
160
		$idx = 0;
161
162
		foreach( $params as $val ) {
163
			$stmt->bind( ++$idx, $val, $this->getType( $val ) );
164
		}
165
166
		return $stmt->execute();
167
	}
168
169
170
	/**
171
	 * Updates the records from the given table
172
	 *
173
	 * @param string $table Name of the table
174
	 * @param array $data Key/value pairs of column name/value to update
175
	 * @param array $conditions Key/value pairs of column names and value to compare with
176
	 * @return \Aimeos\Base\DB\Result\Iface Result object
177
	 */
178
	public function update( string $table, array $data, array $conditions = [] ) : \Aimeos\Base\DB\Result\Iface
179
	{
180
		if( empty( $data ) ) {
181
			throw new \Aimeos\Base\DB\Exception( 'Updating rows requires key/value pairs in second parameter' );
182
		}
183
184
		$set = $where = [];
185
		$sql = 'UPDATE ' . $this->qi( $table ) . ' SET ';
186
187
		foreach( $data as $name => $val ) {
188
			$set[] = $this->qi( $name ) . '=?';
189
		}
190
191
		$sql .= join( ', ', $set );
192
193
		if( !empty( $conditions ) )
194
		{
195
			$sql .= ' WHERE ';
196
197
			foreach( $conditions as $name => $val ) {
198
				$where[] = $this->qi( $name ) . '=?';
199
			}
200
201
			$sql .= join( ', ', $where );
202
		}
203
204
		$stmt = $this->create( $sql );
205
		$idx = 0;
206
207
		foreach( array_merge( $data, $conditions ) as $val ) {
208
			$stmt->bind( ++$idx, $val, $this->getType( $val ) );
209
		}
210
211
		return $stmt->execute();
212
	}
213
214
215
	/**
216
	 * Returns the parameter type for the passed value
217
	 *
218
	 * @param mixed $value Parameter value
219
	 * @return int Parameter type constant
220
	 */
221
	protected function getType( $value ) : int
222
	{
223
		switch( gettype( $value ) )
224
		{
225
			case 'NULL': return \Aimeos\Base\DB\Statement\Base::PARAM_NULL;
226
			case 'boolean': return \Aimeos\Base\DB\Statement\Base::PARAM_BOOL;
227
			case 'integer': return \Aimeos\Base\DB\Statement\Base::PARAM_INT;
228
			case 'double': return \Aimeos\Base\DB\Statement\Base::PARAM_FLOAT;
229
		}
230
231
		return \Aimeos\Base\DB\Statement\Base::PARAM_STR;
232
	}
233
234
235
	/**
236
	 * Returns a quoted identifier for the passed name
237
	 *
238
	 * @param string $name Identifier name
239
	 * @return string Quoted identifier
240
	 * @throws \Aimeos\Base\DB\Exception If identifier name already contains an apostroph
241
	 */
242
	protected function qi( string $name ) : string
243
	{
244
		if( strpos( $name, '"' ) !== false ) {
245
			throw new \Aimeos\Base\DB\Exception( sprintf( 'Identifier "%1$s"must not contain an apostroph' ) );
246
		}
247
248
		return '"' . $name . '"';
249
	}
250
}
251