<commit_before><?php
namespace Boekkooi\Bundle\DoctrineEventStoreBundle\Doctrine\ORM\EventListener;

use Boekkooi\Bundle\DoctrineEventStoreBundle\EventStore\EventSource;
use Boekkooi\Bundle\DoctrineEventStoreBundle\Exception\RuntimeException;
use Doctrine\Common\EventSubscriber;
use Doctrine\ORM\Event\LifecycleEventArgs;
use Doctrine\ORM\Event\LoadClassMetadataEventArgs;
use Doctrine\ORM\Events;
use Doctrine\ORM\Mapping\ClassMetadataInfo;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Boekkooi\Bundle\DoctrineEventStoreBundle\Model\Event;

/**
 * @author <NAME> <<EMAIL>>
 */
class EventSourceListener implements EventSubscriber
{
    /**
     * @var ContainerInterface
     */
    private $container;

    /**
     * @var string
     */
    private $eventSourceClass;

    /**
     * @var \ReflectionProperty
     */
    private $eventSourceReflection;

    public function __construct(ContainerInterface $container)
    {
        if (!$container->has('boekkooi.doctrine_event_store.unit_of_work')) {
            throw new \InvalidArgumentException();
        }

        $this->container = $container;
        $this->eventSourceClass = 'Boekkooi\\Bundle\\DoctrineEventStoreBundle\\Model\\EventSource';
    }

    public function getSubscribedEvents()
    {
        return array(
            Events::loadClassMetadata,
            Events::postFlush
        );
    }

    public function loadClassMetadata(LoadClassMetadataEventArgs $event)
    {
        /** @var ClassMetadataInfo $metadata */
        $metadata = $event->getClassMetadata();
        if ($metadata->isMappedSuperclass) {
            return;
        }

        $refl = $metadata->getReflectionClass();
        if ($refl !== null && $refl->isSubclassOf($this->eventSourceClass)) {
            $metadata->addEntityListener(Events::preRemove, __CLASS__, 'preRemoveHandler');
            $metadata->addEntityListener(Events::preFlush, __CLASS__, 'preFlushHandler');
        }
    }

    public function preRemoveHandler(EventSource $object, LifecycleEventArgs $event)
    {
        $this->getUnitOfWork()->save($object);

        $events = $this->getEventSourceEvents($object, $event);
        if (count($events) > 0) {
            return;
        }

        /** @var \Doctrine\ORM\EntityManager $em */
        $em = $event->getObjectManager();
        $insertions = $em->getUnitOfWork()->getScheduledEntityInsertions();
        foreach ($insertions as $insertion) {
            if (!$insertion instanceof Event) {
                continue;
            }
            // So there is a event in the unit of work well done.
            // Thank you doctrine orphan order :|
            if ($insertion->getEventSourceId() === $object->getId()) {
                return;
            }
        }

        throw new RuntimeException('Unable to remove domain model, no removal event was found.');
    }

    public function preFlushHandler(EventSource $object)
    {
        $this->getUnitOfWork()->save($object);
    }

    public function postFlush()
    {
        $this->getUnitOfWork()->dispatch();
    }

    /**
     * @return \Boekkooi\Bundle\DoctrineEventStoreBundle\Doctrine\UnitOfWork
     */
    protected function getUnitOfWork()
    {
        return $this->container->get('boekkooi.doctrine_event_store.unit_of_work');
    }

    protected function getEventSourceEvents($object, LifecycleEventArgs $event)
    {
        if ($this->eventSourceReflection === null) {
            $reflection = $event->getObjectManager()
                ->getClassMetadata($this->eventSourceClass)
                ->getReflectionClass()
                ->getProperty('events');
            $reflection->setAccessible(true);

            $this->eventSourceReflection = $reflection;
        }

        return $this->eventSourceReflection->getValue($object);
    }
}
<commit_msg>Fixed event listener multiple registrations<commit_after><?php
namespace Boekkooi\Bundle\DoctrineEventStoreBundle\Doctrine\ORM\EventListener;

