Skip to content

Commit 55c62d3

Browse files
jmikolaalcaeus
andauthored
Extract DropEncryptedCollection operation from helper methods (#1055)
This is based on the extraction of CreateEncryptedCollection for PHPLIB-913. Co-authored-by: Andreas Braun <[email protected]>
1 parent b963821 commit 55c62d3

File tree

4 files changed

+152
-28
lines changed

4 files changed

+152
-28
lines changed

src/Collection.php

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
use MongoDB\Operation\DeleteOne;
4141
use MongoDB\Operation\Distinct;
4242
use MongoDB\Operation\DropCollection;
43+
use MongoDB\Operation\DropEncryptedCollection;
4344
use MongoDB\Operation\DropIndexes;
4445
use MongoDB\Operation\EstimatedDocumentCount;
4546
use MongoDB\Operation\Explain;
@@ -495,22 +496,14 @@ public function drop(array $options = [])
495496
$options['writeConcern'] = $this->writeConcern;
496497
}
497498

498-
$encryptedFields = $options['encryptedFields']
499-
?? get_encrypted_fields_from_driver($this->databaseName, $this->collectionName, $this->manager)
500-
?? get_encrypted_fields_from_server($this->databaseName, $this->collectionName, $this->manager, $server)
501-
?? null;
502-
503-
if ($encryptedFields !== null) {
504-
// encryptedFields is not passed to the drop command
505-
unset($options['encryptedFields']);
506-
507-
$encryptedFields = (array) $encryptedFields;
508-
(new DropCollection($this->databaseName, $encryptedFields['escCollection'] ?? 'enxcol_.' . $this->collectionName . '.esc'))->execute($server);
509-
(new DropCollection($this->databaseName, $encryptedFields['eccCollection'] ?? 'enxcol_.' . $this->collectionName . '.ecc'))->execute($server);
510-
(new DropCollection($this->databaseName, $encryptedFields['ecocCollection'] ?? 'enxcol_.' . $this->collectionName . '.ecoc'))->execute($server);
499+
if (! isset($options['encryptedFields'])) {
500+
$options['encryptedFields'] = get_encrypted_fields_from_driver($this->databaseName, $this->collectionName, $this->manager)
501+
?? get_encrypted_fields_from_server($this->databaseName, $this->collectionName, $this->manager, $server);
511502
}
512503

513-
$operation = new DropCollection($this->databaseName, $this->collectionName, $options);
504+
$operation = isset($options['encryptedFields'])
505+
? new DropEncryptedCollection($this->databaseName, $this->collectionName, $options)
506+
: new DropCollection($this->databaseName, $this->collectionName, $options);
514507

515508
return $operation->execute($server);
516509
}

src/Database.php

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
use MongoDB\Operation\DatabaseCommand;
4040
use MongoDB\Operation\DropCollection;
4141
use MongoDB\Operation\DropDatabase;
42+
use MongoDB\Operation\DropEncryptedCollection;
4243
use MongoDB\Operation\ListCollectionNames;
4344
use MongoDB\Operation\ListCollections;
4445
use MongoDB\Operation\ModifyCollection;
@@ -386,22 +387,14 @@ public function dropCollection(string $collectionName, array $options = [])
386387
$options['writeConcern'] = $this->writeConcern;
387388
}
388389

