diff --git a/app/config/services.yml b/app/config/services.yml index a3c388a99..e595b7038 100644 --- a/app/config/services.yml +++ b/app/config/services.yml @@ -44,7 +44,8 @@ services: # the list of events listened by that class. # See http://symfony.com/doc/current/event_dispatcher.html#creating-an-event-subscriber app.console_subscriber: - class: AppBundle\EventListener\ConsoleEventSubscriber + class: AppBundle\EventListener\CheckSQLiteEventSubscriber + arguments: ['@doctrine.orm.entity_manager'] tags: - { name: kernel.event_subscriber } diff --git a/src/AppBundle/EventListener/ConsoleEventSubscriber.php b/src/AppBundle/EventListener/CheckSQLiteEventSubscriber.php similarity index 51% rename from src/AppBundle/EventListener/ConsoleEventSubscriber.php rename to src/AppBundle/EventListener/CheckSQLiteEventSubscriber.php index c8f7503cc..6f2a9114e 100644 --- a/src/AppBundle/EventListener/ConsoleEventSubscriber.php +++ b/src/AppBundle/EventListener/CheckSQLiteEventSubscriber.php @@ -11,10 +11,14 @@ namespace AppBundle\EventListener; +use Doctrine\DBAL\Exception\DriverException; +use Doctrine\ORM\EntityManager; use Symfony\Component\Console\ConsoleEvents; use Symfony\Component\Console\Event\ConsoleExceptionEvent; use Symfony\Component\Console\Style\SymfonyStyle; use Symfony\Component\EventDispatcher\EventSubscriberInterface; +use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent; +use Symfony\Component\HttpKernel\KernelEvents; /** * This application uses by default an SQLite database to store its information. @@ -24,8 +28,23 @@ * * @author Javier Eguiluz */ -class ConsoleEventSubscriber implements EventSubscriberInterface +class CheckSQLiteEventSubscriber implements EventSubscriberInterface { + /** + * @var EntityManager + */ + private $entityManager; + + /** + * CheckSQLiteEventSubscriber constructor. + * + * @param EntityManager $entityManager + */ + public function __construct(EntityManager $entityManager) + { + $this->entityManager = $entityManager; + } + // Event Subscribers must define this method to declare the events they // listen to. You can listen to several events, execute more than one method // for each event and set the priority of each event too. @@ -36,6 +55,8 @@ public static function getSubscribedEvents() // Exceptions are one of the events defined by the Console. See the // rest here: http://symfony.com/doc/current/components/console/events.html ConsoleEvents::EXCEPTION => 'handleDatabaseExceptions', + // See: http://api.symfony.com/3.2/Symfony/Component/HttpKernel/KernelEvents.html + KernelEvents::EXCEPTION => 'onKernelException', ]; } @@ -51,10 +72,43 @@ public function handleDatabaseExceptions(ConsoleExceptionEvent $event) $commandNames = ['doctrine:fixtures:load', 'doctrine:database:create', 'doctrine:schema:create', 'doctrine:database:drop']; if (in_array($event->getCommand()->getName(), $commandNames)) { - if (!extension_loaded('sqlite3')) { + if ($this->isSQLitePlatform() && !extension_loaded('sqlite3')) { $io = new SymfonyStyle($event->getInput(), $event->getOutput()); $io->error('This command requires to have the "sqlite3" PHP extension enabled because, by default, the Symfony Demo application uses SQLite to store its information.'); } } } + + /** + * This method is triggered when kernel exception occurs. And checks if sqlite extension is enabled. + * + * @param GetResponseForExceptionEvent $event + */ + public function onKernelException(GetResponseForExceptionEvent $event) + { + $exception = $event->getException(); + // Since any exception thrown during a Twig template rendering is wrapped in a Twig_Error_Runtime. + // We must get the original exception. + $previousException = $exception->getPrevious(); + + // Driver exception may happen in controller or in twig template rendering + $isDriverException = ($exception instanceof DriverException || $previousException instanceof DriverException); + + // Check if SQLite is enabled + if ($isDriverException && $this->isSQLitePlatform() && !extension_loaded('sqlite3')) { + $event->setException(new \Exception('PHP extension "sqlite3" must be enabled because, by default, the Symfony Demo application uses SQLite to store its information.')); + } + } + + /** + * Check if demo application is configured to use SQLite as database. + * + * @return bool + */ + private function isSQLitePlatform() + { + $databasePlatform = $this->entityManager->getConnection()->getDatabasePlatform(); + + return $databasePlatform ? $databasePlatform->getName() === 'sqlite' : false; + } }