Skip to content

Commit d2d950d

Browse files
committed
Add lazy array and document models with codecs
1 parent a436b81 commit d2d950d

10 files changed

+1261
-1
lines changed

src/Codec/LazyBSONArrayCodec.php

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
<?php
2+
3+
namespace MongoDB\Codec;
4+
5+
use MongoDB\BSON\PackedArray;
6+
use MongoDB\Exception\UnexpectedValueException;
7+
use MongoDB\Model\LazyBSONArray;
8+
9+
use function array_values;
10+
use function sprintf;
11+
12+
/**
13+
* Codec for lazy decoding of BSON PackedArray instances
14+
*
15+
* @template-implements Codec<PackedArray, LazyBSONArray>
16+
*/
17+
class LazyBSONArrayCodec implements Codec, KnowsCodecLibrary
18+
{
19+
/** @var CodecLibrary|null */
20+
private $library = null;
21+
22+
public function attachLibrary(CodecLibrary $library): void
23+
{
24+
$this->library = $library;
25+
}
26+
27+
/** @inheritDoc */
28+
public function canDecode($value): bool
29+
{
30+
return $value instanceof PackedArray;
31+
}
32+
33+
/** @inheritDoc */
34+
public function canEncode($value): bool
35+
{
36+
return $value instanceof LazyBSONArray;
37+
}
38+
39+
/** @inheritDoc */
40+
public function decode($value): LazyBSONArray
41+
{
42+
if (! $value instanceof PackedArray) {
43+
throw new UnexpectedValueException(sprintf('"%s" can only decode from "%s" instances', self::class, PackedArray::class));
44+
}
45+
46+
return new LazyBSONArray($value, $this->getLibrary());
47+
}
48+
49+
/** @inheritDoc */
50+
public function encode($value): PackedArray
51+
{
52+
if (! $value instanceof LazyBSONArray) {
53+
throw new UnexpectedValueException(sprintf('"%s" can only encode "%s" instances', self::class, LazyBSONArray::class));
54+
}
55+
56+
$return = [];
57+
foreach ($value as $offset => $offsetValue) {
58+
$return[$offset] = $this->getLibrary()->canEncode($offsetValue) ? $this->getLibrary()->encode($offsetValue) : $offsetValue;
59+
}
60+
61+
return PackedArray::fromPHP(array_values($return));
62+
}
63+
64+
private function getLibrary(): CodecLibrary
65+
{
66+
return $this->library ?? $this->library = new CodecLibrary(new LazyBSONDocumentCodec(), $this);
67+
}
68+
}

src/Codec/LazyBSONDocumentCodec.php

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
<?php
2+
3+
namespace MongoDB\Codec;
4+
5+
use MongoDB\BSON\Document;
6+
use MongoDB\Exception\UnexpectedValueException;
7+
use MongoDB\Model\LazyBSONDocument;
8+
9+
use function sprintf;
10+
11+
/**
12+
* Codec for lazy decoding of BSON Document instances
13+
*
14+
* @template-implements Codec<Document, LazyBSONDocument>
15+
*/
16+
class LazyBSONDocumentCodec implements Codec, KnowsCodecLibrary
17+
{
18+
/** @var CodecLibrary|null */
19+
private $library = null;
20+
21+
public function attachLibrary(CodecLibrary $library): void
22+
{
23+
$this->library = $library;
24+
}
25+
26+
/** @inheritDoc */
27+
public function canDecode($value): bool
28+
{
29+
return $value instanceof Document;
30+
}
31+
32+
/** @inheritDoc */
33+
public function canEncode($value): bool
34+
{
35+
return $value instanceof LazyBSONDocument;
36+
}
37+
38+
/** @inheritDoc */
39+
public function decode($value): LazyBSONDocument
40+
{
41+
if (! $value instanceof Document) {
42+
throw new UnexpectedValueException(sprintf('"%s" can only decode from "%s" instances', self::class, Document::class));
43+
}
44+
45+
return new LazyBSONDocument($value, $this->getLibrary());
46+
}
47+
48+
/** @inheritDoc */
49+
public function encode($value): Document
50+
{
51+
if (! $value instanceof LazyBSONDocument) {
52+
throw new UnexpectedValueException(sprintf('"%s" can only encode "%s" instances', self::class, LazyBSONDocument::class));
53+
}
54+
55+
$return = [];
56+
foreach ($value as $field => $fieldValue) {
57+
$return[$field] = $this->getLibrary()->canEncode($fieldValue) ? $this->getLibrary()->encode($fieldValue) : $fieldValue;
58+
}
59+
60+
return Document::fromPHP($return);
61+
}
62+
63+
private function getLibrary(): CodecLibrary
64+
{
65+
return $this->library ?? $this->library = new CodecLibrary($this, new LazyBSONArrayCodec());
66+
}
67+
}

src/Model/AsListIterator.php

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<?php
2+
3+
namespace MongoDB\Model;
4+
5+
use IteratorIterator;
6+
use Traversable;
7+
8+
/**
9+
* @internal
10+
* @template TKey as int
11+
* @template TValue
12+
* @template TIterator as Traversable<TKey, TValue>
13+
*
14+
* @template-extends IteratorIterator<int, TValue, TIterator>
15+
*/
16+
final class AsListIterator extends IteratorIterator
17+
{
18+
/** @var int */
19+
private $index = 0;
20+
21+
public function key(): ?int
22+
{
23+
return $this->valid() ? $this->index : null;
24+
}
25+
26+
public function next(): void
27+
{
28+
$this->index++;
29+
30+
parent::next();
31+
}
32+
33+
public function rewind(): void
34+
{
35+
$this->index = 0;
36+
37+
parent::rewind();
38+
}
39+
}

src/Model/CallbackIterator.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ public function __construct(Traversable $traversable, Closure $callback)
4949
#[ReturnTypeWillChange]
5050
public function current()
5151
{
52-
return ($this->callback)($this->iterator->current());
52+
return ($this->callback)($this->iterator->current(), $this->iterator->key());
5353
}
5454

5555
/**

0 commit comments

Comments
 (0)