Passed
Push — master ( 846606...e800c8 )
by Kevin
02:41
created

DatabaseResetter   A

Complexity

Total Complexity 24

Size/Duplication

Total Lines 133
Duplicated Lines 0 %

Test Coverage

Coverage 59.65%

Importance

Changes 3
Bugs 1 Features 0
Metric Value
wmc 24
eloc 53
c 3
b 1
f 0
dl 0
loc 133
ccs 34
cts 57
cp 0.5965
rs 10

12 Methods

Rating   Name   Duplication   Size   Complexity  
A isDAMADoctrineTestBundleEnabled() 0 3 2
A hasBeenReset() 0 7 2
A runCommand() 0 9 2
A objectManagersToReset() 0 7 2
A dropSchema() 0 12 3
A createApplication() 0 6 1
A createSchema() 0 17 4
A connectionsToReset() 0 7 2
A dropAndCreateDatabase() 0 14 3
A resetSchema() 0 7 1
A isResetUsingMigrations() 0 3 1
A resetDatabase() 0 9 1
1
<?php
2
3
namespace Zenstruck\Foundry\Test;
4
5
use DAMA\DoctrineTestBundle\Doctrine\DBAL\StaticDriver;
6
use Doctrine\Persistence\ManagerRegistry;
7
use Symfony\Bundle\FrameworkBundle\Console\Application;
8
use Symfony\Component\Console\Input\ArrayInput;
9
use Symfony\Component\Console\Output\BufferedOutput;
10
use Symfony\Component\HttpKernel\KernelInterface;
11
use Zenstruck\Foundry\Factory;
12
13
/**
14
 * @internal
15
 *
16
 * @author Kevin Bond <[email protected]>
17
 */
