diff --git a/src/Collection/ArrayCollection.php b/src/Collection/ArrayCollection.php index b9171370..2285445a 100644 --- a/src/Collection/ArrayCollection.php +++ b/src/Collection/ArrayCollection.php @@ -21,8 +21,9 @@ /** * @template E of IEntity * @implements ICollection + * @implements MemoryCollection */ -class ArrayCollection implements ICollection +class ArrayCollection implements ICollection, MemoryCollection { /** * @var callable[] @@ -246,6 +247,12 @@ public function countStored(): int } + public function toMemoryCollection(): MemoryCollection + { + return clone $this; + } + + public function setRelationshipMapper(IRelationshipMapper $mapper = null, IEntity $parent = null): ICollection { $this->relationshipMapper = $mapper; diff --git a/src/Collection/DbalCollection.php b/src/Collection/DbalCollection.php index fc22ec24..6a6abf54 100644 --- a/src/Collection/DbalCollection.php +++ b/src/Collection/DbalCollection.php @@ -266,6 +266,14 @@ public function countStored(): int } + public function toMemoryCollection(): MemoryCollection + { + $collection = clone $this; + $entities = $collection->fetchAll(); + return new ArrayCollection($entities, $this->mapper->getRepository()); + } + + public function setRelationshipMapper(IRelationshipMapper $mapper = null, IEntity $parent = null): ICollection { $this->relationshipMapper = $mapper; diff --git a/src/Collection/EmptyCollection.php b/src/Collection/EmptyCollection.php index f40f9d7b..f5f2e042 100644 --- a/src/Collection/EmptyCollection.php +++ b/src/Collection/EmptyCollection.php @@ -13,8 +13,9 @@ /** * @template E of IEntity * @implements ICollection + * @implements MemoryCollection */ -final class EmptyCollection implements ICollection +final class EmptyCollection implements ICollection, MemoryCollection { /** @var IRelationshipMapper|null */ private $relationshipMapper; @@ -126,6 +127,12 @@ public function count(): int } + public function toMemoryCollection(): MemoryCollection + { + return clone $this; + } + + public function subscribeOnEntityFetch(callable $callback): void { } diff --git a/src/Collection/HasManyCollection.php b/src/Collection/HasManyCollection.php index e7cd658b..e5611d0c 100644 --- a/src/Collection/HasManyCollection.php +++ b/src/Collection/HasManyCollection.php @@ -30,6 +30,9 @@ class HasManyCollection implements ICollection */ public $onEntityFetch = []; + /** @var IRepository */ + private $repository; + /** * @var ICollection * @phpstan-var ICollection @@ -63,6 +66,7 @@ public function __construct( callable $diffCallback ) { + $this->repository = $repository; $this->storageCollection = $innerCollection; $this->diffCallback = $diffCallback; $this->inMemoryCollection = new MutableArrayCollection([], $repository); // @phpstan-ignore-line @@ -213,6 +217,14 @@ public function countStored(): int } + public function toMemoryCollection(): MemoryCollection + { + $collection = clone $this; + $entities = $collection->fetchAll(); + return new ArrayCollection($entities, $this->repository); + } + + public function setRelationshipMapper(IRelationshipMapper $mapper = null): ICollection { $this->storageCollection->setRelationshipMapper($mapper); diff --git a/src/Collection/ICollection.php b/src/Collection/ICollection.php index c7066f12..adff093c 100644 --- a/src/Collection/ICollection.php +++ b/src/Collection/ICollection.php @@ -193,6 +193,13 @@ public function fetchPairs(?string $key = null, ?string $value = null): array; public function getIterator(); + /** + * Fetches requested data and returns MemoryCollection instance with the fetched entities. + * @return MemoryCollection + */ + public function toMemoryCollection(): MemoryCollection; + + /** * Sets relationship mapping over the collection. * @return static diff --git a/src/Collection/MemoryCollection.php b/src/Collection/MemoryCollection.php new file mode 100644 index 00000000..1ff9fe75 --- /dev/null +++ b/src/Collection/MemoryCollection.php @@ -0,0 +1,15 @@ + + */ +interface MemoryCollection extends ICollection +{ +} + diff --git a/src/Relationships/IRelationshipCollection.php b/src/Relationships/IRelationshipCollection.php index bfccf920..2b3c9392 100644 --- a/src/Relationships/IRelationshipCollection.php +++ b/src/Relationships/IRelationshipCollection.php @@ -52,7 +52,7 @@ public function toCollection(): ICollection; /** - * Returns true if colletion was loaded. + * Returns true if collection was loaded. */ public function isLoaded(): bool; diff --git a/tests/cases/integration/Collection/collection.phpt b/tests/cases/integration/Collection/collection.phpt index d6dad77b..19dbf1a1 100644 --- a/tests/cases/integration/Collection/collection.phpt +++ b/tests/cases/integration/Collection/collection.phpt @@ -8,8 +8,13 @@ namespace NextrasTests\Orm\Integration\Collection; +use Nextras\Orm\Collection\ArrayCollection; +use Nextras\Orm\Collection\DbalCollection; +use Nextras\Orm\Collection\EmptyCollection; +use Nextras\Orm\Collection\HasManyCollection; use Nextras\Orm\Collection\ICollection; use Nextras\Orm\Exception\NoResultException; +use NextrasTests\Orm\Author; use NextrasTests\Orm\Book; use NextrasTests\Orm\DataTestCase; use NextrasTests\Orm\Ean; @@ -309,6 +314,40 @@ class CollectionTest extends DataTestCase $books = $this->orm->tagFollowers->findBy(['tag->books->id' => 1]); Assert::count(2, $books); } + + + public function testToArrayCollection(): void + { + $c1 = $this->orm->authors->findAll(); + $c2 = $c1->toMemoryCollection(); + Assert::type(ArrayCollection::class, $c2); + Assert::same($c2->count(), $c1->countStored()); + + $author = $this->orm->authors->getByIdChecked(1); + $c3 = $author->books->toCollection(); + $c4 = $c3->toMemoryCollection(); + if ($this->section === Helper::SECTION_ARRAY) { + Assert::type(ArrayCollection::class, $c3); + } else { + Assert::type(DbalCollection::class, $c3); + } + Assert::type(ArrayCollection::class, $c4); + Assert::same($c4->count(), $c3->countStored()); + + $author->books->add(new Book()); + $c5 = $author->books->toCollection(); + $c6 = $c5->toMemoryCollection(); + Assert::type(HasManyCollection::class, $c5); + Assert::type(ArrayCollection::class, $c6); + Assert::same($c6->count(), $c5->countStored()); + + $author = new Author(); + $c7 = $author->tagFollowers->toCollection(); + $c8 = $c7->toMemoryCollection(); + Assert::type(EmptyCollection::class, $c7); + Assert::type(EmptyCollection::class, $c8); + Assert::same($c8->count(), $c7->countStored()); + } }