Skip to content

Commit 4ccc852

Browse files
committed
Use is_document to reject PackedArrays #1117
1 parent bf224ee commit 4ccc852

File tree

8 files changed

+69
-36
lines changed

8 files changed

+69
-36
lines changed

psalm-baseline.xml

Lines changed: 4 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -288,8 +288,7 @@
288288
</MixedReturnStatement>
289289
</file>
290290
<file src="src/Model/SearchIndexInput.php">
291-
<DocblockTypeContradiction occurrences="2">
292-
<code>! is_array($index['definition']) &amp;&amp; ! is_object($index['definition'])</code>
291+
<DocblockTypeContradiction occurrences="1">
293292
<code>isset($index['name']) &amp;&amp; ! is_string($index['name'])</code>
294293
</DocblockTypeContradiction>
295294
</file>
@@ -444,11 +443,8 @@
444443
</MixedMethodCall>
445444
</file>
446445
<file src="src/Operation/CreateSearchIndexes.php">
447-
<DocblockTypeContradiction occurrences="1">
448-
<code>is_array($index)</code>
449-
</DocblockTypeContradiction>
450446
<MixedArgumentTypeCoercion occurrences="1">
451-
<code>$index</code>
447+
<code>(array) $index</code>
452448
</MixedArgumentTypeCoercion>
453449
</file>
454450
<file src="src/Operation/DatabaseCommand.php">
@@ -715,11 +711,6 @@
715711
<code>! is_array($update) &amp;&amp; ! is_object($update)</code>
716712
</DocblockTypeContradiction>
717713
</file>
718-
<file src="src/Operation/UpdateSearchIndex.php">
719-
<DocblockTypeContradiction occurrences="1">
720-
<code>! is_array($definition) &amp;&amp; ! is_object($definition)</code>
721-
</DocblockTypeContradiction>
722-
</file>
723714
<file src="src/Operation/Watch.php">
724715
<DocblockTypeContradiction occurrences="1">
725716
<code>isset($resumeToken) &amp;&amp; ! is_array($resumeToken) &amp;&amp; ! is_object($resumeToken)</code>
@@ -785,18 +776,13 @@
785776
<code>$typeMap['fieldPaths'][$fieldPath]</code>
786777
<code>$value</code>
787778
</MixedAssignment>
788-
<MixedInferredReturnType occurrences="3">
789-
<code>array|object</code>
779+
<MixedInferredReturnType occurrences="2">
790780
<code>array|object|null</code>
791781
<code>array|object|null</code>
792782
</MixedInferredReturnType>
793-
<MixedOperand occurrences="1">
794-
<code>$type</code>
795-
</MixedOperand>
796-
<MixedReturnStatement occurrences="3">
783+
<MixedReturnStatement occurrences="2">
797784
<code>$collectionInfo['options']['encryptedFields'] ?? null</code>
798785
<code>$encryptedFieldsMap[$databaseName . '.' . $collectionName] ?? null</code>
799-
<code>toPHP(fromPHP($document), $typeMap)</code>
800786
</MixedReturnStatement>
801787
</file>
802788
</files>

src/Model/SearchIndexInput.php

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,8 @@
2020
use MongoDB\BSON\Serializable;
2121
use MongoDB\Exception\InvalidArgumentException;
2222

23-
use function is_array;
24-
use function is_object;
2523
use function is_string;
24+
use function MongoDB\is_document;
2625

2726
/**
2827
* Search index input model class.
@@ -49,8 +48,8 @@ public function __construct(array $index)
4948
throw new InvalidArgumentException('Required "definition" document is missing from search index specification');
5049
}
5150

52-
if (! is_array($index['definition']) && ! is_object($index['definition'])) {
53-
throw InvalidArgumentException::invalidType('"definition" option', $index['definition'], 'array or object');
51+
if (! is_document($index['definition'])) {
52+
throw InvalidArgumentException::expectedDocumentType('"definition" option', $index['definition']);
5453
}
5554

5655
// Name is optional, but must be a non-empty string if provided

src/Operation/CreateSearchIndexes.php

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,7 @@
2727
use function array_is_list;
2828
use function array_map;
2929
use function current;
30-
use function is_array;
31-
use function is_object;
30+
use function MongoDB\is_document;
3231
use function sprintf;
3332

3433
/**
@@ -64,13 +63,11 @@ public function __construct(string $databaseName, string $collectionName, array
6463
}
6564

6665
foreach ($indexes as $i => $index) {
67-
if (is_object($index)) {
68-
$index = (array) $index;
69-
} elseif (! is_array($index)) {
70-
throw InvalidArgumentException::invalidType(sprintf('$index[%d]', $i), $index, 'array or object');
66+
if (! is_document($index)) {
67+
throw InvalidArgumentException::expectedDocumentType(sprintf('$indexes[%d]', $i), $index);
7168
}
7269

73-
$this->indexes[] = new SearchIndexInput($index);
70+
$this->indexes[] = new SearchIndexInput((array) $index);
7471
}
7572

7673
$this->databaseName = $databaseName;

src/Operation/UpdateSearchIndex.php

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,7 @@
2323
use MongoDB\Exception\InvalidArgumentException;
2424
use MongoDB\Exception\UnsupportedException;
2525

26-
use function is_array;
27-
use function is_object;
26+
use function MongoDB\is_document;
2827

2928
/**
3029
* Operation for the createIndexes command.
@@ -61,8 +60,8 @@ public function __construct(string $databaseName, string $collectionName, string
6160
throw new InvalidArgumentException('Index name cannot be empty');
6261
}
6362

64-
if (! is_array($definition) && ! is_object($definition)) {
65-
throw InvalidArgumentException::invalidType('$definition', $definition, 'array or object');
63+
if (! is_document($definition)) {
64+
throw InvalidArgumentException::expectedDocumentType('$definition', $definition);
6665
}
6766

6867
$this->databaseName = $databaseName;

tests/Model/IndexInputTest.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,19 +15,22 @@ class IndexInputTest extends TestCase
1515
public function testConstructorShouldRequireKey(): void
1616
{
1717
$this->expectException(InvalidArgumentException::class);
18+
$this->expectExceptionMessage('Required "key" document is missing from index specification');
1819
new IndexInput([]);
1920
}
2021

2122
public function testConstructorShouldRequireKeyToBeArrayOrObject(): void
2223
{
2324
$this->expectException(InvalidArgumentException::class);
25+
$this->expectExceptionMessage('Expected "key" option to have type "document"');
2426
new IndexInput(['key' => 'foo']);
2527
}
2628

2729
/** @dataProvider provideInvalidFieldOrderValues */
2830
public function testConstructorShouldRequireKeyFieldOrderToBeNumericOrString($order): void
2931
{
3032
$this->expectException(InvalidArgumentException::class);
33+
$this->expectExceptionMessage('Expected order value for "x" field within "key" option to have type "numeric or string"');
3134
new IndexInput(['key' => ['x' => $order]]);
3235
}
3336

