diff --git a/application/Espo/Core/Upgrades/Actions/Base.php b/application/Espo/Core/Upgrades/Actions/Base.php index 7a4ce71d3d..fd02e4b772 100644 --- a/application/Espo/Core/Upgrades/Actions/Base.php +++ b/application/Espo/Core/Upgrades/Actions/Base.php @@ -53,6 +53,8 @@ abstract class Base protected $processId = null; + protected $parentProcessId = null; + protected $manifestName = 'manifest.json'; protected $packagePostfix = 'z'; @@ -152,12 +154,19 @@ abstract class Base return $this->getContainer()->get('entityManager'); } - public function throwErrorAndRemovePackage($errorMessage = '') + public function throwErrorAndRemovePackage($errorMessage = '', $deletePackage = true, $systemRebuild = true) { - $this->deletePackageFiles(); - $this->deletePackageArchive(); - $this->disableMaintenanceMode(); - $this->systemRebuild(); + if ($deletePackage) { + $this->deletePackageFiles(); + $this->deletePackageArchive(); + } + + $this->disableMaintenanceMode(true); + + if ($systemRebuild) { + $this->systemRebuild(); + } + throw new Error($errorMessage); } @@ -183,11 +192,21 @@ abstract class Base return $this->processId; } + protected function getParentProcessId() + { + return $this->parentProcessId; + } + public function setProcessId($processId) { $this->processId = $processId; } + public function setParentProcessId($processId) + { + $this->parentProcessId = $processId; + } + /** * Check if version of upgrade/extension is acceptable to current version of EspoCRM * @@ -668,12 +687,12 @@ abstract class Base $packageArchivePath = $this->getPackagePath(true); if (!file_exists($packageArchivePath)) { - throw new Error('Package Archive doesn\'t exist.'); + $this->throwErrorAndRemovePackage('Package Archive doesn\'t exist.', false, false); } $res = $this->getZipUtil()->unzip($packageArchivePath, $packagePath); if ($res === false) { - throw new Error('Unnable to unzip the file - '.$packagePath.'.'); + $this->throwErrorAndRemovePackage('Unnable to unzip the file - '.$packagePath.'.', false, false); } } @@ -769,7 +788,7 @@ abstract class Base $permissionDeniedList = $this->getFileManager()->getLastPermissionDeniedList(); $delimiter = $this->isCli() ? "\n" : "
"; - throw new Error("Permission denied: " . $delimiter . implode($delimiter, $permissionDeniedList)); + $this->throwErrorAndRemovePackage("Permission denied: " . $delimiter . implode($delimiter, $permissionDeniedList), false, false); } } @@ -807,6 +826,12 @@ abstract class Base protected function enableMaintenanceMode() { $config = $this->getConfig(); + $configParamName = $this->getTemporaryConfigParamName(); + $parentConfigParamName = $this->getTemporaryConfigParamName(true); + + if ($config->has($configParamName) || ($parentConfigParamName && $config->has($parentConfigParamName))) { + return; + } $actualParams = [ 'maintenanceMode' => $config->get('maintenanceMode'), @@ -814,7 +839,6 @@ abstract class Base 'useCache' => $config->get('useCache'), ]; - $configParamName = $this->getTemporaryConfigParamName(); $config->set($configParamName, $actualParams); $save = false; @@ -839,23 +863,32 @@ abstract class Base } } - protected function disableMaintenanceMode() + protected function disableMaintenanceMode($force = false) { $config = $this->getConfig(); - $configParamName = $this->getTemporaryConfigParamName(); - $temporaryUpgradeParams = $config->get($configParamName, []); + $configParamList = [ + $this->getTemporaryConfigParamName() + ]; + + if ($force && $this->getTemporaryConfigParamName(true)) { + $configParamList[] = $this->getTemporaryConfigParamName(true); + } $save = false; - foreach ($temporaryUpgradeParams as $paramName => $paramValue) { - if ($config->get($paramName) != $paramValue) { - $config->set($paramName, $paramValue); - $save = true; - } - } + foreach ($configParamList as $configParamName) { + + if (!$config->has($configParamName)) { + continue; + } + + foreach ($config->get($configParamName, []) as $paramName => $paramValue) { + if ($config->get($paramName) != $paramValue) { + $config->set($paramName, $paramValue); + } + } - if ($config->has($configParamName)) { $config->remove($configParamName); $save = true; } @@ -865,9 +898,18 @@ abstract class Base } } - protected function getTemporaryConfigParamName() + protected function getTemporaryConfigParamName($isParentProcess = false) { - return 'temporaryUpgradeParams' . $this->getProcessId(); + $processId = $this->getProcessId(); + + if ($isParentProcess) { + $processId = $this->getParentProcessId(); + if (!$processId) { + return; + } + } + + return 'temporaryUpgradeParams' . $processId; } protected function isCli() diff --git a/application/Espo/Core/Upgrades/Actions/Base/Delete.php b/application/Espo/Core/Upgrades/Actions/Base/Delete.php index face239f41..efad3f3305 100644 --- a/application/Espo/Core/Upgrades/Actions/Base/Delete.php +++ b/application/Espo/Core/Upgrades/Actions/Base/Delete.php @@ -44,6 +44,10 @@ class Delete extends \Espo\Core\Upgrades\Actions\Base $this->setProcessId($processId); + if (isset($data['parentProcessId'])) { + $this->setParentProcessId($data['parentProcessId']); + } + $this->beforeRunAction(); /* delete a package */ @@ -64,4 +68,4 @@ class Delete extends \Espo\Core\Upgrades\Actions\Base return $res; } -} \ No newline at end of file +} diff --git a/application/Espo/Core/Upgrades/Actions/Base/Install.php b/application/Espo/Core/Upgrades/Actions/Base/Install.php index 833f3e6764..77b4e20f59 100644 --- a/application/Espo/Core/Upgrades/Actions/Base/Install.php +++ b/application/Espo/Core/Upgrades/Actions/Base/Install.php @@ -87,6 +87,10 @@ class Install extends \Espo\Core\Upgrades\Actions\Base $this->setProcessId($processId); + if (isset($data['parentProcessId'])) { + $this->setParentProcessId($data['parentProcessId']); + } + /** check if an archive is unzipped, if no then unzip */ $packagePath = $this->getPackagePath(); if (!file_exists($packagePath)) { @@ -264,9 +268,9 @@ class Install extends \Espo\Core\Upgrades\Actions\Base return $res; } - public function throwErrorAndRemovePackage($errorMessage = '') + public function throwErrorAndRemovePackage($errorMessage = '', $deletePackage = true, $systemRebuild = true) { $this->restoreFiles(); - parent::throwErrorAndRemovePackage($errorMessage); + parent::throwErrorAndRemovePackage($errorMessage, $deletePackage, $systemRebuild); } } diff --git a/application/Espo/Core/Upgrades/Actions/Base/Uninstall.php b/application/Espo/Core/Upgrades/Actions/Base/Uninstall.php index be8c541cd1..114e433459 100644 --- a/application/Espo/Core/Upgrades/Actions/Base/Uninstall.php +++ b/application/Espo/Core/Upgrades/Actions/Base/Uninstall.php @@ -46,6 +46,10 @@ class Uninstall extends \Espo\Core\Upgrades\Actions\Base $this->setProcessId($processId); + if (isset($data['parentProcessId'])) { + $this->setParentProcessId($data['parentProcessId']); + } + $this->initialize(); $this->checkIsWritable(); @@ -155,12 +159,10 @@ class Uninstall extends \Espo\Core\Upgrades\Actions\Base return $res; } - public function throwErrorAndRemovePackage($errorMessage = '') + public function throwErrorAndRemovePackage($errorMessage = '', $deletePackage = true, $systemRebuild = true) { $this->restoreFiles(); - $this->disableMaintenanceMode(); - $this->systemRebuild(); - throw new Error($errorMessage); + parent::throwErrorAndRemovePackage($errorMessage, false, $systemRebuild); } protected function getCopyFileList() diff --git a/application/Espo/Core/Upgrades/Actions/Extension/Install.php b/application/Espo/Core/Upgrades/Actions/Extension/Install.php index baa881676c..dd4bd8c134 100644 --- a/application/Espo/Core/Upgrades/Actions/Extension/Install.php +++ b/application/Espo/Core/Upgrades/Actions/Extension/Install.php @@ -28,8 +28,9 @@ ************************************************************************/ namespace Espo\Core\Upgrades\Actions\Extension; -use Espo\Core\Exceptions\Error, - Espo\Core\ExtensionManager; + +use Espo\Core\Exceptions\Error; +use Espo\Core\ExtensionManager; class Install extends \Espo\Core\Upgrades\Actions\Base\Install { @@ -161,7 +162,12 @@ class Install extends \Espo\Core\Upgrades\Actions\Base\Install $extensionEntity->set($data); - return $entityManager->saveEntity($extensionEntity); + try { + $entityManager->saveEntity($extensionEntity); + } catch (\Throwable $e) { + $GLOBALS['log']->error('Error saving Extension entity. The error occurred by existing Hook, more details: ' . $e->getMessage() .' at '. $e->getFile() . ':' . $e->getLine()); + $this->throwErrorAndRemovePackage('Error saving Extension entity. Check logs for details.', false); + } } /** @@ -195,6 +201,7 @@ class Install extends \Espo\Core\Upgrades\Actions\Base\Install 'id' => $extensionEntity->get('id'), 'skipSystemRebuild' => true, 'skipAfterScript' => true, + 'parentProcessId' => $this->getProcessId(), ) ); } @@ -208,7 +215,10 @@ class Install extends \Espo\Core\Upgrades\Actions\Base\Install { $extensionEntity = $this->getExtensionEntity(); - $this->executeAction(ExtensionManager::DELETE, array('id' => $extensionEntity->get('id'))); + $this->executeAction(ExtensionManager::DELETE, array( + 'id' => $extensionEntity->get('id'), + 'parentProcessId' => $this->getProcessId(), + )); } protected function checkDependencies($dependencyList) diff --git a/application/Espo/Core/Upgrades/Actions/Extension/Uninstall.php b/application/Espo/Core/Upgrades/Actions/Extension/Uninstall.php index 08d3b05f2d..bf21b971be 100644 --- a/application/Espo/Core/Upgrades/Actions/Extension/Uninstall.php +++ b/application/Espo/Core/Upgrades/Actions/Extension/Uninstall.php @@ -56,9 +56,14 @@ class Uninstall extends \Espo\Core\Upgrades\Actions\Base\Uninstall { /** Set extension entity, isInstalled = false */ $extensionEntity = $this->getExtensionEntity(); - $extensionEntity->set('isInstalled', false); - $this->getEntityManager()->saveEntity($extensionEntity); + + try { + $this->getEntityManager()->saveEntity($extensionEntity); + } catch (\Throwable $e) { + $GLOBALS['log']->error('Error saving Extension entity. The error occurred by existing Hook, more details: ' . $e->getMessage() .' at '. $e->getFile() . ':' . $e->getLine()); + $this->throwErrorAndRemovePackage('Error saving Extension entity. Check logs for details.', false); + } } protected function getRestoreFileList() @@ -70,4 +75,4 @@ class Uninstall extends \Espo\Core\Upgrades\Actions\Base\Uninstall return $this->data['restoreFileList']; } -} \ No newline at end of file +} diff --git a/tests/unit/Espo/Core/Upgrades/Actions/BaseTest.php b/tests/unit/Espo/Core/Upgrades/Actions/BaseTest.php index b025dbd734..c4135e03b5 100644 --- a/tests/unit/Espo/Core/Upgrades/Actions/BaseTest.php +++ b/tests/unit/Espo/Core/Upgrades/Actions/BaseTest.php @@ -147,8 +147,8 @@ class BaseTest extends \PHPUnit\Framework\TestCase $this->objects['config'] ->expects($this->once()) - ->method('get') - ->will($this->returnValue([])); + ->method('has') + ->will($this->returnValue(false)); $this->reflection->invokeMethod('getManifest', array()); } @@ -229,8 +229,8 @@ class BaseTest extends \PHPUnit\Framework\TestCase $this->objects['config'] ->expects($this->once()) - ->method('get') - ->will($this->returnValue([])); + ->method('has') + ->will($this->returnValue(false)); $this->reflection->invokeMethod('checkVersions', array($versions, $currentVersion, 'error')); } @@ -274,8 +274,8 @@ class BaseTest extends \PHPUnit\Framework\TestCase $this->objects['config'] ->expects($this->once()) - ->method('get') - ->will($this->returnValue([])); + ->method('has') + ->will($this->returnValue(false)); $this->reflection->setProperty('data', array('manifest' => array('type' => 'upgrade')));