GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.

Connection::getLastInsertId()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 1
c 2
b 0
f 0
dl 0
loc 3
rs 10
cc 1
nc 1
nop 0
1
<?php
2
/**
3
 * This file is part of the O2System Framework package.
4
 *
5
 * For the full copyright and license information, please view the LICENSE
6
 * file that was distributed with this source code.
7
 *
8
 * @author         Steeve Andrian Salim
9
 * @copyright      Copyright (c) Steeve Andrian Salim
10
 */
11
// ------------------------------------------------------------------------
12
13
namespace O2System\Database\NoSql\Drivers\MongoDb;
14
15
// ------------------------------------------------------------------------
16
17
use O2System\Database\DataStructures\Config;
18
use O2System\Database\NoSql\Abstracts\AbstractConnection;
19
use O2System\Database\NoSql\DataStructures\Query\Statement;
20
use O2System\Spl\DataStructures\SplArrayObject;
21
use O2System\Spl\Exceptions\RuntimeException;
22
23
/**
24
 * Class Connection
25
 *
26
 * @package O2System\Database\NoSql\Drivers\MongoDb
27
 */
28
class Connection extends AbstractConnection
29
{
30
    /**
31
     * Connection::$handle
32
     *
33
     * MongoDb Connection Instance.
34
     *
35
     * @var \MongoDb\Driver\Manager
36
     */
37
    public $handle;
38
    /**
39
     * Connection::$server
40
     *
41
     * MongoDb Server Instance.
42
     *
43
     * @var \MongoDb\Driver\Server
44
     */
45
    public $server;
46
    /**
47
     * Connection::$platform
48
     *
49
     * Database driver platform name.
50
     *
51
     * @var string
52
     */
53
    protected $platform = 'MongoDb';
54
55
    // ------------------------------------------------------------------------
56
57
    /**
58
     * Connection::isSupported
59
     *
60
     * Check if the platform is supported.
61
     *
62
     * @return bool
63
     */
64
    public function isSupported()
65
    {
66
        return extension_loaded('mongoDb');
67
    }
68
69
    // ------------------------------------------------------------------------
70
71
    /**
72
     * Connection::setDatabase
73
     *
74
     * Set a specific database table to use.
75
     *
76
     * @param string $database Database name.
77
     *
78
     * @return static
79
     */
80
    public function setDatabase($database)
81
    {
82
        $this->database = $database;
83
84
        return $this;
85
    }
86
87
    // ------------------------------------------------------------------------
88
89
    /**
90
     * Connection::getDatabases
91
     *
92
     * Get list of current connection databases.
93
     *
94
     * @return array
95
     */
96
    public function getDatabases()
97
    {
98
        $cursor = $this->server->executeCommand('admin', new \MongoDb\Driver\Command(['listDatabases' => 1]));
99
100
        $cursor->setTypeMap(['root' => 'array', 'document' => 'array']);
101
        $result = current($cursor->toArray());
102
103
        $this->queriesResultCache[ 'databaseNames' ] = [];
104
105
        if ( ! empty($result[ 'databases' ])) {
106
            foreach ($result[ 'databases' ] as $database) {
107
                if ( ! in_array($database[ 'name' ], ['admin', 'local'])) {
108
                    $this->queriesResultCache[ 'databaseNames' ][] = $database[ 'name' ];
109
                }
110
            }
111
        }
112
113
        return $this->queriesResultCache[ 'databaseNames' ];
114
    }
115
116
    // ------------------------------------------------------------------------
117
118
    /**
119
     * Connection::getCollections
120
     *
121
     * Get list of current database collections.
122
     *
123
     * @return array Returns an array
124
     */
125
    public function getCollections()
126
    {
127
        $cursor = $this->server->executeCommand($this->database,
128
            new \MongoDb\Driver\Command(['listCollections' => 1]));
129
        $cursor->setTypeMap(['root' => 'array', 'document' => 'array']);
130
131
        $result = new \IteratorIterator($cursor);
132
133
        $this->queriesResultCache[ 'collectionNames' ] = [];
134
135
        foreach ($result as $collection) {
136
            if ($collection[ 'type' ] === 'collection') {
137
                $this->queriesResultCache[ 'collectionNames' ][] = $collection[ 'name' ];
138
            }
139
        }
140
141
        return $this->queriesResultCache[ 'collectionNames' ];
142
    }
143
144
    // ------------------------------------------------------------------------
145
146
    /**
147
     * Connection::getKeys
148
     *
149
     * @param string $collection The database collection name.
150
     *
151
     * @return array
152
     * @throws \O2System\Spl\Exceptions\RuntimeException
153
     */
154
    public function getKeys($collection)
155
    {
156
        $cursor = $this->server->executeQuery($this->database . '.' . $collection,
157
            new \MongoDb\Driver\Query([], ['limit' => 1]));
158
159
        $result = current($cursor->toArray());
160
161
        $this->queriesResultCache[ 'collectionKeys' ][ $collection ] = [];
162
163
        foreach (get_object_vars($result) as $key => $value) {
164
            $this->queriesResultCache[ 'collectionKeys' ][ $collection ][] = $key;
165
        }
166
167
        return $this->queriesResultCache[ 'collectionKeys' ][ $collection ];
168
    }
169
170
    // ------------------------------------------------------------------------
171
172
    /**
173
     * Connection::getIndexes
174
     *
175
     * @param string $collection The database collection name.
176
     *
177
     * @return array
178
     * @throws \O2System\Spl\Exceptions\RuntimeException
179
     */
180
    public function getIndexes($collection)
181
    {
182
        $cursor = $this->server->executeCommand($this->database,
183
            new \MongoDb\Driver\Command(['listIndexes' => $collection]));
184
        $cursor->setTypeMap(['root' => 'array', 'document' => 'array']);
185
186
        $result = new \IteratorIterator($cursor);
187
188
        $this->queriesResultCache[ 'collectionIndexes' ][ $collection ] = [];
189
190
        foreach ($result as $index) {
191
            $this->queriesResultCache[ 'collectionIndexes' ][ $collection ][] = $index[ 'name' ];
192
        }
193
194
        return $this->queriesResultCache[ 'collectionIndexes' ][ $collection ];
195
    }
196
197
    // ------------------------------------------------------------------------
198
199
    /**
200
     * Connection::getAffectedDocuments
201
     *
202
     * Get the total number of affected rows from the last query execution.
203
     *
204
     * @return int  Returns total number of affected rows
205
     */
206
    public function getAffectedDocuments()
207
    {
208
        return $this->affectedDocuments;
209
    }
210
211
    // ------------------------------------------------------------------------
212
213
    /**
214
     * Connection::getLastInsertId
215
     *
216
     * Get last insert id from the last insert query execution.
217
     *
218
     * @return int  Returns total number of affected rows
219
     */
220
    public function getLastInsertId()
221
    {
222
        return $this->lastInsertId;
223
    }
224
225
    //--------------------------------------------------------------------
226
227
    /**
228
     * Connection::platformGetPlatformVersionHandler
229
     *
230
     * Platform getting version handler.
231
     *
232
     * @return SplArrayObject
233
     */
234
    protected function platformGetPlatformInfoHandler()
235
    {
236
        $metadata = $this->server->getInfo();
237
        $metadata[ 'latency' ] = $this->server->getLatency();
238
        $metadata[ 'type' ] = $this->server->getType();
239
        $metadata[ 'tags' ] = $this->server->getTags();
240
241
        return new SplArrayObject([
242
            'name'     => $this->getPlatform(),
243
            'host'     => $this->server->getHost(),
244
            'port'     => $this->server->getPort(),
245
            'metadata' => $metadata,
246
        ]);
247
    }
248
249
    // ------------------------------------------------------------------------
250
251
    /**
252
     * Connection::platformConnectHandler
253
     *
254
     * Establish the connection.
255
     *
256
     * @param Config $config
257
     *
258
     * @return void
259
     * @throws RuntimeException
260
     */
261
    protected function platformConnectHandler(Config $config)
262
    {
263
        $hostname = empty($config->hostname) ? 'localhost' : $config->hostname;
0 ignored issues
show
Bug Best Practice introduced by
The property hostname does not exist on O2System\Database\DataStructures\Config. Since you implemented __get, consider adding a @property annotation.
Loading history...
264
        $port = empty($config->port) ? 27071 : $config->port;
0 ignored issues
show
Bug Best Practice introduced by
The property port does not exist on O2System\Database\DataStructures\Config. Since you implemented __get, consider adding a @property annotation.
Loading history...
265
        $this->database = $config->database;
0 ignored issues
show
Bug Best Practice introduced by
The property database does not exist on O2System\Database\DataStructures\Config. Since you implemented __get, consider adding a @property annotation.
Loading history...
266
267
        $this->handle = new \MongoDb\Driver\Manager('mongoDb://' . $hostname . ':' . $port);
268
        $this->server = $this->handle->selectServer(new \MongoDb\Driver\ReadPreference(\MongoDb\Driver\ReadPreference::RP_PRIMARY));
269
    }
270
271
    // ------------------------------------------------------------------------
272
273
    /**
274
     * Connection::platformDisconnectHandler
275
     *
276
     * Driver dependent way method for closing the connection.
277
     *
278
     * @return mixed
279
     */
280
    protected function platformDisconnectHandler()
281
    {
282
        $this->server = null;
283
    }
284
285
    // ------------------------------------------------------------------------
286
287
    /**
288
     * Connection::platformExecuteHandler
289
     *
290
     * Driver dependent way method for execute the Sql statement.
291
     *
292
     * @param Statement $statement Query object.
293
     *
294
     * @return bool
295
     */
296
    protected function platformExecuteHandler(Statement &$statement, array $options = [])
297
    {
298
        $this->parseQueryStatement($statement);
299
300
        if (isset($options[ 'method' ])) {
301
302
            $method = $options[ 'method' ];
303
            unset($options[ 'method' ]);
304
305
            $options = array_merge(['safe' => true, 'ordered' => true], $options);
306
            $bulk = new \MongoDb\Driver\BulkWrite($options);
307
            $documents = $statement->getDocument();
308
309
            if (is_numeric(key($documents))) { // batch process
310
                foreach ($documents as $document) {
311
                    switch ($method) {
312
                        case 'insert':
313
                            $this->lastInsertId = $bulk->insert($document);
314
                            break;
315
                        case 'update':
316
                            $this->lastInsertId = $bulk->update($statement->getFilter(),
317
                                $document, $statement->getOptions());
318
                            break;
319
                        case 'delete':
320
                            $this->lastInsertId = $bulk->delete($statement->getFilter(),
321
                                $statement->getOptions());
322
                            break;
323
                    }
324
                }
325
            } else {
326
                switch ($method) {
327
                    case 'insert':
328
                        $this->lastInsertId = $bulk->insert($documents);
329
                        break;
330
                    case 'update':
331
                        $this->lastInsertId = $bulk->update($statement->getFilter(),
332
                            $documents, $statement->getOptions());
333
                        break;
334
                    case 'delete':
335
                        $this->lastInsertId = $bulk->delete($statement->getFilter(),
336
                            $statement->getOptions());
337
                        break;
338
                }
339
            }
340
341
            try {
342
                $result = $this->handle->executeBulkWrite($this->database . '.' . $statement->getCollection(),
343
                    $bulk);
344
345
                $this->lastUpsertedIds = $result->getUpsertedIds();
346
347
                switch ($method) {
348
                    case 'insert':
349
                        $this->affectedDocuments = $result->getInsertedCount();
350
                        break;
351
                    case 'update':
352
                        $this->affectedDocuments = $result->getModifiedCount();
353
                        break;
354
                    case 'delete':
355
                        $this->affectedDocuments = $result->getDeletedCount();
356
                        break;
357
                }
358
359
                return true;
360
            } catch (\MongoDb\Driver\Exception\BulkWriteException $e) {
361
                $statement->addError($e->getCode(), $e->getMessage());
362
            }
363
        }
364
365
        return false;
366
    }
367
368
    // ------------------------------------------------------------------------
369
370
    /**
371
     * Connection::parseQueryStatement
372
     *
373
     * @param  Statement $statement Query object.
374
     *
375
     * @return object
376
     */
377
    protected function parseQueryStatement(Statement &$statement)
378
    {
379
        $builderCache = $statement->getBuilderCache();
380
381
        // Projection Option
382
        if (count($builderCache->select)) {
0 ignored issues
show
Bug Best Practice introduced by
The property select does not exist on O2System\Database\NoSql\...ures\Query\BuilderCache. Since you implemented __get, consider adding a @property annotation.
Loading history...
383
384
            $projection = [];
385
386
            foreach ($builderCache->select as $field) {
387
                $projection[ $field ] = 1;
388
            }
389
390
            $statement->addOption('projection', $projection);
391
        }
392
393
        // Filter Where In
394
        if (count($builderCache->whereIn)) {
0 ignored issues
show
Bug Best Practice introduced by
The property whereIn does not exist on O2System\Database\NoSql\...ures\Query\BuilderCache. Since you implemented __get, consider adding a @property annotation.
Loading history...
395
            foreach ($builderCache->whereIn as $field => $clause) {
396
                if (count($builderCache->orWhereIn)) {
0 ignored issues
show
Bug Best Practice introduced by
The property orWhereIn does not exist on O2System\Database\NoSql\...ures\Query\BuilderCache. Since you implemented __get, consider adding a @property annotation.
Loading history...
397
                    $builderCache->orWhere[ $field ] = ['$in' => $clause];
0 ignored issues
show
Bug introduced by
The property orWhere does not seem to exist on O2System\Database\NoSql\...ures\Query\BuilderCache.
Loading history...
398
                } else {
399
                    $builderCache->where[ $field ] = ['$in' => $clause];
0 ignored issues
show
Bug introduced by
The property where does not seem to exist on O2System\Database\NoSql\...ures\Query\BuilderCache.
Loading history...
400
                }
401
            }
402
        }
403
404
        // Filter Where Not In
405
        if (count($builderCache->whereNotIn)) {
0 ignored issues
show
Bug Best Practice introduced by
The property whereNotIn does not exist on O2System\Database\NoSql\...ures\Query\BuilderCache. Since you implemented __get, consider adding a @property annotation.
Loading history...
406
            foreach ($builderCache->whereNotIn as $field => $clause) {
407
                $builderCache->where[ $field ] = ['$nin' => $clause];
408
            }
409
        }
410
411
        // Filter Or Where In
412
        if (count($builderCache->orWhereIn)) {
413
            foreach ($builderCache->orWhereIn as $field => $clause) {
414
                $builderCache->orWhere[ $field ] = ['$in' => $clause];
415
            }
416
        }
417
418
        // Filter Or Where Not In
419
        if (count($builderCache->orWhereNotIn)) {
0 ignored issues
show
Bug Best Practice introduced by
The property orWhereNotIn does not exist on O2System\Database\NoSql\...ures\Query\BuilderCache. Since you implemented __get, consider adding a @property annotation.
Loading history...
420
            foreach ($builderCache->orWhereNotIn as $field => $clause) {
421
                $builderCache->orWhere[ $field ] = ['$nin' => $clause];
422
            }
423
        }
424
425
        // Filter Where Between
426
        if (count($builderCache->between)) {
0 ignored issues
show
Bug Best Practice introduced by
The property between does not exist on O2System\Database\NoSql\...ures\Query\BuilderCache. Since you implemented __get, consider adding a @property annotation.
Loading history...
427
            foreach ($builderCache->between as $field => $clause) {
428
                $builderCache->where[ $field ] = ['$gte' => $clause[ 'start' ], '$lte' => $clause[ 'end' ]];
429
            }
430
        }
431
432
        // Filter Or Where Between
433
        if (count($builderCache->orBetween)) {
0 ignored issues
show
Bug Best Practice introduced by
The property orBetween does not exist on O2System\Database\NoSql\...ures\Query\BuilderCache. Since you implemented __get, consider adding a @property annotation.
Loading history...
434
            foreach ($builderCache->orBetween as $field => $clause) {
435
                $builderCache->orWhere[ $field ] = ['$gte' => $clause[ 'start' ], '$lte' => $clause[ 'end' ]];
436
            }
437
        }
438
439
        // Filter Where Not Between
440
        if (count($builderCache->notBetween)) {
0 ignored issues
show
Bug Best Practice introduced by
The property notBetween does not exist on O2System\Database\NoSql\...ures\Query\BuilderCache. Since you implemented __get, consider adding a @property annotation.
Loading history...
441
            foreach ($builderCache->notBetween as $field => $clause) {
442
                $builderCache->where[ $field ][ '$not' ] = [
443
                    '$gte' => $clause[ 'start' ],
444
                    '$lte' => $clause[ 'end' ],
445
                ];
446
            }
447
        }
448
449
        // Filter Or Where Not Between
450
        if (count($builderCache->orNotBetween)) {
0 ignored issues
show
Bug Best Practice introduced by
The property orNotBetween does not exist on O2System\Database\NoSql\...ures\Query\BuilderCache. Since you implemented __get, consider adding a @property annotation.
Loading history...
451
            foreach ($builderCache->orNotBetween as $field => $clause) {
452
                $builderCache->orWhere[ $field ][ '$not' ] = [
453
                    '$gte' => $clause[ 'start' ],
454
                    '$lte' => $clause[ 'end' ],
455
                ];
456
            }
457
        }
458
459
        // Filter Where
460
        if (count($builderCache->where)) {
0 ignored issues
show
Bug Best Practice introduced by
The property where does not exist on O2System\Database\NoSql\...ures\Query\BuilderCache. Since you implemented __get, consider adding a @property annotation.
Loading history...
461
            foreach ($builderCache->where as $field => $clause) {
462
                $statement->addFilter($field, $clause);
463
            }
464
        }
465
466
        // Filter Or Where
467
        if (count($builderCache->orWhere)) {
0 ignored issues
show
Bug Best Practice introduced by
The property orWhere does not exist on O2System\Database\NoSql\...ures\Query\BuilderCache. Since you implemented __get, consider adding a @property annotation.
Loading history...
468
            $orWhere = [];
469
            foreach ($builderCache->orWhere as $field => $clause) {
470
                $orWhere[] = [$field => $clause];
471
            }
472
473
            $statement->addFilter('$or', $orWhere);
0 ignored issues
show
Bug introduced by
$orWhere of type array|array<mixed,array> is incompatible with the type integer expected by parameter $value of O2System\Database\NoSql\...\Statement::addFilter(). ( Ignorable by Annotation )

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

473
            $statement->addFilter('$or', /** @scrutinizer ignore-type */ $orWhere);
Loading history...
474
        }
475
476
        // Limit Option
477
        if ($builderCache->limit > 0) {
0 ignored issues
show
Bug Best Practice introduced by
The property limit does not exist on O2System\Database\NoSql\...ures\Query\BuilderCache. Since you implemented __get, consider adding a @property annotation.
Loading history...
478
            $statement->addOption('limit', $builderCache->limit);
479
        }
480
481
        // Offset Option
482
        if ($builderCache->offset > 0) {
0 ignored issues
show
Bug Best Practice introduced by
The property offset does not exist on O2System\Database\NoSql\...ures\Query\BuilderCache. Since you implemented __get, consider adding a @property annotation.
Loading history...
483
            $statement->addOption('skip', $builderCache->offset);
484
        }
485
486
        // Order Option
487
        if (count($builderCache->orderBy)) {
0 ignored issues
show
Bug Best Practice introduced by
The property orderBy does not exist on O2System\Database\NoSql\...ures\Query\BuilderCache. Since you implemented __get, consider adding a @property annotation.
Loading history...
488
489
            $sort = [];
490
            foreach ($builderCache->orderBy as $field => $direction) {
491
                $direction = $direction === 'ASC' ? 1 : -1;
492
                $sort[ $field ] = $direction;
493
            }
494
495
            $statement->addOption('sort', $sort);
496
        }
497
498
        return $statement;
499
    }
500
501
    // ------------------------------------------------------------------------
502
503
    /**
504
     * Connection::platformQueryHandler
505
     *
506
     * Driver dependent way method for execute the Sql statement.
507
     *
508
     * @param \O2System\Database\NoSql\DataStructures\Query\Statement $statement Query object.
509
     *
510
     * @return array
511
     */
512
    protected function platformQueryHandler(Statement &$statement)
513
    {
514
        $this->parseQueryStatement($statement);
515
516
        $cursor = $this->server->executeQuery($this->database . '.' . $statement->getCollection(),
517
            new \MongoDb\Driver\Query($statement->getFilter(), $statement->getOptions()));
518
519
        return $cursor->toArray();
520
    }
521
}
522