Completed
Push — master ( 612476...c205d6 )
by smiley
04:22
created

DBDriverAbstract::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
eloc 3
nc 1
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\DBException;
16
use chillerlan\Database\DBOptions;
17
use chillerlan\Database\DBResult;
18
use Psr\SimpleCache\CacheInterface;
19
20
/**
21
  * @see http://blog.mclaughlinsoftware.com/2010/02/21/php-binding-a-wildcard/ LIKE %...% -> LIKE CONCAT('%',?,'%')
22
 */
23
abstract class DBDriverAbstract implements DBDriverInterface{
24
25
	const CACHEKEY_HASH_ALGO = 'sha256';
26
	/**
27
	 * Holds the database resource object
28
	 *
29
	 * @var resource
30
	 */
31
	protected $db;
32
33
	/**
34
	 * Holds the settings
35
	 *
36
	 * @var \chillerlan\Database\DBOptions
37
	 */
38
	protected $options;
39
40
	/**
41
	 * @var \Psr\SimpleCache\CacheInterface
42
	 */
43
	protected $cacheDriver;
44
45
	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...
46
	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...
47
	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...
48
	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...
49
50
	/**
51
	 * Constructor.
52
	 *
53
	 * @param \chillerlan\Database\DBOptions       $options
54
	 * @param \Psr\SimpleCache\CacheInterface|null $cacheDriver
55
	 */
56
	public function __construct(DBOptions $options, CacheInterface $cacheDriver = null){
57
		$this->options     = $options;
58
		$this->cacheDriver = $cacheDriver;
59
	}
60
61
	/**
62
	 * Returns the plain connection object
63
	 *
64
	 * @return resource the database resource object
65
	 */
66
	public function getDBResource(){
67
		return $this->db;
68
	}
69
70
	/**
71
	 * @param             $callable
72
	 * @param array       $args
73
	 * @param string|null $index
74
	 * @param bool        $assoc
75
	 *
76
	 * @return bool|\chillerlan\Database\DBResult
77
	 */
78
	protected function getResult($callable, array $args, string $index = null, bool $assoc){
79
		$out = new DBResult;
80
		$i   = 0;
81
82
		while($row = call_user_func_array($callable, $args)){
83
			$key = $i;
84
85
			if($assoc && !empty($index)){
86
				$key = $row[$index];
87
			}
88
89
			$out[$key] = $row;
90
			$i++;
91
		}
92
93
		return $i === 0 ? true : $out;
94
	}
95
96
	/**
97
	 * @param string      $sql
98
	 * @param string|null $index
99
	 * @param bool        $assoc
100
	 *
101
	 * @return mixed
102
	 * @throws \chillerlan\Database\DBException
103
	 */
104
	public function raw(string $sql, string $index = null, bool $assoc = true){
105
106
		try{
107
			return $this->__raw($sql, $index, $assoc);
108
		}
109
		catch(\Exception $e){
110
			throw new DBException('sql error: [raw]'.$e->getMessage());
111
		}
112
113
	}
114
115
	/**
116
	 * @param string      $sql
117
	 * @param array       $values
118
	 * @param string|null $index
119
	 * @param bool        $assoc
120
	 *
121
	 * @return mixed
122
	 * @throws \chillerlan\Database\DBException
123
	 */
124
	public function prepared(string $sql, array $values = [], string $index = null, bool $assoc = true){
125
126
		try{
127
			return $this->__prepared($sql, $values, $index, $assoc);
128
		}
129
		catch(\Exception $e){
130
			throw new DBException('sql error: [prepared] '.$e->getMessage());
131
		}
132
133
	}
134
135
	/**
136
	 * @param string $sql
137
	 * @param array  $values
138
	 *
139
	 * @return mixed
140
	 * @throws \chillerlan\Database\DBException
141
	 */
142
	public function multi(string $sql, array $values){
143
144
		if(!is_array($values) || count($values) < 1 || !is_array($values[0]) || count($values[0]) < 1){
145
			throw new DBException('invalid data');
146
		}
147
148
		try{
149
			return $this->__multi($sql, $values);
150
		}
151
		catch(\Exception $e){
152
			throw new DBException('sql error: [multi] '.$e->getMessage());
153
		}
154
155
	}
156
157
	/**
158
	 * @param string         $sql
159
	 * @param array          $data
160
	 * @param array|callable $callback
161
	 *
162
	 * @return mixed
163
	 * @throws \chillerlan\Database\DBException
164
	 */
165
	public function multi_callback(string $sql, array $data, $callback){
166
167
		if(count($data) < 1){
168
			throw new DBException('invalid data');
169
		}
170
171
		if(!is_callable($callback)){
172
			throw new DBException('invalid callback');
173
		}
174
175
		try{
176
			return $this->__multi_callback($sql, $data, $callback);
177
		}
178
		catch(\Exception $e){
179
			throw new DBException('sql error: [multi_callback] '.$e->getMessage());
180
		}
181
182
	}
183
184
	/**
185
	 * @param string      $sql
186
	 * @param array|null  $values
187
	 * @param string|null $index
188
	 *
189
	 * @return string
190
	 */
191
	public function cacheKey(string $sql, array $values = [], string $index = null):string{
192
		return hash(self::CACHEKEY_HASH_ALGO, serialize([$sql, $values, $index]));
193
	}
194
195
	/**
196
	 * @param string      $sql
197
	 * @param array       $values
198
	 * @param string|null $index
199
	 *
200
	 * @return bool|mixed
201
	 */
202 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...
203
204
		if($this->cacheDriver){
205
			return $this->cacheDriver->get($this->cacheKey($sql, $values, $index));
206
		}
207
208
		return false; // @codeCoverageIgnore
209
	}
210
211
	/**
212
	 * @param string      $sql
213
	 * @param array       $values
214
	 * @param string|null $index
215
	 * @param             $response
216
	 * @param int|null    $ttl
217
	 *
218
	 * @return bool
219
	 */
220 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...
221
222
		if($this->cacheDriver){
223
			return $this->cacheDriver->set($this->cacheKey($sql, $values, $index), $response, $ttl);
224
		}
225
226
		return false; // @codeCoverageIgnore
227
	}
228
229
230
	/**
231
	 * @param string      $sql
232
	 * @param string|null $index
233
	 * @param bool        $assoc
234
	 * @param int|null    $ttl
235
	 *
236
	 * @return bool|mixed
237
	 */
238
	public function rawCached(string $sql, string $index = null, bool $assoc = true, int $ttl = null){
239
		$result = $this->cacheGet($sql, [], $index);
240
241 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...
242
			$result = $this->raw($sql, $index, $assoc);
243
244
			$this->cacheSet($sql, [], $index, $result, $ttl);
245
		}
246
247
		return $result;
248
	}
249
250
	/**
251
	 * @param string      $sql
252
	 * @param array       $values
253
	 * @param string|null $index
254
	 * @param bool        $assoc
255
	 * @param int|null    $ttl
256
	 *
257
	 * @return bool|mixed
258
	 */
259
	public function preparedCached(string $sql, array $values = [], string $index = null, bool $assoc = true, int $ttl = null){
260
		$result = $this->cacheGet($sql, $values, $index);
261
262 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...
263
			$result = $this->prepared($sql, $values, $index, $assoc);
264
265
			$this->cacheSet($sql, $values, $index, $result, $ttl);
266
		}
267
268
		return $result;
269
	}
270
}
271