1
0
mirror of synced 2025-01-18 22:41:43 +03:00

Merge pull request #223 from doctrine/DDC-1544

DDC-1544
This commit is contained in:
Benjamin Eberlei 2011-12-17 14:04:54 -08:00
commit bb47e90696
2 changed files with 223 additions and 0 deletions

View File

@ -0,0 +1,94 @@
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\ORM\Tools;
use Doctrine\ORM\Event\LoadClassMetadataEventArgs;
use Doctrine\ORM\Mapping\ClassMetadata;
/**
* ResolveTargetEntityListener
*
* Mechanism to overwrite interfaces or classes specified as association
* targets.
*
* @author Benjamin Eberlei <kontakt@beberlei.de>
* @since 2.2
*/
class ResolveTargetEntityListener
{
/**
* @var array
*/
private $resolveTargetEntities = array();
/**
* Add a target-entity class name to resolve to a new class name.
*
* @param string $originalEntity
* @param string $newEntity
* @param array $mapping
* @return void
*/
public function addResolveTargetEntity($originalEntity, $newEntity, array $mapping)
{
$mapping['targetEntity'] = ltrim($newEntity, "\\");
$this->resolveTargetEntities[ltrim($originalEntity, "\\")] = $mapping;
}
/**
* Process event and resolve new target entity names.
*
* @param LoadClassMetadataEventArgs $args
* @return void
*/
public function loadClassMetadata(LoadClassMetadataEventArgs $args)
{
$cm = $args->getClassMetadata();
foreach ($cm->associationMappings as $assocName => $mapping) {
if (isset($this->resolveTargetEntities[$mapping['targetEntity']])) {
$this->remapAssociation($cm, $mapping);
}
}
}
private function remapAssociation($classMetadata, $mapping)
{
$newMapping = $this->resolveTargetEntities[$mapping['targetEntity']];
$newMapping = array_replace_recursive($mapping, $newMapping);
$newMapping['fieldName'] = $mapping['fieldName'];
unset($classMetadata->associationMappings[$mapping['fieldName']]);
switch ($mapping['type']) {
case ClassMetadata::MANY_TO_MANY:
$classMetadata->mapManyToMany($newMapping);
break;
case ClassMetadata::MANY_TO_ONE:
$classMetadata->mapManyToOne($newMapping);
break;
case ClassMetadata::ONE_TO_MANY:
$classMetadata->mapOneToMany($newMapping);
break;
case ClassMetadata::ONE_TO_ONE:
$classMetadata->mapOneToOne($newMapping);
break;
}
}
}

View File

@ -0,0 +1,129 @@
<?php
namespace Doctrine\Tests\ORM\Tools;
use Doctrine\ORM\Events;
use Doctrine\ORM\Mapping\ClassMetadataFactory;
use Doctrine\ORM\Tools\ResolveTargetEntityListener;
require_once __DIR__ . '/../../TestInit.php';
class ResolveTargetEntityListenerTest extends \Doctrine\Tests\OrmTestCase
{
/**
* @var EntityManager
*/
private $em = null;
/**
* @var ResolveTargetEntityListener
*/
private $listener = null;
/**
* @var ClassMetadataFactory
*/
private $factory = null;
public function setUp()
{
$annotationDriver = $this->createAnnotationDriver();
$this->em = $this->_getTestEntityManager();
$this->em->getConfiguration()->setMetadataDriverImpl($annotationDriver);
$this->factory = new ClassMetadataFactory;
$this->factory->setEntityManager($this->em);
$this->listener = new ResolveTargetEntityListener;
}
/**
* @group DDC-1544
*/
public function testResolveTargetEntityListenerCanResolveTargetEntity()
{
$evm = $this->em->getEventManager();
$this->listener->addResolveTargetEntity(
'Doctrine\Tests\ORM\Tools\ResolveTargetInterface',
'Doctrine\Tests\ORM\Tools\ResolveTargetEntity',
array()
);
$this->listener->addResolveTargetEntity(
'Doctrine\Tests\ORM\Tools\TargetInterface',
'Doctrine\Tests\ORM\Tools\TargetEntity',
array()
);
$evm->addEventListener(Events::loadClassMetadata, $this->listener);
$cm = $this->factory->getMetadataFor('Doctrine\Tests\ORM\Tools\ResolveTargetEntity');
$meta = $cm->associationMappings;
$this->assertSame('Doctrine\Tests\ORM\Tools\TargetEntity', $meta['manyToMany']['targetEntity']);
$this->assertSame('Doctrine\Tests\ORM\Tools\ResolveTargetEntity', $meta['manyToOne']['targetEntity']);
$this->assertSame('Doctrine\Tests\ORM\Tools\ResolveTargetEntity', $meta['oneToMany']['targetEntity']);
$this->assertSame('Doctrine\Tests\ORM\Tools\TargetEntity', $meta['oneToOne']['targetEntity']);
}
}
interface ResolveTargetInterface
{
public function getId();
}
interface TargetInterface extends ResolveTargetInterface
{
}
/**
* @Entity
*/
class ResolveTargetEntity implements ResolveTargetInterface
{
/**
* @Id
* @Column(type="integer")
* @GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @ManyToMany(targetEntity="Doctrine\Tests\ORM\Tools\TargetInterface")
*/
private $manyToMany;
/**
* @ManyToOne(targetEntity="Doctrine\Tests\ORM\Tools\ResolveTargetInterface", inversedBy="oneToMany")
*/
private $manyToOne;
/**
* @OneToMany(targetEntity="Doctrine\Tests\ORM\Tools\ResolveTargetInterface", mappedBy="manyToOne")
*/
private $oneToMany;
/**
* @OneToOne(targetEntity="Doctrine\Tests\ORM\Tools\TargetInterface")
* @JoinColumn(name="target_entity_id", referencedColumnName="id")
*/
private $oneToOne;
public function getId()
{
return $this->id;
}
}
/**
* @Entity
*/
class TargetEntity implements TargetInterface
{
/**
* @Id
* @Column(type="integer")
* @GeneratedValue(strategy="AUTO")
*/
private $id;
public function getId()
{
return $this->id;
}
}