mirror of
https://github.com/SuiteCRM/SuiteCRM-Core.git
synced 2025-09-01 08:00:47 +08:00
Fix #475 - Add deletion warning on upgrade
This commit is contained in:
parent
31a20e84d0
commit
78eb20ccca
5 changed files with 490 additions and 0 deletions
|
@ -66,6 +66,16 @@ class FolderComparator implements FolderComparatorInterface
|
|||
*/
|
||||
protected $toExpandKeys;
|
||||
|
||||
/**
|
||||
* @var string[]
|
||||
*/
|
||||
protected $toReAdd = [];
|
||||
|
||||
/**
|
||||
* @var bool[]
|
||||
*/
|
||||
protected $toReAddKeys;
|
||||
|
||||
/**
|
||||
* FolderCompare constructor.
|
||||
*/
|
||||
|
@ -305,6 +315,38 @@ class FolderComparator implements FolderComparatorInterface
|
|||
return $this->toKeepIgnoreKeys;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set paths to re-add
|
||||
* @param array $toReAdd
|
||||
*/
|
||||
public function setToReAdd(array $toReAdd): void
|
||||
{
|
||||
$this->toReAdd = $toReAdd;
|
||||
$this->toReAddKeys = [];
|
||||
|
||||
foreach ($this->toReAdd as $item) {
|
||||
$this->toReAddKeys[$item] = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get paths to re-add
|
||||
* @return array
|
||||
*/
|
||||
public function getToReAdd(): array
|
||||
{
|
||||
return $this->toReAdd;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get paths to re-add keys
|
||||
* @return array
|
||||
*/
|
||||
public function getToReAddKeys(): array
|
||||
{
|
||||
return $this->toReAddKeys;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add folder directories
|
||||
* @param string $originPath
|
||||
|
|
|
@ -107,6 +107,11 @@ abstract class BaseStepExecutorCommand extends BaseCommand
|
|||
$alerts = $this->getHandler()->getAlerts($position, $context);
|
||||
|
||||
foreach ($alerts as $alert) {
|
||||
$messages = $alert->getMessages();
|
||||
if (empty($messages)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$title = $alert->getTile() ?? 'Alert';
|
||||
$output->writeln($this->colorMessage('comment', $title));
|
||||
|
||||
|
|
|
@ -0,0 +1,195 @@
|
|||
<?php
|
||||
/**
|
||||
* SuiteCRM is a customer relationship management program developed by SalesAgility Ltd.
|
||||
* Copyright (C) 2024 SalesAgility Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU Affero General Public License version 3 as published by the
|
||||
* Free Software Foundation with the addition of the following permission added
|
||||
* to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
|
||||
* IN WHICH THE COPYRIGHT IS OWNED BY SALESAGILITY, SALESAGILITY DISCLAIMS THE
|
||||
* WARRANTY OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU Affero General Public License
|
||||
* version 3, these Appropriate Legal Notices must retain the display of the
|
||||
* "Supercharged by SuiteCRM" logo. If the display of the logos is not reasonably
|
||||
* feasible for technical reasons, the Appropriate Legal Notices must display
|
||||
* the words "Supercharged by SuiteCRM".
|
||||
*/
|
||||
|
||||
namespace App\Install\Service\Upgrade\Steps;
|
||||
|
||||
use App\Engine\Model\Feedback;
|
||||
use App\Engine\Model\ProcessStepTrait;
|
||||
use App\Engine\Service\FolderSync\FolderComparatorInterface;
|
||||
use App\Engine\Service\ProcessSteps\ProcessStepAlert;
|
||||
use App\Install\Service\Upgrade\UpgradePackageHandler;
|
||||
use App\Install\Service\Upgrade\UpgradeStepInterface;
|
||||
|
||||
/**
|
||||
* Class FilesToDeleteCheck
|
||||
* @package App\Install\Service\LegacyMigration\Steps;
|
||||
*/
|
||||
class FilesToDeleteCheck implements UpgradeStepInterface
|
||||
{
|
||||
use ProcessStepTrait;
|
||||
|
||||
public const HANDLER_KEY = 'custom-files-deletion-warning';
|
||||
public const POSITION = 550;
|
||||
public const STAGE = 'upgrade-install';
|
||||
|
||||
/**
|
||||
* @var UpgradePackageHandler
|
||||
*/
|
||||
private $handler;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $projectDir;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $upgradePackageDir;
|
||||
|
||||
/**
|
||||
* @var FolderComparatorInterface
|
||||
*/
|
||||
protected $compare;
|
||||
|
||||
/**
|
||||
* ExternalFilesCheck constructor.
|
||||
* @param UpgradePackageHandler $handler
|
||||
* @param string $projectDir
|
||||
* @param string $upgradePackageDir
|
||||
* @param FolderComparatorInterface $compare
|
||||
* @param array $upgradeConfig
|
||||
*/
|
||||
public function __construct(
|
||||
UpgradePackageHandler $handler,
|
||||
string $projectDir,
|
||||
string $upgradePackageDir,
|
||||
FolderComparatorInterface $compare,
|
||||
array $upgradeConfig
|
||||
) {
|
||||
$this->handler = $handler;
|
||||
$this->projectDir = $projectDir;
|
||||
$this->upgradePackageDir = $upgradePackageDir;
|
||||
$this->compare = $compare;
|
||||
|
||||
$this->compare->setToKeep($upgradeConfig['toKeep']);
|
||||
$this->compare->setToKeepIgnore($upgradeConfig['toKeepIgnore']);
|
||||
$this->compare->setPathsToExpand($upgradeConfig['toExpand']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function getKey(): string
|
||||
{
|
||||
return self::HANDLER_KEY;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function getOrder(): int
|
||||
{
|
||||
return self::POSITION;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function getStage(): string
|
||||
{
|
||||
return self::STAGE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Alert
|
||||
* @param array $context
|
||||
* @return ProcessStepAlert
|
||||
*/
|
||||
public function getAlert(array &$context): ProcessStepAlert
|
||||
{
|
||||
$version = $context['version'];
|
||||
$extractPath = $this->getPackageExtractPath($version);
|
||||
$manifest = $this->runCompare($extractPath);
|
||||
|
||||
$deletionList = [];
|
||||
|
||||
if (!empty($manifest)) {
|
||||
foreach ($manifest as $path => $entry) {
|
||||
if ($entry->action === 'delete') {
|
||||
$deletionList[] = $path;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$alert = new ProcessStepAlert();
|
||||
|
||||
if (!empty($deletionList)) {
|
||||
$alert->setTile("Warning: Potential Custom Files");
|
||||
|
||||
$messages = [
|
||||
"*********************************************************************",
|
||||
"** \e[31m !!! WARNING !!! \e[0m**",
|
||||
"*********************************************************************",
|
||||
"** The following files/directories will be permanently DELETED: **",
|
||||
];
|
||||
|
||||
foreach ($deletionList as $item) {
|
||||
$messages[] = "** - $item";
|
||||
}
|
||||
|
||||
$messages[] = "** **";
|
||||
$messages[] = "** Move any important files to a safe location BEFORE proceeding. **";
|
||||
$messages[] = "*********************************************************************";
|
||||
|
||||
$alert->setMessages($messages);
|
||||
} else {
|
||||
$alert->setMessages([]);
|
||||
}
|
||||
|
||||
return $alert;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get package extract output path
|
||||
* @param string $version
|
||||
* @return string
|
||||
*/
|
||||
public function getPackageExtractPath(string $version): string
|
||||
{
|
||||
return $this->upgradePackageDir . '/' . $version . '-extracted';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $extractPath
|
||||
* @return array
|
||||
*/
|
||||
public function runCompare(string $extractPath): array
|
||||
{
|
||||
return $this->compare->run($extractPath, $this->projectDir);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function execute(array &$context): Feedback
|
||||
{
|
||||
$targetVersion = $context['version'] ?? '';
|
||||
|
||||
return $this->handler->checkFilesToDelete($targetVersion);
|
||||
}
|
||||
}
|
|
@ -95,6 +95,7 @@ class UpgradePackageHandler extends PackageHandler
|
|||
$this->compare->setToKeep($upgradeConfig['toKeep']);
|
||||
$this->compare->setToKeepIgnore($upgradeConfig['toKeepIgnore']);
|
||||
$this->compare->setPathsToExpand($upgradeConfig['toExpand']);
|
||||
$this->compare->setToReAdd($upgradeConfig['toReAdd']);
|
||||
$this->upgradeLogger = $upgradeLogger;
|
||||
}
|
||||
|
||||
|
@ -142,6 +143,21 @@ class UpgradePackageHandler extends PackageHandler
|
|||
return $feedback;
|
||||
}
|
||||
|
||||
/**
|
||||
* Run compare and check files to delete
|
||||
* @param string $version
|
||||
* @return Feedback
|
||||
*/
|
||||
public function checkFilesToDelete(string $version): Feedback
|
||||
{
|
||||
$feedback = new Feedback();
|
||||
$feedback->setSuccess(true);
|
||||
$messages = ['Files to delete checked'];
|
||||
$feedback->setMessages($messages);
|
||||
|
||||
return $feedback;
|
||||
}
|
||||
|
||||
/**
|
||||
* Run compare and check permissions
|
||||
* @param string $version
|
||||
|
@ -215,13 +231,117 @@ class UpgradePackageHandler extends PackageHandler
|
|||
'sync manifest generated: ' . json_encode($manifest, JSON_THROW_ON_ERROR)
|
||||
]);
|
||||
|
||||
$tmpFolder = $this->projectDir . '/tmp/toReAdd';
|
||||
$toReAddItems = $this->compare->getToReAdd();
|
||||
|
||||
$this->copyFilesToReAddToTmpFolder($tmpFolder, $toReAddItems);
|
||||
|
||||
$this->sync->run($extractPath, $this->projectDir, $manifest);
|
||||
|
||||
$this->restoreFilesFromTmpFolder($tmpFolder, $toReAddItems);
|
||||
|
||||
$feedback->setSuccess(true)->setMessages(['Successfully installed package']);
|
||||
|
||||
return $feedback;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy files to be re-added to a temporary folder
|
||||
*
|
||||
* @param string $tmpFolder
|
||||
* @param array $toReAddItems
|
||||
* @return void
|
||||
*/
|
||||
protected function copyFilesToReAddToTmpFolder(string $tmpFolder, array $toReAddItems): void
|
||||
{
|
||||
$filesystem = new Filesystem();
|
||||
|
||||
if (!$filesystem->exists($tmpFolder)) {
|
||||
$filesystem->mkdir($tmpFolder);
|
||||
}
|
||||
|
||||
foreach ($toReAddItems as $item) {
|
||||
$sourcePath = $this->projectDir . '/' . $item;
|
||||
$destinationPath = $tmpFolder . '/' . $item;
|
||||
|
||||
if (is_dir($sourcePath)) {
|
||||
$dirContents = scandir($sourcePath);
|
||||
|
||||
foreach ($dirContents as $file) {
|
||||
if ($file === '.' || $file === '..') {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($file !== 'en_us.lang.php') {
|
||||
$fileSourcePath = $sourcePath . '/' . $file;
|
||||
$fileDestinationPath = $destinationPath . '/' . $file;
|
||||
|
||||
if (file_exists($fileSourcePath)) {
|
||||
if (!is_dir($destinationPath)) {
|
||||
mkdir($destinationPath, 0755, true);
|
||||
}
|
||||
|
||||
$filesystem->copy($fileSourcePath, $fileDestinationPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (file_exists($sourcePath)) {
|
||||
$filesystem->mirror($sourcePath, $destinationPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Restore files from the temporary folder to their original location
|
||||
*
|
||||
* @param string $tmpFolder
|
||||
* @param array $toReAddItems
|
||||
* @return void
|
||||
*/
|
||||
protected function restoreFilesFromTmpFolder(string $tmpFolder, array $toReAddItems): void
|
||||
{
|
||||
$filesystem = new Filesystem();
|
||||
|
||||
foreach ($toReAddItems as $item) {
|
||||
$tmpPath = $tmpFolder . '/' . $item;
|
||||
$finalDestinationPath = $this->projectDir . '/' . $item;
|
||||
|
||||
if (file_exists($tmpPath)) {
|
||||
if (is_dir($tmpPath)) {
|
||||
$dirContents = scandir($tmpPath);
|
||||
|
||||
foreach ($dirContents as $file) {
|
||||
if ($file === '.' || $file === '..') {
|
||||
continue;
|
||||
}
|
||||
|
||||
$fileTmpPath = $tmpPath . '/' . $file;
|
||||
$fileFinalPath = $finalDestinationPath . '/' . $file;
|
||||
|
||||
if ($file === 'en_us.lang.php' && file_exists($fileFinalPath)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (is_dir($fileTmpPath)) {
|
||||
$filesystem->mirror($fileTmpPath, $fileFinalPath);
|
||||
} else {
|
||||
$filesystem->copy($fileTmpPath, $fileFinalPath);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (basename($item) !== 'en_us.lang.php' || !file_exists($finalDestinationPath)) {
|
||||
$filesystem->copy($tmpPath, $finalDestinationPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$filesystem->remove($tmpFolder);
|
||||
}
|
||||
|
||||
/**
|
||||
* Run compare and install package
|
||||
* @param string $version
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue