Completed
Pull Request — master (#24)
by yuuki
11:11
created

CouchbaseConnection::getOptions()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 1
CRAP Score 3.1852

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
rs 9.6666
ccs 1
cts 3
cp 0.3333
crap 3.1852
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\Query\Grammar;
19
use Ytake\LaravelCouchbase\Query\Processor;
20
use Ytake\LaravelCouchbase\Exceptions\NotSupportedException;
21
use Ytake\LaravelCouchbase\VersionTrait;
22
23
/**
24
 * Class CouchbaseConnection.
25
 *
26
 * @author Yuuki Takezawa<[email protected]>
27
 */
28
class CouchbaseConnection extends Connection
29
{
30
    use VersionTrait;
31
32
    /** @var string */
33
    protected $bucket;
34
35
    /** @var \CouchbaseCluster */
36
    protected $connection;
37
38
    /** @var */
39
    protected $managerUser;
40
41
    /** @var */
42
    protected $managerPassword;
43
44
    /** @var array */
45
    protected $options = [];
46
47
    /** @var int */
48
    protected $fetchMode = 0;
49
50
    /** @var array */
51
    protected $enableN1qlServers = [];
52
53 25
    /** @var string */
54
    protected $bucketPassword = '';
55 25
56 25
    /** @var string[] */
57
    protected $metrics;
58 25
59
    /** @var int  default consistency */
60 25
    protected $consistency = \CouchbaseN1qlQuery::NOT_BOUNDED;
61 25
62
    /** @var string[]  function to handle the retrieval of various properties. */
63
    private $properties = [
64
        'operationTimeout',
65
        'viewTimeout',
66
        'durabilityInterval',
67
        'durabilityTimeout',
68
        'httpTimeout',
69
        'configTimeout',
70
        'configDelay',
71
        'configNodeTimeout',
72
        'htconfigIdleTimeout',
73
    ];
74
75
    /**
76
     * @param array $config
77
     */
78
    public function __construct(array $config)
79
    {
80 5
        $this->connection = $this->createConnection($config);
81
        $this->getManagedConfigure($config);
82 5
83
        $this->useDefaultQueryGrammar();
84
85
        $this->useDefaultPostProcessor();
86
    }
87
88 25
    /**
89
     * @param $password
90 25
     *
91
     * @return $this
92
     */
93
    public function setBucketPassword($password)
94
    {
95
        $this->bucketPassword = $password;
96 25
97
        return $this;
98 25
    }
99
100
    /**
101
     * @param $name
102
     *
103
     * @return \CouchbaseBucket
104 25
     */
105
    public function openBucket($name)
106 25
    {
107 25
        return $this->connection->openBucket($name, $this->bucketPassword);
108 25
    }
109 25
110 25
    /**
111
     * @param CouchbaseBucket $bucket
112 25
     *
113
     * @return string[]
114
     */
115
    public function getOptions(\CouchbaseBucket $bucket)
116
    {
117
        $options = [];
118
        foreach ($this->properties as $property) {
119
            $options[$property] = $bucket->$property;
120
        }
121
122
        return $options;
123 25
    }
124
125 25
    /**
126
     * @param CouchbaseBucket $bucket
127
     */
128
    protected function registerOption(\CouchbaseBucket $bucket)
129
    {
130
        if (count($this->options)) {
131
            foreach ($this->options as $option => $value) {
132
                $bucket->$option = $value;
133
            }
134
        }
135
    }
136
137
    /**
138
     * @return Processor
139 15
     */
140
    protected function getDefaultPostProcessor()
141 15
    {
142
        return new Processor();
143
    }
144
145
    /**
146
     * @return Grammar
147
     */
148
    protected function getDefaultQueryGrammar()
149 5
    {
150
        return new Grammar();
151 5
    }
152
153 5
    /**
154
     * @param array $config
155
     */
156
    protected function getManagedConfigure(array $config)
157
    {
158
        $this->enableN1qlServers = (isset($config['enables'])) ? $config['enables'] : [];
159
        $this->options = (isset($config['options'])) ? $config['options'] : [];
160
        $manager = (isset($config['manager'])) ? $config['manager'] : null;
161
        if (is_null($manager)) {
162
            $this->managerUser = (isset($config['user'])) ? $config['user'] : null;
163
            $this->managerPassword = (isset($config['password'])) ? $config['password'] : null;
164
165
            return;
166
        }
167
        $this->managerUser = $config['manager']['user'];
168
        $this->managerPassword = $config['manager']['password'];
169
    }
170
171 1
    /**
172
     * @param $dsn
173
     *
174 1
     * @return \CouchbaseCluster
175
     */
176
    protected function createConnection($dsn)
177 1
    {
178 1
        return (new CouchbaseConnector)->connect($dsn);
179 1
    }
180 1
181
    /**
182 1
     * {@inheritdoc}
183 1
     */
184
    public function getDriverName()
185
    {
186
        return 'couchbase';
187
    }
188
189
    /**
190
     * @return \CouchbaseCluster
191
     */
192 4
    public function getCouchbase()
193
    {
194 4
        return $this->connection;
195
    }
196
197
    /**
198
     * @param string $table
199
     *
200 5
     * @return \Ytake\LaravelCouchbase\Database\QueryBuilder
201
     */
202
    public function table($table)
203 5
    {
204
        $this->bucket = $table;
205
206 5
        return $this->query()->from($table);
207 5
    }
208 5
209 5
    /**
210
     * @param int      $consistency
211 5
     * @param callable $callback
212 5
     *
213
     * @return mixed
214
     */
215
    public function callableConsistency($consistency, callable $callback)
216
    {
217
        $clone = clone $this;
218
        $clone->consistency = $consistency;
219
220
        return call_user_func_array($callback, [$clone]);
221
    }
222
223 5
    /**
224 5
     * @param int $consistency
225
     *
226
     * @return $this
227 5
     */
228 5
    public function consistency($consistency)
229 5
    {
230 5
        $this->consistency = $consistency;
231 5
232
        return $this;
233 5
    }
234 5
235
    /**
236
     * @param string $bucket
237
     *
238
     * @return $this
239
     */
240 1
    public function bucket($bucket)
241
    {
242 1
        $this->bucket = $bucket;
243
244
        return $this;
245
    }
246
247
    /**
248 1
     * {@inheritdoc}
249
     */
250 1
    public function select($query, $bindings = [], $useReadPdo = true)
251
    {
252
        return $this->run($query, $bindings, function ($me, $query, $bindings) {
253
            if ($me->pretending()) {
254
                return [];
255
            }
256 1
            $query = \CouchbaseN1qlQuery::fromString($query);
257
            if ($this->breakingVersion()) {
258 1
                $query->consistency($this->consistency);
259
                $query->positionalParams($bindings);
260
                $bucket = $this->openBucket($this->bucket);
261
                $this->registerOption($bucket);
262
                $result = $bucket->query($query);
263
                $this->metrics = (isset($result->metrics)) ? $result->metrics : [];
264 1
265
                return (isset($result->rows)) ? $result->rows : [];
266 1
            }
267
            // @codeCoverageIgnoreStart
268
            $query->options['args'] = $bindings;
269
            $query->consistency($this->consistency);
270
            $bucket = $this->openBucket($this->bucket);
271
            $this->registerOption($bucket);
272 5
273
            return $bucket->query($query);
274 5
            // @codeCoverageIgnoreEnd
275
        });
276
    }
277 5
278
    /**
279
     * @param string $query
280
     * @param array  $bindings
281
     *
282
     * @return int|mixed
283
     */
284
    public function insert($query, $bindings = [])
285
    {
286
        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...
287
    }
288
289
    /**
290
     * {@inheritdoc}
291
     */
292
    public function affectingStatement($query, $bindings = [])
293
    {
294
        return $this->run($query, $bindings, function ($me, $query, $bindings) {
295
            if ($me->pretending()) {
296
                return 0;
297
            }
298
            $query = \CouchbaseN1qlQuery::fromString($query);
299
300 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...
301
                $query->consistency($this->consistency);
302
                $bucket = $this->openBucket($this->bucket);
303
                $this->registerOption($bucket);
304
                $query->namedParams(['parameters' => $bindings]);
305
                $result = $bucket->query($query);
306
                $this->metrics = (isset($result->metrics)) ? $result->metrics : [];
307
308
                return (isset($result->rows[0])) ? $result->rows[0] : false;
309
            }
310 1
            // @codeCoverageIgnoreStart
311
            $query->consistency($this->consistency);
312 1
            $bucket = $this->openBucket($this->bucket);
313
            $this->registerOption($bucket);
314
            $result = $bucket->query($query, ['parameters' => $bindings]);
315
316
            return (isset($result[0])) ? $result[0] : false;
317
            // @codeCoverageIgnoreEnd
318
        });
319
    }
320 5
321
    /**
322 5
     * @param       $query
323 5
     * @param array $bindings
324 5
     *
325
     * @return mixed
326
     */
327
    public function positionalStatement($query, array $bindings = [])
328
    {
329
        return $this->run($query, $bindings, function ($me, $query, $bindings) {
330
            if ($me->pretending()) {
331
                return 0;
332
            }
333
            $query = \CouchbaseN1qlQuery::fromString($query);
334
335 1 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...
336
                $query->consistency($this->consistency);
337 1
                $query->positionalParams($bindings);
338
                $bucket = $this->openBucket($this->bucket);
339
                $this->registerOption($bucket);
340
                $result = $bucket->query($query);
341
                $this->metrics = (isset($result->metrics)) ? $result->metrics : [];
342
343
                return (isset($result->rows[0])) ? $result->rows[0] : false;
344
            }
345
            // @codeCoverageIgnoreStart
346
            $query->consistency($this->consistency);
347
            $query->options['args'] = $bindings;
348 5
            $bucket = $this->openBucket($this->bucket);
349
            $this->registerOption($bucket);
350 5
            $result = $bucket->query($query);
351
352
            return (isset($result[0])) ? $result[0] : false;
353
            // @codeCoverageIgnoreEnd
354
        });
355
    }
