Completed
Push — master ( ead087...20edd5 )
by smiley
02:40
created

DBDriverAbstract::multi()   B

Complexity

Conditions 6
Paths 3

Size

Total Lines 14
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 14
rs 8.8571
c 0
b 0
f 0
cc 6
eloc 7
nc 3
nop 2
1
<?php
2
/**
3
 * Class DBDriverAbstract
4
 *
5
 * @filesource   DBDriverAbstract.php
6
 * @created      04.11.2015
7
 * @package      chillerlan\Database\Drivers
8
 * @author       Smiley <[email protected]>
9
 * @copyright    2015 Smiley
10
 * @license      MIT
11
 */
12
13
namespace chillerlan\Database\Drivers;
14
15
use chillerlan\Database\DBOptions;
16
use chillerlan\Database\DBResult;
17
use chillerlan\Database\Traits\Magic;
18
use Psr\SimpleCache\CacheInterface;
19
20
/**
21
 * @property string   $dialect
22
 * @property string[] $quotes
23
 *
24
 * @see http://blog.mclaughlinsoftware.com/2010/02/21/php-binding-a-wildcard/ LIKE %...% -> LIKE CONCAT('%',?,'%')
25
 */
26
abstract class DBDriverAbstract implements DBDriverInterface{
27
	use Magic;
28
29
	const CACHEKEY_HASH_ALGO = 'sha256';
30
31
	/**
32
	 * Holds the database resource object
33
	 *
34
	 * @var resource
35
	 */
36
	protected $db;
37
38
	/**
39
	 * Holds the settings
40
	 *
41
	 * @var \chillerlan\Database\DBOptions
42
	 */
43
	protected $options;
44
45
	/**
46
	 * @var \Psr\SimpleCache\CacheInterface
47
	 */
48
	protected $cacheDriver;
49
50
	/**
51
	 * @var string
52
	 */
53
	protected $dialect;
54
55
	/**
56
	 * @var string[]
57
	 */
58
	protected $quotes;
59
60
	protected $source_encoding;
61
	protected $dest_encoding = 'UTF-8';
62
63
	/**
64
	 * Constructor.
65
	 *
66
	 * @param \chillerlan\Database\DBOptions       $options
67
	 * @param \Psr\SimpleCache\CacheInterface|null $cacheDriver
68
	 */
69
	public function __construct(DBOptions $options, CacheInterface $cacheDriver = null){
70
		$this->options     = $options;
71
		$this->cacheDriver = $cacheDriver;
72
	}
73
74
	/*********
75
	 * magic *
76
	 *********/
77
78
	/**
79
	 * @return string
80
	 */
81
	protected function magic_get_dialect():string {
82
		return $this->dialect;
83
	}
84
85
	/**
86
	 * @return array
87
	 */
88
	protected function magic_get_quotes():array {
89
		return $this->quotes;
90
	}
91
92
	abstract protected function __raw(string $sql, string $index = null, bool $assoc = true);
0 ignored issues
show
Documentation introduced by
For interfaces and abstract methods it is generally a good practice to add a @return annotation even if it is just @return void or @return null, so that implementors know what to do in the overridden method.

For interface and abstract methods, it is impossible to infer the return type from the immediate code. In these cases, it is generally advisible to explicitly annotate these methods with a @return doc comment to communicate to implementors of these methods what they are expected to return.

Loading history...
93
	abstract protected function __prepared(string $sql, array $values = [], string $index = null, bool $assoc = true);
0 ignored issues
show
Documentation introduced by
For interfaces and abstract methods it is generally a good practice to add a @return annotation even if it is just @return void or @return null, so that implementors know what to do in the overridden method.

For interface and abstract methods, it is impossible to infer the return type from the immediate code. In these cases, it is generally advisible to explicitly annotate these methods with a @return doc comment to communicate to implementors of these methods what they are expected to return.

Loading history...
94
	abstract protected function __multi(string $sql, array $values);
0 ignored issues
show
Documentation introduced by
For interfaces and abstract methods it is generally a good practice to add a @return annotation even if it is just @return void or @return null, so that implementors know what to do in the overridden method.

For interface and abstract methods, it is impossible to infer the return type from the immediate code. In these cases, it is generally advisible to explicitly annotate these methods with a @return doc comment to communicate to implementors of these methods what they are expected to return.

Loading history...
95
	abstract protected function __multi_callback(string $sql, array $data, $callback);
0 ignored issues
show
Documentation introduced by
For interfaces and abstract methods it is generally a good practice to add a @return annotation even if it is just @return void or @return null, so that implementors know what to do in the overridden method.

For interface and abstract methods, it is impossible to infer the return type from the immediate code. In these cases, it is generally advisible to explicitly annotate these methods with a @return doc comment to communicate to implementors of these methods what they are expected to return.

Loading history...
96
97
	/**
98
	 * @param string $source
99
	 * @param string $dest
100
	 *
101
	 * @return \chillerlan\Database\Drivers\DBDriverInterface
102
	 */
103
	public function convertEncoding(string $source, string $dest = 'UTF-8'):DBDriverInterface{
104
		$this->source_encoding = $source;
105
		$this->dest_encoding = $dest;
106
107
		return $this;
108
	}
109
110
	/**
111
	 * Returns the plain connection object
112
	 *
113
	 * @return resource the database resource object
114
	 */
115
	public function getDBResource(){
116
		return $this->db;
117
	}
118
119
	/**
120
	 * @param string $dbname
121
	 *
122
	 * @return bool
123
	 */
124
	public function selectDB(string $dbname):bool{
125
		return false;
126
	}
127
128
	/**
129
	 * @param             $callable
130
	 * @param array       $args
131
	 * @param string|null $index
132
	 * @param bool        $assoc
133
	 *
134
	 * @return bool|\chillerlan\Database\DBResult
135
	 */
136
	protected function getResult($callable, array $args, string $index = null, bool $assoc){
137
		$out = new DBResult(null, $this->source_encoding, $this->dest_encoding);
138
		$i   = 0;
139
140
		while($row = call_user_func_array($callable, $args)){
141
			$key = $i;
142
143
			if($assoc && !empty($index)){
144
				$key = $row[$index];
145
			}
146
147
			$out[$key] = $row;
148
			$i++;
149
		}
150
151
		return $i === 0 ? true : $out;
152
	}
153
154
	/**
155
	 * @param string      $sql
156
	 * @param string|null $index
157
	 * @param bool        $assoc
158
	 *
159
	 * @return mixed
160
	 * @throws \chillerlan\Database\Drivers\DBDriverException
161
	 */
162 View Code Duplication
	public function raw(string $sql, string $index = null, bool $assoc = true){
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
163
164
		try{
165
			return $this->__raw($sql, $index, $assoc);
166
		}
167
		catch(\Exception $e){
168
			throw new DBDriverException('sql error: ['.get_called_class().'::raw()]'.$e->getMessage());
169
		}
170
171
	}
172
173
	/**
174
	 * @param string      $sql
175
	 * @param array       $values
176
	 * @param string|null $index
177
	 * @param bool        $assoc
178
	 *
179
	 * @return mixed
180
	 * @throws \chillerlan\Database\Drivers\DBDriverException
181
	 */
182 View Code Duplication
	public function prepared(string $sql, array $values = [], string $index = null, bool $assoc = true){
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
183
184
		try{
185
			return $this->__prepared($sql, $values, $index, $assoc);
186
		}
187
		catch(\Exception $e){
188
			throw new DBDriverException('sql error: ['.get_called_class().'::prepared()] '.$e->getMessage());
189
		}
190
191
	}
192
193
	/**
194
	 * @param string $sql
195
	 * @param array  $values
196
	 *
197
	 * @return mixed
198
	 * @throws \chillerlan\Database\Drivers\DBDriverException
199
	 */
200
	public function multi(string $sql, array $values){
201
202
		if(!is_array($values) || count($values) < 1 || !is_array($values[0]) || count($values[0]) < 1){
203
			throw new DBDriverException('invalid data');
204
		}
205
206
		try{
207
			return $this->__multi($sql, $values);
208
		}
209
		catch(\Exception $e){
210
			throw new DBDriverException('sql error: ['.get_called_class().'::multi()] '.$e->getMessage());
211
		}
212
213
	}
214
215
	/**
216
	 * @param string         $sql
217
	 * @param array          $data
218
	 * @param array|callable $callback
219
	 *
220
	 * @return mixed
221
	 * @throws \chillerlan\Database\Drivers\DBDriverException
222
	 */
223
	public function multi_callback(string $sql, array $data, $callback){
224
225
		if(count($data) < 1){
226
			throw new DBDriverException('invalid data');
227
		}
228
229
		if(!is_callable($callback)){
230
			throw new DBDriverException('invalid callback');
231
		}
232
233
		try{
234
			return $this->__multi_callback($sql, $data, $callback);
235
		}
236
		catch(\Exception $e){
237
			throw new DBDriverException('sql error: ['.get_called_class().'::multi_callback()] '.$e->getMessage());
238
		}
239
240
	}
241
242
	/**
243
	 * @param string      $sql
244
	 * @param array|null  $values
245
	 * @param string|null $index
246
	 *
247
	 * @return string
248
	 */
249
	public function cacheKey(string $sql, array $values = [], string $index = null):string{
250
		return hash(self::CACHEKEY_HASH_ALGO, serialize([$sql, $values, $index]));
251
	}
252
253
	/**
254
	 * @param string      $sql
255
	 * @param array       $values
256
	 * @param string|null $index
257
	 *
258
	 * @return bool|mixed
259
	 */
260 View Code Duplication
	protected function cacheGet(string $sql, array $values = [], string $index = null){
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
261
262
		if($this->cacheDriver){
263
			return $this->cacheDriver->get($this->cacheKey($sql, $values, $index));
264
		}
265
266
		return false; // @codeCoverageIgnore
267
	}
268
269
	/**
270
	 * @param string      $sql
271
	 * @param array       $values
272
	 * @param string|null $index
273
	 * @param             $response
274
	 * @param int|null    $ttl
275
	 *
276
	 * @return bool
277
	 */
278 View Code Duplication
	protected function cacheSet(string $sql, array $values = [], string $index = null, $response, int $ttl = null):bool{
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
279
280
		if($this->cacheDriver){
281
			return $this->cacheDriver->set($this->cacheKey($sql, $values, $index), $response, $ttl);
282
		}
283
284
		return false; // @codeCoverageIgnore
285
	}
286
287
288
	/**
289
	 * @param string      $sql
290
	 * @param string|null $index
291
	 * @param bool        $assoc
292
	 * @param int|null    $ttl
293
	 *
294
	 * @return bool|mixed
295
	 */
296
	public function rawCached(string $sql, string $index = null, bool $assoc = true, int $ttl = null){
297
		$result = $this->cacheGet($sql, [], $index);
298
299 View Code Duplication
		if(!$result){
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
300
			$result = $this->raw($sql, $index, $assoc);
301
302
			$this->cacheSet($sql, [], $index, $result, $ttl);
303
		}
304
305
		return $result;
306
	}
307
308
	/**
309
	 * @param string      $sql
310
	 * @param array       $values
311
	 * @param string|null $index
312
	 * @param bool        $assoc
313
	 * @param int|null    $ttl
314
	 *
315
	 * @return bool|mixed
316
	 */
317
	public function preparedCached(string $sql, array $values = [], string $index = null, bool $assoc = true, int $ttl = null){
318
		$result = $this->cacheGet($sql, $values, $index);
319
320 View Code Duplication
		if(!$result){
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
321
			$result = $this->prepared($sql, $values, $index, $assoc);
322
323
			$this->cacheSet($sql, $values, $index, $result, $ttl);
324
		}
325
326
		return $result;
327
	}
328
}
329