Completed
Push — master ( 2f9cff...a9471a )
by yuuki
11s
created

CouchbaseConnection::getOptions()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 5
c 1
b 0
f 0
nc 2
nop 1
dl 0
loc 9
ccs 5
cts 5
cp 1
crap 2
rs 9.6666
1
<?php
2
3
/**
4
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
5
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
6
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
7
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
8
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
9
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
10
 * THE SOFTWARE.
11
 */
12
13
namespace Ytake\LaravelCouchbase\Database;
14
15
use Closure;
16
use CouchbaseBucket;
17
use Illuminate\Database\Connection;
18
use Ytake\LaravelCouchbase\Events\QueryPrepared;
19
use Ytake\LaravelCouchbase\Events\ResultReturning;
20
use Ytake\LaravelCouchbase\Query\Grammar;
21
use Ytake\LaravelCouchbase\Query\Processor;
22
use Ytake\LaravelCouchbase\Exceptions\NotSupportedException;
23
use Ytake\LaravelCouchbase\VersionTrait;
24
25
/**
26
 * Class CouchbaseConnection.
27
 *
28
 * @author Yuuki Takezawa<[email protected]>
29
 */
30
class CouchbaseConnection extends Connection
31
{
32
    use VersionTrait;
33
34
    /** @var string */
35
    protected $bucket;
36
37
    /** @var \CouchbaseCluster */
38
    protected $connection;
39
40
    /** @var */
41
    protected $managerUser;
42
43
    /** @var */
44
    protected $managerPassword;
45
46
    /** @var array */
47
    protected $options = [];
48
49
    /** @var int */
50
    protected $fetchMode = 0;
51
52
    /** @var array */
53
    protected $enableN1qlServers = [];
54
55
    /** @var string */
56
    protected $bucketPassword = '';
57
58
    /** @var string[] */
59
    protected $metrics;
60
61
    /** @var int  default consistency */
62
    protected $consistency = \CouchbaseN1qlQuery::NOT_BOUNDED;
63
64
    /** @var string[]  function to handle the retrieval of various properties. */
65
    private $properties = [
66
        'operationTimeout',
67
        'viewTimeout',
68
        'durabilityInterval',
69
        'durabilityTimeout',
70
        'httpTimeout',
71
        'configTimeout',
72
        'configDelay',
73
        'configNodeTimeout',
74
        'htconfigIdleTimeout',
75
    ];
76
77
    /**
78
     * @param array $config
79
     */
80 28
    public function __construct(array $config)
81
    {
82 28
        $this->connection = $this->createConnection($config);
83 28
        $this->getManagedConfigure($config);
84
85 28
        $this->useDefaultQueryGrammar();
86
87 28
        $this->useDefaultPostProcessor();
88 28
    }
89
90
    /**
91
     * @param $password
92
     *
93
     * @return $this
94
     */
95
    public function setBucketPassword($password)
96
    {
97
        $this->bucketPassword = $password;
98
99
        return $this;
100
    }
101
102
    /**
103
     * @param $name
104
     *
105
     * @return \CouchbaseBucket
106
     */
107 6
    public function openBucket($name)
108
    {
109 6
        return $this->connection->openBucket($name, $this->bucketPassword);
110
    }
111
112
    /**
113
     * @param CouchbaseBucket $bucket
114
     *
115
     * @return string[]
116
     */
117 1
    public function getOptions(\CouchbaseBucket $bucket)
118
    {
119 1
        $options = [];
120 1
        foreach ($this->properties as $property) {
121 1
            $options[$property] = $bucket->$property;
122
        }
123
124 1
        return $options;
125
    }
126
127
    /**
128
     * @param CouchbaseBucket $bucket
129
     */
130 5
    protected function registerOption(\CouchbaseBucket $bucket)
131
    {
132 5
        if (count($this->options)) {
133
            foreach ($this->options as $option => $value) {
134
                $bucket->$option = $value;
135
            }
136
        }
137 5
    }
138
139
    /**
140
     * @return Processor
141
     */
142 28
    protected function getDefaultPostProcessor()
143
    {
144 28
        return new Processor();
145
    }
146
147
    /**
148
     * @return Grammar
149
     */
150 28
    protected function getDefaultQueryGrammar()
151
    {
152 28
        return new Grammar();
153
    }
154
155
    /**
156
     * @param array $config
157
     */
158 28
    protected function getManagedConfigure(array $config)
159
    {
160 28
        $this->enableN1qlServers = (isset($config['enables'])) ? $config['enables'] : [];
161 28
        $this->options = (isset($config['options'])) ? $config['options'] : [];
162 28
        $manager = (isset($config['manager'])) ? $config['manager'] : null;
163 28
        if (is_null($manager)) {
164 28
            $this->managerUser = (isset($config['user'])) ? $config['user'] : null;
165 28
            $this->managerPassword = (isset($config['password'])) ? $config['password'] : null;
166
167 28
            return;
168
        }
169
        $this->managerUser = $config['manager']['user'];
170
        $this->managerPassword = $config['manager']['password'];
171
    }
172
173
    /**
174
     * @param $dsn
175
     *
176
     * @return \CouchbaseCluster
177
     */
178 28
    protected function createConnection($dsn)
179
    {
180 28
        return (new CouchbaseConnector)->connect($dsn);
181
    }
182
183
    /**
184
     * {@inheritdoc}
185
     */
186
    public function getDriverName()
187
    {
188
        return 'couchbase';
189
    }
190
191
    /**
192
     * @return \CouchbaseCluster
193
     */
194 16
    public function getCouchbase()
195
    {
196 16
        return $this->connection;
197
    }
198
199
    /**
200
     * @param string $table
201
     *
202
     * @return \Ytake\LaravelCouchbase\Database\QueryBuilder
203
     */
204 5
    public function table($table)
205
    {
206 5
        $this->bucket = $table;
207
208 5
        return $this->query()->from($table);
209
    }
210
211
    /**
212
     * @param int      $consistency
213
     * @param callable $callback
214
     *
215
     * @return mixed
216
     */
217 1
    public function callableConsistency($consistency, callable $callback)
218
    {
219 1
        $clone = clone $this;
220 1
        $clone->consistency = $consistency;
221
222 1
        return call_user_func_array($callback, [$clone]);
223
    }
224
225
    /**
226
     * @param int $consistency
227
     *
228
     * @return $this
229
     */
230
    public function consistency($consistency)
231
    {
232
        $this->consistency = $consistency;
233
234
        return $this;
235
    }
236
237
    /**
238
     * @param string $bucket
239
     *
240
     * @return $this
241
     */
242
    public function bucket($bucket)
243
    {
244
        $this->bucket = $bucket;
245
246
        return $this;
247
    }
248
249
    /**
250
     * @param \CouchbaseN1qlQuery $query
251
     *
252
     * @return mixed
253
     */
254 5
    protected function executeQuery(\CouchbaseN1qlQuery $query)
255
    {
256 5
        $bucket = $this->openBucket($this->bucket);
257 5
        $this->registerOption($bucket);
258 5
        $this->firePreparedQuery($query);
259 5
        $result = $bucket->query($query);
260 5
        $this->fireReturning($result);
261
262 5
        return $result;
263
    }
264
265
    /**
266
     * {@inheritdoc}
267
     */
268 1
    public function select($query, $bindings = [], $useReadPdo = true)
269
    {
270
        return $this->run($query, $bindings, function ($me, $query, $bindings) {
271 1
            if ($me->pretending()) {
272
                return [];
273
            }
274 1
            $query = \CouchbaseN1qlQuery::fromString($query);
275 1
            if ($this->breakingVersion()) {
276 1
                $query->consistency($this->consistency);
277 1
                $query->positionalParams($bindings);
278 1
                $result = $this->executeQuery($query);
279 1
                $this->metrics = (isset($result->metrics)) ? $result->metrics : [];
280
281 1
                return (isset($result->rows)) ? $result->rows : [];
282
            }
283
            // @codeCoverageIgnoreStart
284
            $query->options['args'] = $bindings;
285
            $query->consistency($this->consistency);
286
287
            return $this->executeQuery($query);
288
            // @codeCoverageIgnoreEnd
289 1
        });
290
    }
291
292
    /**
293
     * @param string $query
294
     * @param array  $bindings
295
     *
296
     * @return int|mixed
297
     */
298 4
    public function insert($query, $bindings = [])
299
    {
300 4
        return $this->affectingStatement($query, $bindings);
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $this->affectingS...ent($query, $bindings); (integer) is incompatible with the return type declared by the interface Illuminate\Database\ConnectionInterface::insert of type boolean.

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:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
301
    }
302
303
    /**
304
     * {@inheritdoc}
305
     */
306 5
    public function affectingStatement($query, $bindings = [])
307
    {
308
        return $this->run($query, $bindings, function ($me, $query, $bindings) {
309 5
            if ($me->pretending()) {
310
                return 0;
311
            }
312 5
            $query = \CouchbaseN1qlQuery::fromString($query);
313
314 5 View Code Duplication
            if ($this->breakingVersion()) {
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...
315 5
                $query->consistency($this->consistency);
316 5
                $query->namedParams(['parameters' => $bindings]);
317 5
                $result = $this->executeQuery($query);
318 5
                $this->metrics = (isset($result->metrics)) ? $result->metrics : [];
319
320 5
                return (isset($result->rows[0])) ? $result->rows[0] : false;
321
            }
322
            // @codeCoverageIgnoreStart
323
            $query->consistency($this->consistency);
324
            $bucket = $this->openBucket($this->bucket);
325
            $this->registerOption($bucket);
326
            $this->firePreparedQuery($query);
327
            $result = $bucket->query($query, ['parameters' => $bindings]);
328
            $this->fireReturning($result);
329
330
            return (isset($result[0])) ? $result[0] : false;
331
            // @codeCoverageIgnoreEnd
332 5
        });
333
    }
334
335
    /**
336
     * @param       $query
337
     * @param array $bindings
338
     *
339
     * @return mixed
340
     */
341
    public function positionalStatement($query, array $bindings = [])
342
    {
343 5
        return $this->run($query, $bindings, function ($me, $query, $bindings) {
344 5
            if ($me->pretending()) {
345
                return 0;
346
            }
347 5
            $query = \CouchbaseN1qlQuery::fromString($query);
348
349 5 View Code Duplication
            if ($this->breakingVersion()) {
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...
350 5
                $query->consistency($this->consistency);
351 5
                $query->positionalParams($bindings);
352 5
                $result = $this->executeQuery($query);
353 5
                $this->metrics = (isset($result->metrics)) ? $result->metrics : [];
354
355 5
                return (isset($result->rows[0])) ? $result->rows[0] : false;
356
            }
357
358
            // @codeCoverageIgnoreStart
359
            $query->consistency($this->consistency);
360
            $query->options['args'] = $bindings;
361
            $result = $this->executeQuery($query);
362
363
            return (isset($result[0])) ? $result[0] : false;
364
            // @codeCoverageIgnoreEnd
365 5
        });
366
    }
367
368
    /**
369
     * {@inheritdoc}
370
     */
371 1
    public function transaction(Closure $callback)
372
    {
373 1
        throw new NotSupportedException(__METHOD__);
0 ignored issues
show
Documentation introduced by
__METHOD__ is of type string, but the function expects a array.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
374
    }
375
376
    /**
377
     * {@inheritdoc}
378
     */
379 1
    public function beginTransaction()
380
    {
381 1
        throw new NotSupportedException(__METHOD__);
0 ignored issues
show
Documentation introduced by
__METHOD__ is of type string, but the function expects a array.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
382
    }
383
384
    /**
385
     * {@inheritdoc}
386
     */
387 1
    public function commit()
388
    {
389 1
        throw new NotSupportedException(__METHOD__);
0 ignored issues
show
Documentation introduced by
__METHOD__ is of type string, but the function expects a array.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
390
    }
391
392
    /**
393
     * {@inheritdoc}
394
     */
395 1
    public function rollBack()
396
    {
397 1
        throw new NotSupportedException(__METHOD__);
0 ignored issues
show
Documentation introduced by
__METHOD__ is of type string, but the function expects a array.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
398
    }
399
400
    /**
401
     * {@inheritdoc}
402
     */
403 5
    protected function reconnectIfMissingConnection()
404
    {
405 5
        if (is_null($this->connection)) {
406
            $this->reconnect();
407
        }
408 5
    }
409
410
    /**
411
     * {@inheritdoc}
412
     */
413
    public function disconnect()
414
    {
415
        $this->connection = null;
416
    }
417
418
    /**
419
     * @param CouchbaseBucket $bucket
420
     *
421
     * @return CouchbaseBucket
422
     */
423
    protected function enableN1ql(CouchbaseBucket $bucket)
424
    {
425
        if (!count($this->enableN1qlServers)) {
426
            return $bucket;
427
        }
428
        $bucket->enableN1ql($this->enableN1qlServers);
429
430
        return $bucket;
431
    }
432
433
    /**
434
     * N1QL upsert query.
435
     *
436
     * @param string $query
437
     * @param array  $bindings
438
     *
439
     * @return int
440
     */
441 1
    public function upsert($query, $bindings = [])
442
    {
443 1
        return $this->affectingStatement($query, $bindings);
444
    }
445
446
    /**
447
     * Get a new query builder instance.
448
     *
449
     * @return \Illuminate\Database\Query\Builder
450
     */
451 5
    public function query()
452
    {
453 5
        return new QueryBuilder(
454 5
            $this, $this->getQueryGrammar(), $this->getPostProcessor()
455
        );
456
    }
457
458
    /**
459
     * Run an update statement against the database.
460
     *
461
     * @param string $query
462
     * @param array  $bindings
463
     *
464
     * @return int|\stdClass
465
     */
466 1
    public function update($query, $bindings = [])
467
    {
468 1
        return $this->positionalStatement($query, $bindings);
469
    }
470
471
    /**
472
     * Run a delete statement against the database.
473
     *
474
     * @param string $query
475
     * @param array  $bindings
476
     *
477
     * @return int|\stdClass
478
     */
479 5
    public function delete($query, $bindings = [])
480
    {
481 5
        return $this->positionalStatement($query, $bindings);
482
    }
483
484
    /**
485
     * @return \string[]
486
     */
487 1
    public function metrics()
488
    {
489 1
        return $this->metrics;
490
    }
491
492
    /**
493
     * @param \CouchbaseN1qlQuery $queryObject
494
     */
495 5
    protected function firePreparedQuery(\CouchbaseN1qlQuery $queryObject)
496
    {
497 5
        if (isset($this->events)) {
498 5
            $this->events->fire(new QueryPrepared($queryObject));
499
        }
500 5
    }
501
502
    /**
503
     * @param mixed $returning
504
     */
505 5
    protected function fireReturning($returning)
506
    {
507 5
        if (isset($this->events)) {
508 5
            $this->events->fire(new ResultReturning($returning));
509
        }
510 5
    }
511
}
512