Skip to content

Commit

Permalink
[references] use manager registry #821
Browse files Browse the repository at this point in the history
  • Loading branch information
l3pp4rd committed Nov 3, 2013
1 parent decb949 commit c2cb8be
Show file tree
Hide file tree
Showing 7 changed files with 60 additions and 62 deletions.
1 change: 0 additions & 1 deletion lib/Gedmo/Mapping/Annotation/Reference.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
*/
abstract class Reference extends Annotation
{
public $type;
public $class;
public $identifier;
public $mappedBy;
Expand Down
3 changes: 1 addition & 2 deletions lib/Gedmo/References/Mapping/Driver/Annotation.php
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ class Annotation extends AnnotationDriver
public function loadExtensionMetadata(ClassMetadata $meta, ExtensionMetadataInterface $exm)
{
$class = $meta->reflClass;
foreach($this->all as $type => $annotation) {
foreach ($this->all as $type => $annotation) {
foreach ($class->getProperties() as $property) {
if ($meta->isMappedSuperclass && !$property->isPrivate() ||
$meta->isInheritedField($property->name) ||
Expand All @@ -61,7 +61,6 @@ public function loadExtensionMetadata(ClassMetadata $meta, ExtensionMetadataInte
if ($reference = $this->reader->getPropertyAnnotation($property, $annotation)) {
$exm->map($type, $property->getName(), array(
'field' => $property->getName(),
'type' => $reference->type,
'class' => $reference->class,
'identifier' => $reference->identifier,
'mappedBy' => $reference->mappedBy,
Expand Down
85 changes: 34 additions & 51 deletions lib/Gedmo/References/ReferencesListener.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\EventArgs;
use Doctrine\Common\Persistence\ObjectManager;
use Doctrine\Common\Persistence\ManagerRegistry;

/**
* Listener for loading and persisting cross database references.
Expand All @@ -21,27 +22,21 @@
class ReferencesListener extends MappedEventSubscriber
{
/**
* A list of object managers to link references,
* in pairs of
* managerType => ObjectManagerInstance
* Object manager registry
*
* Supported types are "entity" and "document"
*
* @var array
* @var \Doctrine\Common\Persistence\ManagerRegistry
*/
private $managers;
private $managerRegistry;

/**
* Listener can be initialized with a list of managers
* Listener should be initialized with manager registry
* to link references
*
* @param array $managers - list of managers, check above
* @param \Doctrine\Common\Persistence\ManagerRegistry $managerRegistry
*/
public function __construct(array $managers = array())
public function __construct(ManagerRegistry $managerRegistry)
{
foreach ($managers as $type => $manager) {
$this->registerManager($type, $manager);
}
$this->managerRegistry = $managerRegistry;
}

/**
Expand Down Expand Up @@ -86,9 +81,8 @@ public function postLoad(EventArgs $event)
if (isset($mapping['identifier'])) {
$referencedObjectId = $meta->getFieldValue($object, $mapping['identifier']);
if (null !== $referencedObjectId) {
$manager = $this->getManager($mapping['type']);
if (get_class($manager) === get_class($om)) {
throw new UnexpectedValueException("Referenced manager is of the same type: {$mapping['type']}");
if ($om === $manager = $this->getManager($mapping['class'])) {
throw new UnexpectedValueException("Referenced manager manages the same class: {$mapping['class']}, use standard relation mapping");
}
$property->setValue($object, $this->getSingleReference($manager, $mapping['class'], $referencedObjectId));
}
Expand All @@ -100,8 +94,10 @@ public function postLoad(EventArgs $event)
$property->setAccessible(true);
if (isset($mapping['mappedBy'])) {
$id = OMH::getIdentifier($om, $object);
$manager = $this->getManager($mapping['type']);
$class = $mapping['class'];
if ($om === $manager = $this->getManager($mapping['class'])) {
throw new UnexpectedValueException("Referenced manager manages the same class: {$mapping['class']}, use standard relation mapping");
}
$refMeta = $manager->getClassMetadata($class);
$refConfig = $this->getConfiguration($manager, $refMeta->name);
if ($ref = $refConfig->getReferenceMapping('referenceOne', $mapping['mappedBy'])) {
Expand Down Expand Up @@ -147,34 +143,6 @@ protected function getNamespace()
return __NAMESPACE__;
}

/**
* Registeners a $manager of type $type
* to support linking references
*
* @param string $type - document or entity
* @param \Doctrine\Common\Persistence\ObjectManager $om
* @return \Gedmo\References\ReferencesListener
*/
public function registerManager($type, ObjectManager $manager)
{
$this->managers[$type] = $manager;
return $this;
}

/**
* Get a registered manager of $type
*
* @param string $type - document or entity
* @return \Doctrine\Common\Persistence\ObjectManager
*/
public function getManager($type)
{
if (!isset($this->managers[$type])) {
throw new UnexpectedValueException("Object manager for type: {$type} is not registered");
}
return $this->managers[$type];
}

/**
* Get a reference to relation managed by another
* manager $om
Expand All @@ -193,6 +161,20 @@ protected function getSingleReference(ObjectManager $om, $class, $identifier)
return $om->getReference($class, $identifier);
}

/**
* Get object manager from registry which handles $class
*
* @param string $class
* @return \Doctrine\Common\Persistence\ObjectManager
*/
private function getManager($class)
{
if (null === $om = $this->managerRegistry->getManagerForClass($class)) {
throw new UnexpectedValueException("Could not find any manager for object class: {$class}");
}
return $om;
}

/**
* Updates linked references
*
Expand All @@ -210,11 +192,10 @@ private function updateReferences(EventArgs $event)
$property->setAccessible(true);
$referencedObject = $property->getValue($object);
if (is_object($referencedObject)) {
$meta->setFieldValue(
$object,
$mapping['identifier'],
OMH::getIdentifier($this->getManager($mapping['type']), $referencedObject)
);
if ($om === $manager = $this->getManager($mapping['class'])) {
throw new UnexpectedValueException("Referenced manager manages the same class: {$mapping['class']}, use standard relation mapping");
}
$meta->setFieldValue($object, $mapping['identifier'], OMH::getIdentifier($manager, $referencedObject));
}
}
}
Expand All @@ -237,7 +218,9 @@ public function updateManyEmbedReferences(EventArgs $event)
$property->setAccessible(true);

$id = OMH::getIdentifier($om, $object);
$manager = $this->getManager('document');
if ($om === $manager = $this->getManager($mapping['class'])) {
throw new UnexpectedValueException("Referenced manager manages the same class: {$mapping['class']}, use standard relation mapping");
}

$class = $mapping['class'];
$refMeta = $manager->getClassMetadata($class);
Expand Down
2 changes: 1 addition & 1 deletion tests/Gedmo/Fixture/References/ODM/MongoDB/Metadata.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ class Metadata
private $name;

/**
* @Gedmo\ReferenceOne(type="entity", class="Gedmo\Fixture\References\ORM\Category", identifier="categoryId")
* @Gedmo\ReferenceOne(class="Gedmo\Fixture\References\ORM\Category", identifier="categoryId")
*/
private $category;

Expand Down
2 changes: 1 addition & 1 deletion tests/Gedmo/Fixture/References/ODM/MongoDB/Product.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ class Product
private $name;

/**
* @Gedmo\ReferenceMany(type="entity", class="Gedmo\Fixture\References\ORM\StockItem", mappedBy="product")
* @Gedmo\ReferenceMany(class="Gedmo\Fixture\References\ORM\StockItem", mappedBy="product")
*/
private $stockItems;

Expand Down
2 changes: 1 addition & 1 deletion tests/Gedmo/Fixture/References/ORM/StockItem.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ class StockItem
private $quantity;

/**
* @Gedmo\ReferenceOne(type="document", class="Gedmo\Fixture\References\ODM\MongoDB\Product", inversedBy="stockItems", identifier="productId")
* @Gedmo\ReferenceOne(class="Gedmo\Fixture\References\ODM\MongoDB\Product", inversedBy="stockItems", identifier="productId")
*/
private $product;

Expand Down
27 changes: 22 additions & 5 deletions tests/Gedmo/References/ReferenceTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,34 @@ class ReferenceTest extends ObjectManagerTestCase
protected function setUp()
{
$evm = new EventManager;
$evm->addEventSubscriber($this->listener = new ReferencesListener);

$this->dm = $this->createDocumentManager($evm);
$this->listener->registerManager('document', $this->dm);
$registryMock = $this->getMockBuilder("Doctrine\Common\Persistence\ManagerRegistry")
->disableOriginalConstructor()
->getMock();

$this->em = $this->createEntityManager($evm);
$this->dm = $dm = $this->createDocumentManager($evm);
$this->em = $em = $this->createEntityManager($evm);
$this->createSchema($this->em, array(
'Gedmo\Fixture\References\ORM\StockItem',
'Gedmo\Fixture\References\ORM\Category'
));
$this->listener->registerManager('entity', $this->em);
$registryMock
->expects($this->any())
->method('getManagerForClass')
->will($this->returnCallback(function($class) use($dm, $em) {
switch ($class) {
case 'Gedmo\Fixture\References\ORM\StockItem':
case 'Gedmo\Fixture\References\ORM\Category':
return $em;
case 'Gedmo\Fixture\References\ODM\MongoDB\Metadata':
case 'Gedmo\Fixture\References\ODM\MongoDB\Product':
return $dm;
default:
return null;
}
}));
$this->listener = new ReferencesListener($registryMock);
$evm->addEventSubscriber($this->listener);
}

protected function tearDown()
Expand Down

0 comments on commit c2cb8be

Please sign in to comment.