Skip to content

Commit

Permalink
Merge pull request #400 from nextras/many_has_many
Browse files Browse the repository at this point in the history
Many has many bugfixes
  • Loading branch information
hrach committed Apr 5, 2020
2 parents 0d8b1c3 + 391d3ec commit 6eee323
Show file tree
Hide file tree
Showing 17 changed files with 148 additions and 251 deletions.
1 change: 1 addition & 0 deletions .gitignore
@@ -1,3 +1,4 @@
/vendor
/composer.lock
/phpstan.neon
/.idea
1 change: 1 addition & 0 deletions composer.json
Expand Up @@ -20,6 +20,7 @@
},
"require": {
"php": ">=7.1",
"ext-json": "*",
"nette/caching": "~2.5 || ~3.0@rc",
"nette/utils": "~2.5 || ~3.0@rc",
"nette/tokenizer": "~2.3 || ~3.0@rc",
Expand Down
1 change: 0 additions & 1 deletion readme.md
Expand Up @@ -18,7 +18,6 @@ Supported platforms:
### Docs & sources

- [Documentation](https://nextras.org/orm/docs)
- [Api Documentation](https://codedoc.pub/nextras/orm)
- [Demo - source code](https://github.com/nextras/orm-demo)
- [Talk at Posledni sobota](https://www.youtube.com/watch?v=6MnONy6DTLs) (czech)

Expand Down
2 changes: 1 addition & 1 deletion src/Collection/ArrayCollection.php
Expand Up @@ -21,7 +21,7 @@

class ArrayCollection implements ICollection
{
/** @var array of callbacks with (\Traversable $entities) arugments */
/** @var array of callbacks with (\Traversable $entities) arguments */
public $onEntityFetch = [];

/** @var array */
Expand Down
2 changes: 1 addition & 1 deletion src/Collection/DbalCollection.php
Expand Up @@ -23,7 +23,7 @@

class DbalCollection implements ICollection
{
/** @var array of callbacks with (\Traversable $entities) arugments */
/** @var array of callbacks with (\Traversable $entities) arguments */
public $onEntityFetch = [];

/** @var IRelationshipMapper|null */
Expand Down
22 changes: 10 additions & 12 deletions src/Mapper/Dbal/DbalMapper.php
Expand Up @@ -197,12 +197,10 @@ public function createCollectionOneHasOne(PropertyMetadata $metadata): ICollecti
}


public function createCollectionManyHasMany(IMapper $mapperTwo, PropertyMetadata $metadata): ICollection
public function createCollectionManyHasMany(IMapper $sourceMapper, PropertyMetadata $metadata): ICollection
{
assert($metadata->relationship !== null);
$targetMapper = $metadata->relationship->isMain ? $mapperTwo : $this;
return $targetMapper->findAll()->setRelationshipMapper(
$this->getRelationshipMapper(Relationship::MANY_HAS_MANY, $metadata, $mapperTwo)
return $this->findAll()->setRelationshipMapper(
$this->getRelationshipMapper(Relationship::MANY_HAS_MANY, $metadata, $sourceMapper)
);
}

Expand All @@ -216,23 +214,23 @@ public function createCollectionOneHasMany(PropertyMetadata $metadata): ICollect


protected function getRelationshipMapper(
$type,
int $type,
PropertyMetadata $metadata,
IMapper $otherMapper = null
IMapper $sourceMapper = null
): IRelationshipMapper
{
$key = $type . spl_object_hash($metadata) . $metadata->name;
if (!isset($this->cacheRM[$key])) {
$this->cacheRM[$key] = $this->createRelationshipMapper($type, $metadata, $otherMapper);
$this->cacheRM[$key] = $this->createRelationshipMapper($type, $metadata, $sourceMapper);
}
return $this->cacheRM[$key];
}


protected function createRelationshipMapper(
$type,
int $type,
PropertyMetadata $metadata,
IMapper $otherMapper = null
IMapper $sourceMapper = null
): IRelationshipMapper
{
switch ($type) {
Expand All @@ -241,8 +239,8 @@ protected function createRelationshipMapper(
case Relationship::ONE_HAS_ONE:
return new RelationshipMapperOneHasOne($this->connection, $this, $metadata);
case Relationship::MANY_HAS_MANY:
assert($otherMapper instanceof DbalMapper);
return new RelationshipMapperManyHasMany($this->connection, $this, $otherMapper, $this->mapperCoordinator, $metadata);
assert($sourceMapper instanceof DbalMapper);
return new RelationshipMapperManyHasMany($this->connection, $this, $sourceMapper, $this->mapperCoordinator, $metadata);
case Relationship::ONE_HAS_MANY:
return new RelationshipMapperOneHasMany($this->connection, $this, $metadata);
default:
Expand Down
29 changes: 16 additions & 13 deletions src/Mapper/Dbal/RelationshipMapperManyHasMany.php
Expand Up @@ -20,6 +20,13 @@
use Nextras\Orm\Entity\Reflection\PropertyMetadata;
use Nextras\Orm\LogicException;
use Nextras\Orm\Mapper\IRelationshipMapperManyHasMany;
use function array_keys;
use function array_merge;
use function assert;
use function count;
use function implode;
use function json_encode;
use function md5;


class RelationshipMapperManyHasMany implements IRelationshipMapperManyHasMany
Expand Down Expand Up @@ -52,31 +59,27 @@ class RelationshipMapperManyHasMany implements IRelationshipMapperManyHasMany
private $mapperCoordinator;


public function __construct(IConnection $connection, DbalMapper $mapperOne, DbalMapper $mapperTwo, DbalMapperCoordinator $mapperCoordinator, PropertyMetadata $metadata)
public function __construct(IConnection $connection, DbalMapper $mapper, DbalMapper $sourceMapper, DbalMapperCoordinator $mapperCoordinator, PropertyMetadata $metadata)
{
assert($metadata->relationship !== null);
$this->connection = $connection;
$this->targetMapper = $mapper;
$this->metadata = $metadata;
$this->mapperCoordinator = $mapperCoordinator;

if ($metadata->relationship->isMain) {
$parameters = $mapperOne->getManyHasManyParameters($metadata, $mapperTwo);
$parameters = $sourceMapper->getManyHasManyParameters($metadata, $mapper);
$this->joinTable = $parameters[0];
[$this->primaryKeyFrom, $this->primaryKeyTo] = $parameters[1];
} else {
assert($metadata->relationship->property !== null);
$parameters = $mapperOne->getManyHasManyParameters(
$parameters = $mapper->getManyHasManyParameters(
$metadata->relationship->entityMetadata->getProperty($metadata->relationship->property),
$mapperTwo
$sourceMapper
);
}
$this->joinTable = $parameters[0];

if ($metadata->relationship->isMain) {
$this->targetMapper = $mapperTwo;
[$this->primaryKeyFrom, $this->primaryKeyTo] = $parameters[1];
} else {
$this->targetMapper = $mapperOne;
$this->joinTable = $parameters[0];
[$this->primaryKeyTo, $this->primaryKeyFrom] = $parameters[1];
}
$this->mapperCoordinator = $mapperCoordinator;
}


Expand Down
2 changes: 1 addition & 1 deletion src/Mapper/IMapper.php
Expand Up @@ -37,7 +37,7 @@ public function createCollectionOneHasOne(PropertyMetadata $metadata): ICollecti
/**
* Creates collection with ManyHasMany mapper.
*/
public function createCollectionManyHasMany(IMapper $mapper, PropertyMetadata $metadata): ICollection;
public function createCollectionManyHasMany(IMapper $sourceMapper, PropertyMetadata $metadata): ICollection;


/**
Expand Down
10 changes: 5 additions & 5 deletions src/Mapper/Memory/ArrayMapper.php
Expand Up @@ -20,6 +20,7 @@
use Nextras\Orm\Mapper\MapperRepositoryTrait;
use Nextras\Orm\Mapper\Memory\Conventions\Conventions;
use Nextras\Orm\Mapper\Memory\Conventions\IConventions;
use function assert;


abstract class ArrayMapper implements IMapper
Expand Down Expand Up @@ -78,12 +79,11 @@ public function createCollectionOneHasOne(PropertyMetadata $metadata): ICollecti
}


public function createCollectionManyHasMany(IMapper $mapperTwo, PropertyMetadata $metadata): ICollection
public function createCollectionManyHasMany(IMapper $sourceMapper, PropertyMetadata $metadata): ICollection
{
assert($metadata->relationship !== null);
$targetMapper = $metadata->relationship->isMain ? $mapperTwo : $this;
$collection = $targetMapper->findAll();
$collection->setRelationshipMapper(new RelationshipMapperManyHasMany($metadata, $this));
assert($sourceMapper instanceof ArrayMapper);
$collection = $this->findAll();
$collection->setRelationshipMapper(new RelationshipMapperManyHasMany($this, $sourceMapper, $metadata));
return $collection;
}

Expand Down
16 changes: 11 additions & 5 deletions src/Mapper/Memory/RelationshipMapperManyHasMany.php
Expand Up @@ -14,21 +14,27 @@
use Nextras\Orm\Entity\IEntity;
use Nextras\Orm\Entity\Reflection\PropertyMetadata;
use Nextras\Orm\Mapper\IRelationshipMapperManyHasMany;
use function assert;


class RelationshipMapperManyHasMany implements IRelationshipMapperManyHasMany
{
/** @var PropertyMetadata */
protected $metadata;

/** @var ArrayMapper */
protected $mapper;

/** @var PropertyMetadata */
protected $metadata;


public function __construct(PropertyMetadata $metadata, ArrayMapper $mapper)
public function __construct(ArrayMapper $mapper, ArrayMapper $sourceMapper, PropertyMetadata $metadata)
{
assert($metadata->relationship !== null);
if ($metadata->relationship->isMain) {
$this->mapper = $mapper;
} else {
$this->mapper = $sourceMapper;
}
$this->metadata = $metadata;
$this->mapper = $mapper;
}


Expand Down
6 changes: 5 additions & 1 deletion src/Relationships/HasMany.php
Expand Up @@ -18,6 +18,10 @@
use Nextras\Orm\InvalidStateException;
use Nextras\Orm\Mapper\IRelationshipMapper;
use Nextras\Orm\Repository\IRepository;
use function assert;
use function is_array;
use function iterator_count;
use function spl_object_hash;


abstract class HasMany implements IRelationshipCollection
Expand Down Expand Up @@ -64,7 +68,7 @@ abstract class HasMany implements IRelationshipCollection

public function __construct(PropertyMetadata $metadata)
{
\assert($metadata->relationship !== null);
assert($metadata->relationship !== null);
$this->metadata = $metadata;
$this->metadataRelationship = $metadata->relationship;
}
Expand Down
22 changes: 10 additions & 12 deletions src/Relationships/ManyHasMany.php
Expand Up @@ -11,6 +11,8 @@
use Nextras\Orm\Collection\ICollection;
use Nextras\Orm\Entity\IEntity;
use Traversable;
use function assert;
use function spl_object_hash;


class ManyHasMany extends HasMany
Expand Down Expand Up @@ -43,12 +45,13 @@ public function doPersist()
$this->toRemove = [];
$this->isModified = false;
$this->collection = null;

if ($this->metadataRelationship->isMain) {
$this->getRelationshipMapper()->clearCache();
$this->getRelationshipMapper()->remove($this->parent, $toRemove);
$this->getRelationshipMapper()->add($this->parent, $toAdd);
}

$this->getRelationshipMapper()->clearCache();
$this->relationshipMapper = null;
}


Expand All @@ -60,14 +63,6 @@ protected function modify(): void

protected function createCollection(): ICollection
{
if ($this->metadataRelationship->isMain) {
$mapperOne = $this->parent->getRepository()->getMapper();
$mapperTwo = $this->getTargetRepository()->getMapper();
} else {
$mapperOne = $this->getTargetRepository()->getMapper();
$mapperTwo = $this->parent->getRepository()->getMapper();
}

/** @phpstan-var callable(Traversable<mixed,IEntity>):void $subscribeCb */
$subscribeCb = function (Traversable $entities) {
if (!$this->metadataRelationship->property) {
Expand All @@ -78,8 +73,9 @@ protected function createCollection(): ICollection
$this->trackEntity($entity);
}
};
$mapper = $this->parent->getRepository()->getMapper();

$collection = $mapperOne->createCollectionManyHasMany($mapperTwo, $this->metadata);
$collection = $this->getTargetRepository()->getMapper()->createCollectionManyHasMany($mapper, $this->metadata);
$collection = $collection->setRelationshipParent($this->parent);
$collection->subscribeOnEntityFetch($subscribeCb);
return $this->applyDefaultOrder($collection);
Expand Down Expand Up @@ -109,7 +105,9 @@ protected function updateRelationshipRemove(IEntity $entity): void
$otherSide = $entity->getProperty($this->metadataRelationship->property);
assert($otherSide instanceof ManyHasMany);
$otherSide->collection = null;
$otherSide->toRemove[spl_object_hash($this->parent)] = $this->parent;
$entityHash = spl_object_hash($this->parent);
$otherSide->toRemove[$entityHash] = $this->parent;
unset($otherSide->tracked[$entityHash]);
$otherSide->modify();
}
}

0 comments on commit 6eee323

Please sign in to comment.