Completed
Push — master ( 42aa60...7d653e )
by Bas
03:14
created

Connection::setDatabase()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 1
dl 0
loc 3
c 0
b 0
f 0
rs 10
cc 1
nc 1
nop 1
1
<?php
2
3
namespace LaravelFreelancerNL\Aranguent;
4
5
use ArangoDBClient\CollectionHandler as ArangoCollectionHandler;
6
use ArangoDBClient\Connection as ArangoConnection;
7
use ArangoDBClient\ConnectionOptions as ArangoConnectionOptions;
8
use ArangoDBClient\DocumentHandler as ArangoDocumentHandler;
9
use ArangoDBClient\Exception;
10
use ArangoDBClient\GraphHandler as ArangoGraphHandler;
11
use ArangoDBClient\Statement;
12
use ArangoDBClient\UserHandler as ArangoUserHandler;
13
use ArangoDBClient\ViewHandler as ArangoViewHandler;
14
use Illuminate\Database\Connection as IlluminateConnection;
15
use Iterator;
16
use LaravelFreelancerNL\Aranguent\Concerns\DetectsDeadlocks;
17
use LaravelFreelancerNL\Aranguent\Concerns\DetectsLostConnections;
18
use LaravelFreelancerNL\Aranguent\Concerns\ManagesTransactions;
19
use LaravelFreelancerNL\Aranguent\Query\Builder as QueryBuilder;
20
use LaravelFreelancerNL\Aranguent\Query\Grammar as QueryGrammar;
21
use LaravelFreelancerNL\Aranguent\Query\Processor;
22
use LaravelFreelancerNL\Aranguent\Schema\Builder as SchemaBuilder;
23
use LaravelFreelancerNL\FluentAQL\QueryBuilder as FluentAQL;
24
25
class Connection extends IlluminateConnection
26
{
27
    use DetectsDeadlocks,
0 ignored issues
show
Bug introduced by
The trait LaravelFreelancerNL\Aran...rns\ManagesTransactions requires the property $collections which is not provided by LaravelFreelancerNL\Aranguent\Connection.
Loading history...
28
        DetectsLostConnections,
29
        ManagesTransactions;
30
31
    /**
32
     * {@inheritdoc}
33
     *
34
     * @var array
35
     */
36
    protected $defaultConfig = [
37
        ArangoConnectionOptions::OPTION_ENDPOINT => 'tcp://localhost:8529',
38
        ArangoConnectionOptions::OPTION_CONNECTION  => 'Keep-Alive',
39
        ArangoConnectionOptions::OPTION_AUTH_USER => null,
40
        ArangoConnectionOptions::OPTION_AUTH_PASSWD => null,
41
        'tablePrefix' => '',
42
    ];
43
44
    protected $config;
45
46
    protected $arangoConnection;
47
48
    protected $readArangoConnection;
49
50
    protected $reconnector;
51
52
    protected $database;
53
54
    protected $schemaGrammar;
55
56
    protected $queryGrammar;
57
58
    protected $pretending;
59
60
    protected $recordsModified;
61
62
    protected $loggingQueries;
63
64
    protected $queryLog;
65
66
    protected $collectionHandler;
67
68
    protected $viewHandler;
69
70
    protected $documentHandler;
71
72
    protected $graphHandler;
73
74
    protected $userHandler;
75
76
    /**
77
     * The ArangoDB driver name.
78
     *
79
     * @var string
80
     */
81
    protected $driverName = 'arangodb';
82
83
    /**
84
     * Connection constructor.
85
     *
86
     * @param array $config
87
     * @throws Exception
88
     */
89
    public function __construct($config = [])
90
    {
91
        $this->config = array_merge($this->defaultConfig, $config);
92
93
        if (isset($this->config ['database'])) {
94
            $this->database = $this->config ['database'];
95
        }
96
97
        $this->tablePrefix = $this->config['tablePrefix'];
98
99
        // activate and set the database client connection
100
        $this->arangoConnection = new ArangoConnection($this->config);
101
102
        // We need to initialize a query grammar and the query post processors
103
        // which are both very important parts of the database abstractions
104
        // so we initialize these to their default values while starting.
105
        $this->useDefaultQueryGrammar();
106
107
        $this->useDefaultPostProcessor();
108
    }
109
110
    /**
111
     * Get a schema builder instance for the connection.
112
     *
113
     * @return \LaravelFreelancerNL\Aranguent\Schema\Builder
114
     */
115
    public function getSchemaBuilder()
116
    {
117
        if (is_null($this->schemaGrammar)) {
118
            $this->useDefaultSchemaGrammar();
119
        }
120
121
        return new SchemaBuilder($this);
122
    }
123
124
    /**
125
     * Get the default query grammar instance.
126
     *
127
     * @return QueryGrammar
128
     */
129
    protected function getDefaultQueryGrammar()
130
    {
131
        return new QueryGrammar;
132
    }
133
134
    /**
135
     * Get the default post processor instance.
136
     *
137
     * @return Processor
138
     */
139
    protected function getDefaultPostProcessor()
140
    {
141
        return new Processor;
142
    }
143
144
    /**
145
     * Run a select statement against the database and returns a generator.
146
     * ($useReadPdo is a dummy to adhere to the interface).
147
     *
148
     * @param string $query
149
     * @param array $bindings
150
     * @param bool $useReadPdo
151
     * @param array|null $transactionCollections
152
     * @return Iterator|null
153
     * @throws Exception
154
     */
155
    public function cursor($query, $bindings = [], $useReadPdo = null, $transactionCollections = null)
156
    {
157
        return $this->run($query, $bindings, function ($query, $bindings) use ($transactionCollections) {
158
            if ($this->pretending()) {
159
                return [];
160
            }
161
            if ($this->transactionLevel() > 0) {
162
                $this->addQueryToTransaction($query, $bindings, $transactionCollections);
163
164
                return [];
165
            }
166
167
            $statement = $this->newArangoStatement($query, $bindings);
168
169
            return $statement->execute();
170
        });
171
    }
172
173
    /**
174
     * Execute an AQL statement and return the boolean result.
175
     *
176
     * @param  string|FluentAQL  $query
177
     * @param  array   $bindings
178
     * @param  array|null   $transactionCollections
179
     * @return bool
180
     */
181
    public function statement($query, $bindings = [], $transactionCollections = null)
182
    {
183
        if ($query instanceof FluentAQL) {
184
            $bindings = $query->binds;
185
            $transactionCollections = $query->collections;
186
            $query = $query->query;
187
        }
188
189
        return $this->run($query, $bindings, function ($query, $bindings) use ($transactionCollections) {
190
            if ($this->pretending()) {
191
                return true;
192
            }
193
            if ($this->transactionLevel() > 0) {
194
                $this->addQueryToTransaction($query, $bindings, $transactionCollections);
195
196
                return true;
197
            }
198
199
            $statement = $this->newArangoStatement($query, $bindings);
200
201
            $cursor = $statement->execute();
202
203
            $affectedDocumentCount = $cursor->getWritesExecuted();
204
            $this->recordsHaveBeenModified($changed = $affectedDocumentCount > 0);
205
206
            return $changed;
207
        });
208
    }
209
210
    /**
211
     * Run an AQL statement and get the number of rows affected.
212
     *
213
     * @param  string|FluentAQL  $query
214
     * @param  array   $bindings
215
     * @param  array|null   $transactionCollections
216
     * @return int
217
     */
218
    public function affectingStatement($query, $bindings = [], $transactionCollections = null)
219
    {
220
        if ($query instanceof FluentAQL) {
221
            $bindings = $query->binds;
222
            $transactionCollections = $query->collections;
223
            $query = $query->query;
224
        }
225
226
        return $this->run($query, $bindings, function ($query, $bindings) use ($transactionCollections) {
227
            if ($this->pretending()) {
228
                return 0;
229
            }
230
            if ($this->transactionLevel() > 0) {
231
                $this->addQueryToTransaction($query, $bindings, $transactionCollections);
232
233
                return 0;
234
            }
235
236
            // For update or delete statements, we want to get the number of rows affected
237
            // by the statement and return that back to the developer. We'll first need
238
            // to execute the statement and get the executed writes from the extra.
239
            $statement = $this->newArangoStatement($query, $bindings);
240
241
            $cursor = $statement->execute();
242
243
            $affectedDocumentCount = $cursor->getWritesExecuted();
244
245
            $this->recordsHaveBeenModified($affectedDocumentCount > 0);
246
247
            return $affectedDocumentCount;
248
        });
249
    }
250
251
    /**
252
     * Run a raw, unprepared query against the connection.
253
     *
254
     * @param string $query
255
     * @return bool
256
     */
257
    public function unprepared($query)
258
    {
259
        return $this->run($query, [], function ($query) {
260
            if ($this->pretending()) {
261
                return true;
262
            }
263
            if ($this->transactionLevel() > 0) {
264
                $this->addQueryToTransaction($query);
265
266
                return [];
267
            }
268
269
            $statement = $this->newArangoStatement($query, []);
270
271
            $cursor = $statement->execute();
272
273
            $affectedDocumentCount = $cursor->getWritesExecuted();
274
275
            $change = $affectedDocumentCount > 0;
276
277
            $this->recordsHaveBeenModified($change);
278
279
            return $change;
280
        });
281
    }
282
283
    /**
284
     * Returns the query execution plan. The query will not be executed.
285
     *
286
     * @param string $query
287
     * @param array $bindings
288
     * @return array
289
     * @throws Exception
290
     */
291
    public function explain($query, $bindings = [])
292
    {
293
        $statement = $this->newArangoStatement($query, $bindings);
294
295
        return $statement->explain();
296
    }
297
298
    /**
299
     * Run a select statement against the database.
300
     *
301
     * @param string|FluentAQL $query
302
     * @param array $bindings
303
     * @param bool $useReadPdo
304
     * @param null|array $transactionCollections
305
     * @return array
306
     */
307
    public function select($query, $bindings = [], $useReadPdo = true, $transactionCollections = null)
308
    {
309
        return $this->execute($query, $bindings, $useReadPdo, $transactionCollections);
310
    }
311
312
    /**
313
     * Run an AQL query against the database and return the results.
314
     *
315
     * @param string|FluentAQL $query
316
     * @param array $bindings
317
     * @param bool $useReadPdo
318
     * @param null|array $transactionCollections
319
     * @return array
320
     */
321
    public function execute($query, $bindings = [], $useReadPdo = true, $transactionCollections = null)
0 ignored issues
show
Unused Code introduced by
The parameter $useReadPdo is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

321
    public function execute($query, $bindings = [], /** @scrutinizer ignore-unused */ $useReadPdo = true, $transactionCollections = null)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $transactionCollections is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

321
    public function execute($query, $bindings = [], $useReadPdo = true, /** @scrutinizer ignore-unused */ $transactionCollections = null)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
322
    {
323
        if ($query instanceof FluentAQL) {
324
            $bindings = $query->binds;
325
            $transactionCollections = $query->collections;
0 ignored issues
show
Unused Code introduced by
The assignment to $transactionCollections is dead and can be removed.
Loading history...
326
            $query = $query->query;
327
        }
328
329
        return $this->run($query, $bindings, function ($query, $bindings, $transactionCollections = null) {
330
            if ($this->pretending()) {
331
                return [];
332
            }
333
            if ($this->transactionLevel() > 0) {
334
                $this->addQueryToTransaction($query, $bindings, $transactionCollections);
335
336
                return [];
337
            }
338
339
            $statement = $this->newArangoStatement($query, $bindings);
340
            $cursor = $statement->execute();
341
342
            return $cursor->getAll();
343
        });
344
    }
345
346
    /**
347
     * Run an insert statement against the database.
348
     *
349
     * @param  string|FluentAQL  $query
350
     * @param  array   $bindings
351
     * @param  array|null   $transactionCollections
352
     * @return bool
353
     */
354
    public function insert($query, $bindings = [], $transactionCollections = null)
355
    {
356
        return $this->statement($query, $bindings, $transactionCollections);
357
    }
358
359
    /**
360
     * Run an update statement against the database.
361
     *
362
     * @param  string|FluentAQL  $query
363
     * @param  array   $bindings
364
     * @param  array|null   $transactionCollections
365
     * @return int
366
     */
367
    public function update($query, $bindings = [], $transactionCollections = null)
368
    {
369
        return $this->affectingStatement($query, $bindings, $transactionCollections);
370
    }
371
372
    /**
373
     * Run a delete statement against the database.
374
     *
375
     * @param  string  $query
376
     * @param  array   $bindings
377
     * @param  array|null   $transactionCollections
378
     * @return int
379
     */
380
    public function delete($query, $bindings = [], $transactionCollections = null)
381
    {
382
        return $this->affectingStatement($query, $bindings, $transactionCollections);
383
    }
384
385
    /**
386
     * Get a new query builder instance.
387
     *
388
     * @return QueryBuilder
389
     */
390
    public function query()
391
    {
392
        return new QueryBuilder(
393
            $this, $this->getQueryGrammar(), $this->getPostProcessor()
0 ignored issues
show
Bug introduced by
$this->getQueryGrammar() of type Illuminate\Database\Query\Grammars\Grammar is incompatible with the type LaravelFreelancerNL\Aranguent\Query\Grammar|null expected by parameter $grammar of LaravelFreelancerNL\Aran...\Builder::__construct(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

393
            $this, /** @scrutinizer ignore-type */ $this->getQueryGrammar(), $this->getPostProcessor()
Loading history...
394
        );
395
    }
396
397
    /**
398
     * Get the collection prefix for the connection.
399
     *
400
     * @return string
401
     */
402
    public function getTablePrefix()
403
    {
404
        return $this->tablePrefix;
405
    }
406
407
    /**
408
     * Disconnect from the underlying ArangoDB connection.
409
     *
410
     * @return void
411
     */
412
    public function disconnect()
413
    {
414
        $this->transactions = 0;
415
416
        $this->arangoConnection = null;
417
    }
418
419
    /**
420
     * Reconnect to the database if a Arango connection is missing.
421
     *
422
     * @return void
423
     */
424
    protected function reconnectIfMissingConnection()
425
    {
426
        if (is_null($this->arangoConnection)) {
427
            $this->reconnect();
428
        }
429
    }
430
431
    public function getArangoConnection()
432
    {
433
        return $this->arangoConnection;
434
    }
435
436
    /**
437
     * @param $query
438
     * @param $bindings
439
     * @param $connection
440
     * @return Statement
441
     * @throws Exception
442
     */
443
    public function newArangoStatement($query, $bindings): Statement
444
    {
445
        $statement = new Statement($this->arangoConnection, ['query' => $query, 'bindVars' => $bindings]);
446
        $statement->setDocumentClass(Document::class);
447
448
        return $statement;
449
    }
450
451
    public function getCollectionHandler()
452
    {
453
        if (! isset($this->collectionHandler)) {
454
            $this->collectionHandler = new ArangoCollectionHandler($this->arangoConnection);
455
            $this->collectionHandler->setDocumentClass(Document::class);
456
        }
457
458
        return $this->collectionHandler;
459
    }
460
461
    public function getDocumentHandler()
462
    {
463
        if (! isset($this->documentHandler)) {
464
            $this->documentHandler = new ArangoDocumentHandler($this->arangoConnection);
465
            $this->documentHandler->setDocumentClass(Document::class);
466
        }
467
468
        return $this->documentHandler;
469
    }
470
471
    public function getUserHandler()
472
    {
473
        if (! isset($this->userHandler)) {
474
            $this->userHandler = new ArangoUserHandler($this->arangoConnection);
475
            $this->userHandler->setDocumentClass(Document::class);
476
        }
477
478
        return $this->userHandler;
479
    }
480
481
    public function getGraphHandler()
482
    {
483
        if (! isset($this->graphHandler)) {
484
            $this->graphHandler = new ArangoGraphHandler($this->arangoConnection);
485
            $this->graphHandler->setDocumentClass(Document::class);
486
        }
487
488
        return $this->graphHandler;
489
    }
490
491
    public function getViewHandler()
492
    {
493
        if (! isset($this->viewHandler)) {
494
            $this->viewHandler = new ArangoViewHandler($this->arangoConnection);
495
            $this->viewHandler->setDocumentClass(Document::class);
496
        }
497
498
        return $this->viewHandler;
499
    }
500
501
    public function setDatabaseName($database)
502
    {
503
        $this->database = $database;
504
        $this->arangoConnection->setDatabase($database);
505
    }
506
507
    public function getDatabaseName()
508
    {
509
        return $this->database;
510
    }
511
}
512