389-
$encryptedFields = $options['encryptedFields']
390-
?? get_encrypted_fields_from_driver($this->databaseName, $collectionName, $this->manager)
391-
?? get_encrypted_fields_from_server($this->databaseName, $collectionName, $this->manager, $server)
392-
?? null;
393-
394-
if ($encryptedFields !== null) {
395-
// encryptedFields is not passed to the drop command
396-
unset($options['encryptedFields']);
397-
398-
$encryptedFields = (array) $encryptedFields;
399-
(new DropCollection($this->databaseName, $encryptedFields['escCollection'] ?? 'enxcol_.' . $collectionName . '.esc'))->execute($server);
400-
(new DropCollection($this->databaseName, $encryptedFields['eccCollection'] ?? 'enxcol_.' . $collectionName . '.ecc'))->execute($server);
401-
(new DropCollection($this->databaseName, $encryptedFields['ecocCollection'] ?? 'enxcol_.' . $collectionName . '.ecoc'))->execute($server);
390+
if (! isset($options['encryptedFields'])) {
391+
$options['encryptedFields'] = get_encrypted_fields_from_driver($this->databaseName, $collectionName, $this->manager)
392+
?? get_encrypted_fields_from_server($this->databaseName, $collectionName, $this->manager, $server);
402393
}
403394

404-
$operation = new DropCollection($this->databaseName, $collectionName, $options);
395+
$operation = isset($options['encryptedFields'])
396+
? new DropEncryptedCollection($this->databaseName, $collectionName, $options)
397+
: new DropCollection($this->databaseName, $collectionName, $options);
405398

406399
return $operation->execute($server);
407400
}
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
<?php
2+
/*
3+
* Copyright 2023-present MongoDB, Inc.
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* https://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
namespace MongoDB\Operation;
19+
20+
// phpcs:ignore SlevomatCodingStandard.Namespaces.UnusedUses.UnusedUse
21+
use MongoDB\BSON\Binary;
22+
use MongoDB\Driver\Exception\RuntimeException as DriverRuntimeException;
23+
use MongoDB\Driver\Server;
24+
use MongoDB\Exception\InvalidArgumentException;
25+
26+
use function is_array;
27+
use function is_object;
28+
29+
/**
30+
* Drop an encrypted collection.
31+
*
32+
* The "encryptedFields" option is required.
33+
*
34+
* This operation additionally drops related metadata collections.
35+
*
36+
* @internal
37+
* @see \MongoDB\Database::dropCollection()
38+
* @see \MongoDB\Collection::drop()
39+
* @see https://github.com/mongodb/specifications/blob/master/source/client-side-encryption/client-side-encryption.rst#drop-collection-helper
40+
* @see https://www.mongodb.com/docs/manual/core/queryable-encryption/fundamentals/manage-collections/
41+
*/
42+
class DropEncryptedCollection implements Executable
43+
{
44+
/** @var DropCollection */
45+
private $dropCollection;
46+
47+
/** @var DropCollection[] */
48+
private $dropMetadataCollections;
49+
50+
/**
51+
* Constructs an operation to drop an encrypted collection and its related
52+
* metadata collections.
53+
*
54+
* The following option is supported in addition to the options for
55+
* DropCollection:
56+
*
57+
* * encryptedFields (document): Configuration for encrypted fields.
58+
* See: https://www.mongodb.com/docs/manual/core/queryable-encryption/fundamentals/encrypt-and-query/
59+
*
60+
* @see DropCollection::__construct() for supported options
61+
* @param string $databaseName Database name
62+
* @param string $collectionName Collection name
63+
* @param array $options DropCollection options
64+
* @throws InvalidArgumentException for parameter/option parsing errors
65+
*/
66+
public function __construct(string $databaseName, string $collectionName, array $options)
67+
{
68+
if (! isset($options['encryptedFields'])) {
69+
throw new InvalidArgumentException('"encryptedFields" option is required');
70+
}
71+
72+
if (! is_array($options['encryptedFields']) && ! is_object($options['encryptedFields'])) {
73+
throw InvalidArgumentException::invalidType('"encryptedFields" option', $options['encryptedFields'], ['array', 'object']);
74+
}
75+
76+
/** @psalm-var array{eccCollection?: ?string, ecocCollection?: ?string, escCollection?: ?string} */
77+
$encryptedFields = (array) $options['encryptedFields'];
78+
79+
$this->dropMetadataCollections = [
80+
new DropCollection($databaseName, $encryptedFields['escCollection'] ?? 'enxcol_.' . $collectionName . '.esc'),
81+
new DropCollection($databaseName, $encryptedFields['eccCollection'] ?? 'enxcol_.' . $collectionName . '.ecc'),
82+
new DropCollection($databaseName, $encryptedFields['ecocCollection'] ?? 'enxcol_.' . $collectionName . '.ecoc'),
83+
];
84+
85+
// DropCollection does not use the "encryptedFields" option
86+
unset($options['encryptedFields']);
87+
88+
$this->dropCollection = new DropCollection($databaseName, $collectionName, $options);
89+
}
90+
91+
/**
92+
* @see Executable::execute()
93+
* @return array|object Command result document from dropping the encrypted collection
94+
* @throws DriverRuntimeException for other driver errors (e.g. connection errors)
95+
*/
96+
public function execute(Server $server)
97+
{
98+
foreach ($this->dropMetadataCollections as $dropMetadataCollection) {
99+
$dropMetadataCollection->execute($server);
100+
}
101+
102+
return $this->dropCollection->execute($server);
103+
}
104+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
<?php
2+
3+
namespace MongoDB\Tests\Operation;
4+
5+
use Generator;
6+
use MongoDB\Exception\InvalidArgumentException;
7+
use MongoDB\Operation\DropEncryptedCollection;
8+
9+
use function get_debug_type;
10+
11+
class DropEncryptedCollectionTest extends TestCase
12+
{
13+
/**
14+
* @dataProvider provideInvalidConstructorOptions
15+
*/
16+
public function testConstructorOptionTypeChecks(array $options): void
17+
{
18+
$this->expectException(InvalidArgumentException::class);
19+
new DropEncryptedCollection($this->getDatabaseName(), $this->getCollectionName(), $options);
20+
}
21+
22+
public function provideInvalidConstructorOptions(): Generator
23+
{
24+
yield 'encryptedFields is required' => [
25+
[],
26+
];
27+
28+
foreach ($this->getInvalidDocumentValues() as $value) {
29+
yield 'encryptedFields type: ' . get_debug_type($value) => [
30+
['encryptedFields' => $value],
31+
];
32+
}
33+
}
34+
}

0 commit comments

Comments
 (0)