Failed Conditions
Branch master (d7812f)
by Herberto
07:52
created

createTestDatabaseBackup()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 4
nc 1
nop 1
dl 0
loc 6
ccs 5
cts 5
cp 1
crap 1
rs 9.4285
c 0
b 0
f 0
1
<?php
0 ignored issues
show
Coding Style Compatibility introduced by
For compatibility and reusability of your code, PSR1 recommends that a file should introduce either new symbols (like classes, functions, etc.) or have side-effects (like outputting something, or including other files), but not both at the same time. The first symbol is defined on line 23 and the first side effect is on line 98.

The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.

The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.

To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.

Loading history...
2
3
declare(strict_types=1);
4
5
namespace Hgraca\DoctrineTestDbRegenerationBundle\EventSubscriber;
6
7
use Exception;
8
use Hgraca\DoctrineTestDbRegenerationBundle\Doctrine\SchemaManager;
9
use Hgraca\DoctrineTestDbRegenerationBundle\Doctrine\SchemaManagerInterface;
10
use PHPUnit\Framework\TestListener;
11
use PHPUnit\Framework\TestListenerDefaultImplementation;
12
13
if (
14
    class_exists('PHPUnit_Runner_Version')
15
    && version_compare(PHPUnit_Runner_Version::id(), '5', '>=')
16
    && version_compare(PHPUnit_Runner_Version::id(), '6', '<')
17
) {
18
    // PHPUnit 5
19
20
    /**
21
     * @codeCoverageIgnore We can never cover both of these classes, although we do cover the trait
22
     */
23
    class DbRegenerationPHPUnitEventSubscriber extends \PHPUnit_Framework_BaseTestListener
0 ignored issues
show
Bug introduced by
The type PHPUnit_Framework_BaseTestListener was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
24
    {
25
        use DbRegenerationPHPUnitEventSubscriberTrait;
26
27
        /**
28
         * @throws \Exception
29
         */
30
        public function startTest(\PHPUnit_Framework_Test $test): void
0 ignored issues
show
Bug introduced by
The type PHPUnit_Framework_Test was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
31
        {
32
            $this->onTestStart($test);
33
        }
34
35
        /**
36
         * @throws \Exception
37
         */
38
        public function endTest(\PHPUnit_Framework_Test $test, $time): void
39
        {
40
            $this->onEndTest($test);
41
        }
42
    }
43
} elseif (class_exists('\PHPUnit\Runner\Version') && version_compare(\PHPUnit\Runner\Version::id(), '7', '<')) {
44
    // PHPUnit 6+
45
46
    /**
47
     * @codeCoverageIgnore We can never cover both of these classes, although we do cover the trait
48
     */
49
    class DbRegenerationPHPUnitEventSubscriber implements TestListener
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class should be in its own file to aid autoloaders.

Having each class in a dedicated file usually plays nice with PSR autoloaders and is therefore a well established practice. If you use other autoloaders, you might not want to follow this rule.

Loading history...
50
    {
51
        use TestListenerDefaultImplementation,
52
            DbRegenerationPHPUnitEventSubscriberTrait;
53
54
        /**
55
         * @throws \Exception
56
         */
57
        public function startTest(\PHPUnit\Framework\Test $test): void
58
        {
59
            $this->onTestStart($test);
60
        }
61
62
        /**
63
         * @throws \Exception
64
         */
65
        public function endTest(\PHPUnit\Framework\Test $test, $time): void
66
        {
67
            $this->onEndTest($test);
68
        }
69
    }
70
} elseif (class_exists('\PHPUnit\Runner\Version') && version_compare(\PHPUnit\Runner\Version::id(), '7', '>=')) {
71
    // PHPUnit 7+
72
73
    /**
74
     * @codeCoverageIgnore We can never cover both of these classes, although we do cover the trait
75
     */
76
    class DbRegenerationPHPUnitEventSubscriber implements TestListener
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class should be in its own file to aid autoloaders.

Having each class in a dedicated file usually plays nice with PSR autoloaders and is therefore a well established practice. If you use other autoloaders, you might not want to follow this rule.

Loading history...
77
    {
78
        use TestListenerDefaultImplementation,
79
            DbRegenerationPHPUnitEventSubscriberTrait;
80
81
        /**
82
         * @throws \Exception
83
         */
84
        public function startTest(\PHPUnit\Framework\Test $test): void
85
        {
86
            $this->onTestStart($test);
87
        }
88
89
        /**
90
         * @throws \Exception
91
         */
92
        public function endTest(\PHPUnit\Framework\Test $test, float $time): void
93
        {
94
            $this->onEndTest($test);
95
        }
96
    }
97
} else {
98
    throw new Exception('DoctrineTestDbRegenerationBundle doesn\'t work with such an old version of PHPUnit.');
99
}
100
101
trait DbRegenerationPHPUnitEventSubscriberTrait
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class should be in its own file to aid autoloaders.

Having each class in a dedicated file usually plays nice with PSR autoloaders and is therefore a well established practice. If you use other autoloaders, you might not want to follow this rule.

