mirror of
https://github.com/espocrm/espocrm.git
synced 2026-07-01 08:26:04 +00:00
Improved upgrade/install extenions feature
This commit is contained in:
@@ -28,7 +28,6 @@ class ExtensionManager extends Upgrades\Base
|
||||
|
||||
protected $params = array(
|
||||
'packagePath' => 'data/upload/extensions',
|
||||
|
||||
'backupPath' => 'data/.backup/extensions',
|
||||
|
||||
'scriptNames' => array(
|
||||
|
||||
@@ -30,6 +30,7 @@ class UpgradeManager extends Upgrades\Base
|
||||
|
||||
protected $params = array(
|
||||
'packagePath' => 'data/upload/upgrades',
|
||||
'backupPath' => 'data/.backup/upgrades',
|
||||
|
||||
'scriptNames' => array(
|
||||
'before' => 'BeforeUpgrade',
|
||||
|
||||
@@ -304,7 +304,7 @@ abstract class Base
|
||||
/**
|
||||
* Get a list of files defined in manifest.json
|
||||
*
|
||||
* @return [type] [description]
|
||||
* @return array
|
||||
*/
|
||||
protected function getDeleteFileList()
|
||||
{
|
||||
@@ -352,6 +352,18 @@ abstract class Base
|
||||
return $this->data['fileList'];
|
||||
}
|
||||
|
||||
protected function getRestoreFileList()
|
||||
{
|
||||
if (!isset($this->data['restoreFileList'])) {
|
||||
$backupPath = $this->getPath('backupPath');
|
||||
$backupFilePath = Util::concatPath($backupPath, self::FILES);
|
||||
|
||||
$this->data['restoreFileList'] = $this->getFileManager()->getFileList($backupFilePath, true, '', true, true);
|
||||
}
|
||||
|
||||
return $this->data['restoreFileList'];
|
||||
}
|
||||
|
||||
protected function copy($sourcePath, $destPath, $recursively = false, array $fileList = null, $copyOnlyFiles = false)
|
||||
{
|
||||
try {
|
||||
@@ -506,4 +518,23 @@ abstract class Base
|
||||
{
|
||||
return $this->getContainer()->get('dataManager')->clearCache();
|
||||
}
|
||||
|
||||
protected function checkIsWritable()
|
||||
{
|
||||
$fullFileList = array_merge($this->getDeleteFileList(), $this->getCopyFileList());
|
||||
|
||||
$result = $this->getFileManager()->isWritableList($fullFileList);
|
||||
if (!$result) {
|
||||
$permissionDeniedList = $this->getFileManager()->getLastPermissionDeniedList();
|
||||
throw new Error("Permission denied in <br>". implode(", <br>", $permissionDeniedList));
|
||||
}
|
||||
}
|
||||
|
||||
protected function backupExistingFiles()
|
||||
{
|
||||
$fullFileList = array_merge($this->getDeleteFileList(), $this->getCopyFileList());
|
||||
|
||||
$backupPath = $this->getPath('backupPath');
|
||||
return $this->copy('', array($backupPath, self::FILES), false, $fullFileList);
|
||||
}
|
||||
}
|
||||
@@ -23,6 +23,7 @@
|
||||
namespace Espo\Core\Upgrades\Actions\Base;
|
||||
|
||||
use Espo\Core\Exceptions\Error;
|
||||
use Espo\Core\Utils\Util;
|
||||
|
||||
class Install extends \Espo\Core\Upgrades\Actions\Base
|
||||
{
|
||||
@@ -58,15 +59,15 @@ class Install extends \Espo\Core\Upgrades\Actions\Base
|
||||
$this->isAcceptable();
|
||||
}
|
||||
|
||||
$this->beforeRunAction();
|
||||
//check permissions copied and deleted files
|
||||
$this->checkIsWritable();
|
||||
|
||||
$this->backupExistingFiles();
|
||||
|
||||
/* run before install script */
|
||||
$this->runScript('before');
|
||||
|
||||
/* remove files defined in a manifest */
|
||||
if (!$this->deleteFiles()) {
|
||||
$this->throwErrorAndRemovePackage('Permission denied to delete files.');
|
||||
}
|
||||
$this->beforeRunAction();
|
||||
|
||||
/* copy files from directory "Files" to EspoCRM files */
|
||||
if (!$this->copyFiles()) {
|
||||
@@ -74,15 +75,18 @@ class Install extends \Espo\Core\Upgrades\Actions\Base
|
||||
}
|
||||
$this->isCopied = true;
|
||||
|
||||
/* remove files defined in a manifest */
|
||||
$this->deleteFiles();
|
||||
|
||||
if (!$this->systemRebuild()) {
|
||||
$this->throwErrorAndRemovePackage('Error occurred while EspoCRM rebuild.');
|
||||
}
|
||||
|
||||
$this->afterRunAction();
|
||||
|
||||
/* run before install script */
|
||||
$this->runScript('after');
|
||||
|
||||
$this->afterRunAction();
|
||||
|
||||
$this->clearCache();
|
||||
|
||||
/* delete unziped files */
|
||||
@@ -93,15 +97,25 @@ class Install extends \Espo\Core\Upgrades\Actions\Base
|
||||
|
||||
protected function restoreFiles()
|
||||
{
|
||||
$backupPath = $this->getPath('backupPath');
|
||||
|
||||
$res = true;
|
||||
if ($this->isCopied) {
|
||||
$res &= $this->copy(array($backupPath, self::FILES), '', true);
|
||||
$GLOBALS['log']->info('Restore: copy back');
|
||||
if (!$this->isCopied) {
|
||||
return;
|
||||
}
|
||||
|
||||
$res &= $this->getFileManager()->removeInDir($backupPath, true);
|
||||
$GLOBALS['log']->info('Installer: Restore previous files.');
|
||||
|
||||
$backupPath = $this->getPath('backupPath');
|
||||
$backupFilePath = Util::concatPath($backupPath, self::FILES);
|
||||
|
||||
$backupFileList = $this->getRestoreFileList();
|
||||
$copyFileList = $this->getCopyFileList();
|
||||
$deleteFileList = array_diff($copyFileList, $backupFileList);
|
||||
|
||||
$res = $this->copy($backupFilePath, '', true);
|
||||
$res &= $this->getFileManager()->remove($deleteFileList, null, true);
|
||||
|
||||
if ($res) {
|
||||
$this->getFileManager()->removeInDir($backupPath, true);
|
||||
}
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
@@ -37,34 +37,36 @@ class Uninstall extends \Espo\Core\Upgrades\Actions\Base
|
||||
|
||||
$this->setProcessId($processId);
|
||||
|
||||
$this->beforeRunAction();
|
||||
$this->checkIsWritable();
|
||||
|
||||
/* run before install script */
|
||||
$this->runScript('beforeUninstall');
|
||||
|
||||
$this->beforeRunAction();
|
||||
|
||||
$backupPath = $this->getPath('backupPath');
|
||||
if (file_exists($backupPath)) {
|
||||
|
||||
/* remove extension files, saved in fileList */
|
||||
if (!$this->deleteFiles(true)) {
|
||||
throw new Error('Permission denied to delete files.');
|
||||
}
|
||||
|
||||
/* copy core files */
|
||||
if (!$this->copyFiles()) {
|
||||
throw new Error('Cannot copy files.');
|
||||
throw new $this->throwErrorAndRemovePackage('Cannot copy files.');
|
||||
}
|
||||
|
||||
/* remove extension files, saved in fileList */
|
||||
if (!$this->deleteFiles(true)) {
|
||||
throw new $this->throwErrorAndRemovePackage('Permission denied to delete files.');
|
||||
}
|
||||
}
|
||||
|
||||
if (!$this->systemRebuild()) {
|
||||
throw new Error('Error occurred while EspoCRM rebuild.');
|
||||
throw new $this->throwErrorAndRemovePackage('Error occurred while EspoCRM rebuild.');
|
||||
}
|
||||
|
||||
$this->afterRunAction();
|
||||
|
||||
/* run before install script */
|
||||
$this->runScript('afterUninstall');
|
||||
|
||||
$this->afterRunAction();
|
||||
|
||||
$this->clearCache();
|
||||
|
||||
/* delete backup files */
|
||||
@@ -73,12 +75,6 @@ class Uninstall extends \Espo\Core\Upgrades\Actions\Base
|
||||
$GLOBALS['log']->debug('Uninstallation process ['.$processId.']: end run.');
|
||||
}
|
||||
|
||||
protected function getDeleteFileList()
|
||||
{
|
||||
$extensionEntity = $this->getExtensionEntity();
|
||||
return $extensionEntity->get('fileList');
|
||||
}
|
||||
|
||||
protected function restoreFiles()
|
||||
{
|
||||
$packagePath = $this->getPath('packagePath');
|
||||
@@ -131,4 +127,41 @@ class Uninstall extends \Espo\Core\Upgrades\Actions\Base
|
||||
throw new Error($errorMessage);
|
||||
}
|
||||
|
||||
protected function getCopyFileList()
|
||||
{
|
||||
if (!isset($this->data['fileList'])) {
|
||||
$backupPath = $this->getPath('backupPath');
|
||||
$filesPath = Util::concatPath($backupPath, self::FILES);
|
||||
|
||||
$this->data['fileList'] = $this->getFileManager()->getFileList($filesPath, true, '', true, true);
|
||||
}
|
||||
|
||||
return $this->data['fileList'];
|
||||
}
|
||||
|
||||
protected function getRestoreFileList()
|
||||
{
|
||||
if (!isset($this->data['restoreFileList'])) {
|
||||
$packagePath = $this->getPackagePath();
|
||||
$filesPath = Util::concatPath($packagePath, self::FILES);
|
||||
|
||||
if (!file_exists($filesPath)) {
|
||||
$this->unzipArchive($packagePath);
|
||||
}
|
||||
|
||||
$this->data['restoreFileList'] = $this->getFileManager()->getFileList($filesPath, true, '', true, true);
|
||||
}
|
||||
|
||||
return $this->data['restoreFileList'];
|
||||
}
|
||||
|
||||
protected function getDeleteFileList()
|
||||
{
|
||||
$packageFileList = $this->getRestoreFileList();
|
||||
$backupFileList = $this->getCopyFileList();
|
||||
|
||||
$deleteFileList = array_diff($packageFileList, $backupFileList);
|
||||
|
||||
return $deleteFileList;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,8 +37,6 @@ class Install extends \Espo\Core\Upgrades\Actions\Base\Install
|
||||
$this->uninstallExtension();
|
||||
$this->deleteExtension();
|
||||
}
|
||||
|
||||
$this->copyExistingFiles();
|
||||
}
|
||||
|
||||
protected function afterRunAction()
|
||||
@@ -51,12 +49,11 @@ class Install extends \Espo\Core\Upgrades\Actions\Base\Install
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function copyExistingFiles()
|
||||
protected function backupExistingFiles()
|
||||
{
|
||||
$fileList = $this->getCopyFileList();
|
||||
$backupPath = $this->getPath('backupPath');
|
||||
parent::backupExistingFiles();
|
||||
|
||||
$res = $this->copy('', array($backupPath, self::FILES), false, $fileList);
|
||||
$backupPath = $this->getPath('backupPath');
|
||||
|
||||
/** copy scripts files */
|
||||
$packagePath = $this->getPackagePath();
|
||||
@@ -65,19 +62,6 @@ class Install extends \Espo\Core\Upgrades\Actions\Base\Install
|
||||
return $res;
|
||||
}
|
||||
|
||||
protected function restoreFiles()
|
||||
{
|
||||
$res = true;
|
||||
if ($this->isCopied) {
|
||||
$extensionFileList = $this->getCopyFileList();
|
||||
$res &= $this->getFileManager()->remove($extensionFileList);
|
||||
}
|
||||
|
||||
$res &= parent::restoreFiles();
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
protected function isNew()
|
||||
{
|
||||
$extensionEntity = $this->getExtensionEntity();
|
||||
|
||||
@@ -68,4 +68,14 @@ class Uninstall extends \Espo\Core\Upgrades\Actions\Base\Uninstall
|
||||
$extensionEntity->set('isInstalled', false);
|
||||
$this->getEntityManager()->saveEntity($extensionEntity);
|
||||
}
|
||||
|
||||
protected function getRestoreFileList()
|
||||
{
|
||||
if (!isset($this->data['restoreFileList'])) {
|
||||
$extensionEntity = $this->getExtensionEntity();
|
||||
$this->data['restoreFileList'] = $extensionEntity->get('fileList');
|
||||
}
|
||||
|
||||
return $this->data['restoreFileList'];
|
||||
}
|
||||
}
|
||||
@@ -24,17 +24,12 @@ namespace Espo\Core\Upgrades\Actions\Upgrade;
|
||||
|
||||
class Install extends \Espo\Core\Upgrades\Actions\Base\Install
|
||||
{
|
||||
protected function systemRebuild()
|
||||
protected function afterRunAction()
|
||||
{
|
||||
$manifest = $this->getManifest();
|
||||
|
||||
$res = $this->getConfig()->set('version', $manifest['version']);
|
||||
if (method_exists($this->getConfig(), 'save')) {
|
||||
$res = $this->getConfig()->save();
|
||||
}
|
||||
$res &= parent::systemRebuild();
|
||||
|
||||
return $res;
|
||||
$this->getConfig()->set('version', $manifest['version']);
|
||||
$this->getConfig()->save();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -29,6 +29,8 @@ class Manager
|
||||
{
|
||||
private $permission;
|
||||
|
||||
private $permissionDeniedList = array();
|
||||
|
||||
public function __construct(\Espo\Core\Utils\Config $config = null)
|
||||
{
|
||||
$params = null;
|
||||
@@ -774,5 +776,73 @@ return '.var_export($content, true).';
|
||||
?>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if $paths are writable. Permission denied list are defined in getLastPermissionDeniedList()
|
||||
*
|
||||
* @param array $paths
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function isWritableList(array $paths)
|
||||
{
|
||||
$permissionDeniedList = array();
|
||||
|
||||
$result = true;
|
||||
foreach ($paths as $path) {
|
||||
$rowResult = $this->isWritable($path);
|
||||
if (!$rowResult) {
|
||||
$permissionDeniedList[] = $path;
|
||||
}
|
||||
$result &= $rowResult;
|
||||
}
|
||||
|
||||
if (!empty($permissionDeniedList)) {
|
||||
$this->permissionDeniedList = $this->getPermissionUtils()->arrangePermissionList($permissionDeniedList);
|
||||
}
|
||||
|
||||
return (bool) $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get last permission denied list
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getLastPermissionDeniedList()
|
||||
{
|
||||
return $this->permissionDeniedList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if $path is writable
|
||||
*
|
||||
* @param string | array $path
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function isWritable($path)
|
||||
{
|
||||
$existFile = $this->getExistsPath($path);
|
||||
|
||||
return is_writable($existFile);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get exists path. Ex. if check /var/www/espocrm/custom/someFile.php and this file doesn't extist, result will be /var/www/espocrm/custom
|
||||
*
|
||||
* @param string | array $path
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function getExistsPath($path)
|
||||
{
|
||||
$fullPath = $this->concatPaths($path);
|
||||
|
||||
if (!file_exists($fullPath)) {
|
||||
$fullPath = $this->getExistsPath($fullPath, PATHINFO_DIRNAME);
|
||||
}
|
||||
|
||||
return $fullPath;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user