Skip to content

Commit f57bb3e

Browse files
committedFeb 7, 2020
NEXT-6669 - Add \Shopware\Core\Framework\Plugin::removeMigrations
Add `\Shopware\Core\Framework\Plugin\Context\UninstallContext::enableKeepMigrations`, to opt-in into the default behaviour starting with v6.3.0.
1 parent bc01033 commit f57bb3e

File tree

7 files changed

+155
-10
lines changed

7 files changed

+155
-10
lines changed
 

‎CHANGELOG-6.1.md

+2
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,8 @@ To get the diff between two versions, go to https://github.com/shopware/platform
8989
* The `\Shopware\Core\Framework\DataAbstractionLayer\Field\PriceField` can now contains a `listPrice`
9090
* `\Shopware\Core\Checkout\Cart\Price\Struct\CalculatedPrice` supports now list prices.
9191
* Fix mail sending via sendmail transport
92+
* You can now opt-out of removing your plugin migrations on uninstall by calling `\Shopware\Core\Framework\Plugin\Context\UninstallContext::enableKeepMigrations`
93+
* Added `\Shopware\Core\Framework\Plugin::removeMigrations` to remove plugin migration entries.
9294
* Storefront
9395
* Fixed the cookie privacy hint to use the correct link `privacyPage` instead of `shippingPaymentInfoPage`
9496
* Added the parameter `useBackdrop` to the `page-loading-indicator.utils.js` `remove` and `create` methods. Defaults to `true`

‎UPGRADE-6.1.md

+1
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,7 @@ Core
248248
* After: `public function getEntityTag(string $id, string $entityName): string`
249249
* If you called this function, simply replace the second function parameter to your entity name
250250
* Currently both ways are supported. The `string $entityName` type hint will be added with `v6.3.0`
251+
* We'll stop deleting the plugin migration data on plugin uninstall in `v6.3.0` If you want to keep removing it anyway you have to call `\Shopware\Core\Framework\Plugin::removeMigrations`.
251252
252253
Administration
253254
--------------

‎src/Core/Framework/Plugin.php

+12
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
use Shopware\Core\Framework\Plugin\Context\InstallContext;
1010
use Shopware\Core\Framework\Plugin\Context\UninstallContext;
1111
use Shopware\Core\Framework\Plugin\Context\UpdateContext;
12+
use Shopware\Core\Kernel;
1213
use Symfony\Component\Routing\RouteCollectionBuilder;
1314

1415
abstract class Plugin extends Bundle
@@ -95,6 +96,17 @@ public function getAdditionalBundles(AdditionalBundleParameters $parameters): ar
9596
return [];
9697
}
9798

99+
final public function removeMigrations(): void
100+
{
101+
// namespace should not start with `shopware`
102+
if (mb_stripos($this->getMigrationNamespace(), 'shopware') === 0) {
103+
throw new \RuntimeException('Deleting Shopware migrations is not allowed');
104+
}
105+
106+
$class = addcslashes($this->getMigrationNamespace(), '\\_%') . '%';
107+
Kernel::getConnection()->executeQuery('DELETE FROM migration WHERE class LIKE :class', ['class' => $class]);
108+
}
109+
98110
public function getBasePath(): string
99111
{
100112
return $this->basePath;

‎src/Core/Framework/Plugin/Context/UninstallContext.php

+28-1
Original file line numberDiff line numberDiff line change
@@ -12,19 +12,46 @@ class UninstallContext extends InstallContext
1212
*/
1313
private $keepUserData;
1414

15+
/**
16+
* @var bool
17+
*/
18+
private $keepMigrations;
19+
1520
public function __construct(
1621
Plugin $plugin,
1722
Context $context,
1823
string $currentShopwareVersion,
1924
string $currentPluginVersion,
20-
bool $keepUserData
25+
bool $keepUserData,
26+
bool $keepMigrations = false
2127
) {
2228
parent::__construct($plugin, $context, $currentShopwareVersion, $currentPluginVersion);
2329
$this->keepUserData = $keepUserData;
30+
$this->keepMigrations = $keepMigrations;
2431
}
2532

2633
public function keepUserData(): bool
2734
{
2835
return $this->keepUserData;
2936
}
37+
38+
/**
39+
* By default the executed migrations for plugins are deleted during uninstall.
40+
*
41+
* Call `enableKeepMigrations` to opt-out from the deletion
42+
*
43+
* The default will change to true in v6.3.0
44+
*/
45+
public function keepMigrations(): bool
46+
{
47+
return $this->keepMigrations;
48+
}
49+
50+
/**
51+
* This will be the default in v6.3.0
52+
*/
53+
public function enableKeepMigrations(): void
54+
{
55+
$this->keepMigrations = true;
56+
}
3057
}

‎src/Core/Framework/Plugin/PluginLifecycleService.php

+9-9
Original file line numberDiff line numberDiff line change
@@ -231,14 +231,20 @@ public function uninstallPlugin(
231231
$shopwareContext,
232232
$this->shopwareVersion,
233233
$plugin->getVersion(),
234-
$keepUserData
234+
$keepUserData,
235+
/* @deprecated tag:v6.3.0 - This default value will change to `true` */
236+
false
235237
);
236238

237239
$this->eventDispatcher->dispatch(new PluginPreUninstallEvent($plugin, $uninstallContext));
238240
$this->assetInstaller->removeAssetsOfBundle($pluginBaseClassString);
239241

240242
$pluginBaseClass->uninstall($uninstallContext);
241243

244+
if (!$uninstallContext->keepMigrations()) {
245+
$pluginBaseClass->removeMigrations();
246+
}
247+
242248
$this->updatePluginData(
243249
[
244250
'id' => $plugin->getId(),
@@ -450,16 +456,10 @@ private function runMigrations(Plugin $pluginBaseClass): void
450456
}
451457

452458
$this->migrationCollection->addDirectory($migrationPath, $pluginBaseClass->getMigrationNamespace());
453-
$this->migrationLoader->syncMigrationCollection($pluginBaseClass->getNamespace());
454-
iterator_to_array($this->migrationRunner->migrate());
455-
}
456459

457-
private function removeMigrations(Plugin $pluginBaseClass): void
458-
{
459-
$class = $pluginBaseClass->getMigrationNamespace() . '\%';
460-
$class = str_replace('\\', '\\\\', $class);
460+
$this->migrationLoader->syncMigrationCollection($pluginBaseClass->getNamespace());
461461

462-
$this->connection->executeQuery('DELETE FROM migration WHERE class LIKE :class', ['class' => $class]);
462+
iterator_to_array($this->migrationRunner->migrate());
463463
}
464464

465465
private function hasPluginUpdate(string $updateVersion, string $currentVersion): bool

‎src/Core/Framework/Test/Plugin/PluginLifecycleServiceTest.php

+90
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,14 @@ protected function tearDown(): void
109109
$this->getContainer()
110110
->get(Connection::class)
111111
->rollBack();
112+
113+
if (isset($_SERVER['FAKE_MIGRATION_NAMESPACE'])) {
114+
unset($_SERVER['FAKE_MIGRATION_NAMESPACE']);
115+
}
116+
117+
if (isset($_SERVER['TEST_KEEP_MIGRATIONS'])) {
118+
unset($_SERVER['TEST_KEEP_MIGRATIONS']);
119+
}
112120
}
113121

114122
public function testInstallPlugin(): void
@@ -315,6 +323,88 @@ public function testDeactivatePluginNotActivatedThrowsException(): void
315323
$this->pluginLifecycleService->deactivatePlugin($pluginInstalled, $this->context);
316324
}
317325

326+
public function testRemoveMigrations(): void
327+
{
328+
$this->pluginService->refreshPlugins($this->context, new NullIO());
329+
330+
$plugin = $this->getTestPlugin();
331+
332+
$overAllCount = $this->getMigrationCount('');
333+
334+
$this->pluginLifecycleService->installPlugin($plugin, $this->context);
335+
336+
$swagTestCount = $this->getMigrationCount('SwagTest\\Migration\\');
337+
static::assertEquals(1, $swagTestCount);
338+
339+
$this->pluginLifecycleService->uninstallPlugin($plugin, $this->context);
340+
341+
$swagTestCount = $this->getMigrationCount('SwagTest\\Migration\\');
342+
static::assertEquals(0, $swagTestCount);
343+
344+
$newOverAllCount = $this->getMigrationCount('');
345+
static::assertEquals($overAllCount, $newOverAllCount);
346+
}
347+
348+
public function testDontRemoveMigrations(): void
349+
{
350+
$_SERVER['TEST_KEEP_MIGRATIONS'] = true;
351+
352+
$this->pluginService->refreshPlugins($this->context, new NullIO());
353+
354+
$plugin = $this->getTestPlugin();
355+
356+
$overAllCount = $this->getMigrationCount('');
357+
358+
$this->pluginLifecycleService->installPlugin($plugin, $this->context);
359+
360+
$swagTestCount = $this->getMigrationCount('SwagTest\\Migration\\');
361+
static::assertEquals(1, $swagTestCount);
362+
363+
$this->pluginLifecycleService->uninstallPlugin($plugin, $this->context);
364+
365+
$swagTestCount = $this->getMigrationCount('SwagTest\\Migration\\');
366+
static::assertEquals(1, $swagTestCount);
367+
368+
$newOverAllCount = $this->getMigrationCount('');
369+
static::assertEquals($overAllCount + $swagTestCount, $newOverAllCount);
370+
}
371+
372+
public function testRemoveMigrationsCannotRemoveShopwareMigrations(): void
373+
{
374+
$this->pluginService->refreshPlugins($this->context, new NullIO());
375+
376+
$overAllCount = $this->getMigrationCount('');
377+
378+
$swagTest = new SwagTest(true, '', '');
379+
380+
$_SERVER['FAKE_MIGRATION_NAMESPACE'] = 'Shopware\\Core';
381+
382+
$exception = null;
383+
384+
try {
385+
$swagTest->removeMigrations();
386+
} catch (\Exception $e) {
387+
$exception = $e;
388+
}
389+
390+
$newOverAllCount = $this->getMigrationCount('');
391+
392+
static::assertEquals($overAllCount, $newOverAllCount);
393+
394+
static::assertNotNull($exception, 'Expected exception to be thrown');
395+
}
396+
397+
private function getMigrationCount(string $namespacePrefix): int
398+
{
399+
$result = $this->connection->executeQuery(
400+
'SELECT COUNT(*) FROM migration WHERE class LIKE :class',
401+
['class' => addcslashes($namespacePrefix, '\\_%') . '%']
402+
)
403+
->fetchColumn();
404+
405+
return (int) $result;
406+
}
407+
318408
private function createPluginLifecycleService(): PluginLifecycleService
319409
{
320410
return new PluginLifecycleService(

‎src/Core/Framework/Test/Plugin/_fixture/plugins/SwagTest/src/SwagTest.php

+13
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface;
66
use Shopware\Core\Framework\Plugin;
7+
use Shopware\Core\Framework\Plugin\Context\UninstallContext;
78
use Shopware\Core\System\SystemConfig\SystemConfigService;
89

910
class SwagTest extends Plugin
@@ -58,4 +59,16 @@ public function manualSetter(EntityRepositoryInterface $categoryRepository): voi
5859
{
5960
$this->categoryRepository = $categoryRepository;
6061
}
62+
63+
public function uninstall(UninstallContext $uninstallContext): void
64+
{
65+
if (isset($_SERVER['TEST_KEEP_MIGRATIONS'])) {
66+
$uninstallContext->enableKeepMigrations();
67+
}
68+
}
69+
70+
public function getMigrationNamespace(): string
71+
{
72+
return $_SERVER['FAKE_MIGRATION_NAMESPACE'] ?? parent::getMigrationNamespace();
73+
}
6174
}

0 commit comments

Comments
 (0)
Please sign in to comment.