Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow multiple relationships to a target entity. #615

Merged
merged 4 commits into from
Apr 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/EventListener/LogRevisionsListener.php
Original file line number Diff line number Diff line change
Expand Up @@ -464,7 +464,8 @@ private function getInsertRevisionSQL(EntityManagerInterface $em, ClassMetadata
*/
private function getInsertJoinTableRevisionSQL(ClassMetadata $class, ClassMetadata $targetClass, array $assoc): string
{
$cacheKey = $class->name.'.'.$targetClass->name;
$cacheKey = $class->name.'.'.$targetClass->name.'.'.$assoc['joinTable']['name'];

if (!isset($this->insertJoinTableRevisionSQL[$cacheKey])
&& isset($assoc['relationToSourceKeyColumns'], $assoc['relationToTargetKeyColumns'], $assoc['joinTable']['name'])) {
$placeholders = ['?', '?'];
Expand Down
93 changes: 93 additions & 0 deletions tests/Fixtures/Relation/ManyToManyMultipleRelationshipEntity.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
<?php

declare(strict_types=1);

/*
* This file is part of the Sonata Project package.
*
* (c) Thomas Rabaix <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Sonata\EntityAuditBundle\Tests\Fixtures\Relation;

use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\DBAL\Types\Types;
use Doctrine\ORM\Mapping as ORM;

#[ORM\Entity]
class ManyToManyMultipleRelationshipEntity
{
/**
* @var int|null
*/
#[ORM\Id]
#[ORM\Column(type: Types::INTEGER)]
#[ORM\GeneratedValue]
protected $id;

/**
* @var string|null
*/
#[ORM\Column(type: Types::STRING)]
protected $title;

/**
* @var Collection<int, ManyToManyMultipleTargetEntity>
*/
#[ORM\ManyToMany(targetEntity: ManyToManyMultipleTargetEntity::class)]
#[ORM\JoinTable(name: 'many_to_many_primary_target')]
protected $primaryTargets = [];

Check failure on line 43 in tests/Fixtures/Relation/ManyToManyMultipleRelationshipEntity.php

View workflow job for this annotation

GitHub Actions / PHPStan

Property Sonata\EntityAuditBundle\Tests\Fixtures\Relation\ManyToManyMultipleRelationshipEntity::$primaryTargets (Doctrine\Common\Collections\Collection<int, Sonata\EntityAuditBundle\Tests\Fixtures\Relation\ManyToManyMultipleTargetEntity>) does not accept default value of type array{}.

Check failure on line 43 in tests/Fixtures/Relation/ManyToManyMultipleRelationshipEntity.php

View workflow job for this annotation

GitHub Actions / Psalm

InvalidPropertyAssignmentValue

tests/Fixtures/Relation/ManyToManyMultipleRelationshipEntity.php:43:33: InvalidPropertyAssignmentValue: $this->primaryTargets with declared type 'Doctrine\Common\Collections\Collection<int, Sonata\EntityAuditBundle\Tests\Fixtures\Relation\ManyToManyMultipleTargetEntity>' cannot be assigned type 'array<never, never>' (see https://psalm.dev/145)

/**
* @var Collection<int, ManyToManyMultipleTargetEntity>
*/
#[ORM\ManyToMany(targetEntity: ManyToManyMultipleTargetEntity::class)]
#[ORM\JoinTable(name: 'many_to_many_secondary_target')]
protected $secondaryTargets;

public function __construct()
{
$this->primaryTargets = new ArrayCollection();
$this->secondaryTargets = new ArrayCollection();
}


public function getId(): ?int
{
return $this->id;
}

public function getTitle(): ?string
{
return $this->title;
}

public function setTitle(string $title): void
{
$this->title = $title;
}

public function getPrimaryTargets(): ArrayCollection|Collection|array

Check failure on line 74 in tests/Fixtures/Relation/ManyToManyMultipleRelationshipEntity.php

View workflow job for this annotation

GitHub Actions / PHPStan

Method Sonata\EntityAuditBundle\Tests\Fixtures\Relation\ManyToManyMultipleRelationshipEntity::getPrimaryTargets() return type has no value type specified in iterable type array.

Check failure on line 74 in tests/Fixtures/Relation/ManyToManyMultipleRelationshipEntity.php

View workflow job for this annotation

GitHub Actions / PHPStan

Method Sonata\EntityAuditBundle\Tests\Fixtures\Relation\ManyToManyMultipleRelationshipEntity::getPrimaryTargets() return type has no value type specified in iterable type array|Doctrine\Common\Collections\Collection.

Check failure on line 74 in tests/Fixtures/Relation/ManyToManyMultipleRelationshipEntity.php

View workflow job for this annotation

GitHub Actions / PHPStan

Method Sonata\EntityAuditBundle\Tests\Fixtures\Relation\ManyToManyMultipleRelationshipEntity::getPrimaryTargets() return type with generic interface Doctrine\Common\Collections\Collection does not specify its types: TKey, T
{
return $this->primaryTargets;
}

public function addPrimaryTarget(ManyToManyMultipleTargetEntity $target): void
{
$this->primaryTargets[] = $target;
}

public function getSecondaryTargets(): ArrayCollection|Collection

Check failure on line 84 in tests/Fixtures/Relation/ManyToManyMultipleRelationshipEntity.php

View workflow job for this annotation

GitHub Actions / PHPStan

Method Sonata\EntityAuditBundle\Tests\Fixtures\Relation\ManyToManyMultipleRelationshipEntity::getSecondaryTargets() return type with generic interface Doctrine\Common\Collections\Collection does not specify its types: TKey, T
{
return $this->secondaryTargets;
}

public function addSecondaryTarget(ManyToManyMultipleTargetEntity $target): void
{
$this->secondaryTargets[] = $target;
}
}
38 changes: 38 additions & 0 deletions tests/Fixtures/Relation/ManyToManyMultipleTargetEntity.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<?php

declare(strict_types=1);

/*
* This file is part of the Sonata Project package.
*
* (c) Thomas Rabaix <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Sonata\EntityAuditBundle\Tests\Fixtures\Relation;

use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\DBAL\Types\Types;
use Doctrine\ORM\Mapping as ORM;

#[ORM\Entity]
class ManyToManyMultipleTargetEntity
{
/**
* @var int|null
*/
#[ORM\Id]
#[ORM\Column(type: Types::INTEGER)]
#[ORM\GeneratedValue]
protected $id;


public function getId(): ?int
{
return $this->id;
}

}
43 changes: 43 additions & 0 deletions tests/RelationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
use Sonata\EntityAuditBundle\Tests\Fixtures\Relation\DataLegalEntity;
use Sonata\EntityAuditBundle\Tests\Fixtures\Relation\DataPrivateEntity;
use Sonata\EntityAuditBundle\Tests\Fixtures\Relation\FoodCategory;
use Sonata\EntityAuditBundle\Tests\Fixtures\Relation\ManyToManyMultipleRelationshipEntity;
use Sonata\EntityAuditBundle\Tests\Fixtures\Relation\ManyToManyMultipleTargetEntity;
use Sonata\EntityAuditBundle\Tests\Fixtures\Relation\OneToOneAuditedEntity;
use Sonata\EntityAuditBundle\Tests\Fixtures\Relation\OneToOneMasterEntity;
use Sonata\EntityAuditBundle\Tests\Fixtures\Relation\OneToOneNotAuditedEntity;
Expand Down Expand Up @@ -65,6 +67,8 @@ final class RelationTest extends BaseTest
DataLegalEntity::class,
DataPrivateEntity::class,
DataContainerEntity::class,
ManyToManyMultipleRelationshipEntity::class,
ManyToManyMultipleTargetEntity::class,
];

protected $auditedEntities = [
Expand All @@ -87,6 +91,8 @@ final class RelationTest extends BaseTest
DataLegalEntity::class,
DataPrivateEntity::class,
DataContainerEntity::class,
ManyToManyMultipleRelationshipEntity::class,
ManyToManyMultipleTargetEntity::class,
];

public function testUndefinedIndexesInUOWForRelations(): void
Expand Down Expand Up @@ -358,6 +364,43 @@ public function testManyToMany(): void
static::assertCount(1, $audited->getOwnedInverse());
}

