Skip to content

Commit

Permalink
Use is_document to reject PackedArrays mongodb#1117
Browse files Browse the repository at this point in the history
  • Loading branch information
GromNaN committed Jul 24, 2023
1 parent 5c9de65 commit 6c2532b
Show file tree
Hide file tree
Showing 8 changed files with 66 additions and 19 deletions.
2 changes: 1 addition & 1 deletion psalm-baseline.xml
Original file line number Diff line number Diff line change
Expand Up @@ -311,7 +311,7 @@
</file>
<file src="src/Operation/CreateSearchIndexes.php">
<MixedArgumentTypeCoercion>
<code>$index</code>
<code>(array) $index</code>
</MixedArgumentTypeCoercion>
</file>
<file src="src/Operation/DatabaseCommand.php">
Expand Down
7 changes: 3 additions & 4 deletions src/Model/SearchIndexInput.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,8 @@
use MongoDB\BSON\Serializable;
use MongoDB\Exception\InvalidArgumentException;

use function is_array;
use function is_object;
use function is_string;
use function MongoDB\is_document;

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

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

// Name is optional, but must be a non-empty string if provided
Expand Down
11 changes: 4 additions & 7 deletions src/Operation/CreateSearchIndexes.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,7 @@
use function array_is_list;
use function array_map;
use function current;
use function is_array;
use function is_object;
use function MongoDB\is_document;
use function sprintf;

/**
Expand Down Expand Up @@ -64,13 +63,11 @@ public function __construct(string $databaseName, string $collectionName, array
}

foreach ($indexes as $i => $index) {
if (is_object($index)) {
$index = (array) $index;
} elseif (! is_array($index)) {
throw InvalidArgumentException::invalidType(sprintf('$index[%d]', $i), $index, 'array or object');
if (! is_document($index)) {
throw InvalidArgumentException::expectedDocumentType(sprintf('$indexes[%d]', $i), $index);
}

$this->indexes[] = new SearchIndexInput($index);
$this->indexes[] = new SearchIndexInput((array) $index);
}

$this->databaseName = $databaseName;
Expand Down
7 changes: 3 additions & 4 deletions src/Operation/UpdateSearchIndex.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,7 @@
use MongoDB\Exception\InvalidArgumentException;
use MongoDB\Exception\UnsupportedException;

use function is_array;
use function is_object;
use function MongoDB\is_document;

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

if (! is_array($definition) && ! is_object($definition)) {
throw InvalidArgumentException::invalidType('$definition', $definition, 'array or object');
if (! is_document($definition)) {
throw InvalidArgumentException::expectedDocumentType('$definition', $definition);
}

$this->databaseName = $databaseName;
Expand Down
4 changes: 4 additions & 0 deletions tests/Model/IndexInputTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,19 +15,22 @@ class IndexInputTest extends TestCase
public function testConstructorShouldRequireKey(): void
{
$this->expectException(InvalidArgumentException::class);
$this->expectExceptionMessage('Required "key" document is missing from index specification');
new IndexInput([]);
}

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

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

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

Expand Down
48 changes: 48 additions & 0 deletions tests/Model/SearchIndexInputTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<?php

namespace MongoDB\Tests\Model;

use MongoDB\BSON\Serializable;
use MongoDB\Exception\InvalidArgumentException;
use MongoDB\Model\SearchIndexInput;
use MongoDB\Tests\TestCase;

class SearchIndexInputTest extends TestCase
{
public function testConstructorIndexDefinitionMustBeDefined(): void
{
$this->expectException(InvalidArgumentException::class);
$this->expectExceptionMessage('Required "definition" document is missing from search index specification');
new SearchIndexInput([]);
}

public function testConstructorIndexDefinitionMustBeADocument(): void
{
$this->expectException(InvalidArgumentException::class);
$this->expectExceptionMessage('Expected "definition" option to have type "document"');
new SearchIndexInput(['definition' => 'foo']);
}

public function testConstructorShouldRequireNameToBeString(): void
{
$this->expectException(InvalidArgumentException::class);
$this->expectExceptionMessage('Expected "name" option to have type "string"');
new SearchIndexInput(['definition' => ['mapping' => ['dynamid' => true]], 'name' => 1]);
}

public function testBsonSerialization(): void
{
$expected = (object) [
'name' => 'my_search',
'definition' => ['mapping' => ['dynamic' => true]],
];

$indexInput = new SearchIndexInput([
'name' => 'my_search',
'definition' => ['mapping' => ['dynamic' => true]],
]);

$this->assertInstanceOf(Serializable::class, $indexInput);
$this->assertEquals($expected, $indexInput->bsonSerialize());
}
}
4 changes: 2 additions & 2 deletions tests/Operation/CreateSearchIndexesTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public function testConstructorIndexesArgumentMustBeAList(): void
public function testConstructorIndexDefinitionMustBeADocument($index): void
{
$this->expectException(InvalidArgumentException::class);
$this->expectExceptionMessage('Expected $index[0] to have type "array or object"');
$this->expectExceptionMessage('Expected $indexes[0] to have type "document"');
new CreateSearchIndexes($this->getDatabaseName(), $this->getCollectionName(), [$index]);
}

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

Expand Down
2 changes: 1 addition & 1 deletion tests/Operation/UpdateSearchIndexTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public function testConstructorIndexNameMustNotBeEmpty(): void
public function testConstructorIndexDefinitionMustBeADocument($definition): void
{
$this->expectException(InvalidArgumentException::class);
$this->expectExceptionMessage('Expected $definition to have type "array or object"');
$this->expectExceptionMessage('Expected $definition to have type "document"');
new UpdateSearchIndex($this->getDatabaseName(), $this->getCollectionName(), 'index name', $definition);
}
}

0 comments on commit 6c2532b

Please sign in to comment.