356
357
    /**
358
     * {@inheritdoc}
359
     */
360
    public function transaction(Closure $callback)
361
    {
362
        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...
363
    }
364
365
    /**
366
     * {@inheritdoc}
367
     */
368
    public function beginTransaction()
369
    {
370
        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...
371
    }
372
373
    /**
374
     * {@inheritdoc}
375
     */
376
    public function commit()
377
    {
378
        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...
379
    }
380
381
    /**
382
     * {@inheritdoc}
383
     */
384
    public function rollBack()
385
    {
386
        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...
387
    }
388
389
    /**
390
     * {@inheritdoc}
391
     */
392
    protected function reconnectIfMissingConnection()
393
    {
394
        if (is_null($this->connection)) {
395
            $this->reconnect();
396
        }
397
    }
398
399
    /**
400
     * {@inheritdoc}
401
     */
402
    public function disconnect()
403
    {
404
        $this->connection = null;
405
    }
406
407
    /**
408
     * @param CouchbaseBucket $bucket
409
     *
410
     * @return CouchbaseBucket
411
     */
412
    protected function enableN1ql(CouchbaseBucket $bucket)
413
    {
414
        if (!count($this->enableN1qlServers)) {
415
            return $bucket;
416
        }
417
        $bucket->enableN1ql($this->enableN1qlServers);
418
419
        return $bucket;
420
    }
