Last active
August 29, 2016 17:13
-
-
Save koemeet/237e54f51c59e7b793a8 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* (c) Steffen Brem <steffenbrem@gmail.com> | |
* | |
* For the full copyright and license information, please view the LICENSE | |
* file that was distributed with this source code. | |
*/ | |
namespace Mango\Bundle\ContentBundle\EventListener\PHPCR; | |
use Doctrine\Common\Collections\ArrayCollection; | |
use Doctrine\Common\EventSubscriber; | |
use Doctrine\Common\Persistence\Event\LifecycleEventArgs; | |
use Doctrine\Common\Persistence\Event\ManagerEventArgs; | |
use Doctrine\ODM\PHPCR\DocumentManager; | |
use Doctrine\ODM\PHPCR\Mapping\ClassMetadata; | |
use Doctrine\ORM\EntityManager; | |
use Gedmo\References\LazyCollection; | |
/** | |
* AbstractReferenceListener | |
* | |
* @author Steffen Brem <steffenbrem@gmail.com> | |
*/ | |
abstract class AbstractReferenceListener implements EventSubscriber | |
{ | |
protected $em; | |
private $_scheduledInserts = []; | |
private $_scheduledUpdates = []; | |
/** | |
* @param EntityManager $em | |
*/ | |
public function __construct(EntityManager $em) | |
{ | |
$this->em = $em; | |
} | |
/** | |
* Returns an array of events this subscriber wants to listen to. | |
* | |
* @return array | |
*/ | |
public function getSubscribedEvents() | |
{ | |
return [ | |
'prePersist', | |
'preUpdate', | |
'postLoad', | |
'onFlush', | |
'postFlush', | |
]; | |
} | |
/** | |
* @param LifecycleEventArgs $event | |
*/ | |
public function prePersist(LifecycleEventArgs $event) | |
{ | |
$object = $event->getObject(); | |
if (!$this->supports($object)) { | |
return; | |
} | |
/** @var ClassMetadata $metadata */ | |
$metadata = $event->getObjectManager()->getClassMetadata(get_class($object)); | |
$value = $this->getReferenceId($object); | |
if (!$metadata->hasField($this->getFieldName())) { | |
throw new \RuntimeException(sprintf( | |
'Class "%s" doesn\'t have the property "%s" mapped, add this field mapping to your doctrine mapping.', | |
get_class($object), | |
$this->getFieldName() | |
)); | |
} | |
$metadata->setFieldValue($object, $this->getFieldName(), $value); | |
} | |
/** | |
* @param LifecycleEventArgs $event | |
*/ | |
public function preUpdate(LifecycleEventArgs $event) | |
{ | |
$this->prePersist($event); | |
} | |
/** | |
* @param LifecycleEventArgs $event | |
*/ | |
public function postLoad(LifecycleEventArgs $event) | |
{ | |
$object = $event->getObject(); | |
if (!$this->supports($object)) { | |
return; | |
} | |
/** @var ClassMetadata $metadata */ | |
$metadata = $event->getObjectManager()->getClassMetadata(get_class($object)); | |
$id = $metadata->getFieldValue($object, $this->getFieldName()); | |
$prop = $metadata->getReflectionClass()->getProperty($this->getFieldName()); | |
$prop->setAccessible(true); | |
if (is_array($id)) { | |
$prop->setValue($object, new LazyCollection( | |
function () use ($id) { | |
if (count($id) > 0) { | |
$results = $this->em | |
->getRepository($this->getClassName()) | |
->findBy([ | |
'id' => $id, | |
]) | |
; | |
} else { | |
$results = []; | |
} | |
return new ArrayCollection((is_array($results) ? $results : $results->toArray())); | |
} | |
)); | |
} else { | |
$prop->setValue($object, $this->em->getReference( | |
$this->getClassName(), | |
$id | |
)); | |
} | |
} | |
/** | |
* Keep track of what documents where updated or inserted, whe need to refresh those later. | |
* | |
* @param ManagerEventArgs $event | |
*/ | |
public function onFlush(ManagerEventArgs $event) | |
{ | |
$manager = $event->getObjectManager(); | |
if ($manager instanceof DocumentManager) { | |
$uow = $manager->getUnitOfWork(); | |
$this->_scheduledInserts = $uow->getScheduledInserts(); | |
$this->_scheduledUpdates = $uow->getScheduledUpdates(); | |
} | |
} | |
/** | |
* Refresh document after insert and update. | |
* | |
* @param ManagerEventArgs $event | |
*/ | |
public function postFlush(ManagerEventArgs $event) | |
{ | |
$manager = $event->getObjectManager(); | |
if ($manager instanceof DocumentManager) { | |
foreach ($this->_scheduledInserts as $document) { | |
if ($this->supports($document)) { | |
$manager->refresh($document); | |
} | |
} | |
foreach ($this->_scheduledUpdates as $document) { | |
if ($this->supports($document)) { | |
$manager->refresh($document); | |
} | |
} | |
} | |
} | |
/** | |
* @return string | |
*/ | |
abstract protected function getClassName(); | |
/** | |
* @return mixed | |
*/ | |
abstract protected function getFieldName(); | |
/** | |
* @param $object | |
* | |
* @return mixed | |
*/ | |
abstract protected function getReferenceId($object); | |
/** | |
* @param $object | |
* | |
* @return bool | |
*/ | |
abstract protected function supports($object); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* (c) Steffen Brem <steffenbrem@gmail.com> | |
* | |
* For the full copyright and license information, please view the LICENSE | |
* file that was distributed with this source code. | |
*/ | |
namespace Mango\Bundle\ContentBundle\EventListener\PHPCR; | |
use Mango\Component\Core\Model\Channel; | |
use Sylius\Component\Channel\Model\ChannelsAwareInterface; | |
/** | |
* ChannelsReferenceListener | |
* | |
* @author Steffen Brem <steffenbrem@gmail.com> | |
*/ | |
class ChannelsReferenceListener extends AbstractReferenceListener | |
{ | |
protected $fieldName = 'channels'; | |
/** | |
* @return string | |
*/ | |
protected function getClassName() | |
{ | |
return Channel::class; | |
} | |
/** | |
* The field name on the PHPCR document that holds the id(s) of the reference. | |
* | |
* @return mixed | |
*/ | |
protected function getFieldName() | |
{ | |
return $this->fieldName; | |
} | |
/** | |
* Returns the ids of all channels on a `ChannelAware` document. | |
* | |
* @param ChannelsAwareInterface $object | |
* | |
* @return mixed | |
*/ | |
protected function getReferenceId($object) | |
{ | |
$ids = []; | |
foreach ($object->getChannels() as $channel) { | |
$ids[] = $channel->getId(); | |
} | |
return $ids; | |
} | |
/** | |
* Check if the current PHPCR document ($object) is supported by this listener. | |
* | |
* @param $object | |
* | |
* @return bool | |
*/ | |
protected function supports($object) | |
{ | |
return $object instanceof ChannelsAwareInterface; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment