Failed Conditions
Pull Request — master (#2)
by Herberto
11:45
created

onTestStart()   B

Complexity

Conditions 5
Paths 5

Size

Total Lines 12
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 5

Importance

Changes 0
Metric Value
cc 5
eloc 6
nc 5
nop 1
dl 0
loc 12
ccs 7
cts 7
cp 1
crap 5
rs 8.8571
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
    /**
134
     * @var array
135
     */
136
    private $executeMigrations;
137
138 16
    public function __construct(
139
        int $shouldRemoveDbAfterEveryTest = 1,
140
        int $shouldRegenerateDbOnEveryTest = 1,
141
        int $shouldReuseExistingDbBkp = 0,
142
        array $executeMigrations = [],
143
        SchemaManagerInterface $schemaManager = null
144
    ) {
145 16
        $this->shouldRemoveDbAfterEveryTest = (bool) $shouldRemoveDbAfterEveryTest;
146 16
        $this->shouldRegenerateDbOnEveryTest = (bool) $shouldRegenerateDbOnEveryTest;
147 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...
148 16
        $this->executeMigrations = $executeMigrations;
149 16
        self::$schemaManager = $schemaManager;
150 16
    }
151
152
    /**
153
     * @throws \Exception
154
     */
155 8
    private function onTestStart($test): void
156
    {
157 8
        if (!$test instanceof DatabaseAwareTestInterface) {
158 4
            return;
159
        }
160
161 4
        if (!$this->hasCreatedTestDatabaseBackup()) {
162 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

162
            $this->createTestDatabaseBackup(/** @scrutinizer ignore-type */ $this->shouldReuseExistingDbBkp);
Loading history...
163
        }
164
165 4
        if (!$this->hasRestoredTestDatabase() || $this->shouldRegenerateDbOnEveryTest) {
166 4
            $this->restoreTestDatabase();
167
        }
168 4
    }
169
170
    /**
171
     * At the end of each test that used the DB,
172
     * we remove the dirty DB just in case we forget
173
     * to add the interface to another test and it
174
     * ends up using a dirty DB, yielding unreliable results.
175
     * Its safer but slower though, so we can turn it off if we want to.
176
     *
177
     * @throws \ErrorException
178
     */
179 8
    public function onEndTest($test): void
180
    {
181 8
        if (!$this->shouldRemoveDbAfterEveryTest || !$test instanceof DatabaseAwareTestInterface) {
182 4
            return;
183
        }
184
185 4
        if ($this->shouldRegenerateDbOnEveryTest) {
186 2
            $this->getSchemaManager()->removeTestDatabase();
187
        }
188 4
    }
189
190
    /**
191
     * @throws \ErrorException
192
     */
193 6
    public static function getSchemaManager(): SchemaManagerInterface
194
    {
195 6
        return self::$schemaManager ?? self::$schemaManager = SchemaManager::constructUsingTestContainer();
196
    }
197
198 4
    private function hasCreatedTestDatabaseBackup(): bool
199
    {
200 4
        return $this->hasCreatedTestDatabaseBackup;
201
    }
202
203 4
    private function createdTestDatabaseBackup(): void
204
    {
205 4
        $this->hasCreatedTestDatabaseBackup = true;
206 4
    }
207
208 4
    private function hasRestoredTestDatabase(): bool
209
    {
210 4
        return $this->hasRestoredTestDatabase;
211
    }
212
213 4
    private function restoredTestDatabase(): void
214
    {
215 4
        $this->hasRestoredTestDatabase = true;
216 4
    }
217
218
    /**
219
     * @throws \ErrorException
220
     */
221 4
    private function createTestDatabaseBackup(bool $shouldReuseExistingDbBkp = false): void
222
    {
223 4
        $this->switchOffDoctrineTestBundleStaticDriver();
224 4
        $this->getSchemaManager()->createTestDatabaseBackup($shouldReuseExistingDbBkp, $this->executeMigrations);
225 4
        $this->createdTestDatabaseBackup();
226 4
        $this->switchOnDoctrineTestBundleStaticDriver();
227 4
    }
228
229
    /**
230
     * @throws \ErrorException
231
     */
232 4
    private function restoreTestDatabase(): void
233
    {
234 4
        $this->getSchemaManager()->restoreTestDatabase();
235 4
        $this->restoredTestDatabase();
236 4
    }
237
238 4
    private function switchOffDoctrineTestBundleStaticDriver(): void
239
    {
240 4
        if (\class_exists('DAMA\DoctrineTestBundle\Doctrine\DBAL\StaticDriver')) {
241
            \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...
242
        }
243 4
    }
244
245 4
    private function switchOnDoctrineTestBundleStaticDriver(): void
246
    {
247 4
        if (\class_exists('DAMA\DoctrineTestBundle\Doctrine\DBAL\StaticDriver')) {
248
            \DAMA\DoctrineTestBundle\Doctrine\DBAL\StaticDriver::setKeepStaticConnections(true);
249
        }
250 4
    }
251
}
252