use Boekkooi\Bundle\DoctrineEventStoreBundle\EventStore\EventSource;
use Boekkooi\Bundle\DoctrineEventStoreBundle\Exception\RuntimeException;
use Doctrine\Common\EventSubscriber;
use Doctrine\ORM\Event\LifecycleEventArgs;
use Doctrine\ORM\Event\LoadClassMetadataEventArgs;
use Doctrine\ORM\Events;
use Doctrine\ORM\Mapping\ClassMetadataInfo;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Boekkooi\Bundle\DoctrineEventStoreBundle\Model\Event;

/**
 * @author <NAME> <<EMAIL>>
 */
class EventSourceListener implements EventSubscriber
{
    /**
     * @var ContainerInterface
     */
    private $container;

    /**
     * @var string
     */
    private $eventSourceClass;

    /**
     * @var \ReflectionProperty
     */
    private $eventSourceReflection;

    public function __construct(ContainerInterface $container)
    {
        if (!$container->has('boekkooi.doctrine_event_store.unit_of_work')) {
            throw new \InvalidArgumentException();
        }

        $this->container = $container;
        $this->eventSourceClass = 'Boekkooi\\Bundle\\DoctrineEventStoreBundle\\Model\\EventSource';
    }

    public function getSubscribedEvents()
    {
        return array(
            Events::loadClassMetadata,
            Events::postFlush
        );
    }

    public function loadClassMetadata(LoadClassMetadataEventArgs $event)
    {
        /** @var ClassMetadataInfo $metadata */
        $metadata = $event->getClassMetadata();
        $refl = $metadata->getReflectionClass();
        if ($refl === null || !$refl->isSubclassOf($this->eventSourceClass)) {
            return;
        }
        
        $this->registerEventListener($metadata, Events::preRemove, 'preRemoveHandler');
        $this->registerEventListener($metadata, Events::preFlush, 'preFlushHandler');
    }

    public function preRemoveHandler(EventSource $object, LifecycleEventArgs $event)
    {
        $this->getUnitOfWork()->save($object);

        $events = $this->getEventSourceEvents($object, $event);
        if (count($events) > 0) {
            return;
        }

        /** @var \Doctrine\ORM\EntityManager $em */
        $em = $event->getObjectManager();
        $insertions = $em->getUnitOfWork()->getScheduledEntityInsertions();
        foreach ($insertions as $insertion) {
            if (!$insertion instanceof Event) {
                continue;
            }
            // So there is a event in the unit of work well done.
            // Thank you doctrine orphan order :|
            if ($insertion->getEventSourceId() === $object->getId()) {
                return;
            }
        }

        throw new RuntimeException('Unable to remove domain model, no removal event was found.');
    }

    public function preFlushHandler(EventSource $object)
    {
        $this->getUnitOfWork()->save($object);
    }

    public function postFlush()
    {
        $this->getUnitOfWork()->dispatch();
    }

    /**
     * @return \Boekkooi\Bundle\DoctrineEventStoreBundle\Doctrine\UnitOfWork
     */
    protected function getUnitOfWork()
    {
        return $this->container->get('boekkooi.doctrine_event_store.unit_of_work');
    }

    protected function getEventSourceEvents($object, LifecycleEventArgs $event)
    {
        if ($this->eventSourceReflection === null) {
            $reflection = $event->getObjectManager()
                ->getClassMetadata($this->eventSourceClass)
                ->getReflectionClass()
                ->getProperty('events');
            $reflection->setAccessible(true);

            $this->eventSourceReflection = $reflection;
        }

        return $this->eventSourceReflection->getValue($object);
    }
    
    protected function registerEventListener(ClassMetadataInfo $metadata, $eventName, $method)
    {
        $class = $metadata->fullyQualifiedClassName(__CLASS__);

        // Check if the event listener is not already registered
        $listener = array(
            'class'  => $class,
            'method' => $method
        );
        if (
            isset($metadata->entityListeners[$eventName]) &&
            in_array($listener, $metadata->entityListeners[$eventName])
        ) {
            return;
        }

        // Register listener
        $metadata->addEntityListener($eventName, $class, $method);
    }
}

{'fraction_non_alphanumeric': 0.1189586597565385, 'fraction_numerical': 0.0002410509822827528, 'mean_word_length': 2.621999127018769, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 84, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2764253', 'n_tokens_mistral': 2247, 'n_tokens_neox': 2210, 'n_words': 397}