This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | declare(strict_types=1); |
||
3 | |||
4 | /** |
||
5 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||
6 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||
7 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
||
8 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||
9 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
||
10 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
||
11 | * THE SOFTWARE. |
||
12 | */ |
||
13 | |||
14 | namespace Ytake\LaravelCouchbase\Database; |
||
15 | |||
16 | use Closure; |
||
17 | use Couchbase\Bucket; |
||
18 | use Couchbase\Cluster; |
||
19 | use Couchbase\ClusterManager; |
||
20 | use Couchbase\N1qlQuery; |
||
21 | use Illuminate\Database\Connection; |
||
22 | use Ytake\LaravelCouchbase\Events\QueryPrepared; |
||
23 | use Ytake\LaravelCouchbase\Events\ResultReturning; |
||
24 | use Ytake\LaravelCouchbase\Exceptions\NotSupportedException; |
||
25 | use Ytake\LaravelCouchbase\Query\Builder as QueryBuilder; |
||
26 | use Ytake\LaravelCouchbase\Query\Grammar; |
||
27 | use Ytake\LaravelCouchbase\Query\Processor; |
||
28 | use Ytake\LaravelCouchbase\Query\View; |
||
29 | use Ytake\LaravelCouchbase\Schema\Builder; |
||
30 | |||
31 | /** |
||
32 | * Class CouchbaseConnection. |
||
33 | * |
||
34 | * @author Yuuki Takezawa<[email protected]> |
||
35 | */ |
||
36 | class CouchbaseConnection extends Connection |
||
37 | { |
||
38 | /** @var string */ |
||
39 | protected $bucket; |
||
40 | |||
41 | /** @var Cluster */ |
||
42 | protected $connection; |
||
43 | |||
44 | /** @var */ |
||
45 | protected $managerUser; |
||
46 | |||
47 | /** @var */ |
||
48 | protected $managerPassword; |
||
49 | |||
50 | /** @var array */ |
||
51 | protected $options = []; |
||
52 | |||
53 | /** @var int */ |
||
54 | protected $fetchMode = 0; |
||
55 | |||
56 | /** @var array */ |
||
57 | protected $enableN1qlServers = []; |
||
58 | |||
59 | /** @var string */ |
||
60 | protected $bucketPassword = ''; |
||
61 | |||
62 | /** @var string[] */ |
||
63 | protected $metrics; |
||
64 | |||
65 | /** @var int default consistency */ |
||
66 | protected $consistency = N1qlQuery::NOT_BOUNDED; |
||
67 | |||
68 | /** @var string[] function to handle the retrieval of various properties. */ |
||
69 | private $properties = [ |
||
70 | 'operationTimeout', |
||
71 | 'viewTimeout', |
||
72 | 'durabilityInterval', |
||
73 | 'durabilityTimeout', |
||
74 | 'httpTimeout', |
||
75 | 'configTimeout', |
||
76 | 'configDelay', |
||
77 | 'configNodeTimeout', |
||
78 | 'htconfigIdleTimeout', |
||
79 | ]; |
||
80 | |||
81 | /** @var array */ |
||
82 | protected $config = []; |
||
83 | |||
84 | /** @var string */ |
||
85 | private $name; |
||
86 | |||
87 | /** @var bool */ |
||
88 | private $crossBucket = true; |
||
89 | |||
90 | /** |
||
91 | * @param array $config |
||
92 | * @param string $name |
||
93 | */ |
||
94 | 92 | public function __construct(array $config, $name) |
|
95 | { |
||
96 | 92 | $this->config = $config; |
|
97 | 92 | $this->name = $name; |
|
98 | 92 | $this->getManagedConfigure($config); |
|
99 | |||
100 | 92 | $this->useDefaultQueryGrammar(); |
|
101 | |||
102 | 92 | $this->useDefaultPostProcessor(); |
|
103 | 92 | } |
|
104 | |||
105 | /** |
||
106 | * @param string $password |
||
107 | * |
||
108 | * @return CouchbaseConnection |
||
109 | */ |
||
110 | public function setBucketPassword(string $password): CouchbaseConnection |
||
111 | { |
||
112 | $this->bucketPassword = $password; |
||
113 | |||
114 | return $this; |
||
115 | } |
||
116 | |||
117 | /** |
||
118 | * @param string $name |
||
119 | * |
||
120 | * @return Bucket |
||
121 | */ |
||
122 | 40 | public function openBucket(string $name): Bucket |
|
123 | { |
||
124 | 40 | $couchbase = $this->getCouchbase(); |
|
125 | 40 | if ($this->bucketPassword === '') { |
|
126 | 40 | return $couchbase->openBucket($name); |
|
127 | } |
||
128 | |||
129 | return $couchbase->openBucket($name, $this->bucketPassword); |
||
130 | } |
||
131 | |||
132 | /** |
||
133 | * @return ClusterManager |
||
134 | */ |
||
135 | 12 | public function manager(): ClusterManager |
|
136 | { |
||
137 | 12 | return $this->getCouchbase()->manager($this->managerUser, $this->managerPassword); |
|
138 | } |
||
139 | |||
140 | /** |
||
141 | * @param Bucket $bucket |
||
142 | * |
||
143 | * @return string[] |
||
144 | */ |
||
145 | 2 | public function getOptions(Bucket $bucket): array |
|
146 | { |
||
147 | 2 | $options = []; |
|
148 | 2 | foreach ($this->properties as $property) { |
|
149 | 2 | $options[$property] = $bucket->$property; |
|
150 | } |
||
151 | |||
152 | 2 | return $options; |
|
153 | } |
||
154 | |||
155 | /** |
||
156 | * @param Bucket $bucket |
||
157 | */ |
||
158 | 16 | protected function registerOption(Bucket $bucket) |
|
159 | { |
||
160 | 16 | if (count($this->options)) { |
|
161 | foreach ($this->options as $option => $value) { |
||
162 | $bucket->$option = $value; |
||
163 | } |
||
164 | } |
||
165 | 16 | } |
|
166 | |||
167 | /** |
||
168 | * @return Processor |
||
169 | */ |
||
170 | 92 | protected function getDefaultPostProcessor() |
|
171 | { |
||
172 | 92 | return new Processor(); |
|
173 | } |
||
174 | |||
175 | /** |
||
176 | * @return Grammar |
||
177 | */ |
||
178 | 92 | protected function getDefaultQueryGrammar() |
|
179 | { |
||
180 | 92 | return new Grammar(); |
|
181 | } |
||
182 | |||
183 | /** |
||
184 | * @return Builder|\Illuminate\Database\Schema\Builder |
||
185 | */ |
||
186 | 16 | public function getSchemaBuilder() |
|
187 | { |
||
188 | 16 | return new Builder($this); |
|
189 | } |
||
190 | |||
191 | /** |
||
192 | * @param array $config enable(array), options(array), administrator(array), bucket_password(string) |
||
193 | */ |
||
194 | 92 | protected function getManagedConfigure(array $config) |
|
195 | { |
||
196 | 92 | $this->enableN1qlServers = (isset($config['enables'])) ? $config['enables'] : []; |
|
197 | 92 | $this->options = (isset($config['options'])) ? $config['options'] : []; |
|
198 | 92 | $manager = (isset($config['administrator'])) ? $config['administrator'] : null; |
|
199 | 92 | $this->managerUser = ''; |
|
200 | 92 | $this->managerPassword = ''; |
|
201 | 92 | if (!is_null($manager)) { |
|
202 | 92 | $this->managerUser = $config['administrator']['user']; |
|
203 | 92 | $this->managerPassword = $config['administrator']['password']; |
|
204 | } |
||
205 | 92 | $this->bucketPassword = (isset($config['bucket_password'])) ? $config['bucket_password'] : ''; |
|
206 | 92 | } |
|
207 | |||
208 | /** |
||
209 | * {@inheritdoc} |
||
210 | */ |
||
211 | 18 | public function getName() |
|
212 | { |
||
213 | 18 | return $this->name; |
|
214 | } |
||
215 | |||
216 | /** |
||
217 | * @return \Couchbase\Cluster |
||
218 | */ |
||
219 | protected function createConnection(): Cluster |
||
220 | { |
||
221 | 74 | $this->setReconnector(function () { |
|
222 | $this->connection = (new CouchbaseConnector)->connect($this->config); |
||
223 | |||
224 | return $this; |
||
225 | 74 | }); |
|
226 | |||
227 | 74 | return (new CouchbaseConnector)->connect($this->config); |
|
228 | } |
||
229 | |||
230 | /** |
||
231 | * {@inheritdoc} |
||
232 | */ |
||
233 | public function getDriverName() |
||
234 | { |
||
235 | return 'couchbase'; |
||
236 | } |
||
237 | |||
238 | /** |
||
239 | * @return Cluster |
||
240 | */ |
||
241 | 72 | public function getCouchbase(): Cluster |
|
242 | { |
||
243 | 72 | if (is_null($this->connection)) { |
|
244 | 60 | $this->connection = $this->createConnection(); |
|
245 | } |
||
246 | |||
247 | 72 | return $this->connection; |
|
248 | } |
||
249 | |||
250 | /** |
||
251 | * @param string $table |
||
252 | * |
||
253 | * @return QueryBuilder |
||
254 | */ |
||
255 | 16 | public function table($table) |
|
256 | { |
||
257 | 16 | return $this->bucket($table)->query()->from($table); |
|
258 | } |
||
259 | |||
260 | /** |
||
261 | * @param int $consistency |
||
262 | * @param callable $callback |
||
263 | * |
||
264 | * @return mixed |
||
265 | */ |
||
266 | 2 | public function callableConsistency(int $consistency, callable $callback) |
|
267 | { |
||
268 | 2 | $clone = clone $this; |
|
269 | 2 | $clone->consistency = $consistency; |
|
270 | |||
271 | 2 | return call_user_func_array($callback, [$clone]); |
|
272 | } |
||
273 | |||
274 | /** |
||
275 | * @param int $consistency |
||
276 | * |
||
277 | * @return CouchbaseConnection |
||
278 | */ |
||
279 | public function consistency(int $consistency): CouchbaseConnection |
||
280 | { |
||
281 | $this->consistency = $consistency; |
||
282 | |||
283 | return $this; |
||
284 | } |
||
285 | |||
286 | /** |
||
287 | * @param bool $cross |
||
288 | */ |
||
289 | public function crossBucket(bool $cross): void |
||
290 | { |
||
291 | $this->crossBucket = $cross; |
||
292 | } |
||
293 | |||
294 | /** |
||
295 | * @param string $bucket |
||
296 | * |
||
297 | * @return $this |
||
298 | */ |
||
299 | 18 | public function bucket(string $bucket): CouchbaseConnection |
|
300 | { |
||
301 | 18 | $this->bucket = $bucket; |
|
302 | |||
303 | 18 | return $this; |
|
304 | } |
||
305 | |||
306 | /** |
||
307 | * @param N1qlQuery $query |
||
308 | * |
||
309 | * @return mixed |
||
310 | */ |
||
311 | 16 | protected function executeQuery(N1qlQuery $query) |
|
312 | { |
||
313 | 16 | $bucket = $this->openBucket($this->bucket); |
|
314 | 16 | $this->registerOption($bucket); |
|
315 | 16 | $this->firePreparedQuery($query); |
|
316 | 16 | $result = $bucket->query($query); |
|
317 | 16 | $this->fireReturning($result); |
|
318 | |||
319 | 16 | return $result; |
|
320 | } |
||
321 | |||
322 | /** |
||
323 | * @param string $query |
||
324 | * @param array $bindings |
||
325 | * |
||
326 | * @return \stdClass |
||
327 | */ |
||
328 | 10 | protected function execute(string $query, array $bindings = []) |
|
329 | { |
||
330 | 10 | $query = N1qlQuery::fromString($query); |
|
331 | 10 | $query->consistency($this->consistency); |
|
332 | 10 | $query->crossBucket($this->crossBucket); |
|
333 | 10 | $query->positionalParams($bindings); |
|
334 | 10 | $result = $this->executeQuery($query); |
|
335 | 10 | $this->metrics = $result->metrics ?? []; |
|
336 | |||
337 | 10 | return $result; |
|
338 | } |
||
339 | |||
340 | /** |
||
341 | * {@inheritdoc} |
||
342 | */ |
||
343 | public function select($query, $bindings = [], $useReadPdo = true) |
||
344 | { |
||
345 | 10 | return $this->run($query, $bindings, function ($query, $bindings) { |
|
346 | 10 | if ($this->pretending()) { |
|
347 | return []; |
||
348 | } |
||
349 | |||
350 | 10 | $result = $this->execute($query, $bindings); |
|
351 | 10 | $returning = []; |
|
352 | 10 | if (isset($result->rows)) { |
|
353 | 10 | foreach ($result->rows as $row) { |
|
354 | 4 | if (!isset($row->{$this->bucket})) { |
|
355 | 2 | return [$row]; |
|
356 | } |
||
357 | 4 | $returning[] = $row; |
|
358 | } |
||
359 | } |
||
360 | |||
361 | 10 | return $returning; |
|
362 | 10 | }); |
|
363 | } |
||
364 | |||
365 | /** |
||
366 | * {@inheritdoc} |
||
367 | */ |
||
368 | public function cursor($query, $bindings = [], $useReadPdo = true) |
||
369 | { |
||
370 | 2 | return $this->run($query, $bindings, function ($query, $bindings) { |
|
371 | if ($this->pretending()) { |
||
372 | return []; |
||
373 | } |
||
374 | |||
375 | $result = $this->execute($query, $bindings); |
||
376 | if (isset($result->rows)) { |
||
377 | foreach ($result->rows as $row) { |
||
378 | yield $row->{$this->bucket}; |
||
379 | } |
||
380 | } |
||
381 | 2 | }); |
|
382 | } |
||
383 | |||
384 | /** |
||
385 | * @param string $query |
||
386 | * @param array $bindings |
||
387 | * |
||
388 | * @return int|mixed |
||
389 | */ |
||
390 | 10 | public function insert($query, $bindings = []) |
|
391 | { |
||
392 | 10 | return $this->affectingStatement($query, $bindings); |
|
0 ignored issues
–
show
|
|||
393 | } |
||
394 | |||
395 | /** |
||
396 | * {@inheritdoc} |
||
397 | */ |
||
398 | public function affectingStatement($query, $bindings = []) |
||
399 | { |
||
400 | 12 | return $this->run($query, $bindings, function ($query, $bindings) { |
|
401 | 12 | if ($this->pretending()) { |
|
402 | return 0; |
||
403 | } |
||
404 | 12 | $query = N1qlQuery::fromString($query); |
|
405 | 12 | $query->consistency($this->consistency); |
|
406 | 12 | $query->crossBucket($this->crossBucket); |
|
407 | 12 | $query->namedParams(['parameters' => $bindings]); |
|
408 | 12 | $result = $this->executeQuery($query); |
|
409 | 12 | $this->metrics = $result->metrics ?? []; |
|
410 | 12 | if (!count($result->rows)) { |
|
411 | return false; |
||
412 | } |
||
413 | |||
414 | 12 | return $result->rows[0]->{$this->bucket} ?? $result->rows[0]; |
|
415 | 12 | }); |
|
416 | } |
||
417 | |||
418 | /** |
||
419 | * @param string $query |
||
420 | * @param array $bindings |
||
421 | * |
||
422 | * @return mixed |
||
423 | */ |
||
424 | public function positionalStatement(string $query, array $bindings = []) |
||
425 | { |
||
426 | 6 | return $this->run($query, $bindings, function ($query, $bindings) { |
|
427 | 6 | if ($this->pretending()) { |
|
428 | return 0; |
||
429 | } |
||
430 | 6 | $query = N1qlQuery::fromString($query); |
|
431 | 6 | $query->consistency($this->consistency); |
|
432 | 6 | $query->crossBucket($this->crossBucket); |
|
433 | 6 | $query->positionalParams($bindings); |
|
434 | 6 | $result = $this->executeQuery($query); |
|
435 | 6 | $this->metrics = $result->metrics ?? []; |
|
436 | 6 | if (!count($result->rows)) { |
|
437 | return false; |
||
438 | } |
||
439 | |||
440 | 6 | return $result->rows[0]->{$this->bucket} ?? $result->rows[0]; |
|
441 | 6 | }); |
|
442 | } |
||
443 | |||
444 | /** |
||
445 | * {@inheritdoc} |
||
446 | */ |
||
447 | 2 | public function transaction(Closure $callback, $attempts = 1) |
|
448 | { |
||
449 | 2 | throw new NotSupportedException(__METHOD__); |
|
450 | } |
||
451 | |||
452 | /** |
||
453 | * {@inheritdoc} |
||
454 | */ |
||
455 | 2 | public function beginTransaction() |
|
456 | { |
||
457 | 2 | throw new NotSupportedException(__METHOD__); |
|
458 | } |
||
459 | |||
460 | /** |
||
461 | * {@inheritdoc} |
||
462 | */ |
||
463 | 2 | public function commit() |
|
464 | { |
||
465 | 2 | throw new NotSupportedException(__METHOD__); |
|
466 | } |
||
467 | |||
468 | /** |
||
469 | * {@inheritdoc} |
||
470 | */ |
||
471 | 2 | public function rollBack($toLevel = null) |
|
472 | { |
||
473 | 2 | throw new NotSupportedException(__METHOD__); |
|
474 | } |
||
475 | |||
476 | /** |
||
477 | * {@inheritdoc} |
||
478 | */ |
||
479 | 16 | protected function reconnectIfMissingConnection() |
|
480 | { |
||
481 | 16 | if (is_null($this->connection)) { |
|
482 | 12 | $this->reconnect(); |
|
483 | } |
||
484 | 16 | } |
|
485 | |||
486 | /** |
||
487 | * {@inheritdoc} |
||
488 | */ |
||
489 | 14 | public function disconnect() |
|
490 | { |
||
491 | 14 | $this->connection = null; |
|
492 | 14 | } |
|
493 | |||
494 | /** |
||
495 | * N1QL upsert query. |
||
496 | * |
||
497 | * @param string $query |
||
498 | * @param array $bindings |
||
499 | * |
||
500 | * @return int |
||
501 | */ |
||
502 | 2 | public function upsert(string $query, array $bindings = []) |
|
503 | { |
||
504 | 2 | return $this->affectingStatement($query, $bindings); |
|
505 | } |
||
506 | |||
507 | /** |
||
508 | * Get a new query builder instance. |
||
509 | * |
||
510 | * @return QueryBuilder |
||
511 | */ |
||
512 | 16 | public function query() |
|
513 | { |
||
514 | 16 | return new QueryBuilder( |
|
515 | 16 | $this, $this->getQueryGrammar(), $this->getPostProcessor() |
|
516 | ); |
||
517 | } |
||
518 | |||
519 | /** |
||
520 | * @param string|null $bucket |
||
521 | * |
||
522 | * @return View |
||
523 | */ |
||
524 | 2 | public function view(string $bucket = null): View |
|
525 | { |
||
526 | 2 | $bucket = is_null($bucket) ? $this->bucket : $bucket; |
|
527 | |||
528 | 2 | return new View($this->openBucket($bucket), $this->events); |
|
529 | } |
||
530 | |||
531 | /** |
||
532 | * Run an update statement against the database. |
||
533 | * |
||
534 | * @param string $query |
||
535 | * @param array $bindings |
||
536 | * |
||
537 | * @return int|\stdClass |
||
538 | */ |
||
539 | 2 | public function update($query, $bindings = []) |
|
540 | { |
||
541 | 2 | return $this->positionalStatement($query, $bindings); |
|
542 | } |
||
543 | |||
544 | /** |
||
545 | * Run a delete statement against the database. |
||
546 | * |
||
547 | * @param string $query |
||
548 | * @param array $bindings |
||
549 | * |
||
550 | * @return int|\stdClass |
||
551 | */ |
||
552 | 4 | public function delete($query, $bindings = []) |
|
553 | { |
||
554 | 4 | return $this->positionalStatement($query, $bindings); |
|
555 | } |
||
556 | |||
557 | /** |
||
558 | * @return \string[] |
||
559 | */ |
||
560 | 2 | public function metrics(): array |
|
561 | { |
||
562 | 2 | return $this->metrics; |
|
563 | } |
||
564 | |||
565 | /** |
||
566 | * @param N1qlQuery $queryObject |
||
567 | */ |
||
568 | 16 | protected function firePreparedQuery(N1qlQuery $queryObject) |
|
569 | { |
||
570 | 16 | if (isset($this->events)) { |
|
571 | 16 | $this->events->dispatch(new QueryPrepared($queryObject)); |
|
572 | } |
||
573 | 16 | } |
|
574 | |||
575 | /** |
||
576 | * @param mixed $returning |
||
577 | */ |
||
578 | 16 | protected function fireReturning($returning) |
|
579 | { |
||
580 | 16 | if (isset($this->events)) { |
|
581 | 16 | $this->events->dispatch(new ResultReturning($returning)); |
|
582 | } |
||
583 | 16 | } |
|
584 | |||
585 | /** |
||
586 | * @param null|\PDO $pdo |
||
587 | * |
||
588 | * @return $this |
||
589 | */ |
||
590 | 14 | public function setPdo($pdo) |
|
591 | { |
||
592 | 14 | $this->connection = $this->createConnection(); |
|
593 | 14 | $this->getManagedConfigure($this->config); |
|
594 | 14 | $this->useDefaultQueryGrammar(); |
|
595 | 14 | $this->useDefaultPostProcessor(); |
|
596 | |||
597 | 14 | return $this; |
|
598 | } |
||
599 | } |
||
600 |
If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.
Let’s take a look at an example:
Our function
my_function
expects aPost
object, and outputs the author of the post. The base classPost
returns a simple string and outputting a simple string will work just fine. However, the child classBlogPost
which is a sub-type ofPost
instead decided to return anobject
, and is therefore violating the SOLID principles. If aBlogPost
were passed tomy_function
, PHP would not complain, but ultimately fail when executing thestrtoupper
call in its body.