Skip to content

Commit a9a67c8

Browse files
committed
Bulk write models refactoring and fixes, other fixes
1 parent f0a575b commit a9a67c8

14 files changed

+183
-25
lines changed

src/Collection.php

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ public function insertMany($documents, array $options = [])
123123
*/
124124
public function deleteOne($filter, array $options = [])
125125
{
126-
list($bulkOptions, $options) = $this->extractBulkWriteOptions($options);
126+
list($bulkOptions, $options) = self::extractBulkWriteOptions($options);
127127
$model = new DeleteOne($filter, $options);
128128
$bulkWriteResult = $this->bulkWrite([$model], $bulkOptions);
129129

@@ -137,7 +137,7 @@ public function deleteOne($filter, array $options = [])
137137
*/
138138
public function deleteMany($filter, array $options = [])
139139
{
140-
list($bulkOptions, $options) = $this->extractBulkWriteOptions($options);
140+
list($bulkOptions, $options) = self::extractBulkWriteOptions($options);
141141
$model = new DeleteMany($filter, $options);
142142
$bulkWriteResult = $this->bulkWrite([$model], $bulkOptions);
143143

@@ -152,7 +152,7 @@ public function deleteMany($filter, array $options = [])
152152
*/
153153
public function updateOne($filter, $update, array $options = [])
154154
{
155-
list($bulkOptions, $options) = $this->extractBulkWriteOptions($options);
155+
list($bulkOptions, $options) = self::extractBulkWriteOptions($options);
156156
$model = new UpdateOne($filter, $update, $options);
157157

158158
$bulkWriteResult = $this->bulkWrite([$model], $bulkOptions);
@@ -168,7 +168,7 @@ public function updateOne($filter, $update, array $options = [])
168168
*/
169169
public function updateMany($filter, $update, array $options = [])
170170
{
171-
list($bulkOptions, $options) = $this->extractBulkWriteOptions($options);
171+
list($bulkOptions, $options) = self::extractBulkWriteOptions($options);
172172
$model = new UpdateMany($filter, $update, $options);
173173

174174
$bulkWriteResult = $this->bulkWrite([$model], $bulkOptions);
@@ -184,7 +184,7 @@ public function updateMany($filter, $update, array $options = [])
184184
*/
185185
public function replaceOne($filter, $replacement, array $options = [])
186186
{
187-
list($bulkOptions, $options) = $this->extractBulkWriteOptions($options);
187+
list($bulkOptions, $options) = self::extractBulkWriteOptions($options);
188188
$model = new ReplaceOne($filter, $replacement, $options);
189189

190190
$bulkWriteResult = $this->bulkWrite([$model], $bulkOptions);
@@ -196,10 +196,10 @@ public function replaceOne($filter, $replacement, array $options = [])
196196
* @param array $options
197197
* @return array
198198
*/
199-
private function extractBulkWriteOptions(array $options)
199+
private static function extractBulkWriteOptions(array $options)
200200
{
201-
$resolver = BulkWriteOptions::getCachedResolver();
202-
$bulkWriteOptions = array_intersect_key($options, array_flip($resolver->getDefinedOptions()));
201+
$definedOptions = BulkWriteOptions::getDefinedOptions();
202+
$bulkWriteOptions = array_intersect_key($options, array_flip($definedOptions));
203203
$operationOptions = array_diff_key($options, $bulkWriteOptions);
204204

205205
return [$bulkWriteOptions, $operationOptions];

src/Command/CommandBuilder.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ class CommandBuilder
2121
private $databaseName;
2222

2323
/**
24-
* CommandBuilder constructor.
2524
* @param Connection $connection
2625
* @param string $databaseName
2726
*/

src/Command/CommandWrapper.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@ class CommandWrapper
4242
private static $cachedResolvers;
4343

4444
/**
45-
* Command constructor.
4645
* @param Connection $connection
4746
* @param string $databaseName
4847
* @param string $commandClass

src/Connection.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@ class Connection
4545
private $commandBuilders = [];
4646

4747
/**
48-
* Client constructor.
4948
* @param string $uri
5049
* @param array $options
5150
* @param array $driverOptions

src/Database.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ class Database implements DatabaseInterface
2121
private $connection;
2222

2323
/**
24-
* Database constructor.
2524
* @param Connection $connection
2625
* @param string $databaseName
2726
*/

src/Index.php

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ class Index
2828
private $name;
2929

3030
/**
31-
* Index constructor.
3231
* @param array $keys
3332
* @param array $options
3433
*/
@@ -38,13 +37,15 @@ public function __construct(array $keys, array $options = [])
3837
throw new InvalidArgumentException('$keys array cannot be empty');
3938
}
4039

41-
foreach ($keys as $fieldName => $value) {
42-
ensureValidDocumentFieldName($fieldName);
43-
}
44-
4540
$resolver = new OptionsResolver();
4641
IndexOptions::configureOptions($resolver);
47-
$options = $resolver->resolve($options);
42+
43+
try {
44+
$options = $resolver->resolve($options);
45+
} catch(\Symfony\Component\OptionsResolver\Exception\InvalidArgumentException $e) {
46+
throw new InvalidArgumentException($e->getMessage());
47+
}
48+
4849

4950
if (empty($options['name'])) {
5051
$options['name'] = self::generateIndexName($options['key']);

src/Operation/OperationInterface.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?php
2+
3+
namespace Tequila\MongoDB\Operation;
4+
5+
use Tequila\MongoDB\Connection;
6+
7+
interface OperationInterface
8+
{
9+
/**
10+
* @param Connection $connection
11+
* @param string $databaseName
12+
* @param string $collectionName
13+
* @return mixed
14+
*/
15+
public function execute(Connection $connection, $databaseName, $collectionName);
16+
}

src/Options/Read/FindOptions.php

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
<?php
2+
3+
namespace Tequila\MongoDB\Options\Read;
4+
5+
use MongoDB\Driver\ReadConcern;
6+
use MongoDB\Driver\ReadPreference;
7+
use Symfony\Component\OptionsResolver\Options;
8+
use Symfony\Component\OptionsResolver\OptionsResolver;
9+
use Tequila\MongoDB\Options\ConfigurableInterface;
10+
use Tequila\MongoDB\Options\Traits\CachedResolverTrait;
11+
12+
class FindOptions implements ConfigurableInterface
13+
{
14+
use CachedResolverTrait {
15+
CachedResolverTrait::resolve as resolveOptions;
16+
}
17+
18+
const CURSOR_TYPE_NON_TAILABLE = 1;
19+
const CURSOR_TYPE_TAILABLE = 2;
20+
const CURSOR_TYPE_TAILABLE_AWAIT = 3;
21+
22+
/**
23+
* @param array $options
24+
* @return array
25+
*/
26+
public static function resolve(array $options)
27+
{
28+
$options = self::resolveOptions($options);
29+
30+
if (!empty($options['allowPartialResults'])) {
31+
$options['partial'] = true;
32+
}
33+
34+
if (isset($options['cursorType'])) {
35+
$cursorType = $options['cursorType'];
36+
37+
if (in_array($cursorType, [self::CURSOR_TYPE_TAILABLE, self::CURSOR_TYPE_TAILABLE_AWAIT], true)) {
38+
$options['tailable'] = true;
39+
}
40+
41+
if (self::CURSOR_TYPE_TAILABLE_AWAIT === $cursorType) {
42+
$options['awaitData'] = true;
43+
}
44+
45+
unset($options['cursorType']);
46+
}
47+
48+
if (isset($options['comment'])) {
49+
$options['modifiers']['$comment'] = $options['comment'];
50+
unset($options['comment']);
51+
}
52+
53+
if (isset($options['maxTimeMS'])) {
54+
$options['modifiers']['$maxTimeMS'] = $options['maxTimeMS'];
55+
unset($options['comment']);
56+
}
57+
58+
if(empty($options['modifiers'])) {
59+
unset($options['modifiers']);
60+
}
61+
62+
return $options;
63+
}
64+
65+
public static function configureOptions(OptionsResolver $resolver)
66+
{
67+
$resolver->setDefined([
68+
'allowPartialResults',
69+
'awaitData',
70+
'batchSize',
71+
'collation', // for MongoDB 3.4 and higher
72+
'comment',
73+
'cursorType',
74+
'exhaust',
75+
'limit',
76+
'maxTimeMS',
77+
'modifiers',
78+
'noCursorTimeout',
79+
'oplogReplay',
80+
'partial',
81+
'projection',
82+
'readConcern',
83+
'readPreference',
84+
'skip',
85+
'sort',
86+
'tailable',
87+
'typeMap',
88+
]);
89+
90+
$resolver
91+
->setAllowedTypes('allowPartialResults', 'bool')
92+
->setAllowedTypes('batchSize', 'integer')
93+
->setAllowedTypes('collation', 'string')
94+
->setAllowedTypes('comment', 'string')
95+
->setAllowedValues('cursorType', [
96+
self::CURSOR_TYPE_NON_TAILABLE,
97+
self::CURSOR_TYPE_TAILABLE,
98+
self::CURSOR_TYPE_TAILABLE_AWAIT,
99+
])
100+
->setAllowedTypes('exhaust', 'bool')
101+
->setAllowedTypes('limit', 'integer')
102+
->setAllowedTypes('maxTimeMS', 'integer')
103+
->setAllowedTypes('modifiers', ['array', 'object'])
104+
->setDefault('modifiers', [])
105+
->setAllowedTypes('noCursorTimeout', 'bool')
106+
->setAllowedTypes('oplogReplay', 'bool')
107+
->setAllowedTypes('projection', ['array', 'object'])
108+
->setAllowedTypes('readConcern', ReadConcern::class)
109+
->setAllowedTypes('readPreference', ReadPreference::class)
110+
->setAllowedTypes('skip', 'integer')
111+
->setAllowedTypes('sort', ['array', 'object'])
112+
->setAllowedTypes('typeMap', 'array');
113+
114+
$resolver->setNormalizer('cursorType', function(Options $options, $cursorType) {
115+
if (in_array($cursorType, [self::CURSOR_TYPE_TAILABLE, self::CURSOR_TYPE_TAILABLE_AWAIT], true)) {
116+
$options['tailable'] = true;
117+
}
118+
119+
if (self::CURSOR_TYPE_TAILABLE_AWAIT === $cursorType) {
120+
$options['awaitData'] = true;
121+
}
122+
123+
return $cursorType;
124+
});
125+
}
126+
}

src/Options/Traits/CachedResolverTrait.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ trait CachedResolverTrait
2020
public static function resolve(array $options)
2121
{
2222
try {
23-
return self::getCachedResolver()->resolve($options);
23+
return self::getResolver()->resolve($options);
2424
} catch (OptionsResolverException $e) {
2525
throw new InvalidArgumentException($e->getMessage());
2626
}
@@ -36,7 +36,7 @@ public static function configureOptions(OptionsResolver $resolver)
3636
/**
3737
* @return OptionsResolver
3838
*/
39-
private static function getCachedResolver()
39+
private static function getResolver()
4040
{
4141
if (!self::$cachedResolver) {
4242
self::$cachedResolver = new OptionsResolver();

src/Write/Bulk/BulkWriteOptions.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,4 +28,12 @@ public static function configureOptions(OptionsResolver $resolver)
2828
->setDefault('bypassDocumentValidation', true)
2929
->setDefault('ordered', true);
3030
}
31+
32+
/**
33+
* @return \string[]
34+
*/
35+
public static function getDefinedOptions()
36+
{
37+
return self::getResolver()->getDefinedOptions();
38+
}
3139
}

src/Write/Model/DeleteMany.php

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22

33
namespace Tequila\MongoDB\Write\Model;
44

5-
use Tequila\MongoDB\Write\Options\DeleteManyOptions;
5+
use Tequila\MongoDB\Exception\InvalidArgumentException;
6+
use Tequila\MongoDB\Write\Options\DeleteOptions;
67

78
class DeleteMany implements WriteModelInterface
89
{
@@ -16,7 +17,13 @@ class DeleteMany implements WriteModelInterface
1617
public function __construct($filter, array $options = [])
1718
{
1819
$this->ensureValidFilter($filter);
20+
if (isset($options['limit']) && 1 === $options['limit']) {
21+
throw new InvalidArgumentException(
22+
'DeleteMany operation does not allow option "limit" to be set to 1'
23+
);
24+
}
25+
1926
$this->filter = $filter;
20-
$this->options = DeleteManyOptions::getCachedResolver()->resolve($options);
27+
$this->options = DeleteOptions::resolve($options);
2128
}
2229
}

src/Write/Model/DeleteOne.php

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace Tequila\MongoDB\Write\Model;
44

5+
use Tequila\MongoDB\Exception\InvalidArgumentException;
56
use Tequila\MongoDB\Write\Options\DeleteOptions;
67

78
class DeleteOne implements WriteModelInterface
@@ -16,8 +17,13 @@ class DeleteOne implements WriteModelInterface
1617
public function __construct($filter, array $options = [])
1718
{
1819
$this->ensureValidFilter($filter);
20+
if (isset($options['limit']) && 0 === $options['limit']) {
21+
throw new InvalidArgumentException(
22+
'DeleteOne operation does not allow option "limit" to be set to 0'
23+
);
24+
}
1925

2026
$this->filter = $filter;
21-
$this->options = DeleteOptions::->resolve($options);
27+
$this->options = DeleteOptions::resolve($options);
2228
}
2329
}

src/Write/Model/UpdateMany.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ class UpdateMany implements WriteModelInterface
1212
use Traits\BulkUpdateTrait;
1313

1414
/**
15-
* Update constructor.
1615
* @param array|object $filter
1716
* @param array|object $update
1817
* @param array $options

src/Write/Model/UpdateOne.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ class UpdateOne implements WriteModelInterface
1212
use Traits\BulkUpdateTrait;
1313

1414
/**
15-
* Update constructor.
1615
* @param array|object $filter
1716
* @param array|object $update
1817
* @param array $options

0 commit comments

Comments
 (0)