Skip to content

Commit d135cb1

Browse files
committed
Fix #23031 (patch apply attempt should check patch aliases)
1 parent 7ad8863 commit d135cb1

File tree

2 files changed

+145
-17
lines changed

2 files changed

+145
-17
lines changed

lib/internal/Magento/Framework/Setup/Patch/PatchApplier.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,9 @@ public function applyDataPatch($moduleName = null)
161161
$this->moduleDataSetup->getConnection()->beginTransaction();
162162
$dataPatch->apply();
163163
$this->patchHistory->fixPatch(get_class($dataPatch));
164+
foreach ($dataPatch->getAliases() as $patchAlias) {
165+
$this->patchHistory->fixPatch($patchAlias);
166+
}
164167
$this->moduleDataSetup->getConnection()->commit();
165168
} catch (\Exception $e) {
166169
$this->moduleDataSetup->getConnection()->rollBack();
@@ -237,6 +240,9 @@ public function applySchemaPatch($moduleName = null)
237240
$schemaPatch = $this->patchFactory->create($schemaPatch, ['schemaSetup' => $this->schemaSetup]);
238241
$schemaPatch->apply();
239242
$this->patchHistory->fixPatch(get_class($schemaPatch));
243+
foreach ($schemaPatch->getAliases() as $patchAlias) {
244+
$this->patchHistory->fixPatch($patchAlias);
245+
}
240246
} catch (\Exception $e) {
241247
throw new SetupException(
242248
new Phrase(

lib/internal/Magento/Framework/Setup/Test/Unit/Patch/PatchApplierTest.php

Lines changed: 139 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,11 @@
1010
use Magento\Framework\DB\Adapter\AdapterInterface;
1111
use Magento\Framework\Module\ModuleResource;
1212
use Magento\Framework\ObjectManagerInterface;
13+
use Magento\Framework\Setup\Exception;
1314
use Magento\Framework\Setup\ModuleDataSetupInterface;
15+
use Magento\Framework\Setup\Patch\DataPatchInterface;
1416
use Magento\Framework\Setup\Patch\PatchBackwardCompatability;
17+
use Magento\Framework\Setup\Patch\PatchInterface;
1518
use Magento\Framework\Setup\SchemaSetupInterface;
1619
use Magento\Framework\TestFramework\Unit\Helper\ObjectManager;
1720
use Magento\Framework\Setup\Patch\PatchApplier;
@@ -169,8 +172,10 @@ public function testApplyDataPatchForNewlyInstalledModule($moduleName, $dataPatc
169172

170173
$patch1 = $this->createMock(\SomeDataPatch::class);
171174
$patch1->expects($this->once())->method('apply');
175+
$patch1->expects($this->once())->method('getAliases')->willReturn([]);
172176
$patch2 = $this->createMock(\OtherDataPatch::class);
173177
$patch2->expects($this->once())->method('apply');
178+
$patch2->expects($this->once())->method('getAliases')->willReturn([]);
174179
$this->objectManagerMock->expects($this->any())->method('create')->willReturnMap(
175180
[
176181
['\\' . \SomeDataPatch::class, ['moduleDataSetup' => $this->moduleDataSetupMock], $patch1],
@@ -188,6 +193,60 @@ public function testApplyDataPatchForNewlyInstalledModule($moduleName, $dataPatc
188193
$this->patchApllier->applyDataPatch($moduleName);
189194
}
190195

196+
/**
197+
* @param $moduleName
198+
* @param $dataPatches
199+
* @param $moduleVersionInDb
200+
*
201+
* @dataProvider applyDataPatchDataNewModuleProvider()
202+
*
203+
* @expectedException Exception
204+
* @expectedExceptionMessageRegExp "Unable to apply data patch .+ cannot be applied twice"
205+
*/
206+
public function testApplyDataPatchForAlias($moduleName, $dataPatches, $moduleVersionInDb)
207+
{
208+
$this->dataPatchReaderMock->expects($this->once())
209+
->method('read')
210+
->with($moduleName)
211+
->willReturn($dataPatches);
212+
213+
$this->moduleResourceMock->expects($this->any())->method('getDataVersion')->willReturnMap(
214+
[
215+
[$moduleName, $moduleVersionInDb]
216+
]
217+
);
218+
219+
$patch1 = $this->createMock(DataPatchInterface::class);
220+
$patch1->expects($this->once())->method('getAliases')->willReturn(['PatchAlias']);
221+
$patchClass = get_class($patch1);
222+
223+
$patchRegistryMock = $this->createAggregateIteratorMock(PatchRegistry::class, [$patchClass], ['registerPatch']);
224+
$patchRegistryMock->expects($this->any())
225+
->method('registerPatch');
226+
227+
$this->patchRegistryFactoryMock->expects($this->any())
228+
->method('create')
229+
->willReturn($patchRegistryMock);
230+
231+
$this->objectManagerMock->expects($this->any())->method('create')->willReturnMap(
232+
[
233+
['\\' . $patchClass, ['moduleDataSetup' => $this->moduleDataSetupMock], $patch1],
234+
]
235+
);
236+
$this->connectionMock->expects($this->exactly(1))->method('beginTransaction');
237+
$this->connectionMock->expects($this->never())->method('commit');
238+
$this->patchHistoryMock->expects($this->any())->method('fixPatch')->will(
239+
$this->returnCallback(
240+
function ($param1) {
241+
if ($param1 == 'PatchAlias') {
242+
throw new \LogicException(sprintf("Patch %s cannot be applied twice", $param1));
243+
}
244+
}
245+
)
246+
);
247+
$this->patchApllier->applyDataPatch($moduleName);
248+
}
249+
191250
/**
192251
* @return array
193252
*/
@@ -243,8 +302,10 @@ public function testApplyDataPatchForInstalledModule($moduleName, $dataPatches,
243302

244303
$patch1 = $this->createMock(\SomeDataPatch::class);
245304
$patch1->expects(self::never())->method('apply');
305+
$patch1->expects(self::any())->method('getAliases')->willReturn([]);
246306
$patch2 = $this->createMock(\OtherDataPatch::class);
247307
$patch2->expects(self::once())->method('apply');
308+
$patch2->expects(self::any())->method('getAliases')->willReturn([]);
248309
$this->objectManagerMock->expects(self::any())->method('create')->willReturnMap(
249310
[
250311
['\\' . \SomeDataPatch::class, ['moduleDataSetup' => $this->moduleDataSetupMock], $patch1],
@@ -279,7 +340,7 @@ public function applyDataPatchDataInstalledModuleProvider()
279340
* @param $dataPatches
280341
* @param $moduleVersionInDb
281342
*
282-
* @expectedException \Magento\Framework\Setup\Exception
343+
* @expectedException Exception
283344
* @expectedExceptionMessage Patch Apply Error
284345
*
285346
* @dataProvider applyDataPatchDataInstalledModuleProvider()
@@ -328,7 +389,7 @@ public function testApplyDataPatchRollback($moduleName, $dataPatches, $moduleVer
328389
}
329390

330391
/**
331-
* @expectedException \Magento\Framework\Setup\Exception
392+
* @expectedException Exception
332393
* @expectedExceptionMessageRegExp "Patch [a-zA-Z0-9\_]+ should implement DataPatchInterface"
333394
*/
334395
public function testNonDataPatchApply()
@@ -434,8 +495,10 @@ public function testSchemaPatchAplly($moduleName, $schemaPatches, $moduleVersion
434495

435496
$patch1 = $this->createMock(\SomeSchemaPatch::class);
436497
$patch1->expects($this->never())->method('apply');
498+
$patch1->expects($this->any())->method('getAliases')->willReturn([]);
437499
$patch2 = $this->createMock(\OtherSchemaPatch::class);
438500
$patch2->expects($this->once())->method('apply');
501+
$patch2->expects($this->any())->method('getAliases')->willReturn([]);
439502
$this->patchFactoryMock->expects($this->any())->method('create')->willReturnMap(
440503
[
441504
[\SomeSchemaPatch::class, ['schemaSetup' => $this->schemaSetupMock], $patch1],
@@ -448,6 +511,55 @@ public function testSchemaPatchAplly($moduleName, $schemaPatches, $moduleVersion
448511
$this->patchApllier->applySchemaPatch($moduleName);
449512
}
450513

514+
/**
515+
* @param $moduleName
516+
* @param $schemaPatches
517+
* @param $moduleVersionInDb
518+
*
519+
* @dataProvider schemaPatchDataProvider()
520+
*
521+
* @expectedException Exception
522+
* @expectedExceptionMessageRegExp "Unable to apply patch .+ cannot be applied twice"
523+
*/
524+
public function testSchemaPatchApplyForPatchAlias($moduleName, $schemaPatches, $moduleVersionInDb)
525+
{
526+
$this->schemaPatchReaderMock->expects($this->once())
527+
->method('read')
528+
->with($moduleName)
529+
->willReturn($schemaPatches);
530+
531+
$this->moduleResourceMock->expects($this->any())->method('getDbVersion')->willReturnMap(
532+
[
533+
[$moduleName, $moduleVersionInDb]
534+
]
535+
);
536+
537+
$patch1 = $this->createMock(PatchInterface::class);
538+
$patch1->expects($this->once())->method('getAliases')->willReturn(['PatchAlias']);
539+
$patchClass = get_class($patch1);
540+
541+
$patchRegistryMock = $this->createAggregateIteratorMock(PatchRegistry::class, [$patchClass], ['registerPatch']);
542+
$patchRegistryMock->expects($this->any())
543+
->method('registerPatch');
544+
545+
$this->patchRegistryFactoryMock->expects($this->any())
546+
->method('create')
547+
->willReturn($patchRegistryMock);
548+
549+
$this->patchFactoryMock->expects($this->any())->method('create')->willReturn($patch1);
550+
$this->patchHistoryMock->expects($this->any())->method('fixPatch')->will(
551+
$this->returnCallback(
552+
function ($param1) {
553+
if ($param1 == 'PatchAlias') {
554+
throw new \LogicException(sprintf("Patch %s cannot be applied twice", $param1));
555+
}
556+
}
557+
)
558+
);
559+
560+
$this->patchApllier->applySchemaPatch($moduleName);
561+
}
562+
451563
public function testRevertDataPatches()
452564
{
453565
$patches = [\RevertableDataPatch::class];
@@ -534,33 +646,43 @@ private function createAggregateIteratorMock($className, array $items = [], arra
534646

535647
$someIterator->expects($this->any())
536648
->method('rewind')
537-
->willReturnCallback(function () use ($iterator) {
538-
$iterator->rewind();
539-
});
649+
->willReturnCallback(
650+
function () use ($iterator) {
651+
$iterator->rewind();
652+
}
653+
);
540654

541655
$someIterator->expects($this->any())
542656
->method('current')
543-
->willReturnCallback(function () use ($iterator) {
544-
return $iterator->current();
545-
});
657+
->willReturnCallback(
658+
function () use ($iterator) {
659+
return $iterator->current();
660+
}
661+
);
546662

547663
$someIterator->expects($this->any())
548664
->method('key')
549-
->willReturnCallback(function () use ($iterator) {
550-
return $iterator->key();
551-
});
665+
->willReturnCallback(
666+
function () use ($iterator) {
667+
return $iterator->key();
668+
}
669+
);
552670

553671
$someIterator->expects($this->any())
554672
->method('next')
555-
->willReturnCallback(function () use ($iterator) {
556-
$iterator->next();
557-
});
673+
->willReturnCallback(
674+
function () use ($iterator) {
675+
$iterator->next();
676+
}
677+
);
558678

559679
$someIterator->expects($this->any())
560680
->method('valid')
561-
->willReturnCallback(function () use ($iterator) {
562-
return $iterator->valid();
563-
});
681+
->willReturnCallback(
682+
function () use ($iterator) {
683+
return $iterator->valid();
684+
}
685+
);
564686

565687
return $mockIteratorAggregate;
566688
}

0 commit comments

Comments
 (0)