Permalink
Browse files

Merge pull request #23 from GeometriaLab/feature/fetchRelations-37093959

Feature/fetch relations 37093959
  • Loading branch information...
2 parents 739bd4c + fdd62de commit 57edcc835e8532f2e1b1db8bac0a134fa20f5a76 @Shumkov Shumkov committed Dec 29, 2012
View
16 library/GeometriaLab/Api/Stdlib/Extractor/Service.php
@@ -7,7 +7,10 @@
Zend\Stdlib\Exception\BadMethodCallException as ZendBadMethodCallException;
use GeometriaLab\Model\ModelInterface,
+ GeometriaLab\Model\Persistent\ModelInterface as PersistentModelInterface,
GeometriaLab\Model\CollectionInterface,
+ GeometriaLab\Model\Collection,
+ GeometriaLab\Model\Persistent\Collection as PersistentCollection,
GeometriaLab\Api\Paginator\ModelPaginator,
GeometriaLab\Api\Stdlib\Extractor\Extractor,
GeometriaLab\Api\Exception\InvalidFieldsException;
@@ -81,10 +84,13 @@ public function extract($data, $fields = array())
if ($data instanceof ModelPaginator) {
$collection = $data->getItems();
- } else if ($data instanceof CollectionInterface) {
+ } elseif ($data instanceof CollectionInterface) {
$collection = $data;
- } else if ($data instanceof ModelInterface) {
- $collection = new \GeometriaLab\Model\Collection();
+ } elseif ($data instanceof PersistentModelInterface) {
+ $collection = new PersistentCollection();
+ $collection->push($data);
+ } elseif ($data instanceof ModelInterface) {
+ $collection = new Collection();
$collection->push($data);
} else {
throw new \InvalidArgumentException('Data must be CollectionInterface, ModelInterface or ModelPaginator');
@@ -108,6 +114,10 @@ public function extract($data, $fields = array())
$dataCollection = array();
$invalidFields = array();
+ if ($collection instanceof PersistentCollection) {
+ $collection->fetchRelations();
+ }
+
foreach ($collection as $model) {
$fieldsData = $extractor->extract($model, $extractFields);
$invalidFields = $extractor->getInvalidFields();
View
94 library/GeometriaLab/Model/Persistent/Collection.php
@@ -5,13 +5,95 @@
class Collection extends \GeometriaLab\Model\Collection implements CollectionInterface
{
/**
- * @todo Implement fetching of nested relations
- * @param array $propertyNames
- * @return CollectionInterface|void
- * @throws \RuntimeException
+ * Fetch models relations
+ *
+ * @param array|string|null $relationNames Array of relation names
+ * @param bool $refresh
+ * @return Collection
*/
- public function fetchRelations(array $propertyNames = array())
+ public function fetchRelations($relationNames = null, $refresh = false)
{
- throw new \RuntimeException('Not implemented yet!');
+ if ($relationNames === null) {
+ $relations = $this->getRelations();
+ if (empty($relations)) {
+ return $this;
+ }
+
+ $relationNames = array_map(function($relation) {
+ return null;
+ }, $relations);
+ }
+
+ $relationNames = $this->parseRelationNames($relationNames);
+
+ foreach ($relationNames as $relationName => $childRelations) {
+ $relation = $this->getRelation($relationName);
+ if ($relation !== null) {
+ $relation->setTargetObjectsToCollection($this, $refresh, $childRelations);
+ }
+ }
+
+ $this->rewind();
+
+ return $this;
+ }
+
+ /**
+ * Parse relation names
+ *
+ * @param array|string|null $relationNames
+ * @return array
+ * @throws \InvalidArgumentException
+ */
+ protected function parseRelationNames($relationNames = null)
+ {
+ $relations = array();
+
+ foreach ((array) $relationNames as $relationName => $childRelations) {
+ if (is_numeric($relationName)) {
+ if (!is_string($childRelations)) {
+ throw new \InvalidArgumentException("Child relation must be a string but " . gettype($childRelations) . " is given.");
+ }
+ $relationName = $childRelations;
+ $childRelations = null;
+ }
+ $relations[$relationName] = $childRelations;
+ }
+
+ return $relations;
+ }
+
+ /**
+ * Get relation by name
+ *
+ * @param string $name Relation name
+ * @return Relation\AbstractRelation|null
+ * @throws \InvalidArgumentException
+ */
+ protected function getRelation($name)
+ {
+ $model = $this->getFirst();
+ if ($model instanceof AbstractModel) {
+ if (!$model->hasRelation($name)) {
+ throw new \InvalidArgumentException("Model doesn't have '{$name}' relation");
+ }
+ return $model->getRelation($name);
+ }
+ return null;
+ }
+
+ /**
+ * Get all relations
+ *
+ * @return Relation\AbstractRelation|null
+ */
+ protected function getRelations()
+ {
+ $model = $this->getFirst();
+ if ($model instanceof AbstractModel) {
+ return $model->getRelations();
+ } else {
+ return array();
+ }
}
}
View
5 library/GeometriaLab/Model/Persistent/CollectionInterface.php
@@ -8,8 +8,9 @@
* Fetch models relations
*
* @abstract
- * @param array $propertyNames
+ * @param array|string|null $relationNames Array of relation names
+ * @param bool $refresh Refresh relations from storage
* @return CollectionInterface
*/
- public function fetchRelations(array $propertyNames = array());
+ public function fetchRelations($relationNames = null, $refresh = false);
}
View
24 library/GeometriaLab/Model/Persistent/Relation/AbstractRelation.php
@@ -3,7 +3,9 @@
namespace GeometriaLab\Model\Persistent\Relation;
use GeometriaLab\Model\ModelInterface,
- GeometriaLab\Model\Persistent\Schema\Property\Relation\AbstractRelation as AbstractRelationProperty;
+ GeometriaLab\Model\Persistent\Schema\Property\Relation\AbstractRelation as AbstractRelationProperty,
+ GeometriaLab\Model\Persistent\Collection,
+ GeometriaLab\Model\Persistent\Mapper\MapperInterface;
abstract class AbstractRelation
{
@@ -64,4 +66,24 @@ public function getOriginModel()
{
return $this->originModel;
}
+
+ /**
+ * Get target mapper object
+ *
+ * @return MapperInterface
+ */
+ public function getTargetMapper()
+ {
+ return call_user_func(array($this->getProperty()->getTargetModelClass(), 'getMapper'));
+ }
+
+ /**
+ * Set target objects to collection models
+ *
+ * @param Collection $collection
+ * @param bool $refresh
+ * @param string $childRelations
+ * @return void
+ */
+ abstract public function setTargetObjectsToCollection(Collection $collection, $refresh = false, $childRelations = null);
}
View
81 library/GeometriaLab/Model/Persistent/Relation/BelongsTo.php
@@ -2,7 +2,8 @@
namespace GeometriaLab\Model\Persistent\Relation;
-use GeometriaLab\Model\Persistent\ModelInterface;
+use GeometriaLab\Model\Persistent\ModelInterface,
+ GeometriaLab\Model\Persistent\Collection;
class BelongsTo extends AbstractRelation
{
@@ -22,9 +23,7 @@ public function getTargetModel($refresh = false)
$originPropertyValue = $this->getOriginModel()->get($this->getProperty()->getOriginProperty());
if ($originPropertyValue !== null) {
- /* @var \GeometriaLab\Model\Persistent\Mapper\MapperInterface $targetMapper */
- $targetMapper = call_user_func(array($this->getProperty()->getTargetModelClass(), 'getMapper'));
-
+ $targetMapper = $this->getTargetMapper();
$condition = array($this->getProperty()->getTargetProperty() => $originPropertyValue);
$query = $targetMapper->createQuery()->where($condition);
@@ -51,7 +50,7 @@ public function setTargetModel(ModelInterface $targetModel = null)
throw new \InvalidArgumentException('Target property is null');
}
- $this->targetModel = false;
+ $this->targetModel = $targetModel;
} else {
$targetPropertyValue = null;
@@ -67,10 +66,82 @@ public function setTargetModel(ModelInterface $targetModel = null)
return $this;
}
+ /**
+ * @return BelongsTo
+ */
public function resetTargetModel()
{
$this->targetModel = false;
return $this;
}
+
+ /**
+ * Doe's it have target model?
+ *
+ * @return bool
+ */
+ public function hasTargetModel()
+ {
+ return $this->targetModel !== false;
+ }
+
+ /**
+ * Set target objects to collection models
+ *
+ * @param Collection $collection
+ * @param bool $refresh
+ * @param string $childRelations
+ * @return void
+ */
+ public function setTargetObjectsToCollection(Collection $collection, $refresh = false, $childRelations = null)
+ {
+ $localModels = array();
+
+ foreach ($collection as $model) {
+ /* @var $model \GeometriaLab\Model\Persistent\AbstractModel */
+ $relation = $model->getRelation($this->getProperty()->getName());
+ if ($relation instanceof HasMany) {
+ $hasTargetModel = $relation->hasTargetModels();
+ } else {
+ $hasTargetModel = $relation->hasTargetModel();
+ }
+ if ($refresh || !$hasTargetModel) {
+ // TODO '0' value will not pass check, should it?
+ $value = $model->get($this->getProperty()->getOriginProperty());
+ if ($value) {
+ $localModels[$value][] = $model;
+ }
+ $relation->resetTargetModel();
+ }
+ }
+
+ if (count($localModels) == 0) {
+ return;
+ }
+
+ $condition = array(
+ $this->getProperty()->getTargetProperty() => array(
+ '$in' => array_keys($localModels)
+ )
+ );
+
+ $targetMapper = $this->getTargetMapper();
+ $query = $targetMapper->createQuery()->where($condition);
+ $targetModels = $targetMapper->getAll($query);
+
+ if ($childRelations !== null) {
+ $targetModels->fetchRelations($childRelations);
+ }
+
+ foreach ($targetModels as $targetModel) {
+ /* @var ModelInterface $targetModel */
+ $targetProperty = $this->getProperty()->getTargetProperty();
+ $relationName = $this->getProperty()->getName();
+ foreach ($localModels[$targetModel->get($targetProperty)] as $localModel) {
+ /* @var ModelInterface $localModel */
+ $localModel->set($relationName, $targetModel);
+ }
+ }
+ }
}
View
94 library/GeometriaLab/Model/Persistent/Relation/HasMany.php
@@ -3,7 +3,9 @@
namespace GeometriaLab\Model\Persistent\Relation;
use GeometriaLab\Model\Persistent\CollectionInterface,
- GeometriaLab\Model\Persistent\Schema\Property\Relation\HasMany as HasManyProperty;
+ GeometriaLab\Model\Persistent\Collection,
+ GeometriaLab\Model\Persistent\Schema\Property\Relation\HasMany as HasManyProperty,
+ GeometriaLab\Model\Persistent\ModelInterface;
class HasMany extends AbstractRelation
{
@@ -19,8 +21,7 @@ class HasMany extends AbstractRelation
public function getTargetModels($refresh = false)
{
if ($refresh || $this->targetModels === false) {
- $targetMapper = call_user_func(array($this->getProperty()->getTargetModelClass(), 'getMapper'));
-
+ $targetMapper = $this->getTargetMapper();
$originPropertyValue = $this->getOriginModel()->get($this->getProperty()->getOriginProperty());
if ($originPropertyValue === null) {
@@ -49,6 +50,26 @@ public function setTargetModels(CollectionInterface $collection)
}
/**
+ * @return HasMany
+ */
+ public function resetTargetModel()
+ {
+ $this->targetModels = false;
+
+ return $this;
+ }
+
+ /**
+ * Doe's it have target models?
+ *
+ * @return bool
+ */
+ public function hasTargetModels()
+ {
+ return $this->targetModels !== false;
+ }
+
+ /**
* @return int
*/
public function removeTargetRelations()
@@ -76,4 +97,71 @@ public function removeTargetRelations()
return count($targetModels);
}
+
+ /**
+ * Set target objects to collection models
+ *
+ * @param Collection $collection
+ * @param bool $refresh
+ * @param string $childRelations
+ * @return void
+ */
+ public function setTargetObjectsToCollection(Collection $collection, $refresh = false, $childRelations = null)
+ {
+ $localModels = array();
+
+ foreach ($collection as $model) {
+ /* @var $model \GeometriaLab\Model\Persistent\AbstractModel */
+ $relation = $model->getRelation($this->getProperty()->getName());
+ if ($relation instanceof HasMany) {
+ $hasTargetModel = $relation->hasTargetModels();
+ } else {
+ $hasTargetModel = $relation->hasTargetModel();
+ }
+ if ($refresh || !$hasTargetModel) {
+ // TODO '0' value will not pass check, should it?
+ $value = $model->get($this->getProperty()->getOriginProperty());
+ if ($value) {
+ $localModels[$value][] = $model;
+ }
+ $relation->resetTargetModel();
+ }
+ }
+
+ if (count($localModels) == 0) {
+ return;
+ }
+
+ $condition = array(
+ $this->getProperty()->getTargetProperty() => array(
+ '$in' => array_keys($localModels)
+ )
+ );
+
+ $targetMapper = $this->getTargetMapper();
+ $query = $targetMapper->createQuery()->where($condition);
+ $targetModels = $targetMapper->getAll($query);
+
+ if ($childRelations !== null) {
+ $targetModels->fetchRelations($childRelations);
+ }
+
+ $targetCollectionClass = get_class($targetModels);
+
+ foreach ($localModels as $value => $models) {
+ /* @var CollectionInterface $targetCollection */
+ $targetCollection = new $targetCollectionClass();
+ $targetProperty = $this->getProperty()->getTargetProperty();
+ foreach ($targetModels as $targetModel) {
+ /* @var ModelInterface $targetModel */
+ if ($targetModel->get($targetProperty) === $value) {
+ $targetCollection->push($targetModel);
+ }
+ }
+ $relationName = $this->getProperty()->getName();
+ foreach ($models as $model) {
+ $model->set($relationName, $targetCollection);
+ }
+ }
+ }
}
View
88 library/GeometriaLab/Model/Persistent/Relation/HasOne.php
@@ -3,7 +3,8 @@
namespace GeometriaLab\Model\Persistent\Relation;
use GeometriaLab\Model\Persistent\ModelInterface,
- GeometriaLab\Model\Persistent\Schema\Property\Relation\HasOne as HasOneProperty;
+ GeometriaLab\Model\Persistent\Schema\Property\Relation\HasOne as HasOneProperty,
+ GeometriaLab\Model\Persistent\Collection;
class HasOne extends AbstractRelation
{
@@ -22,11 +23,7 @@ public function getTargetModel($refresh = false)
$originPropertyValue = $this->getOriginModel()->get($this->getProperty()->getOriginProperty());
if ($originPropertyValue !== null) {
- /**
- * @var \GeometriaLab\Model\Persistent\Mapper\MapperInterface $targetMapper
- */
- $targetMapper = call_user_func(array($this->getProperty()->getTargetModelClass(), 'getMapper'));
-
+ $targetMapper = $this->getTargetMapper();
$condition = array($this->getProperty()->getTargetProperty() => $originPropertyValue);
$query = $targetMapper->createQuery()->where($condition);
@@ -51,6 +48,26 @@ public function setTargetModel(ModelInterface $foreignModel)
}
/**
+ * @return HasOne
+ */
+ public function resetTargetModel()
+ {
+ $this->targetModel = false;
+
+ return $this;
+ }
+
+ /**
+ * Doe's it have target model?
+ *
+ * @return bool
+ */
+ public function hasTargetModel()
+ {
+ return $this->targetModel !== false;
+ }
+
+ /**
* @return int
*/
public function removeTargetRelation()
@@ -76,4 +93,63 @@ public function removeTargetRelation()
return 1;
}
+
+ /**
+ * Set target objects to collection models
+ *
+ * @param Collection $collection
+ * @param bool $refresh
+ * @param string $childRelations
+ * @return void
+ */
+ public function setTargetObjectsToCollection(Collection $collection, $refresh = false, $childRelations = null)
+ {
+ $localModels = array();
+
+ foreach ($collection as $model) {
+ /* @var $model \GeometriaLab\Model\Persistent\AbstractModel */
+ $relation = $model->getRelation($this->getProperty()->getName());
+ if ($relation instanceof HasMany) {
+ $hasTargetModel = $relation->hasTargetModels();
+ } else {
+ $hasTargetModel = $relation->hasTargetModel();
+ }
+ if ($refresh || !$hasTargetModel) {
+ // TODO '0' value will not pass check, should it?
+ $value = $model->get($this->getProperty()->getOriginProperty());
+ if ($value) {
+ $localModels[$value][] = $model;
+ }
+ $relation->resetTargetModel();
+ }
+ }
+
+ if (count($localModels) == 0) {
+ return;
+ }
+
+ $condition = array(
+ $this->getProperty()->getTargetProperty() => array(
+ '$in' => array_keys($localModels)
+ )
+ );
+
+ $targetMapper = $this->getTargetMapper();
+ $query = $targetMapper->createQuery()->where($condition);
+ $targetModels = $targetMapper->getAll($query);
+
+ if ($childRelations !== null) {
+ $targetModels->fetchRelations($childRelations);
+ }
+
+ foreach ($targetModels as $targetModel) {
+ /* @var ModelInterface $targetModel */
+ $targetProperty = $this->getProperty()->getTargetProperty();
+ $relationName = $this->getProperty()->getName();
+ foreach ($localModels[$targetModel->get($targetProperty)] as $localModel) {
+ /* @var ModelInterface $localModel */
+ $localModel->set($relationName, $targetModel);
+ }
+ }
+ }
}
View
18 library/GeometriaLab/Mongo/Model/Mapper.php
@@ -542,10 +542,24 @@ static public function setServiceManager(ZendServiceManager $serviceManager)
protected function transformModelDataForStorage(array $data)
{
if (isset($data['id'])) {
- $data['_id'] = new \MongoId($data['id']);
- if ((string)$data['_id'] != $data['id']) {
+ if (is_array($data['id'])) {
+ foreach ($data['id'] as &$value) {
+ if (is_array($value)) {
+ foreach ($value as &$val) {
+ $val = new \MongoId($val);
+ }
+ } else {
+ $value = new \MongoId($value);
+ }
+ }
$data['_id'] = $data['id'];
+ } else {
+ $data['_id'] = new \MongoId($data['id']);
+ if ((string)$data['_id'] != $data['id']) {
+ $data['_id'] = $data['id'];
+ }
}
+
unset($data['id']);
}
View
177 tests/GeometriaLabTest/Model/Persistent/CollectionTest.php
@@ -2,15 +2,178 @@
namespace GeometriaLabTest\Model\Persistent;
-use GeometriaLab\Model\Persistent\Collection,
- GeometriaLabTest\Model\Persistent\TestModels\Model;
+use GeometriaLabTest\Mongo\AbstractTestCase,
+ GeometriaLabTest\Model\Persistent\TestModels\Relations\Man,
+ GeometriaLabTest\Model\Persistent\TestModels\Relations\Dog,
+ GeometriaLabTest\Model\Persistent\TestModels\Relations\Woman;
-class CollectionTest extends \PHPUnit_Framework_TestCase
+class CollectionTest extends AbstractTestCase
{
- public function testFetchRelations()
+ public function testFetchAllRelations()
{
- $this->setExpectedException('\RuntimeException', 'Not implemented yet!');
- $c = new Collection();
- $c->fetchRelations(array('foo'));
+ $this->createModels();
+ $this->createModels();
+
+ $collection = Man::getMapper()->getAll();
+
+ foreach ($collection as $model) {
+ /* @var Man $model */
+ $this->assertFalse($model->getRelation('dog')->hasTargetModel());
+ $this->assertFalse($model->getRelation('women')->hasTargetModels());
+ }
+
+ $collection->fetchRelations();
+
+ foreach ($collection as $model) {
+ /* @var Man $model */
+ $this->assertTrue($model->getRelation('dog')->hasTargetModel());
+ $this->assertTrue($model->getRelation('women')->hasTargetModels());
+ }
+ }
+
+ public function testFetchOneRelation()
+ {
+ $this->createModels();
+ $this->createModels();
+
+ $collection = Man::getMapper()->getAll();
+
+ foreach ($collection as $model) {
+ /* @var Man $model */
+ $this->assertFalse($model->getRelation('dog')->hasTargetModel());
+ $this->assertFalse($model->getRelation('women')->hasTargetModels());
+ }
+
+ $collection->fetchRelations(
+ 'dog'
+ );
+
+ foreach ($collection as $model) {
+ /* @var Man $model */
+ $this->assertTrue($model->getRelation('dog')->hasTargetModel());
+ $this->assertFalse($model->getRelation('women')->hasTargetModels());
+ }
+ }
+
+ public function testNestedHasOneRelation()
+ {
+ $this->createModels();
+ $this->createModels();
+
+ $collection = Man::getMapper()->getAll();
+
+ foreach ($collection as $model) {
+ /* @var Man $model */
+ $this->assertFalse($model->getRelation('dog')->hasTargetModel());
+ }
+
+ $collection->fetchRelations(array(
+ 'dog' => 'man',
+ ));
+
+ foreach ($collection as $model) {
+ /* @var Man $model */
+ $this->assertTrue($model->getRelation('dog')->hasTargetModel());
+ $this->assertTrue($model->get('dog')->getRelation('man')->hasTargetModel());
+ }
+ }
+
+ public function testNestedBelongsToRelation()
+ {
+ $this->createModels();
+ $this->createModels();
+
+ $collection = Dog::getMapper()->getAll();
+
+ foreach ($collection as $model) {
+ /* @var Dog $model */
+ $this->assertFalse($model->getRelation('man')->hasTargetModel());
+ }
+
+ $collection->fetchRelations(array(
+ 'man' => 'women',
+ ));
+
+ foreach ($collection as $model) {
+ /* @var Dog $model */
+ $this->assertTrue($model->getRelation('man')->hasTargetModel());
+ $this->assertTrue($model->get('man')->getRelation('women')->hasTargetModels());
+
+ foreach ($model->get('man')->get('women') as $woman) {
+ $this->assertInstanceOf('\GeometriaLabTest\Model\Persistent\TestModels\Relations\Woman', $woman);
+ }
+ }
+ }
+
+ public function testNestedHasManyRelation()
+ {
+ $this->createModels();
+ $this->createModels();
+
+ $query = Woman::getMapper()->createQuery();
+ $collection = Woman::getMapper()->getAll($query);
+
+ foreach ($collection as $model) {
+ /* @var Woman $model */
+ $this->assertFalse($model->getRelation('man')->hasTargetModel());
+ }
+
+ $collection->fetchRelations(array(
+ 'man' => 'dog',
+ ));
+
+ foreach ($collection as $model) {
+ /* @var Woman $model */
+ $this->assertTrue($model->getRelation('man')->hasTargetModel());
+ $this->assertTrue($model->get('man')->getRelation('dog')->hasTargetModel());
+ }
+ }
+
+ public function testNotExistentRelation()
+ {
+ $this->setExpectedException("\\InvalidArgumentException", "Model doesn't have 'bad' relation");
+
+ $this->createModels();
+
+ $collection = Woman::getMapper()->getAll();
+ $collection->fetchRelations('bad');
+ }
+
+ public function testBadChildRelationName()
+ {
+ $this->setExpectedException("\\InvalidArgumentException", "Child relation must be a string but integer is given.");
+
+ $this->createModels();
+
+ $collection = Woman::getMapper()->getAll();
+ $collection->fetchRelations(array('man' => 1));
+ }
+
+ protected function createModels()
+ {
+ $philip = new Man(array(
+ 'name' => 'Philip',
+ ));
+ $philip->save();
+
+ $seymour = new Dog(array(
+ 'name' => 'Seymour',
+ 'manId' => $philip->id,
+ ));
+ $seymour->save();
+
+ $michelle = new Woman(array(
+ 'name' => 'Michelle',
+ 'manId' => $philip->id,
+ ));
+ $michelle->save();
+
+ $leela = new Woman(array(
+ 'name' => 'Leela',
+ 'manId' => $philip->id,
+ ));
+ $leela->save();
+
+
}
}
View
18 tests/GeometriaLabTest/Model/Persistent/TestModels/Relations/Dog.php
@@ -0,0 +1,18 @@
+<?php
+
+namespace GeometriaLabTest\Model\Persistent\TestModels\Relations;
+
+use GeometriaLab\Model\Persistent\AbstractModel;
+
+/**
+ * @property string $id {"primary": true}
+ * @property string $name
+ * @property string $manId
+ * @property \GeometriaLabTest\Model\Persistent\TestModels\Relations\Man $man {"relation": "belongsTo", "originProperty": "manId"}
+ *
+ * @method static \GeometriaLab\Mongo\Model\Mapper getMapper() {"mongoInstanceName": "default", "collectionName": "dog"}
+ */
+class Dog extends AbstractModel
+{
+
+}
View
21 tests/GeometriaLabTest/Model/Persistent/TestModels/Relations/Man.php
@@ -0,0 +1,21 @@
+<?php
+
+namespace GeometriaLabTest\Model\Persistent\TestModels\Relations;
+
+use GeometriaLab\Model\Persistent\AbstractModel;
+
+/**
+ * @property string $id {"primary": true}
+ * @property string $name
+ *
+ * @property \GeometriaLabTest\Model\Persistent\TestModels\Relations\Dog $dog {"relation": "hasOne", "targetProperty": "manId"}
+ * @property \GeometriaLab\Model\Persistent\Collection $women {"relation": "hasMany",
+ * "targetProperty": "manId",
+ * "targetModelClass": "\\GeometriaLabTest\\Model\\Persistent\\TestModels\\Relations\\Woman"}
+ *
+ * @method static \GeometriaLab\Mongo\Model\Mapper getMapper() {"mongoInstanceName": "default", "collectionName": "man"}
+ */
+class Man extends AbstractModel
+{
+
+}
View
18 tests/GeometriaLabTest/Model/Persistent/TestModels/Relations/Woman.php
@@ -0,0 +1,18 @@
+<?php
+
+namespace GeometriaLabTest\Model\Persistent\TestModels\Relations;
+
+use GeometriaLab\Model\Persistent\AbstractModel;
+
+/**
+ * @property string $id {"primary": true}
+ * @property string $name
+ * @property string $manId
+ * @property \GeometriaLabTest\Model\Persistent\TestModels\Relations\Man $man {"relation": "belongsTo", "originProperty": "manId"}
+ *
+ * @method static \GeometriaLab\Mongo\Model\Mapper getMapper() {"mongoInstanceName": "default", "collectionName": "woman"}
+ */
+class Woman extends AbstractModel
+{
+
+}

0 comments on commit 57edcc8

Please sign in to comment.