Completed
Push — master ( 0835cd...0d9cbc )
by yuuki
7s
created

CouchbaseConnection::affectingStatement()   A

Complexity

Conditions 3
Paths 1

Size

Total Lines 15
Code Lines 9

Duplication

Lines 14
Ratio 93.33 %

Code Coverage

Tests 8
CRAP Score 3

Importance

Changes 3
Bugs 0 Features 2
Metric Value
cc 3
eloc 9
c 3
b 0
f 2
nc 1
nop 2
dl 14
loc 15
ccs 8
cts 8
cp 1
crap 3
rs 9.4285
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
22
/**
23
 * Class CouchbaseConnection.
24
 */
25
class CouchbaseConnection extends Connection
26
{
27
    /** @var string */
28
    protected $bucket;
29
30
    /** @var \CouchbaseCluster */
31
    protected $connection;
32
33
    /** @var */
34
    protected $managerUser;
35
36
    /** @var */
37
    protected $managerPassword;
38
39
    /** @var int */
40
    protected $fetchMode = 0;
41
42
    /** @var array */
43
    protected $enableN1qlServers = [];
44
45
    /** @var string  */
46
    protected $bucketPassword = '';
47
48
    /**
49
     * @param array $config
50
     */
51 23
    public function __construct(array $config)
52
    {
53 23
        $this->connection = $this->createConnection($config);
54 23
        $this->getManagedConfigure($config);
55
56 23
        $this->useDefaultQueryGrammar();
57
58 23
        $this->useDefaultPostProcessor();
59 23
    }
60
61
    /**
62
     * @param $password
63
     *
64
     * @return $this
65
     */
66
    public function setBucketPassword($password)
67
    {
68
        $this->bucketPassword = $password;
69
70
        return $this;
71
    }
72
73
    /**
74
     * @param $name
75
     *
76
     * @return \CouchbaseBucket
77
     */
78 5
    public function openBucket($name)
79
    {
80 5
        return $this->connection->openBucket($name, $this->bucketPassword);
81
    }
82
83
    /**
84
     * @return Processor
85
     */
86 23
    protected function getDefaultPostProcessor()
87
    {
88 23
        return new Processor();
89
    }
90
91
    /**
92
     * @return Grammar
93
     */
94 23
    protected function getDefaultQueryGrammar()
95
    {
96 23
        return new Grammar();
97
    }
98
99
    /**
100
     * @param array $config
101
     */
102 23
    protected function getManagedConfigure(array $config)
103
    {
104 23
        $this->enableN1qlServers = (isset($config['enables'])) ? $config['enables'] : [];
105 23
        $manager = (isset($config['manager'])) ? $config['manager'] : null;
106 23
        if (is_null($manager)) {
107 23
            $this->managerUser = (isset($config['user'])) ? $config['user'] : null;
108 23
            $this->managerPassword = (isset($config['password'])) ? $config['password'] : null;
109
110 23
            return;
111
        }
112
        $this->managerUser = $config['manager']['user'];
113
        $this->managerPassword = $config['manager']['password'];
114
    }
115
116
    /**
117
     * @param $dsn
118
     *
119
     * @return \CouchbaseCluster
120
     */
121 23
    protected function createConnection($dsn)
122
    {
123 23
        return (new CouchbaseConnector())->connect($dsn);
124
    }
125
126
    /**
127
     * {@inheritdoc}
128
     */
129
    public function getDriverName()
130
    {
131
        return 'couchbase';
132
    }
133
134
    /**
135
     * @return \CouchbaseCluster
136
     */
137 14
    public function getCouchbase()
138
    {
139 14
        return $this->connection;
140
    }
141
142
    /**
143
     * @param string $table
144
     *
145
     * @return \Ytake\LaravelCouchbase\Database\QueryBuilder
146
     */
147 5
    public function table($table)
148
    {
149 5
        $this->bucket = $table;
150
151 5
        return $this->query()->from($table);
152
    }
153
154
    /**
155
     * @param string $bucket
156
     *
157
     * @return $this
158
     */
159
    public function bucket($bucket)
160
    {
161
        $this->bucket = $bucket;
162
163
        return $this;
164
    }
165
166
    /**
167
     * {@inheritdoc}
168
     */
169 3
    public function select($query, $bindings = [], $useReadPdo = true)
170
    {
171
        return $this->run($query, $bindings, function ($me, $query, $bindings) {
172 3
            if ($me->pretending()) {
173
                return [];
174
            }
175 3
            $query = \CouchbaseN1qlQuery::fromString($query);
176 3
            $query->options['args'] = $bindings;
177 3
            $query->consistency(\CouchbaseN1qlQuery::REQUEST_PLUS);
178 3
            $bucket = $this->openBucket($this->bucket);
179
180 3
            return $bucket->query($query);
181 3
        });
182
    }
183
184
    /**
185
     * @param string $query
186
     * @param array  $bindings
187
     *
188
     * @return int|mixed
189
     */
190 4
    public function insert($query, $bindings = [])
191
    {
192 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...
193
    }
194
195
    /**
196
     * {@inheritdoc}
197
     */
198 5 View Code Duplication
    public function affectingStatement($query, $bindings = [])
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...
199
    {
200
        return $this->run($query, $bindings, function ($me, $query, $bindings) {
201 5
            if ($me->pretending()) {
202
                return 0;
203
            }
204 5
            $query = \CouchbaseN1qlQuery::fromString($query);
205 5
            $query->consistency(\CouchbaseN1qlQuery::REQUEST_PLUS);
206
207 5
            $bucket = $this->openBucket($this->bucket);
208 5
            $result = $bucket->query($query, ['parameters' => $bindings]);
209
210 5
            return (isset($result[0])) ? $result[0] : false;
211 5
        });
212
    }
213
214
    /**
215
     * @param       $query
216
     * @param array $bindings
217
     *
218
     * @return mixed
219
     */
220 View Code Duplication
    public function positionalStatement($query, array $bindings = [])
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 5
        return $this->run($query, $bindings, function ($me, $query, $bindings) {
223 5
            if ($me->pretending()) {
224
                return 0;
225
            }
226 5
            $query = \CouchbaseN1qlQuery::fromString($query);
227 5
            $query->consistency(\CouchbaseN1qlQuery::STATEMENT_PLUS);
228 5
            $query->options['args'] = $bindings;
229 5
            $bucket = $this->openBucket($this->bucket);
230 5
            $result = $bucket->query($query);
231
232 5
            return (isset($result[0])) ? $result[0] : false;
233 5
        });
234
    }
