<?php
namespace League\Tactician\Doctrine\ORM;
use Doctrine\ORM\EntityManagerInterface;
use League\Tactician\Middleware;
use Exception;
use Throwable;
/**
* Wraps command execution inside a Doctrine ORM transaction
*/
class TransactionMiddleware implements Middleware
{
/**
* @var EntityManagerInterface
*/
private $entityManager;
/**
* @param EntityManagerInterface $entityManager
*/
public function __construct(EntityManagerInterface $entityManager)
{
$this->entityManager = $entityManager;
}
/**
* Executes the given command and optionally returns a value
*
* @param object $command
* @param callable $next
* @return mixed
* @throws Throwable
* @throws Exception
*/
public function execute($command, callable $next)
{
$this->entityManager->beginTransaction();
try {
$returnValue = $next($command);
$this->entityManager->flush();
$this->entityManager->commit();
} catch (Exception $e) {
$this->rollbackTransaction();
throw $e;
} catch (Throwable $e) {
$this->rollbackTransaction();
throw $e;
}
return $returnValue;
}
/**
* Rollback the current transaction and close the entity manager when possible.
*/
protected function rollbackTransaction()
{
$this->entityManager->rollback();
$connection = $this->entityManager->getConnection();
if (!$connection->isTransactionActive() || $connection->isRollbackOnly()) {
$this->entityManager->close();
}
}
}