diff --git a/src/EntityMap.php b/src/EntityMap.php index f98b246..6098827 100755 --- a/src/EntityMap.php +++ b/src/EntityMap.php @@ -481,7 +481,9 @@ public function getEmbeddables(): array */ public function getProperties(): array { - return $this->properties; + return get_parent_class(__CLASS__) !== false + ? array_unique(array_merge($this->properties, parent::getProperties())) + : $this->properties; } /** diff --git a/src/System/Proxies/CollectionProxy.php b/src/System/Proxies/CollectionProxy.php index 8b74735..7f0abd0 100644 --- a/src/System/Proxies/CollectionProxy.php +++ b/src/System/Proxies/CollectionProxy.php @@ -3,6 +3,7 @@ namespace Analogue\ORM\System\Proxies; use Analogue\ORM\EntityCollection; +use Analogue\ORM\Relationships\Relationship; use Analogue\ORM\System\Manager; use CachingIterator; use Illuminate\Support\Collection; @@ -73,18 +74,28 @@ public function initializeProxy() : bool return true; } - $relation = $this->relationshipMethod; - $entity = $this->parentEntity; - - $entityMap = Manager::getMapper($entity)->getEntityMap(); - - $this->items = $entityMap->$relation($entity)->getResults($relation)->all() + $this->addedItems; + $this->items = $this->getRelationshipInstance() + ->getResults($this->relationshipMethod)->all() + $this->addedItems; $this->relationshipLoaded = true; return true; } + /** + * Return instance of the underlying relationship. + * + * @return Relationship + */ + protected function getRelationshipInstance() : Relationship + { + $relation = $this->relationshipMethod; + $entity = $this->parentEntity; + $entityMap = Manager::getMapper($entity)->getEntityMap(); + + return $entityMap->$relation($entity); + } + /** * {@inheritdoc} */ @@ -187,6 +198,18 @@ public function diff($items) return $parent->diff($items); } + /** + * {@inheritdoc} + */ + public function diffUsing($items, callable $callback) + { + $this->initializeProxy(); + + $parent = $this->toBaseCollection(); + + return $parent->diff($items, $callback); + } + /** * {@inheritdoc} */ @@ -1109,10 +1132,19 @@ public function getCachingIterator($flags = CachingIterator::CALL_TOSTRING) */ public function count() { - // TODO rely on QB if not initialized - $this->initializeProxy(); + return $this->relationshipLoaded + ? parent::count() + : $this->countUsingDatabaseQuery(); + } - return parent::count(); + /** + * Do a count query and return the result. + * + * @return int + */ + protected function countUsingDatabaseQuery() : int + { + return $this->getRelationshipInstance()->count(); } /** diff --git a/tests/cases/CollectionProxyTest.php b/tests/cases/CollectionProxyTest.php index 2f3b957..528100f 100644 --- a/tests/cases/CollectionProxyTest.php +++ b/tests/cases/CollectionProxyTest.php @@ -1,8 +1,8 @@ assertTrue(true); } + /** @test */ + public function we_can_do_a_count_operation_on_proxy_without_loading_it() + { + $id = $this->createRelatedSet(3); + $user = mapper(User::class)->find($id); + $this->assertFalse($user->groups->isProxyInitialized()); + $this->assertEquals(3, $user->groups->count()); + $this->assertFalse($user->groups->isProxyInitialized()); + $this->assertCount(3, $user->groups->all()); + $this->assertTrue($user->groups->isProxyInitialized()); + } + /** @test */ public function we_can_push_to_a_collection_proxy_without_loading_it() { @@ -66,4 +78,26 @@ public function we_can_push_to_a_collection_proxy_without_loading_it() public function we_can_remove_from_a_lazy_collection_without_loading_it() { } + + /** + * Create a random related set. + * + * @return int + */ + protected function createRelatedSet($relatedCount = 1) + { + $userId = $this->insertUser(); + for ($x = 1; $x <= $relatedCount; $x++) { + $groupId = $this->rawInsert('groups', [ + 'id' => $this->randId(), + 'name' => $this->faker()->sentence, + ]); + $this->rawInsert('groups_users', [ + 'user_id' => $userId, + 'group_id' => $groupId, + ]); + } + + return $userId; + } }