src/EventSubscriber/CheckRequirementsSubscriber.php line 60

Open in your IDE?
  1. <?php
  2. /*
  3. * This file is part of the Symfony package.
  4. *
  5. * (c) Fabien Potencier <fabien@symfony.com>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. namespace App\EventSubscriber;
  11. use Doctrine\DBAL\Exception\DriverException;
  12. use Doctrine\ORM\EntityManagerInterface;
  13. use Symfony\Component\Console\ConsoleEvents;
  14. use Symfony\Component\Console\Event\ConsoleErrorEvent;
  15. use Symfony\Component\Console\Style\SymfonyStyle;
  16. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  17. use Symfony\Component\HttpKernel\Event\ExceptionEvent;
  18. use Symfony\Component\HttpKernel\KernelEvents;
  19. /**
  20. * This application uses by default an SQLite database to store its information.
  21. * That's why the 'sqlite3' extension must be enabled in PHP. This event
  22. * subscriber listens to console events and in case of an exception caused by
  23. * a disabled 'sqlite3' extension, it displays a meaningful error message.
  24. *
  25. * @author Javier Eguiluz <javier.eguiluz@gmail.com>
  26. */
  27. class CheckRequirementsSubscriber implements EventSubscriberInterface
  28. {
  29. private $entityManager;
  30. public function __construct(EntityManagerInterface $entityManager)
  31. {
  32. $this->entityManager = $entityManager;
  33. }
  34. // Event Subscribers must define this method to declare the events they
  35. // listen to. You can listen to several events, execute more than one method
  36. // for each event and set the priority of each event too.
  37. // See https://symfony.com/doc/current/event_dispatcher.html#creating-an-event-subscriber
  38. public static function getSubscribedEvents(): array
  39. {
  40. return [
  41. // Errors are one of the events defined by the Console. See the
  42. // rest here: https://symfony.com/doc/current/components/console/events.html
  43. ConsoleEvents::ERROR => 'handleConsoleError',
  44. // See: http://api.symfony.com/master/Symfony/Component/HttpKernel/KernelEvents.html
  45. KernelEvents::EXCEPTION => 'handleKernelException',
  46. ];
  47. }
  48. /**
  49. * This method checks if there has been an error in a command related to
  50. * the database and then, it checks if the 'sqlite3' PHP extension is enabled
  51. * or not to display a better error message.
  52. */
  53. public function handleConsoleError(ConsoleErrorEvent $event): void
  54. {
  55. $commandNames = ['doctrine:fixtures:load', 'doctrine:database:create', 'doctrine:schema:create', 'doctrine:database:drop'];
  56. if ($event->getCommand() && in_array($event->getCommand()->getName(), $commandNames, true)) {
  57. if ($this->isSQLitePlatform() && !extension_loaded('sqlite3')) {
  58. $io = new SymfonyStyle($event->getInput(), $event->getOutput());
  59. $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.');
  60. }
  61. }
  62. }
  63. /**
  64. * This method checks if the triggered exception is related to the database
  65. * and then, it checks if the required 'sqlite3' PHP extension is enabled.
  66. */
  67. public function handleKernelException(ExceptionEvent $event): void
  68. {
  69. $exception = $event->getThrowable();
  70. // Since any exception thrown during a Twig template rendering is wrapped
  71. // in a Twig_Error_Runtime, we must get the original exception.
  72. $previousException = $exception->getPrevious();
  73. // Driver exception may happen in controller or in twig template rendering
  74. $isDriverException = ($exception instanceof DriverException || $previousException instanceof DriverException);
  75. // Check if SQLite is enabled
  76. if ($isDriverException && $this->isSQLitePlatform() && !extension_loaded('sqlite3')) {
  77. $event->setException(new \Exception('PHP extension "sqlite3" must be enabled because, by default, the Symfony Demo application uses SQLite to store its information.'));
  78. }
  79. }
  80. /**
  81. * Checks if the application is using SQLite as its database.
  82. */
  83. private function isSQLitePlatform(): bool
  84. {
  85. $databasePlatform = $this->entityManager->getConnection()->getDatabasePlatform();
  86. return $databasePlatform ? 'sqlite' === $databasePlatform->getName() : false;
  87. }
  88. }