Loading history...
102
{
103
    /**
104
     * @var bool
105
     */
106
    private $hasCreatedTestDatabaseBackup = false;
107
108
    /**
109
     * @var bool
110
     */
111
    private $hasRestoredTestDatabase = false;
112
113
    /**
114
     * @var SchemaManagerInterface
115
     */
116
    private static $schemaManager;
117
118
    /**
119
     * @var bool
120
     */
121
    private $shouldRegenerateDbOnEveryTest;
122
123
    /**
124
     * @var bool
125
     */
126
    private $shouldRemoveDbAfterEveryTest;
127
128
    /**
129
     * @var int
130
     */
131
    private $shouldReuseExistingDbBkp;
132
133 16
    public function __construct(
134
        int $shouldRemoveDbAfterEveryTest = 1,
135
        int $shouldRegenerateDbOnEveryTest = 1,
136
        int $shouldReuseExistingDbBkp = 0,
137
        SchemaManagerInterface $schemaManager = null
138
    ) {
139 16
        $this->shouldRemoveDbAfterEveryTest = (bool) $shouldRemoveDbAfterEveryTest;
140 16
        $this->shouldRegenerateDbOnEveryTest = (bool) $shouldRegenerateDbOnEveryTest;
141 16
        $this->shouldReuseExistingDbBkp = (bool) $shouldReuseExistingDbBkp;
0 ignored issues
show
Documentation Bug introduced by
The property $shouldReuseExistingDbBkp was declared of type integer, but (bool)$shouldReuseExistingDbBkp is of type boolean. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
142 16
        self::$schemaManager = $schemaManager;
143 16
    }
144
145
    /**
146
     * @throws \Exception
147
     */
148 8
    private function onTestStart($test): void
149
    {
150 8
        if (!$test instanceof DatabaseAwareTestInterface) {
151 4
            return;
152
        }
153
154 4
        if (!$this->hasCreatedTestDatabaseBackup()) {
155 4
            $this->createTestDatabaseBackup($this->shouldReuseExistingDbBkp);
0 ignored issues
show
Bug introduced by
$this->shouldReuseExistingDbBkp of type integer is incompatible with the type boolean expected by parameter $shouldReuseExistingDbBkp of Hgraca\DoctrineTestDbReg...ateTestDatabaseBackup(). ( Ignorable by Annotation )

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

155
            $this->createTestDatabaseBackup(/** @scrutinizer ignore-type */ $this->shouldReuseExistingDbBkp);
Loading history...
156
        }
157
158 4
        if (!$this->hasRestoredTestDatabase() || $this->shouldRegenerateDbOnEveryTest) {
159 4
            $this->restoreTestDatabase();
160
        }
161 4
    }
162
163
    /**
164
     * At the end of each test that used the DB,
165
     * we remove the dirty DB just in case we forget
166
     * to add the interface to another test and it
167
     * ends up using a dirty DB, yielding unreliable results.
168
     * Its safer but slower though, so we can turn it off if we want to.
169
     */
170 8
    public function onEndTest($test): void
171
    {
172 8
        if (!$this->shouldRemoveDbAfterEveryTest || !$test instanceof DatabaseAwareTestInterface) {
173 4
            return;
174
        }
175
176 4
        if ($this->shouldRegenerateDbOnEveryTest) {
177 2
            $this->getSchemaManager()->removeTestDatabase();
178
        }
179 4
    }
180
181 6
    public static function getSchemaManager(): SchemaManagerInterface
182
    {
183 6
        return self::$schemaManager ?? self::$schemaManager = SchemaManager::constructUsingTestContainer();
184
    }
185
186 4
    private function hasCreatedTestDatabaseBackup(): bool
187
    {
188 4
        return $this->hasCreatedTestDatabaseBackup;
189
    }
190
191 4
    private function createdTestDatabaseBackup(): void
192
    {
193 4
        $this->hasCreatedTestDatabaseBackup = true;
194 4
    }
195
196 4
    private function hasRestoredTestDatabase(): bool
197
    {
198 4
        return $this->hasRestoredTestDatabase;
199
    }
200
201 4
    private function restoredTestDatabase(): void
202
    {
203 4
        $this->hasRestoredTestDatabase = true;
204 4
    }
205
206 4
    private function createTestDatabaseBackup(bool $shouldReuseExistingDbBkp = false): void
207
    {
208 4
        $this->switchOffDoctrineTestBundleStaticDriver();
209 4
        $this->getSchemaManager()->createTestDatabaseBackup($shouldReuseExistingDbBkp);
210 4
        $this->createdTestDatabaseBackup();
211 4
        $this->switchOnDoctrineTestBundleStaticDriver();
212 4
    }
213
214 4
    private function restoreTestDatabase(): void
215
    {
216 4
        $this->getSchemaManager()->restoreTestDatabase();
217 4
        $this->restoredTestDatabase();
218 4
    }
219
220 4
    private function switchOffDoctrineTestBundleStaticDriver(): void
221
    {
222 4
        if (\class_exists('DAMA\DoctrineTestBundle\Doctrine\DBAL\StaticDriver')) {
223
            \DAMA\DoctrineTestBundle\Doctrine\DBAL\StaticDriver::setKeepStaticConnections(false);
0 ignored issues
show
Bug introduced by
The type DAMA\DoctrineTestBundle\Doctrine\DBAL\StaticDriver was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
224
        }
225 4
    }
226
227 4
    private function switchOnDoctrineTestBundleStaticDriver(): void
228
    {
229 4
        if (\class_exists('DAMA\DoctrineTestBundle\Doctrine\DBAL\StaticDriver')) {
230
            \DAMA\DoctrineTestBundle\Doctrine\DBAL\StaticDriver::setKeepStaticConnections(true);
231
        }
232 4
    }
233
}
234