235
236
    /**
237
     * {@inheritdoc}
238
     */
239 1
    public function transaction(Closure $callback)
240
    {
241 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...
242
    }
243
244
    /**
245
     * {@inheritdoc}
246
     */
247 1
    public function beginTransaction()
248
    {
249 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...
250
    }
251
252
    /**
253
     * {@inheritdoc}
254
     */
255 1
    public function commit()
256
    {
257 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...
258
    }
259
260
    /**
261
     * {@inheritdoc}
262
     */
263 1
    public function rollBack()
264
    {
265 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...
266
    }
267
268
    /**
269
     * {@inheritdoc}
270
     */
271 5
    protected function reconnectIfMissingConnection()
272
    {
273 5
        if (is_null($this->connection)) {
274
            $this->reconnect();
275
        }
276 5
    }
277
278
    /**
279
     * {@inheritdoc}
280
     */
281
    public function disconnect()
282
    {
283
        $this->connection = null;
284
    }
285
286
    /**
287
     * @param CouchbaseBucket $bucket
288
     *
289
     * @return CouchbaseBucket
290
     */
291
    protected function enableN1ql(CouchbaseBucket $bucket)
292
    {
293
        if (!count($this->enableN1qlServers)) {
294
            return $bucket;
295
        }
296
        $bucket->enableN1ql($this->enableN1qlServers);
297
298
        return $bucket;
299
    }
300
301
    /**
302
     * N1QL upsert query.
303
     *
304
     * @param string $query
305
     * @param array  $bindings
306
     *
307
     * @return int
308
     */
309 1
    public function upsert($query, $bindings = [])
310
    {
311 1
        return $this->affectingStatement($query, $bindings);
312
    }
313
314
    /**
315
     * Get a new query builder instance.
316
     *
317
     * @return \Illuminate\Database\Query\Builder
318
     */
319 5
    public function query()
320
    {
321 5
        return new QueryBuilder(
322 5
            $this, $this->getQueryGrammar(), $this->getPostProcessor()
323
        );
324
    }
325
326
    /**
327
     * Run an update statement against the database.
328
     *
329
     * @param string $query
330
     * @param array  $bindings
331
     *
332
     * @return int|\stdClass
333
     */
334 1
    public function update($query, $bindings = [])
335
    {
336 1
        return $this->positionalStatement($query, $bindings);
337
    }
338
339
    /**
340
     * Run a delete statement against the database.
341
     *
342
     * @param string $query
343
     * @param array  $bindings
344
     *
345
     * @return int|\stdClass
346
     */
347 5
    public function delete($query, $bindings = [])
348
    {
349 5
        return $this->positionalStatement($query, $bindings);
350
    }
351
}
352