Issues (124)

src/Database/Drivers/MongoDB.php (6 issues)

1
<?php
2
3
namespace CodexShaper\DBM\Database\Drivers;
4
5
use CodexShaper\DBM\Database\Drivers\MongoDB\Index;
6
use CodexShaper\DBM\Models\CollectionField;
7
use CodexShaper\DBM\Models\DBM_Collection;
8
use CodexShaper\DBM\Traits\MongoConnection;
9
use Illuminate\Support\Facades\DB;
10
11
class MongoDB
12
{
13
    use MongoConnection;
14
15
    /**
16
     * Run MongoDB command.
17
     *
18
     * @return  \MongoDB\Driver\Cursor
19
     */
20
    public function command(array $command)
21
    {
22
        return static::getMongoClient()->{$this->admin}->command($command);
0 ignored issues
show
Bug Best Practice introduced by
The method CodexShaper\DBM\Database...ngoDB::getMongoClient() is not static, but was called statically. ( Ignorable by Annotation )

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

22
        return static::/** @scrutinizer ignore-call */ getMongoClient()->{$this->admin}->command($command);
Loading history...
23
    }
24
25
    /**
26
     * Rename collection.
27
     *
28
     * @param   string  $fromNs
29
     * @param   string  $toNs
30
     *
31
     * @return  \MongoDB\Driver\Cursor
32
     */
33
    public function renameCollection($fromNs, $toNs)
34
    {
35
        return $this->command(['renameCollection' => $fromNs, 'to' => $toNs]);
36
    }
37
38
    /**
39
     * Rename fields.
40
     *
41
     * @param   string  $collectionName
42
     * @param   array   $fields
43
     *
44
     * @return  void
45
     */
46
    public function renameFields($collectionName, $fields)
47
    {
48
        $rename = [];
49
        foreach ($fields as $oldName => $newName) {
50
            $rename[$oldName] = $newName;
51
        }
52
        $update = [
53
            '$rename' => $rename,
54
        ];
55
56
        $this->selectCollection($collectionName)->updateMany([], $update, ['upsert' => true]);
57
    }
58
59
    /**
60
     * Get the MongoDB database object.
61
     *
62
     * @return  \MongoDB\Database
0 ignored issues
show
The type MongoDB\Database was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
63
     */
64
    public function getDB()
65
    {
66
        return DB::connection()->getMongoDB();
0 ignored issues
show
The method getMongoDB() does not exist on Illuminate\Database\ConnectionInterface. ( Ignorable by Annotation )

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

66
        return DB::connection()->/** @scrutinizer ignore-call */ getMongoDB();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
67
    }
68
69
    /**
70
     * Get the MongoDB collection namespace.
71
     *
72
     * @param   string  $databaseName
73
     * @param   string  $collectionName
74
     * @return string
75
     */
76
    public function getNamespace($databaseName, $collectionName)
77
    {
78
        return $databaseName.'.'.$collectionName;
79
    }
80
81
    /**
82
     * Get the all collections.
83
     *
84
     * @return  \MongoDB\Model\CollectionInfoIterator
0 ignored issues
show
The type MongoDB\Model\CollectionInfoIterator was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
85
     */
86
    public function getCollections()
87
    {
88
        return $this->getDB()->listCollections();
89
    }
90
91
    /**
92
     * Get the all collections name.
93
     *
94
     * @return  array
95
     */
96
    public function getCollectionNames()
97
    {
98
        $collections = $this->getCollections();
99
        $collectionNames = [];
100
        foreach ($collections as $key => $collection) {
101
            $collectionNames[] = $collection->getName();
102
        }
103
104
        return $collectionNames;
105
    }
106
107
    /**
108
     * Check MongoDB collection.
109
     *
110
     * @param   string $collectionName
111
     *
112
     * @return  bool
113
     */
114
    public function hasCollection($collectionName)
115
    {
116
        return (in_array($collectionName, $this->getCollectionNames())) ? true : false;
117
    }
118
119
    /**
120
     * Create MongoDB colelction.
121
     *
122
     * @param   string $collectionName
123
     *
124
     * @return  array|object Command result document
125
     */
126
    public function createCollection($collectionName)
127
    {
128
        return $this->getDB()->createCollection($collectionName);
129
    }
130
131
    /**
132
     * Get MongoDB colelction.
133
     *
134
     * @param   string $collectionName
135
     *
136
     * @return  array
137
     */
138
    public function getCollection($collectionName)
139
    {
140
        return [
141
            'name' => $collectionName,
142
            'oldName' => $collectionName,
143
            'columns' => $this->getColumns($collectionName),
144
            'indexes' => Index::getIndexes($this->selectCollection($collectionName)),
145
            'foreignKeys' => [],
146
            'primaryKeyName' => ['_id'],
147
            'options' => [],
148
        ];
149
    }
150
151
    /**
152
     * Update MongoDB colelction.
153
     *
154
     * @param   array $collection
155
     *
156
     * @return  bool
157
     */
158
    public function updateCollection($collection)
159
    {
160
        $newName = $collection['name'];
161
        $oldName = $collection['oldName'];
162
        $collectionName = $oldName;
163
        $connection = config('database.default');
164
        $database = config('database.connections.'.$connection.'.database');
165
        $fromNs = $this->getNamespace($database, $oldName);
166
        $toNs = $this->getNamespace($database, $newName);
167
168
        if ($newName != $oldName) {
169
            $this->renameCollection($fromNs, $toNs);
170
            $collectionName = $newName;
171
        }
172
173
        $this->setFields($collectionName, $this->getColumns($collectionName));
174
        Index::setIndexes($this->selectCollection($collectionName), $collection['indexes']);
175
176
        return true;
177
    }
178
179
    /**
180
     * Rename MongoDB colelction columns.
181
     *
182
     * @param   string $collectionName
183
     * @param   array $fields
184
     *
185
     * @return  void
186
     */
187
    public function renameColumns($collectionName, $fields)
188
    {
189
        $collection = $this->selectCollection($collectionName);
190
        $renames = [];
191
        foreach ($fields as $field) {
192
            if ($field->oldName != '') {
193
                if ($field->oldName != $field->name) {
194
                    $renames[$field->oldName] = $field->name;
195
                }
196
            }
197
        }
198
        $update = [];
199
        if ($field->oldName != '') {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $field seems to be defined by a foreach iteration on line 191. Are you sure the iterator is never empty, otherwise this variable is not defined?
Loading history...
200
            $update['$rename'] = $renames;
201
            $collection->updateMany([], $update, ['upsert' => true]);
202
            $dbmCollection = DBM_Collection::where('name', $collectionName)->first();
203
            foreach ($renames as $oldName => $newName) {
204
                $collection_field = CollectionField::where([
205
                    'dbm_collection_id' => $dbmCollection->_id,
206
                    'old_name' => $oldName,
207
                ])->first();
208
                $collection_field->old_name = $newName;
209
                $collection_field->update();
210
            }
211
        }
212
    }
213
214
    /**
215
     * Add MongoDB colelction columns.
216
     *
217
     * @param   string $collectionName
218
     *
219
     * @return  void
220
     */
221
    public function addColumns($collectionName)
222
    {
223
        $collection = $this->selectCollection($collectionName);
224
        $newFields = $this->getColumnsName($collectionName);
225
        $update = [];
226
227
        if ($collection->count() > 0) {
228
            foreach ($newFields as $newField) {
229
                $cursor = $collection->find();
230
                $iterator = iterator_to_array($cursor);
231
232
                foreach ($iterator as $document) {
233
                    $columnNames = [];
234
                    $id = '';
235
                    foreach ($document as $columnName => $columnValue) {
236
                        if (is_object($columnValue)) {
237
                            foreach ($columnValue as $key => $value) {
238
                                if ($columnName == '_id') {
239
                                    $id = $value;
240
                                }
241
                            }
242
                        }
243
                        $columnNames[] = $columnName;
244
                    }
245
246
                    if ($id != '' && ! in_array($newField, $columnNames)) {
247
                        $update['$set'] = [$newField => ''];
248
                        $collection->updateOne(
249
                            ['_id' => new \MongoDB\BSON\ObjectID($id)],
250
                            $update,
251
                            ['upsert' => true]
252
                        );
253
                    }
254
                }
255
            }
256
        }
257
    }
258
259
    /**
260
     * Remove MongoDB colelction columns.
261
     *
262
     * @param   string $collectionName
263
     *
264
     * @return  void
265
     */
266
    public function removeColumns($collectionName)
267
    {
268
        $collection = $this->selectCollection($collectionName);
269
        $newFields = $this->getColumnsName($collectionName);
270
        $columns = $this->getCollectionColumns($collectionName);
271
        $update = [];
272
        $unsets = [];
273
274
        foreach ($columns as $column) {
275
            if (! in_array($column, $newFields)) {
276
                $unsets[$column] = '';
277
            }
278
        }
279
280
        if (count($unsets) > 0) {
281
            $update['$unset'] = $unsets;
282
            $collection->updateMany([], $update, ['upsert' => true]);
283
        }
284
    }
285
286
    /**
287
     * Set MongoDB colelction fields.
288
     *
289
     * @param   string $collectionName
290
     * @param   array $fields
291
     *
292
     * @return  void
293
     */
294
    public function setFields($collectionName, $fields)
295
    {
296
        //Rename Columns
297
        $this->renameColumns($collectionName, $fields);
298
        //Add Columns
299
        $this->addColumns($collectionName);
300
        //Remove Columns
301
        $this->removeColumns($collectionName);
302
    }
303
304
    /**
305
     * Drop MongoDB colelction.
306
     *
307
     * @param   string $collectionName
308
     *
309
     * @return  void
310
     */
311
    public function dropCollection($collectionName)
312
    {
313
        $this->getDB()->dropCollection($collectionName);
314
    }
315
316
    /**
317
     * Select MongoDB colelction.
318
     *
319
     * @param   string $collectionName
320
     *
321
     * @return  \MongoDB\Collection
0 ignored issues
show
The type MongoDB\Collection was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
322
     */
323
    public function selectCollection($collectionName)
324
    {
325
        return $this->getDB()->selectCollection($collectionName);
326
    }
327
328
    /**
329
     * Get MongoDB colelction columns.
330
     *
331
     * @param   string $collectionName
332
     *
333
     * @return  array
334
     */
335
    public function getCollectionColumns($collectionName)
336
    {
337
        $cursor = $this->selectCollection($collectionName)->find();
338
        $iterator = iterator_to_array($cursor);
339
        $columnNames = [];
340
341
        foreach ($iterator as $document) {
342
            foreach ($document as $columnName => $columnValue) {
343
                $columnNames[] = $columnName;
344
            }
345
        }
346
347
        return array_values(array_unique($columnNames));
348
    }
349
350
    /**
351
     * Get MongoDB columns.
352
     *
353
     * @param   string $collectionName
354
     *
355
     * @return  array
356
     */
357
    public function getColumns($collectionName)
358
    {
359
        $columns = [];
360
361
        if ($collection = DBM_Collection::where('name', $collectionName)->first()) {
362
            $fields = $collection->fields;
363
            foreach ($fields as $field) {
364
                $columns[] = (object) [
365
                    'name' => $field->name,
366
                    'oldName' => $field->old_name,
367
                    'type' => [
368
                        'name' => $field->type,
369
                    ],
370
                    'autoincrement' => false,
371
                    'default' => null,
372
                    'length' => null,
373
                ];
374
            }
375
        } else {
376
            $fields = $this->getCollectionColumns($collectionName);
377
            foreach ($fields as $field) {
378
                $columns[] = (object) [
379
                    'name' => $field,
380
                    'oldName' => $field,
381
                    'type' => [
382
                        'name' => '',
383
                    ],
384
                    'autoincrement' => false,
385
                    'default' => null,
386
                    'length' => null,
387
                ];
388
            }
389
        }
390
391
        return $columns;
392
    }
393
394
    /**
395
     * Get colelction ColumnsName.
396
     *
397
     * @param   string $collectionName
398
     *
399
     * @return  array
400
     */
401
    public function getColumnsName($collectionName)
402
    {
403
        return DBM_Collection::where('name', $collectionName)->first()->fields->pluck('name')->toArray();
404
    }
405
}
406