@@ -39,6 +42,7 @@ public function provideInvalidFieldOrderValues()
3942
public function testConstructorShouldRequireNameToBeString(): void
4043
{
4144
$this->expectException(InvalidArgumentException::class);
45+
$this->expectExceptionMessage('Expected "name" option to have type "string"');
4246
new IndexInput(['key' => ['x' => 1], 'name' => 1]);
4347
}
4448

tests/Model/SearchIndexInputTest.php

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
<?php
2+
3+
namespace MongoDB\Tests\Model;
4+
5+
use MongoDB\BSON\Serializable;
6+
use MongoDB\Exception\InvalidArgumentException;
7+
use MongoDB\Model\SearchIndexInput;
8+
use MongoDB\Tests\TestCase;
9+
10+
class SearchIndexInputTest extends TestCase
11+
{
12+
public function testConstructorIndexDefinitionMustBeDefined(): void
13+
{
14+
$this->expectException(InvalidArgumentException::class);
15+
$this->expectExceptionMessage('Required "definition" document is missing from search index specification');
16+
new SearchIndexInput([]);
17+
}
18+
19+
public function testConstructorIndexDefinitionMustBeADocument(): void
20+
{
21+
$this->expectException(InvalidArgumentException::class);
22+
$this->expectExceptionMessage('Expected "definition" option to have type "document"');
23+
new SearchIndexInput(['definition' => 'foo']);
24+
}
25+
26+
public function testConstructorShouldRequireNameToBeString(): void
27+
{
28+
$this->expectException(InvalidArgumentException::class);
29+
$this->expectExceptionMessage('Expected "name" option to have type "string"');
30+
new SearchIndexInput(['definition' => ['mapping' => ['dynamid' => true]], 'name' => 1]);
31+
}
32+
33+
public function testBsonSerialization(): void
34+
{
35+
$expected = (object) [
36+
'name' => 'my_search',
37+
'definition' => ['mapping' => ['dynamic' => true]],
38+
];
39+
40+
$indexInput = new SearchIndexInput([
41+
'name' => 'my_search',
42+
'definition' => ['mapping' => ['dynamic' => true]],
43+
]);
44+
45+
$this->assertInstanceOf(Serializable::class, $indexInput);
46+
$this->assertEquals($expected, $indexInput->bsonSerialize());
47+
}
48+
}

tests/Operation/CreateSearchIndexesTest.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ public function testConstructorIndexesArgumentMustBeAList(): void
1818
public function testConstructorIndexDefinitionMustBeADocument($index): void
1919
{
2020
$this->expectException(InvalidArgumentException::class);
21-
$this->expectExceptionMessage('Expected $index[0] to have type "array or object"');
21+
$this->expectExceptionMessage('Expected $indexes[0] to have type "document"');
2222
new CreateSearchIndexes($this->getDatabaseName(), $this->getCollectionName(), [$index]);
2323
}
2424

@@ -41,7 +41,7 @@ public function testConstructorIndexDefinitionMustBeDefined(): void
4141
public function testConstructorIndexDefinitionMustBeAnArray($definition): void
4242
{
4343
$this->expectException(InvalidArgumentException::class);
44-
$this->expectExceptionMessage('Expected "definition" option to have type "array or object"');
44+
$this->expectExceptionMessage('Expected "definition" option to have type "document"');
4545
new CreateSearchIndexes($this->getDatabaseName(), $this->getCollectionName(), [['definition' => $definition]]);
4646
}
4747

tests/Operation/UpdateSearchIndexTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ public function testConstructorIndexNameMustNotBeEmpty(): void
1717
public function testConstructorIndexDefinitionMustBeADocument($definition): void
1818
{
1919
$this->expectException(InvalidArgumentException::class);
20-
$this->expectExceptionMessage('Expected $definition to have type "array or object"');
20+
$this->expectExceptionMessage('Expected $definition to have type "document"');
2121
new UpdateSearchIndex($this->getDatabaseName(), $this->getCollectionName(), 'index name', $definition);
2222
}
2323
}

0 commit comments

Comments
 (0)