18
final class DatabaseResetter
19
{
20
    /** @var bool */
21
    private static $hasBeenReset = false;
22
23
    public static function hasBeenReset(): bool
24
    {
25
        if (isset($_SERVER['FOUNDRY_DISABLE_DATABASE_RESET'])) {
26
            return true;
27
        }
28
29
        return self::$hasBeenReset;
30
    }
31
32 634
    public static function isDAMADoctrineTestBundleEnabled(): bool
33
    {
34 634
        return \class_exists(StaticDriver::class) && StaticDriver::isKeepStaticConnections();
35
    }
36
37
    public static function resetDatabase(KernelInterface $kernel): void
38
    {
39
        $application = self::createApplication($kernel);
40
        $registry = $kernel->getContainer()->get('doctrine');
41
42
        self::dropAndCreateDatabase($application, $registry);
0 ignored issues
show
Bug introduced by
It seems like $registry can also be of type null; however, parameter $registry of Zenstruck\Foundry\Test\D...dropAndCreateDatabase() does only seem to accept Doctrine\Persistence\ManagerRegistry, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

42
        self::dropAndCreateDatabase($application, /** @scrutinizer ignore-type */ $registry);
Loading history...
43
        self::createSchema($application, $registry);
0 ignored issues
show
Bug introduced by
It seems like $registry can also be of type null; however, parameter $registry of Zenstruck\Foundry\Test\D...esetter::createSchema() does only seem to accept Doctrine\Persistence\ManagerRegistry, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

43
        self::createSchema($application, /** @scrutinizer ignore-type */ $registry);
Loading history...
44
45
        self::$hasBeenReset = true;
46
    }
47
48
    public static function resetSchema(KernelInterface $kernel): void
49
    {
50
        $application = self::createApplication($kernel);
51
        $registry = $kernel->getContainer()->get('doctrine');
52
53
        self::dropSchema($application, $registry);
0 ignored issues
show
Bug introduced by
It seems like $registry can also be of type null; however, parameter $registry of Zenstruck\Foundry\Test\D...eResetter::dropSchema() does only seem to accept Doctrine\Persistence\ManagerRegistry, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

53
        self::dropSchema($application, /** @scrutinizer ignore-type */ $registry);
Loading history...
54
        self::createSchema($application, $registry);
0 ignored issues
show
Bug introduced by
It seems like $registry can also be of type null; however, parameter $registry of Zenstruck\Foundry\Test\D...esetter::createSchema() does only seem to accept Doctrine\Persistence\ManagerRegistry, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

54
        self::createSchema($application, /** @scrutinizer ignore-type */ $registry);
Loading history...
55
    }
56
57
    private static function isResetUsingMigrations(): bool
58
    {
59
        return 'migrate' === ($_SERVER['FOUNDRY_RESET_MODE'] ?? 'schema');
60
    }
61
62 381
    private static function dropAndCreateDatabase(Application $application, ManagerRegistry $registry): void
63
    {
64 381
        foreach (self::connectionsToReset($registry) as $connection) {
65 381
            $dropParams = ['--connection' => $connection, '--force' => true];
66
67 381
            if ('sqlite' !== $registry->getConnection($connection)->getDatabasePlatform()->getName()) {
68 381
                // sqlite does not support "--if-exists" (ref: https://github.com/doctrine/dbal/pull/2402)
69 381
                $dropParams['--if-exists'] = true;
70
            }
71 381
72
            self::runCommand($application, 'doctrine:database:drop', $dropParams);
73 381
74 381
            self::runCommand($application, 'doctrine:database:create', [
75 381
                '--connection' => $connection,
76
            ]);
77
        }
78
    }
79 381
80 186
    private static function createSchema(Application $application, ManagerRegistry $registry): void
81
    {
82
        if (self::isResetUsingMigrations()) {
83 381
            self::runCommand($application, 'doctrine:migrations:migrate', ['-n' => true]);
84 381
        } else {
85
            foreach (self::objectManagersToReset($registry) as $manager) {
86 381
                self::runCommand($application, 'doctrine:schema:create', [
87
                    '--em' => $manager,
88 381
                ]);
89 381
            }
90 381
        }
91
92
        if (!Factory::isBooted()) {
93
            TestState::bootFromContainer($application->getKernel()->getContainer());
94 381
        }
95
96 381
        TestState::flushGlobalState();
97
    }
98 381
99 381
    private static function dropSchema(Application $application, ManagerRegistry $registry): void
100 381
    {
101
        if (self::isResetUsingMigrations()) {
102
            self::dropAndCreateDatabase($application, $registry);
103 381
104
            return;
105
        }
106 381
107
        foreach (self::objectManagersToReset($registry) as $manager) {
108 381
            self::runCommand($application, 'doctrine:schema:drop', [
109
                '--em' => $manager,
110 381
                '--force' => true,
111 381
            ]);
112
        }
113 381
    }
114
115
    private static function runCommand(Application $application, string $command, array $parameters = []): void
116
    {
117
        $exit = $application->run(
118
            new ArrayInput(\array_merge(['command' => $command], $parameters)),
119
            $output = new BufferedOutput()
120
        );
121
122
        if (0 !== $exit) {
123
            throw new \RuntimeException(\sprintf('Error running "%s": %s', $command, $output->fetch()));
124
        }
125 381
    }
126
127 381
    private static function createApplication(KernelInterface $kernel): Application
128
    {
129
        $application = new Application($kernel);
130
        $application->setAutoExit(false);
131 381
132
        return $application;
133
    }
134
135
    private static function connectionsToReset(ManagerRegistry $registry): array
136
    {
137
        if (isset($_SERVER['FOUNDRY_RESET_CONNECTIONS'])) {
138
            return \explode(',', $_SERVER['FOUNDRY_RESET_CONNECTIONS']);
139
        }
140
141
        return [$registry->getDefaultConnectionName()];
142
    }
143
144
    private static function objectManagersToReset(ManagerRegistry $registry): array
145
    {
146
        if (isset($_SERVER['FOUNDRY_RESET_OBJECT_MANAGERS'])) {
147
            return \explode(',', $_SERVER['FOUNDRY_RESET_OBJECT_MANAGERS']);
148
        }
149
150
        return [$registry->getDefaultManagerName()];
151
    }
152
}
153