1
|
|
|
<?php |
2
|
|
|
/* |
3
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
4
|
|
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
5
|
|
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
6
|
|
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
7
|
|
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
8
|
|
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
9
|
|
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
10
|
|
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
11
|
|
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
12
|
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
13
|
|
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
14
|
|
|
*/ |
15
|
|
|
|
16
|
|
|
if (class_exists('MongoDB', false)) { |
17
|
|
|
return; |
18
|
|
|
} |
19
|
|
|
|
20
|
|
|
use Alcaeus\MongoDbAdapter\Helper; |
21
|
|
|
use Alcaeus\MongoDbAdapter\TypeConverter; |
22
|
|
|
use Alcaeus\MongoDbAdapter\ExceptionConverter; |
23
|
|
|
use MongoDB\Model\CollectionInfo; |
24
|
|
|
|
25
|
|
|
/** |
26
|
|
|
* Instances of this class are used to interact with a database. |
27
|
|
|
* @link http://www.php.net/manual/en/class.mongodb.php |
28
|
|
|
*/ |
29
|
|
|
class MongoDB |
30
|
|
|
{ |
31
|
|
|
use Helper\ReadPreference; |
32
|
|
|
use Helper\SlaveOkay; |
33
|
|
|
use Helper\WriteConcern; |
34
|
|
|
|
35
|
|
|
const PROFILING_OFF = 0; |
36
|
|
|
const PROFILING_SLOW = 1; |
37
|
|
|
const PROFILING_ON = 2; |
38
|
|
|
|
39
|
|
|
/** |
40
|
|
|
* @var MongoClient |
41
|
|
|
*/ |
42
|
|
|
protected $connection; |
43
|
|
|
|
44
|
|
|
/** |
45
|
|
|
* @var \MongoDB\Database |
46
|
|
|
*/ |
47
|
|
|
protected $db; |
48
|
|
|
|
49
|
|
|
/** |
50
|
|
|
* @var string |
51
|
|
|
*/ |
52
|
|
|
protected $name; |
53
|
|
|
|
54
|
|
|
/** |
55
|
|
|
* Creates a new database |
56
|
|
|
* |
57
|
|
|
* This method is not meant to be called directly. The preferred way to create an instance of MongoDB is through {@see Mongo::__get()} or {@see Mongo::selectDB()}. |
58
|
|
|
* @link http://www.php.net/manual/en/mongodb.construct.php |
59
|
|
|
* @param MongoClient $conn Database connection. |
60
|
|
|
* @param string $name Database name. |
61
|
|
|
* @throws Exception |
62
|
|
|
*/ |
63
|
|
|
public function __construct(MongoClient $conn, $name) |
64
|
|
|
{ |
65
|
|
|
$this->checkDatabaseName($name); |
66
|
|
|
$this->connection = $conn; |
67
|
|
|
$this->name = (string) $name; |
68
|
|
|
|
69
|
|
|
$this->setReadPreferenceFromArray($conn->getReadPreference()); |
70
|
|
|
$this->setWriteConcernFromArray($conn->getWriteConcern()); |
71
|
|
|
|
72
|
|
|
$this->createDatabaseObject(); |
73
|
|
|
} |
74
|
|
|
|
75
|
|
|
/** |
76
|
|
|
* @return \MongoDB\Database |
77
|
|
|
* @internal This method is not part of the ext-mongo API |
78
|
|
|
*/ |
79
|
|
|
public function getDb() |
80
|
|
|
{ |
81
|
|
|
return $this->db; |
82
|
|
|
} |
83
|
|
|
|
84
|
|
|
/** |
85
|
|
|
* The name of this database |
86
|
|
|
* |
87
|
|
|
* @link http://www.php.net/manual/en/mongodb.--tostring.php |
88
|
|
|
* @return string Returns this database's name. |
89
|
|
|
*/ |
90
|
|
|
public function __toString() |
91
|
|
|
{ |
92
|
|
|
return $this->name; |
93
|
|
|
} |
94
|
|
|
|
95
|
|
|
/** |
96
|
|
|
* Gets a collection |
97
|
|
|
* |
98
|
|
|
* @link http://www.php.net/manual/en/mongodb.get.php |
99
|
|
|
* @param string $name The name of the collection. |
100
|
|
|
* @return MongoCollection |
101
|
|
|
*/ |
102
|
|
|
public function __get($name) |
103
|
|
|
{ |
104
|
|
|
// Handle w and wtimeout properties that replicate data stored in $readPreference |
105
|
|
|
if ($name === 'w' || $name === 'wtimeout') { |
106
|
|
|
return $this->getWriteConcern()[$name]; |
107
|
|
|
} |
108
|
|
|
|
109
|
|
|
return $this->selectCollection($name); |
110
|
|
|
} |
111
|
|
|
|
112
|
|
|
/** |
113
|
|
|
* @param string $name |
114
|
|
|
* @param mixed $value |
115
|
|
|
*/ |
116
|
|
|
public function __set($name, $value) |
117
|
|
|
{ |
118
|
|
|
if ($name === 'w' || $name === 'wtimeout') { |
119
|
|
|
trigger_error("The '{$name}' property is read-only", E_USER_DEPRECATED); |
120
|
|
|
} |
121
|
|
|
} |
122
|
|
|
|
123
|
|
|
/** |
124
|
|
|
* Returns information about collections in this database |
125
|
|
|
* |
126
|
|
|
* @link http://www.php.net/manual/en/mongodb.getcollectioninfo.php |
127
|
|
|
* @param array $options An array of options for listing the collections. |
128
|
|
|
* @return array |
129
|
|
|
*/ |
130
|
|
|
public function getCollectionInfo(array $options = []) |
131
|
|
|
{ |
132
|
|
|
$includeSystemCollections = false; |
133
|
|
|
// The includeSystemCollections option is no longer supported in the command |
134
|
|
|
if (isset($options['includeSystemCollections'])) { |
135
|
|
|
$includeSystemCollections = $options['includeSystemCollections']; |
136
|
|
|
unset($options['includeSystemCollections']); |
137
|
|
|
} |
138
|
|
|
|
139
|
|
|
try { |
140
|
|
|
$collections = $this->db->listCollections($options); |
141
|
|
|
} catch (\MongoDB\Driver\Exception\Exception $e) { |
142
|
|
|
throw ExceptionConverter::toLegacy($e); |
143
|
|
|
} |
144
|
|
|
|
145
|
|
|
$getCollectionInfo = function (CollectionInfo $collectionInfo) { |
146
|
|
|
// @todo do away with __debugInfo once https://jira.mongodb.org/browse/PHPLIB-226 is fixed |
147
|
|
|
$info = $collectionInfo->__debugInfo(); |
148
|
|
|
|
149
|
|
|
return array_filter( |
150
|
|
|
[ |
151
|
|
|
'name' => $collectionInfo->getName(), |
152
|
|
|
'type' => isset($info['type']) ? $info['type'] : null, |
153
|
|
|
'options' => $collectionInfo->getOptions(), |
154
|
|
|
'info' => isset($info['info']) ? (array) $info['info'] : null, |
155
|
|
|
'idIndex' => isset($info['idIndex']) ? (array) $info['idIndex'] : null, |
156
|
|
|
], |
157
|
|
|
function ($item) { |
158
|
|
|
return $item !== null; |
159
|
|
|
} |
160
|
|
|
); |
161
|
|
|
}; |
162
|
|
|
|
163
|
|
|
$eligibleCollections = array_filter( |
164
|
|
|
iterator_to_array($collections), |
165
|
|
|
$this->getSystemCollectionFilterClosure($includeSystemCollections) |
166
|
|
|
); |
167
|
|
|
|
168
|
|
|
return array_map($getCollectionInfo, $eligibleCollections); |
169
|
|
|
} |
170
|
|
|
|
171
|
|
|
/** |
172
|
|
|
* Get all collections from this database |
173
|
|
|
* |
174
|
|
|
* @link http://www.php.net/manual/en/mongodb.getcollectionnames.php |
175
|
|
|
* @param array $options An array of options for listing the collections. |
176
|
|
|
* @return array Returns the names of the all the collections in the database as an array |
177
|
|
|
*/ |
178
|
|
|
public function getCollectionNames(array $options = []) |
179
|
|
|
{ |
180
|
|
|
$includeSystemCollections = false; |
181
|
|
|
// The includeSystemCollections option is no longer supported in the command |
182
|
|
|
if (isset($options['includeSystemCollections'])) { |
183
|
|
|
$includeSystemCollections = $options['includeSystemCollections']; |
184
|
|
|
unset($options['includeSystemCollections']); |
185
|
|
|
} |
186
|
|
|
|
187
|
|
|
try { |
188
|
|
|
$collections = $this->db->listCollections($options); |
189
|
|
|
} catch (\MongoDB\Driver\Exception\Exception $e) { |
190
|
|
|
throw ExceptionConverter::toLegacy($e); |
191
|
|
|
} |
192
|
|
|
|
193
|
|
|
$getCollectionName = function (CollectionInfo $collectionInfo) { |
194
|
|
|
return $collectionInfo->getName(); |
195
|
|
|
}; |
196
|
|
|
|
197
|
|
|
$eligibleCollections = array_filter( |
198
|
|
|
iterator_to_array($collections), |
199
|
|
|
$this->getSystemCollectionFilterClosure($includeSystemCollections) |
200
|
|
|
); |
201
|
|
|
|
202
|
|
|
return array_map($getCollectionName, $eligibleCollections); |
203
|
|
|
} |
204
|
|
|
|
205
|
|
|
/** |
206
|
|
|
* @return MongoClient |
207
|
|
|
* @internal This method is not part of the ext-mongo API |
208
|
|
|
*/ |
209
|
|
|
public function getConnection() |
210
|
|
|
{ |
211
|
|
|
return $this->connection; |
212
|
|
|
} |
213
|
|
|
|
214
|
|
|
/** |
215
|
|
|
* Fetches toolkit for dealing with files stored in this database |
216
|
|
|
* |
217
|
|
|
* @link http://www.php.net/manual/en/mongodb.getgridfs.php |
218
|
|
|
* @param string $prefix The prefix for the files and chunks collections. |
219
|
|
|
* @return MongoGridFS Returns a new gridfs object for this database. |
220
|
|
|
*/ |
221
|
|
|
public function getGridFS($prefix = "fs") |
222
|
|
|
{ |
223
|
|
|
return new \MongoGridFS($this, $prefix); |
224
|
|
|
} |
225
|
|
|
|
226
|
|
|
/** |
227
|
|
|
* Gets this database's profiling level |
228
|
|
|
* |
229
|
|
|
* @link http://www.php.net/manual/en/mongodb.getprofilinglevel.php |
230
|
|
|
* @return int Returns the profiling level. |
231
|
|
|
*/ |
232
|
|
|
public function getProfilingLevel() |
233
|
|
|
{ |
234
|
|
|
$result = $this->command(['profile' => -1]); |
235
|
|
|
|
236
|
|
|
return ($result['ok'] && isset($result['was'])) ? $result['was'] : 0; |
237
|
|
|
} |
238
|
|
|
|
239
|
|
|
/** |
240
|
|
|
* Sets this database's profiling level |
241
|
|
|
* |
242
|
|
|
* @link http://www.php.net/manual/en/mongodb.setprofilinglevel.php |
243
|
|
|
* @param int $level Profiling level. |
244
|
|
|
* @return int Returns the previous profiling level. |
245
|
|
|
*/ |
246
|
|
|
public function setProfilingLevel($level) |
247
|
|
|
{ |
248
|
|
|
$result = $this->command(['profile' => $level]); |
249
|
|
|
|
250
|
|
|
return ($result['ok'] && isset($result['was'])) ? $result['was'] : 0; |
251
|
|
|
} |
252
|
|
|
|
253
|
|
|
/** |
254
|
|
|
* Drops this database |
255
|
|
|
* |
256
|
|
|
* @link http://www.php.net/manual/en/mongodb.drop.php |
257
|
|
|
* @return array Returns the database response. |
258
|
|
|
*/ |
259
|
|
|
public function drop() |
260
|
|
|
{ |
261
|
|
|
return TypeConverter::toLegacy($this->db->drop()); |
262
|
|
|
} |
263
|
|
|
|
264
|
|
|
/** |
265
|
|
|
* Repairs and compacts this database |
266
|
|
|
* |
267
|
|
|
* @link http://www.php.net/manual/en/mongodb.repair.php |
268
|
|
|
* @param bool $preserve_cloned_files [optional] <p>If cloned files should be kept if the repair fails.</p> |
269
|
|
|
* @param bool $backup_original_files [optional] <p>If original files should be backed up.</p> |
270
|
|
|
* @return array <p>Returns db response.</p> |
271
|
|
|
*/ |
272
|
|
|
public function repair($preserve_cloned_files = false, $backup_original_files = false) |
273
|
|
|
{ |
274
|
|
|
$command = [ |
275
|
|
|
'repairDatabase' => 1, |
276
|
|
|
'preserveClonedFilesOnFailure' => $preserve_cloned_files, |
277
|
|
|
'backupOriginalFiles' => $backup_original_files, |
278
|
|
|
]; |
279
|
|
|
|
280
|
|
|
return $this->command($command); |
281
|
|
|
} |
282
|
|
|
|
283
|
|
|
/** |
284
|
|
|
* Gets a collection |
285
|
|
|
* |
286
|
|
|
* @link http://www.php.net/manual/en/mongodb.selectcollection.php |
287
|
|
|
* @param string $name <b>The collection name.</b> |
288
|
|
|
* @throws Exception if the collection name is invalid. |
289
|
|
|
* @return MongoCollection Returns a new collection object. |
290
|
|
|
*/ |
291
|
|
|
public function selectCollection($name) |
292
|
|
|
{ |
293
|
|
|
return new MongoCollection($this, $name); |
294
|
|
|
} |
295
|
|
|
|
296
|
|
|
/** |
297
|
|
|
* Creates a collection |
298
|
|
|
* |
299
|
|
|
* @link http://www.php.net/manual/en/mongodb.createcollection.php |
300
|
|
|
* @param string $name The name of the collection. |
301
|
|
|
* @param array $options |
302
|
|
|
* @return MongoCollection Returns a collection object representing the new collection. |
303
|
|
|
*/ |
304
|
|
|
public function createCollection($name, $options = []) |
305
|
|
|
{ |
306
|
|
|
try { |
307
|
|
|
if (isset($options['capped'])) { |
308
|
|
|
$options['capped'] = (bool) $options['capped']; |
309
|
|
|
} |
310
|
|
|
|
311
|
|
|
$this->db->createCollection($name, $options); |
312
|
|
|
} catch (\MongoDB\Driver\Exception\Exception $e) { |
313
|
|
|
return false; |
|
|
|
|
314
|
|
|
} |
315
|
|
|
|
316
|
|
|
return $this->selectCollection($name); |
317
|
|
|
} |
318
|
|
|
|
319
|
|
|
/** |
320
|
|
|
* Drops a collection |
321
|
|
|
* |
322
|
|
|
* @link http://www.php.net/manual/en/mongodb.dropcollection.php |
323
|
|
|
* @param MongoCollection|string $coll MongoCollection or name of collection to drop. |
324
|
|
|
* @return array Returns the database response. |
325
|
|
|
* |
326
|
|
|
* @deprecated Use MongoCollection::drop() instead. |
327
|
|
|
*/ |
328
|
|
|
public function dropCollection($coll) |
329
|
|
|
{ |
330
|
|
|
if ($coll instanceof MongoCollection) { |
331
|
|
|
$coll = $coll->getName(); |
332
|
|
|
} |
333
|
|
|
|
334
|
|
|
return TypeConverter::toLegacy($this->db->dropCollection((string) $coll)); |
335
|
|
|
} |
336
|
|
|
|
337
|
|
|
/** |
338
|
|
|
* Get a list of collections in this database |
339
|
|
|
* |
340
|
|
|
* @link http://www.php.net/manual/en/mongodb.listcollections.php |
341
|
|
|
* @param array $options |
342
|
|
|
* @return MongoCollection[] Returns a list of MongoCollections. |
343
|
|
|
*/ |
344
|
|
|
public function listCollections(array $options = []) |
345
|
|
|
{ |
346
|
|
|
return array_map([$this, 'selectCollection'], $this->getCollectionNames($options)); |
347
|
|
|
} |
348
|
|
|
|
349
|
|
|
/** |
350
|
|
|
* Creates a database reference |
351
|
|
|
* |
352
|
|
|
* @link http://www.php.net/manual/en/mongodb.createdbref.php |
353
|
|
|
* @param string $collection The collection to which the database reference will point. |
354
|
|
|
* @param mixed $document_or_id |
355
|
|
|
* @return array Returns a database reference array. |
356
|
|
|
*/ |
357
|
|
|
public function createDBRef($collection, $document_or_id) |
358
|
|
|
{ |
359
|
|
View Code Duplication |
if ($document_or_id instanceof \MongoId) { |
|
|
|
|
360
|
|
|
$id = $document_or_id; |
361
|
|
|
} elseif (is_object($document_or_id)) { |
362
|
|
|
if (! isset($document_or_id->_id)) { |
363
|
|
|
$id = $document_or_id; |
364
|
|
|
} else { |
365
|
|
|
$id = $document_or_id->_id; |
366
|
|
|
} |
367
|
|
|
} elseif (is_array($document_or_id)) { |
368
|
|
|
if (! isset($document_or_id['_id'])) { |
369
|
|
|
return null; |
370
|
|
|
} |
371
|
|
|
|
372
|
|
|
$id = $document_or_id['_id']; |
373
|
|
|
} else { |
374
|
|
|
$id = $document_or_id; |
375
|
|
|
} |
376
|
|
|
|
377
|
|
|
return MongoDBRef::create($collection, $id); |
378
|
|
|
} |
379
|
|
|
|
380
|
|
|
|
381
|
|
|
/** |
382
|
|
|
* Fetches the document pointed to by a database reference |
383
|
|
|
* |
384
|
|
|
* @link http://www.php.net/manual/en/mongodb.getdbref.php |
385
|
|
|
* @param array $ref A database reference. |
386
|
|
|
* @return array Returns the document pointed to by the reference. |
387
|
|
|
*/ |
388
|
|
|
public function getDBRef(array $ref) |
389
|
|
|
{ |
390
|
|
|
$db = (isset($ref['$db']) && $ref['$db'] !== $this->name) ? $this->connection->selectDB($ref['$db']) : $this; |
391
|
|
|
return MongoDBRef::get($db, $ref); |
392
|
|
|
} |
393
|
|
|
|
394
|
|
|
/** |
395
|
|
|
* Runs JavaScript code on the database server. |
396
|
|
|
* |
397
|
|
|
* @link http://www.php.net/manual/en/mongodb.execute.php |
398
|
|
|
* @param MongoCode|string $code Code to execute. |
399
|
|
|
* @param array $args [optional] Arguments to be passed to code. |
400
|
|
|
* @return array Returns the result of the evaluation. |
401
|
|
|
*/ |
402
|
|
|
public function execute($code, array $args = []) |
403
|
|
|
{ |
404
|
|
|
return $this->command(['eval' => $code, 'args' => $args]); |
405
|
|
|
} |
406
|
|
|
|
407
|
|
|
/** |
408
|
|
|
* Execute a database command |
409
|
|
|
* |
410
|
|
|
* @link http://www.php.net/manual/en/mongodb.command.php |
411
|
|
|
* @param array $data The query to send. |
412
|
|
|
* @param array $options |
413
|
|
|
* @return array Returns database response. |
414
|
|
|
*/ |
415
|
|
|
public function command(array $data, $options = [], &$hash = null) |
|
|
|
|
416
|
|
|
{ |
417
|
|
|
try { |
418
|
|
|
$cursor = new \MongoCommandCursor($this->connection, $this->name, $data); |
419
|
|
|
$cursor->setReadPreference($this->getReadPreference()); |
|
|
|
|
420
|
|
|
|
421
|
|
|
return iterator_to_array($cursor)[0]; |
422
|
|
|
} catch (\MongoDB\Driver\Exception\Exception $e) { |
423
|
|
|
return ExceptionConverter::toResultArray($e); |
424
|
|
|
} |
425
|
|
|
} |
426
|
|
|
|
427
|
|
|
/** |
428
|
|
|
* Check if there was an error on the most recent db operation performed |
429
|
|
|
* |
430
|
|
|
* @link http://www.php.net/manual/en/mongodb.lasterror.php |
431
|
|
|
* @return array Returns the error, if there was one. |
432
|
|
|
*/ |
433
|
|
|
public function lastError() |
434
|
|
|
{ |
435
|
|
|
return $this->command(array('getLastError' => 1)); |
436
|
|
|
} |
437
|
|
|
|
438
|
|
|
/** |
439
|
|
|
* Checks for the last error thrown during a database operation |
440
|
|
|
* |
441
|
|
|
* @link http://www.php.net/manual/en/mongodb.preverror.php |
442
|
|
|
* @return array Returns the error and the number of operations ago it occurred. |
443
|
|
|
*/ |
444
|
|
|
public function prevError() |
445
|
|
|
{ |
446
|
|
|
return $this->command(array('getPrevError' => 1)); |
447
|
|
|
} |
448
|
|
|
|
449
|
|
|
/** |
450
|
|
|
* Clears any flagged errors on the database |
451
|
|
|
* |
452
|
|
|
* @link http://www.php.net/manual/en/mongodb.reseterror.php |
453
|
|
|
* @return array Returns the database response. |
454
|
|
|
*/ |
455
|
|
|
public function resetError() |
456
|
|
|
{ |
457
|
|
|
return $this->command(array('resetError' => 1)); |
458
|
|
|
} |
459
|
|
|
|
460
|
|
|
/** |
461
|
|
|
* Creates a database error |
462
|
|
|
* |
463
|
|
|
* @link http://www.php.net/manual/en/mongodb.forceerror.php |
464
|
|
|
* @return boolean Returns the database response. |
465
|
|
|
*/ |
466
|
|
|
public function forceError() |
467
|
|
|
{ |
468
|
|
|
return $this->command(array('forceerror' => 1)); |
469
|
|
|
} |
470
|
|
|
|
471
|
|
|
/** |
472
|
|
|
* Log in to this database |
473
|
|
|
* |
474
|
|
|
* @link http://www.php.net/manual/en/mongodb.authenticate.php |
475
|
|
|
* @param string $username The username. |
476
|
|
|
* @param string $password The password (in plaintext). |
477
|
|
|
* @return array Returns database response. If the login was successful, it will return 1. |
478
|
|
|
* |
479
|
|
|
* @deprecated This method is not implemented, supply authentication credentials through the connection string instead. |
480
|
|
|
*/ |
481
|
|
|
public function authenticate($username, $password) |
|
|
|
|
482
|
|
|
{ |
483
|
|
|
throw new \Exception('The MongoDB::authenticate method is not supported. Please supply authentication credentials through the connection string'); |
484
|
|
|
} |
485
|
|
|
|
486
|
|
|
/** |
487
|
|
|
* {@inheritdoc} |
488
|
|
|
*/ |
489
|
|
|
public function setReadPreference($readPreference, $tags = null) |
490
|
|
|
{ |
491
|
|
|
$result = $this->setReadPreferenceFromParameters($readPreference, $tags); |
492
|
|
|
$this->createDatabaseObject(); |
493
|
|
|
|
494
|
|
|
return $result; |
495
|
|
|
} |
496
|
|
|
|
497
|
|
|
/** |
498
|
|
|
* {@inheritdoc} |
499
|
|
|
*/ |
500
|
|
|
public function setWriteConcern($wstring, $wtimeout = 0) |
501
|
|
|
{ |
502
|
|
|
$result = $this->setWriteConcernFromParameters($wstring, $wtimeout); |
503
|
|
|
$this->createDatabaseObject(); |
504
|
|
|
|
505
|
|
|
return $result; |
506
|
|
|
} |
507
|
|
|
|
508
|
|
|
protected function notImplemented() |
509
|
|
|
{ |
510
|
|
|
throw new \Exception('Not implemented'); |
511
|
|
|
} |
512
|
|
|
|
513
|
|
|
/** |
514
|
|
|
* @return \MongoDB\Database |
515
|
|
|
*/ |
516
|
|
View Code Duplication |
private function createDatabaseObject() |
|
|
|
|
517
|
|
|
{ |
518
|
|
|
$options = [ |
519
|
|
|
'readPreference' => $this->readPreference, |
520
|
|
|
'writeConcern' => $this->writeConcern, |
521
|
|
|
]; |
522
|
|
|
|
523
|
|
|
if ($this->db === null) { |
524
|
|
|
$this->db = $this->connection->getClient()->selectDatabase($this->name, $options); |
525
|
|
|
} else { |
526
|
|
|
$this->db = $this->db->withOptions($options); |
527
|
|
|
} |
528
|
|
|
} |
529
|
|
|
|
530
|
|
|
private function checkDatabaseName($name) |
531
|
|
|
{ |
532
|
|
|
if (empty($name)) { |
533
|
|
|
throw new \Exception('Database name cannot be empty'); |
534
|
|
|
} |
535
|
|
|
if (strlen($name) >= 64) { |
536
|
|
|
throw new \Exception('Database name cannot exceed 63 characters'); |
537
|
|
|
} |
538
|
|
|
if (strpos($name, chr(0)) !== false) { |
539
|
|
|
throw new \Exception('Database name cannot contain null bytes'); |
540
|
|
|
} |
541
|
|
|
|
542
|
|
|
$invalidCharacters = ['.', '$', '/', ' ', '\\']; |
543
|
|
|
foreach ($invalidCharacters as $char) { |
544
|
|
|
if (strchr($name, $char) !== false) { |
545
|
|
|
throw new \Exception('Database name contains invalid characters'); |
546
|
|
|
} |
547
|
|
|
} |
548
|
|
|
} |
549
|
|
|
|
550
|
|
|
/** |
551
|
|
|
* @param bool $includeSystemCollections |
552
|
|
|
* @return Closure |
553
|
|
|
*/ |
554
|
|
|
private function getSystemCollectionFilterClosure($includeSystemCollections = false) |
555
|
|
|
{ |
556
|
|
|
return function (CollectionInfo $collectionInfo) use ($includeSystemCollections) { |
557
|
|
|
return $includeSystemCollections || ! preg_match('#^system\.#', $collectionInfo->getName()); |
558
|
|
|
}; |
559
|
|
|
} |
560
|
|
|
|
561
|
|
|
/** |
562
|
|
|
* @return array |
563
|
|
|
*/ |
564
|
|
|
public function __sleep() |
565
|
|
|
{ |
566
|
|
|
return ['connection', 'name']; |
567
|
|
|
} |
568
|
|
|
} |
569
|
|
|
|
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:
Our function
my_function
expects aPost
object, and outputs the author of the post. The base classPost
returns a simple string and outputting a simple string will work just fine. However, the child classBlogPost
which is a sub-type ofPost
instead decided to return anobject
, and is therefore violating the SOLID principles. If aBlogPost
were passed tomy_function
, PHP would not complain, but ultimately fail when executing thestrtoupper
call in its body.