Completed
Push — master ( 55ad28...46082e )
by Mr
02:03
created

Mongodb::update()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 20
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 20
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 10
nc 2
nop 3
1
<?php
2
3
namespace DrMVC\Database\Drivers;
4
5
use MongoDB\BSON\ObjectID;
6
use MongoDB\Driver\Exception\Exception as MongoException;
7
use MongoDB\Driver\Exception\InvalidArgumentException;
8
use MongoDB\Driver\Exception\RuntimeException;
9
use MongoDB\Driver\Exception\BulkWriteException;
10
use MongoDB\Driver\Manager as MongoManager;
11
use MongoDB\Driver\BulkWrite as MongoBulk;
12
use MongoDB\Driver\WriteConcern as MongoWrite;
13
use MongoDB\Driver\Command as MongoCommand;
14
use MongoDB\Driver\Query as MongoQuery;
15
use DrMVC\Database\Exception;
16
17
/**
18
 * Class for work with modern MongoDB php driver (for PHP >= 7.0)
19
 * @package DrMVC\Database\Drivers
20
 */
21
class Mongodb extends NoSQL
22
{
23
    const DEFAULT_HOST = 'localhost';
24
    const DEFAULT_PORT = '27017';
25
26
    /**
27
     * @link http://nl1.php.net/manual/en/mongodb-driver-manager.construct.php
28
     *
29
     * Additional connection string options, which will overwrite any options with
30
     * the same name in the uri parameter.
31
     */
32
    const AVAILABLE_OPTIONS = [
33
        'appname',
34
        'authMechanism',
35
        'authMechanismProperties',
36
        'authSource',
37
        'canonicalizeHostname',
38
        'compressors',
39
        'connectTimeoutMS',
40
        'gssapiServiceName',
41
        'heartbeatFrequencyMS',
42
        'journal',
43
        'localThresholdMS',
44
        'maxStalenessSeconds',
45
        'password',
46
        'readConcernLevel',
47
        'readPreference',
48
        'readPreferenceTags',
49
        'replicaSet',
50
        'retryWrites',
51
        'safe',
52
        'serverSelectionTimeoutMS',
53
        'serverSelectionTryOnce',
54
        'slaveOk',
55
        'socketCheckIntervalMS',
56
        'socketTimeoutMS',
57
        'ssl',
58
        'username',
59
        'w',
60
        'wTimeoutMS',
61
        'zlibCompressionLevel'
62
    ];
63
64
    const AVAILABLE_DRIVER_OPTIONS = [
65
        'allow_invalid_hostname',
66
        'ca_dir',
67
        'ca_file',
68
        'crl_file',
69
        'pem_file',
70
        'pem_pwd',
71
        'context',
72
        'weak_cert_validation'
73
    ];
74
75
    /**
76
     * Get current connection
77
     *
78
     * @return  MongoManager
79
     */
80
    public function getInstance(): MongoManager
81
    {
82
        return $this->_instance;
83
    }
84
85
    /**
86
     * Initiate connection with database
87
     *
88
     * @return  DriverInterface
89
     */
90
    public function connect(): DriverInterface
91
    {
92
        // URL options
93
        $options = $this->getConfig()->get();
94
95
        // Driver options
96
        $optionsDriver = $options['driver_options']->get();
97
98
        try {
99
            $connection = new MongoManager(
100
                $this->getDsn(),
101
                $this->getOptions($options, self::AVAILABLE_OPTIONS),
102
                $this->getOptions($optionsDriver, self::AVAILABLE_DRIVER_OPTIONS)
103
            );
104
            $this->setInstance($connection);
105
106
        } catch (RuntimeException $e) {
107
            new Exception('Unable to connect');
108
        } catch (InvalidArgumentException $e) {
109
            new Exception('Invalid argument provided');
110
        }
111
112
        return $this;
113
    }
114
115
    /**
116
     * Generate DSN by parameters in config
117
     *
118
     * @param   array $config
119
     * @return  string
120
     */
121
    public function genDsn($config): string
122
    {
123
        // Get driver of connection
124
        $driver = strtolower($config['driver']);
125
        $url = $config['url'];
126
127
        return "$driver://$url";
128
    }
129
130
    /**
131
     * Generate options array
132
     *
133
     * @param   array $options
134
     * @param   array $allowed
135
     * @return  array
136
     */
137
    private function getOptions(array $options, array $allowed): array
138
    {
139
        $result = [];
140
        foreach ($options as $key => $value) {
141
            if (\in_array($key, $allowed, false)) {
142
                $result[$key] = $value;
143
            }
144
        }
145
        return $result;
146
    }
147
148
    /**
149
     * @return MongoBulk
150
     */
151
    private function getBulk(): MongoBulk
152
    {
153
        try {
154
            $bulk = new MongoBulk();
155
        } catch (InvalidArgumentException $e) {
156
            new Exception('Unable to create Bulk object');
157
        }
158
        return $bulk;
159
    }
160
161
    /**
162
     * @return ObjectID
163
     */
164
    private function getID(): ObjectID
165
    {
166
        try {
167
            $objectID = new ObjectID();
168
        } catch (InvalidArgumentException $e) {
169
            new Exception('ObjectID could not to be generated');
170
        }
171
        return $objectID;
172
    }
173
174
    /**
175
     * @return MongoWrite
176
     */
177
    private function getWrite(): MongoWrite
178
    {
179
        try {
180
            $write = new MongoWrite(MongoWrite::MAJORITY, 1000);
181
        } catch (InvalidArgumentException $e) {
182
            new Exception('WriteConcern could not to be initiated');
183
        }
184
        return $write;
185
    }
186
187
    /**
188
     * Insert in database and return of inserted element
189
     *
190
     * @param   array $data array of columns and values
191
     * @return  mixed
192
     */
193
    public function insert(array $data): string
194
    {
195
        // Set bulk object
196
        $bulk = $this->getBulk();
197
198
        // Set object ID as id of item
199
        $data['_id'] = $this->getID();
200
201
        // Set statement
202
        $bulk->insert($data);
203
204
        try {
205
            $this->getInstance()->executeBulkWrite(
206
                $this->getParam('database') . '.' . $this->getCollection(),
207
                $bulk,
208
                $this->getWrite()
209
            );
210
211
        } catch (BulkWriteException $e) {
212
            new Exception('Unable to write in database');
213
        }
214
215
        return (string) $data['_id'];
216
    }
217
218
    /**
219
     * Create query object from filter and option arrays
220
     *
221
     * @param   array $where
222
     * @param   array $options
223
     * @return  MongoQuery
224
     */
225
    private function getQuery(array $where, array $options): MongoQuery
226
    {
227
        try {
228
            $query = new MongoQuery($where, $options);
229
        } catch (InvalidArgumentException $e) {
230
            new Exception('WriteConcern could not to be initiated');
231
        }
232
        return $query;
233
    }
234
235
    /**
236
     * Execute MongoQuery
237
     *
238
     * @param   array $filter
239
     * @param   array $options
240
     * @return  mixed
241
     */
242
    public function select(array $filter = [], array $options = [])
243
    {
244
        // Create query object from filter and option arrays
245
        $query = $this->getQuery($filter, $options);
246
247
        try {
248
            $cursor = $this->getInstance()->executeQuery(
249
                $this->getParam('database') . '.' . $this->getCollection(),
250
                $query
251
            );
252
            $response = $cursor->toArray();
253
254
        } catch (MongoException $e) {
255
            new Exception('Unable to execute query');
256
        }
257
258
        return $response;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $response does not seem to be defined for all execution paths leading up to this point.
Loading history...
259
    }
260
261
    /**
262
     * Update data in database
263
     *
264
     * @param   array $data
265
     * @param   array $filter
266
     * @param   array $updateOptions
267
     * @return  mixed
268
     */
269
    public function update(array $data, array $filter = [], array $updateOptions = [])
270
    {
271
        // Set bulk object
272
        $bulk = $this->getBulk();
273
274
        // Set statement
275
        $bulk->update($filter, $data, $updateOptions);
276
277
        try {
278
            $response = $this->getInstance()->executeBulkWrite(
279
                $this->getParam('database') . '.' . $this->getCollection(),
280
                $bulk,
281
                $this->getWrite()
282
            );
283
284
        } catch (BulkWriteException $e) {
285
            new Exception('Unable to write in database');
286
        }
287
288
        return $response;
289
    }
290
291
    /**
292
     * Delete data from table/collection
293
     *
294
     * @param   array $filter
295
     * @param   array $deleteOptions
296
     * @return  mixed
297
     */
298
    public function delete(array $filter, array $deleteOptions = [])
299
    {
300
        // Set bulk object
301
        $bulk = $this->getBulk();
302
303
        // Set statement
304
        $bulk->delete($filter, $deleteOptions);
305
306
        try {
307
            $response = $this->getInstance()->executeBulkWrite(
308
                $this->getParam('database') . '.' . $this->getCollection(),
309
                $bulk,
310
                $this->getWrite()
311
            );
312
313
        } catch (BulkWriteException $e) {
314
            new Exception('Unable to write in database');
315
        }
316
317
        return $response;
318
    }
319
320
    /**
321
     * Create command from query
322
     *
323
     * @param   array $query
324
     * @return  MongoCommand
325
     */
326
    private function getCommand($query): MongoCommand
327
    {
328
        try {
329
            $command = new MongoCommand($query);
330
        } catch (InvalidArgumentException $e) {
331
            new Exception('WriteConcern could not to be initiated');
332
        }
333
        return $command;
334
    }
335
336
    /**
337
     * Execute MongoCommand
338
     *
339
     * @param   array $query should be like new MongoDB\Driver\Query($filter, $options);
340
     * @return  mixed
341
     */
342
    public function command(array $query)
343
    {
344
        // Create command from query
345
        $command = $this->getCommand($query);
346
347
        try {
348
            $cursor = $this->getInstance()->executeCommand(
349
                $this->getParam('database'),
350
                $command
351
            );
352
            $response = $cursor->toArray();
353
354
        } catch (MongoException $e) {
355
            new Exception('Unable to execute command');
356
        }
357
358
        return $response;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $response does not seem to be defined for all execution paths leading up to this point.
Loading history...
359
    }
360
361
}
362