diff --git a/lib/internal/Magento/Framework/Setup/Patch/PatchApplier.php b/lib/internal/Magento/Framework/Setup/Patch/PatchApplier.php index e1b0e2842628d..cac6783b3bbbc 100644 --- a/lib/internal/Magento/Framework/Setup/Patch/PatchApplier.php +++ b/lib/internal/Magento/Framework/Setup/Patch/PatchApplier.php @@ -159,10 +159,9 @@ public function applyDataPatch($moduleName = null) } else { try { $this->moduleDataSetup->getConnection()->beginTransaction(); - $dataPatch->apply(); - $this->patchHistory->fixPatch(get_class($dataPatch)); - foreach ($dataPatch->getAliases() as $patchAlias) { - $this->patchHistory->fixPatch($patchAlias); + if (!$this->checkPatchAliases($dataPatch)) { + $dataPatch->apply(); + $this->patchHistory->fixPatch(get_class($dataPatch)); } $this->moduleDataSetup->getConnection()->commit(); } catch (\Exception $e) { @@ -238,10 +237,9 @@ public function applySchemaPatch($moduleName = null) * @var SchemaPatchInterface $schemaPatch */ $schemaPatch = $this->patchFactory->create($schemaPatch, ['schemaSetup' => $this->schemaSetup]); - $schemaPatch->apply(); - $this->patchHistory->fixPatch(get_class($schemaPatch)); - foreach ($schemaPatch->getAliases() as $patchAlias) { - $this->patchHistory->fixPatch($patchAlias); + if (!$this->checkPatchAliases($schemaPatch)) { + $schemaPatch->apply(); + $this->patchHistory->fixPatch(get_class($schemaPatch)); } } catch (\Exception $e) { throw new SetupException( @@ -292,4 +290,20 @@ public function revertDataPatches($moduleName = null) } } } + + /** + * Checks is patch was applied with current alias name + * + * @param DataPatchInterface|SchemaPatchInterface $dataPatch + * @return bool + */ + private function checkPatchAliases($dataPatch): bool + { + if ($dataPatchAliases = $dataPatch->getAliases()) { + foreach ($dataPatchAliases as $patchAlias) { + return $this->patchHistory->isApplied($patchAlias) ?? true; + } + } + return false; + } } diff --git a/lib/internal/Magento/Framework/Setup/Test/Unit/Patch/PatchApplierTest.php b/lib/internal/Magento/Framework/Setup/Test/Unit/Patch/PatchApplierTest.php index 82c267dc7d51f..98fb52ceabf76 100644 --- a/lib/internal/Magento/Framework/Setup/Test/Unit/Patch/PatchApplierTest.php +++ b/lib/internal/Magento/Framework/Setup/Test/Unit/Patch/PatchApplierTest.php @@ -24,6 +24,7 @@ use Magento\Framework\Setup\SchemaSetupInterface; use Magento\Framework\Setup\SetupInterface; use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; +use phpDocumentor\Reflection\Types\True_; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; @@ -203,8 +204,6 @@ public function testApplyDataPatchForNewlyInstalledModule($moduleName, $dataPatc */ public function testApplyDataPatchForAlias($moduleName, $dataPatches, $moduleVersionInDb) { - $this->expectException('Exception'); - $this->expectExceptionMessageMatches('"Unable to apply data patch .+ cannot be applied twice"'); $this->dataPatchReaderMock->expects($this->once()) ->method('read') ->with($moduleName) @@ -218,6 +217,7 @@ public function testApplyDataPatchForAlias($moduleName, $dataPatches, $moduleVer $patch1 = $this->getMockForAbstractClass(DataPatchInterface::class); $patch1->expects($this->once())->method('getAliases')->willReturn(['PatchAlias']); + $patch1->expects($this->never())->method('apply'); $patchClass = get_class($patch1); $patchRegistryMock = $this->createAggregateIteratorMock(PatchRegistry::class, [$patchClass], ['registerPatch']); @@ -233,15 +233,6 @@ public function testApplyDataPatchForAlias($moduleName, $dataPatches, $moduleVer ['\\' . $patchClass, ['moduleDataSetup' => $this->moduleDataSetupMock], $patch1], ] ); - $this->connectionMock->expects($this->exactly(1))->method('beginTransaction'); - $this->connectionMock->expects($this->never())->method('commit'); - $this->patchHistoryMock->expects($this->any())->method('fixPatch')->willReturnCallback( - function ($param1) { - if ($param1 == 'PatchAlias') { - throw new \LogicException(sprintf("Patch %s cannot be applied twice", $param1)); - } - } - ); $this->patchApllier->applyDataPatch($moduleName); } @@ -516,8 +507,6 @@ public function testSchemaPatchAplly($moduleName, $schemaPatches, $moduleVersion */ public function testSchemaPatchApplyForPatchAlias($moduleName, $schemaPatches, $moduleVersionInDb) { - $this->expectException('Exception'); - $this->expectExceptionMessageMatches('"Unable to apply patch .+ cannot be applied twice"'); $this->schemaPatchReaderMock->expects($this->once()) ->method('read') ->with($moduleName)