Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/Model/BSONDocument.php
Original file line number Diff line number Diff line change
Expand Up @@ -52,12 +52,12 @@
* by default.
*
* @see https://php.net/arrayobject.construct
* @param array<string, mixed> $input
* @param object|array<string, mixed> $input
* @psalm-param class-string<ArrayIterator<string,mixed>>|class-string<ArrayObject<string,mixed>> $iteratorClass
*/
public function __construct(array $input = [], int $flags = ArrayObject::ARRAY_AS_PROPS, string $iteratorClass = ArrayIterator::class)
public function __construct(array|object $input = [], int $flags = ArrayObject::ARRAY_AS_PROPS, string $iteratorClass = ArrayIterator::class)
{
parent::__construct($input, $flags, $iteratorClass);

Check failure on line 60 in src/Model/BSONDocument.php

View workflow job for this annotation

GitHub Actions / Psalm

PossiblyInvalidArgument

src/Model/BSONDocument.php:60:29: PossiblyInvalidArgument: Argument 1 of ArrayObject::__construct expects (array<TKey:ArrayObject as array-key, TValue:ArrayObject as mixed>)|null|object, but possibly different type array<string, mixed>|object provided (see https://psalm.dev/092)
}

/**
Expand Down
16 changes: 16 additions & 0 deletions tests/Model/BSONDocumentTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,22 @@ public function testConstructorDefaultsToPropertyAccess(): void
$this->assertSame('bar', $document->foo);
}

public function testConstructorWithStandardObject(): void
{
$document = new BSONDocument((object) ['foo' => 'bar']);
$this->assertSame('bar', $document->foo);
}

public function testConstructorWithClassObject(): void
{
$document = new BSONDocument(new class () {
public string $foo = 'bar';
protected string $baz = 'qux';
});
$this->assertSame('bar', $document->foo);
$this->assertObjectNotHasProperty('baz', $document);
Copy link
Member

@jmikola jmikola Dec 4, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is essentially a test of ArrayObject itself. I think it'd be preferable to test bsonSerialize() (note: jsonSerialize() has the same implementation), so we can see what would actually get serialized to BSON.

My concern is that we should preserve the same encoding behavior as the extension, which will only encodes public properties.

See: https://3v4l.org/47VCv#v8.4.1

I think it's bit strange that the encoded names for protected and private properties still end up in output from ArrayObject::getArrayCopy(), and are preserved when casting back to an object. It's certainly odd that the stdClass instance resulting from that cast ends up with non-public properties, but that's likely an oddity of PHP itself.

If we can get away with only accepting stdClass|array, that might circumvent this issue.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, I followed your suggestion on allowing only array|stdClass. That covers the request.

}

public function testBsonSerializeCastsToObject(): void
{
$data = [0 => 'foo', 2 => 'bar'];
Expand Down
Loading