Passed
Push — fix_coverage_in_scrutinizer ( cd0379...a04ba4 )
by Herberto
13:22
created

handleKernelException()   B

Complexity

Conditions 5
Paths 4

Size

Total Lines 15
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 5.0729

Importance

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