public function testManyToManyMultipleRelationshipSameTargetEntity(): void
{
$em = $this->getEntityManager();
$auditReader = $this->getAuditManager()->createAuditReader($em);

// create an entity that has multiple many-to-many relationships to the same target entity.

$targetOne = new ManyToManyMultipleTargetEntity();
$targetTwo = new ManyToManyMultipleTargetEntity();

$manyToMany = new ManyToManyMultipleRelationshipEntity();
$manyToMany->setTitle('manyToMany#1');
$manyToMany->addPrimaryTarget($targetOne);
$manyToMany->addSecondaryTarget($targetTwo);

$em->persist($targetOne);
$em->persist($targetTwo);
$em->persist($manyToMany);

$em->flush(); // #1

$manyToManyId = $manyToMany->getId();
static::assertNotNull($manyToManyId);

$audited = $auditReader->find(ManyToManyMultipleRelationshipEntity::class, $manyToManyId, 1);

static::assertNotNull($audited);

// ensure that there is an audited entry for the primaryTargets property
static::assertInstanceOf(Collection::class, $audited->getPrimaryTargets());
static::assertCount(1, $audited->getPrimaryTargets());

// ensure that there is an audited entry for the secondaryTargets property
static::assertInstanceOf(Collection::class, $audited->getSecondaryTargets());
static::assertCount(1, $audited->getSecondaryTargets());
}

/**
* @group mysql
*/
Expand Down
Loading