421
422
    /**
423
     * N1QL upsert query.
424
     *
425
     * @param string $query
426
     * @param array  $bindings
427
     *
428
     * @return int
429
     */
430
    public function upsert($query, $bindings = [])
431
    {
432
        return $this->affectingStatement($query, $bindings);
433
    }
434
435
    /**
436
     * Get a new query builder instance.
437
     *
438
     * @return \Illuminate\Database\Query\Builder
439
     */
440
    public function query()
441
    {
442
        return new QueryBuilder(
443
            $this, $this->getQueryGrammar(), $this->getPostProcessor()
444
        );
445
    }
446
447
    /**
448
     * Run an update statement against the database.
449
     *
450
     * @param string $query
451
     * @param array  $bindings
452
     *
453
     * @return int|\stdClass
454
     */
455
    public function update($query, $bindings = [])
456
    {
457
        return $this->positionalStatement($query, $bindings);
458
    }
459
460
    /**
461
     * Run a delete statement against the database.
462
     *
463
     * @param string $query
464
     * @param array  $bindings
465
     *
466
     * @return int|\stdClass
467
     */
468
    public function delete($query, $bindings = [])
469
    {
470
        return $this->positionalStatement($query, $bindings);
471
    }
472
473
    /**
474
     * @return \string[]
475
     */
476
    public function metrics()
477
    {
478
        return $this->metrics;
479
    }
480
}
481