<?php/* * This file is part of EC-CUBE * * Copyright(c) EC-CUBE CO.,LTD. All Rights Reserved. * * http://www.ec-cube.co.jp/ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */namespace Eccube\EventListener;use Doctrine\DBAL\Connection;use Doctrine\DBAL\TransactionIsolationLevel;use Doctrine\ORM\EntityManager;use Doctrine\ORM\EntityManagerInterface;use Symfony\Component\EventDispatcher\EventSubscriberInterface;use Symfony\Component\HttpKernel\Event\ExceptionEvent;use Symfony\Component\HttpKernel\Event\RequestEvent;use Symfony\Component\HttpKernel\Event\TerminateEvent;use Symfony\Component\HttpKernel\KernelEvents;/** * トランザクション制御のためのListener */class TransactionListener implements EventSubscriberInterface{    /**     * @var EntityManagerInterface     */    protected $em;    /**     * @var bool     */    protected $isEnabled = true;    /**     * TransactionListener constructor.     *     * @param EntityManager $em     * @param bool $isEnabled     */    public function __construct(EntityManagerInterface $em, $isEnabled = true)    {        $this->em = $em;        $this->isEnabled = $isEnabled;    }    /**     * Disable transaction listener.     */    public function disable()    {        $this->isEnabled = false;    }    /**     * Kernel request listener callback.     *     * @param RequestEvent $event     */    public function onKernelRequest(RequestEvent $event)    {        if (!$this->isEnabled) {            log_debug('Transaction Listener is disabled.');            return;        }        if (!$event->isMainRequest()) {            return;        }        /** @var Connection $Connection */        $Connection = $this->em->getConnection();        if (!$Connection->isConnected()) {            $Connection->connect();        }        $Connection->setAutoCommit(false);        $Connection->setTransactionIsolation(TransactionIsolationLevel::READ_COMMITTED);        $this->em->beginTransaction();        log_debug('Begin Transaction.');    }    /**     * Kernel exception listener callback.     *     * @param ExceptionEvent $event     */    public function onKernelException(ExceptionEvent $event)    {        if (!$this->isEnabled) {            log_debug('Transaction Listener is disabled.');            return;        }        if (!$event->isMainRequest()) {            return;        }        if ($this->em->getConnection()->getNativeConnection()->inTransaction()) {            if ($this->em->getConnection()->isRollbackOnly()) {                $this->em->rollback();            }            log_debug('Rollback executed.');        } else {            log_debug('Transaction is not active. Rollback skipped.');        }    }    /**     *  Kernel terminate listener callback.     *     * @param PostResponseEvent $event     */    public function onKernelTerminate(TerminateEvent $event)    {        if (!$this->isEnabled) {            log_debug('Transaction Listener is disabled.');            return;        }        if ($this->em->getConnection()->getNativeConnection()->inTransaction()) {            if ($this->em->getConnection()->isRollbackOnly()) {                $this->em->rollback();                log_debug('Rollback executed.');            } else {                $this->em->commit();                log_debug('Commit executed.');            }        } else {            log_debug('Transaction is not active. Rollback skipped.');        }    }    /**     * Return the events to subscribe to.     *     * @return array     */    public static function getSubscribedEvents()    {        return [            KernelEvents::REQUEST => 'onKernelRequest',            KernelEvents::EXCEPTION => 'onKernelException',            KernelEvents::TERMINATE => 'onKernelTerminate',        ];    }}