mirror of
https://github.com/SuiteCRM/SuiteCRM-Core.git
synced 2025-08-29 07:50:08 +08:00
Add Upgrade Command
- Add Upgrade Package handler -- Add base package handler service with re-usable api handle packages -- Re-usable service to extract and apply upgrade packages -- Add upgrade settings to configs - Add Base command -- Add abstract class with common input processing logic - Add Upgrade Command -- Add re-usable UpgradeHandler with api for applying upgrades -- Add command to call upgrade handler -- Add service feedback -- Call clear cache on upgrade command - Add Upgrade step by step execution -- Add process step interface and executor --- add common logging to each step execution --- add debug logging for each step execution --- allow running processes step by step --- allow configuring steps independently -- Move upgrade handler and upgrade command to use step executor -- Add upgrade log -- Improve upgrade command output
This commit is contained in:
parent
dc27646e31
commit
d22cfbbf8f
22 changed files with 1610 additions and 4 deletions
|
@ -24,6 +24,7 @@
|
|||
"prefer-stable": true,
|
||||
"require": {
|
||||
"ext-json": "*",
|
||||
"ext-zip": "*",
|
||||
"api-platform/api-pack": "^1.2",
|
||||
"elasticsearch/elasticsearch": "^5.3",
|
||||
"ezyang/htmlpurifier": "^4.10",
|
||||
|
|
|
@ -6,6 +6,7 @@ services:
|
|||
public: false # Allows optimizing the container by removing unused services.
|
||||
bind:
|
||||
$projectDir: '%kernel.project_dir%'
|
||||
$upgradePackageDir: '%packages.upgrade.dir%'
|
||||
$legacyDir: '%legacy.dir%'
|
||||
$legacyPath: '%legacy.path%'
|
||||
$legacySessionName: '%legacy.session_name%'
|
||||
|
@ -38,6 +39,7 @@ services:
|
|||
$legacyToFrontEndFieldsMap: '%record.fields.legacy_to_frontend_fields_map%'
|
||||
$uiConfigs: '%ui%'
|
||||
$extensions: '%extensions%'
|
||||
$upgradeConfig: '%upgrades%'
|
||||
_instanceof:
|
||||
App\Process\Service\ProcessHandlerInterface:
|
||||
tags: [ 'app.process.handler' ]
|
||||
|
@ -59,6 +61,11 @@ services:
|
|||
tags: [ 'app.data.statistics.handler' ]
|
||||
App\ViewDefinitions\LegacyHandler\SubpanelButtonMapperInterface:
|
||||
tags: [ 'subpanel.button.definition.mapper' ]
|
||||
# Always instantiate new instance for implementing classes
|
||||
App\Engine\Model\ProcessStepInterface:
|
||||
shared: false
|
||||
App\Install\Service\Upgrade\UpgradeStepInterface:
|
||||
tags: [ 'app.upgrade.step' ]
|
||||
|
||||
# makes classes in src/ available to be used as services
|
||||
# this creates a service per class whose id is the fully-qualified class name
|
||||
|
@ -187,6 +194,12 @@ services:
|
|||
arguments:
|
||||
- !tagged { tag: 'subpanel.button.definition.mapper' }
|
||||
|
||||
App\Install\Service\Upgrade\UpgradeHandler:
|
||||
# inject all services tagged with app.upgrade.step as first argument
|
||||
arguments:
|
||||
- !tagged { tag: 'app.upgrade.step' }
|
||||
- '@monolog.logger.upgrade'
|
||||
|
||||
App\Process\Service\ActionNameMapperInterface: '@App\Engine\LegacyHandler\ActionNameMapperHandler'
|
||||
App\Process\Service\BulkActionDefinitionProviderInterface: '@App\Process\Service\BulkActionDefinitionProvider'
|
||||
App\FieldDefinitions\Service\FieldDefinitionsProviderInterface: '@App\FieldDefinitions\LegacyHandler\FieldDefinitionsHandler'
|
||||
|
|
|
@ -4,7 +4,7 @@ monolog:
|
|||
type: stream
|
||||
path: "%kernel.logs_dir%/%kernel.environment%.log"
|
||||
level: debug
|
||||
channels: ["!event"]
|
||||
channels: ["!event", "!upgrade"]
|
||||
# uncomment to get logging in your browser
|
||||
# you may have to allow bigger header sizes in your Web server configuration
|
||||
#firephp:
|
||||
|
@ -16,4 +16,4 @@ monolog:
|
|||
console:
|
||||
type: console
|
||||
process_psr_3_messages: false
|
||||
channels: ["!event", "!doctrine", "!console"]
|
||||
channels: ["!event", "!doctrine", "!console", "!upgrade"]
|
||||
|
|
8
config/packages/monolog.yaml
Normal file
8
config/packages/monolog.yaml
Normal file
|
@ -0,0 +1,8 @@
|
|||
monolog:
|
||||
channels: ['upgrade']
|
||||
handlers:
|
||||
upgrade:
|
||||
type: stream
|
||||
path: "%kernel.project_dir%/logs/upgrade.log"
|
||||
level: debug
|
||||
channels: ["upgrade"]
|
|
@ -7,6 +7,7 @@ monolog:
|
|||
excluded_http_codes: [404, 405]
|
||||
# Prevents memory leaks
|
||||
buffer_size: 50
|
||||
channels: ["!upgrade"]
|
||||
nested:
|
||||
type: stream
|
||||
path: "%kernel.logs_dir%/%kernel.environment%.log"
|
||||
|
@ -14,7 +15,7 @@ monolog:
|
|||
console:
|
||||
type: console
|
||||
process_psr_3_messages: false
|
||||
channels: ["!event", "!doctrine"]
|
||||
channels: ["!event", "!doctrine", "!upgrade"]
|
||||
deprecation:
|
||||
type: stream
|
||||
path: "%kernel.logs_dir%/%kernel.environment%.deprecations.log"
|
||||
|
|
|
@ -5,7 +5,7 @@ monolog:
|
|||
action_level: error
|
||||
handler: nested
|
||||
excluded_http_codes: [404, 405]
|
||||
channels: ["!event"]
|
||||
channels: ["!event", "!upgrade"]
|
||||
nested:
|
||||
type: stream
|
||||
path: "%kernel.logs_dir%/%kernel.environment%.log"
|
||||
|
|
|
@ -4,6 +4,7 @@ framework:
|
|||
parameters:
|
||||
secret: '%env(APP_SECRET)%'
|
||||
legacy.dir: '%kernel.project_dir%/public/legacy'
|
||||
packages.upgrade.dir: '%kernel.project_dir%/tmp/package/upgrade'
|
||||
legacy.path: '/legacy'
|
||||
legacy.session_name: 'LEGACYSESSID'
|
||||
default_session_name: 'PHPSESSID'
|
||||
|
|
27
config/services/system/upgrades.yaml
Normal file
27
config/services/system/upgrades.yaml
Normal file
|
@ -0,0 +1,27 @@
|
|||
parameters:
|
||||
upgrades:
|
||||
toKeep:
|
||||
- 'cache'
|
||||
- 'extensions'
|
||||
- 'public/extensions'
|
||||
- 'public/legacy/modules'
|
||||
- 'public/legacy/custom'
|
||||
- 'public/legacy/cache'
|
||||
- 'public/legacy/upload'
|
||||
- 'public/legacy/Api/V8/OAuth2/private.key'
|
||||
- 'public/legacy/Api/V8/OAuth2/public.key'
|
||||
- 'public/legacy/config.php'
|
||||
- 'public/legacy/config_override.php'
|
||||
- 'public/legacy/config_si.php'
|
||||
- 'public/legacy/suitecrm.log'
|
||||
- 'public/legacy/install.log'
|
||||
- 'logs'
|
||||
- '.env.local'
|
||||
- '.env.local.php'
|
||||
toExpand:
|
||||
- 'public'
|
||||
- 'public/legacy'
|
||||
- 'public/legacy/modules'
|
||||
- 'public/legacy/Api'
|
||||
- 'public/legacy/Api/V8'
|
||||
- 'public/legacy/Api/V8/OAuth2'
|
103
core/backend/Engine/Model/Feedback.php
Normal file
103
core/backend/Engine/Model/Feedback.php
Normal file
|
@ -0,0 +1,103 @@
|
|||
<?php
|
||||
/**
|
||||
* SuiteCRM is a customer relationship management program developed by SalesAgility Ltd.
|
||||
* Copyright (C) 2021 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\Engine\Model;
|
||||
|
||||
class Feedback
|
||||
{
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
public $success;
|
||||
|
||||
/**
|
||||
* @var string[]
|
||||
*/
|
||||
public $messages = [];
|
||||
|
||||
/**
|
||||
* @var string[]
|
||||
*/
|
||||
public $debug = [];
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function isSuccess(): bool
|
||||
{
|
||||
return $this->success;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $success
|
||||
* @return Feedback
|
||||
*/
|
||||
public function setSuccess(bool $success): Feedback
|
||||
{
|
||||
$this->success = $success;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
public function getMessages(): array
|
||||
{
|
||||
return $this->messages ?? [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string[] $messages
|
||||
* @return Feedback
|
||||
*/
|
||||
public function setMessages(array $messages): Feedback
|
||||
{
|
||||
$this->messages = $messages;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
public function getDebug(): array
|
||||
{
|
||||
return $this->debug;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string[] $debug
|
||||
* @return Feedback
|
||||
*/
|
||||
public function setDebug(array $debug): Feedback
|
||||
{
|
||||
$this->debug = $debug;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
79
core/backend/Engine/Model/MultiFeedback.php
Normal file
79
core/backend/Engine/Model/MultiFeedback.php
Normal file
|
@ -0,0 +1,79 @@
|
|||
<?php
|
||||
/**
|
||||
* SuiteCRM is a customer relationship management program developed by SalesAgility Ltd.
|
||||
* Copyright (C) 2021 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\Engine\Model;
|
||||
|
||||
class MultiFeedback
|
||||
{
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
public $success;
|
||||
|
||||
/**
|
||||
* @var Feedback[]
|
||||
*/
|
||||
public $feedback = [];
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function isSuccess(): bool
|
||||
{
|
||||
return $this->success;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $success
|
||||
* @return MultiFeedback
|
||||
*/
|
||||
public function setSuccess(bool $success): MultiFeedback
|
||||
{
|
||||
$this->success = $success;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Feedback[]
|
||||
*/
|
||||
public function getFeedback(): array
|
||||
{
|
||||
return $this->feedback;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Feedback[] $feedback
|
||||
* @return MultiFeedback
|
||||
*/
|
||||
public function setFeedback(array $feedback): MultiFeedback
|
||||
{
|
||||
$this->feedback = $feedback;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
69
core/backend/Engine/Model/ProcessStepInterface.php
Normal file
69
core/backend/Engine/Model/ProcessStepInterface.php
Normal file
|
@ -0,0 +1,69 @@
|
|||
<?php
|
||||
/**
|
||||
* SuiteCRM is a customer relationship management program developed by SalesAgility Ltd.
|
||||
* Copyright (C) 2021 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\Engine\Model;
|
||||
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
interface ProcessStepInterface
|
||||
{
|
||||
/**
|
||||
* Get step key
|
||||
* @return string
|
||||
*/
|
||||
public function getKey(): string;
|
||||
|
||||
/**
|
||||
* Get execution order
|
||||
* @return int
|
||||
*/
|
||||
public function getOrder(): int;
|
||||
|
||||
/**
|
||||
* Execute step
|
||||
* @param array $context
|
||||
* @return Feedback
|
||||
*/
|
||||
public function execute(array &$context): Feedback;
|
||||
|
||||
/**
|
||||
* Run step
|
||||
* @param array $context
|
||||
* @return Feedback
|
||||
*/
|
||||
public function run(array &$context): Feedback;
|
||||
|
||||
/**
|
||||
* @return LoggerInterface|null
|
||||
*/
|
||||
public function getLogger(): ?LoggerInterface;
|
||||
|
||||
/**
|
||||
* @param LoggerInterface $logger
|
||||
*/
|
||||
public function setLogger(LoggerInterface $logger): void;
|
||||
}
|
160
core/backend/Engine/Model/ProcessStepTrait.php
Normal file
160
core/backend/Engine/Model/ProcessStepTrait.php
Normal file
|
@ -0,0 +1,160 @@
|
|||
<?php
|
||||
/**
|
||||
* SuiteCRM is a customer relationship management program developed by SalesAgility Ltd.
|
||||
* Copyright (C) 2021 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\Engine\Model;
|
||||
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
trait ProcessStepTrait
|
||||
{
|
||||
/**
|
||||
* @var LoggerInterface
|
||||
*/
|
||||
protected $logger;
|
||||
|
||||
/**
|
||||
* Run step
|
||||
* @param array $context
|
||||
* @return Feedback
|
||||
*/
|
||||
public function run(array &$context): Feedback
|
||||
{
|
||||
$this->logStart();
|
||||
|
||||
$feedback = $this->execute($context);
|
||||
|
||||
$this->logStepFeedback($feedback);
|
||||
|
||||
return $feedback;
|
||||
}
|
||||
|
||||
/**
|
||||
* Log step start
|
||||
*/
|
||||
protected function logStart(): void
|
||||
{
|
||||
if ($this->getLogger() === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->logger->info('Running step: ' . $this->getKey());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return LoggerInterface|null
|
||||
*/
|
||||
public function getLogger(): ?LoggerInterface
|
||||
{
|
||||
return $this->logger;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param LoggerInterface $logger
|
||||
*/
|
||||
public function setLogger(LoggerInterface $logger): void
|
||||
{
|
||||
$this->logger = $logger;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get step key
|
||||
* @return string
|
||||
*/
|
||||
abstract public function getKey(): string;
|
||||
|
||||
/**
|
||||
* Execute step
|
||||
* @param array $context
|
||||
* @return Feedback
|
||||
*/
|
||||
abstract protected function execute(array &$context): Feedback;
|
||||
|
||||
/**
|
||||
* Log step feedback
|
||||
* @param Feedback $feedback
|
||||
*/
|
||||
protected function logStepFeedback(Feedback $feedback): void
|
||||
{
|
||||
if ($this->getLogger() === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($feedback->isSuccess() === false) {
|
||||
$this->logger->error('step: ' . $this->getKey() . ' | status: failed');
|
||||
} else {
|
||||
$this->logger->info('step: ' . $this->getKey() . ' | status: done');
|
||||
}
|
||||
|
||||
$this->logFeedbackMessages($feedback);
|
||||
$this->logFeedbackDebug($feedback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Log feedback messages
|
||||
* @param Feedback $feedback
|
||||
*/
|
||||
protected function logFeedbackMessages(Feedback $feedback): void
|
||||
{
|
||||
$messages = $feedback->getMessages() ?? [];
|
||||
|
||||
if (empty($messages)) {
|
||||
$this->logger->info('step: ' . $this->getKey() . ' | messages: no messages');
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$this->logger->info('step: ' . $this->getKey() . ' | messages:');
|
||||
|
||||
foreach ($messages as $message) {
|
||||
|
||||
$this->logger->info($message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Log feedback debug
|
||||
* @param Feedback $feedback
|
||||
*/
|
||||
protected function logFeedbackDebug(Feedback $feedback): void
|
||||
{
|
||||
$debugInfo = $feedback->getDebug() ?? [];
|
||||
|
||||
if (empty($debugInfo)) {
|
||||
$this->logger->info('step: ' . $this->getKey() . ' | debug: no debug info');
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$this->logger->info('step: ' . $this->getKey() . ' | debug:');
|
||||
|
||||
foreach ($debugInfo as $debug) {
|
||||
|
||||
$this->logger->info($debug);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
207
core/backend/Engine/Service/ProcessSteps/ProcessStepExecutor.php
Normal file
207
core/backend/Engine/Service/ProcessSteps/ProcessStepExecutor.php
Normal file
|
@ -0,0 +1,207 @@
|
|||
<?php
|
||||
/**
|
||||
* SuiteCRM is a customer relationship management program developed by SalesAgility Ltd.
|
||||
* Copyright (C) 2021 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\Engine\Service\ProcessSteps;
|
||||
|
||||
use App\Engine\Model\Feedback;
|
||||
use App\Engine\Model\MultiFeedback;
|
||||
use App\Engine\Model\ProcessStepInterface;
|
||||
use BadMethodCallException;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
abstract class ProcessStepExecutor implements ProcessStepExecutorInterface
|
||||
{
|
||||
/**
|
||||
* @var LoggerInterface
|
||||
*/
|
||||
protected $logger;
|
||||
|
||||
/**
|
||||
* @var ProcessStepInterface[]
|
||||
*/
|
||||
protected $steps;
|
||||
|
||||
/**
|
||||
* @var ProcessStepInterface[][]
|
||||
*/
|
||||
protected $orderedSteps;
|
||||
|
||||
/**
|
||||
* Run all steps in order
|
||||
* @param array $context
|
||||
* @return MultiFeedback feedback
|
||||
*/
|
||||
public function runAll(array $context): MultiFeedback
|
||||
{
|
||||
$result = new MultiFeedback();
|
||||
$result->setSuccess(true);
|
||||
|
||||
$context = $context ?? [];
|
||||
$context['stepsFeedback'] = [];
|
||||
|
||||
foreach ($this->orderedSteps as $positionSteps) {
|
||||
foreach ($positionSteps as $step) {
|
||||
$feedback = $step->run($context);
|
||||
|
||||
$context['stepsFeedback'][$step->getKey()] = $feedback;
|
||||
|
||||
if ($feedback->isSuccess() === false) {
|
||||
|
||||
$result->setSuccess(false);
|
||||
$result->setFeedback($context['stepsFeedback']);
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$result->setFeedback($context['stepsFeedback']);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $stepKey
|
||||
* @param array $context
|
||||
* @return Feedback feedback
|
||||
*/
|
||||
public function run(string $stepKey, array $context): Feedback
|
||||
{
|
||||
if (empty($this->steps[$stepKey])) {
|
||||
throw new BadMethodCallException("$stepKey not found");
|
||||
}
|
||||
|
||||
$context = $context ?? [];
|
||||
$context['stepsFeedback'] = [];
|
||||
|
||||
return $this->steps[$stepKey]->run($context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Has position
|
||||
* @param int $position
|
||||
* @return bool
|
||||
*/
|
||||
public function hasPosition(int $position): bool
|
||||
{
|
||||
$positionSteps = $this->orderedSteps[$position] ?? [];
|
||||
if (empty($positionSteps)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Run next
|
||||
* @param int $position
|
||||
* @param array $context
|
||||
* @return MultiFeedback
|
||||
*/
|
||||
public function runPosition(int $position, array $context): MultiFeedback
|
||||
{
|
||||
$positionSteps = $this->orderedSteps[$position] ?? [];
|
||||
|
||||
if (empty($positionSteps)) {
|
||||
$result = new MultiFeedback();
|
||||
$result->setSuccess(false);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
$result = new MultiFeedback();
|
||||
$result->setSuccess(true);
|
||||
$context = $context ?? [];
|
||||
$context['stepsFeedback'] = [];
|
||||
|
||||
foreach ($positionSteps as $step) {
|
||||
$feedback = $step->run($context);
|
||||
|
||||
$context['stepsFeedback'][$step->getKey()] = $feedback;
|
||||
|
||||
if ($feedback->isSuccess() === false) {
|
||||
$result->setSuccess(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$result->setFeedback($context['stepsFeedback']);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get position keys
|
||||
* @param int $position
|
||||
* @return string[]
|
||||
*/
|
||||
public function getPositionKeys(int $position): array
|
||||
{
|
||||
$positionSteps = $this->orderedSteps[$position] ?? [];
|
||||
if (empty($positionSteps)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return array_keys($positionSteps);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param iterable $handlers
|
||||
* @param LoggerInterface $logger
|
||||
*/
|
||||
protected function initSteps(iterable $handlers, LoggerInterface $logger): void
|
||||
{
|
||||
/**
|
||||
* @var $ordered ProcessStepInterface[][]
|
||||
*/
|
||||
$ordered = [];
|
||||
|
||||
/**
|
||||
* @var $handlers ProcessStepInterface[]
|
||||
*/
|
||||
foreach ($handlers as $step) {
|
||||
$key = $step->getKey() ?? '';
|
||||
$order = $step->getOrder() ?? count($this->orderedSteps);
|
||||
|
||||
$step->setLogger($logger);
|
||||
|
||||
$positionSteps = $ordered[$order] ?? [];
|
||||
$positionSteps[$key] = $step;
|
||||
$ordered[$order] = $positionSteps;
|
||||
|
||||
$this->steps[$key] = $step;
|
||||
}
|
||||
|
||||
ksort($ordered, SORT_NUMERIC);
|
||||
|
||||
$this->orderedSteps = [];
|
||||
|
||||
foreach ($ordered as $item) {
|
||||
$this->orderedSteps[] = $item;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
<?php
|
||||
/**
|
||||
* SuiteCRM is a customer relationship management program developed by SalesAgility Ltd.
|
||||
* Copyright (C) 2021 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\Engine\Service\ProcessSteps;
|
||||
|
||||
use App\Engine\Model\Feedback;
|
||||
use App\Engine\Model\MultiFeedback;
|
||||
|
||||
interface ProcessStepExecutorInterface
|
||||
{
|
||||
/**
|
||||
* Run all steps in order
|
||||
* @param array $context
|
||||
* @return MultiFeedback feedback
|
||||
*/
|
||||
public function runAll(array $context): MultiFeedback;
|
||||
|
||||
/**
|
||||
* @param string $stepKey
|
||||
* @param array $context
|
||||
* @return Feedback feedback
|
||||
*/
|
||||
public function run(string $stepKey, array $context): Feedback;
|
||||
|
||||
/**
|
||||
* Has position
|
||||
* @param int $position
|
||||
* @return bool
|
||||
*/
|
||||
public function hasPosition(int $position): bool;
|
||||
|
||||
/**
|
||||
* Run position
|
||||
* @param int $position
|
||||
* @param array $context
|
||||
* @return MultiFeedback
|
||||
*/
|
||||
public function runPosition(int $position, array $context): MultiFeedback;
|
||||
|
||||
/**
|
||||
* Get position keys
|
||||
* @param int $position
|
||||
* @return string[]
|
||||
*/
|
||||
public function getPositionKeys(int $position): array;
|
||||
}
|
200
core/backend/Install/Command/BaseCommand.php
Normal file
200
core/backend/Install/Command/BaseCommand.php
Normal file
|
@ -0,0 +1,200 @@
|
|||
<?php
|
||||
/**
|
||||
* SuiteCRM is a customer relationship management program developed by SalesAgility Ltd.
|
||||
* Copyright (C) 2021 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\Command;
|
||||
|
||||
use App\Engine\Model\Feedback;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\HttpFoundation\Session\SessionInterface;
|
||||
|
||||
abstract class BaseCommand extends Command
|
||||
{
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $inputConfig = [];
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
protected $initSession = false;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $defaultSessionName;
|
||||
|
||||
/**
|
||||
* @var SessionInterface
|
||||
*/
|
||||
protected $session;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $legacySessionName;
|
||||
|
||||
/**
|
||||
* @required
|
||||
* @param string $defaultSessionName
|
||||
*/
|
||||
public function setDefaultSessionName(string $defaultSessionName): void
|
||||
{
|
||||
$this->defaultSessionName = $defaultSessionName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @required
|
||||
* @param string $legacySessionName
|
||||
*/
|
||||
public function setLegacySessionName(string $legacySessionName): void
|
||||
{
|
||||
$this->legacySessionName = $legacySessionName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @required
|
||||
* @param SessionInterface $session
|
||||
*/
|
||||
public function setSession(SessionInterface $session): void
|
||||
{
|
||||
$this->session = $session;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function execute(InputInterface $input, OutputInterface $output): int
|
||||
{
|
||||
$arguments = [];
|
||||
|
||||
$helper = $this->getHelper('question');
|
||||
|
||||
foreach ($this->inputConfig as $key => $option) {
|
||||
$value = $input->getOption($key);
|
||||
if (empty($value)) {
|
||||
$value = $helper->ask($input, $output, $option['question']);
|
||||
}
|
||||
$arguments[$key] = $value;
|
||||
}
|
||||
|
||||
if ($this->initSession) {
|
||||
$this->startSession();
|
||||
}
|
||||
|
||||
return $this->executeCommand($input, $output, $arguments);
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute command actions
|
||||
* @param InputInterface $input
|
||||
* @param OutputInterface $output
|
||||
* @param array $inputs
|
||||
* @return int
|
||||
*/
|
||||
abstract protected function executeCommand(InputInterface $input, OutputInterface $output, array $inputs): int;
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
protected function configure(): void
|
||||
{
|
||||
$inputs = [];
|
||||
|
||||
foreach ($this->inputConfig as $key => $item) {
|
||||
$inputs[$key] = $item['argument'];
|
||||
}
|
||||
|
||||
$this->setDefinition(
|
||||
$inputs
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Start Session
|
||||
*/
|
||||
protected function startSession(): void
|
||||
{
|
||||
if ($this->session->isStarted()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->session->setName($this->defaultSessionName);
|
||||
|
||||
$this->session->start();
|
||||
}
|
||||
|
||||
/**
|
||||
* Write feedback for a given step
|
||||
* @param string $step
|
||||
* @param OutputInterface $output
|
||||
* @param Feedback $feedback
|
||||
*/
|
||||
protected function writeStepFeedback(string $step, OutputInterface $output, Feedback $feedback): void
|
||||
{
|
||||
$status = '<info>done</info>';
|
||||
if ($feedback->isSuccess() === false) {
|
||||
$status = '<error>failed</error>';
|
||||
}
|
||||
|
||||
$output->writeln('step: ' . $step . ' | status: ' . $status);
|
||||
|
||||
$this->writeFeedbackMessages($output, $feedback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write feedback messages
|
||||
* @param OutputInterface $output
|
||||
* @param Feedback $feedback
|
||||
*/
|
||||
protected function writeFeedbackMessages(OutputInterface $output, Feedback $feedback): void
|
||||
{
|
||||
$messages = $feedback->getMessages() ?? [];
|
||||
|
||||
foreach ($messages as $message) {
|
||||
|
||||
$output->writeln($this->colorMessage($feedback, $message));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Feedback $feedback
|
||||
* @param string $message
|
||||
* @return string
|
||||
*/
|
||||
protected function colorMessage(Feedback $feedback, string $message): string
|
||||
{
|
||||
$colorTag = 'info';
|
||||
if ($feedback->isSuccess() === false) {
|
||||
$colorTag = 'error';
|
||||
}
|
||||
|
||||
return implode('', ["<$colorTag>", $message, "</$colorTag>"]);
|
||||
}
|
||||
}
|
133
core/backend/Install/Command/UpgradeCommand.php
Normal file
133
core/backend/Install/Command/UpgradeCommand.php
Normal file
|
@ -0,0 +1,133 @@
|
|||
<?php
|
||||
/**
|
||||
* SuiteCRM is a customer relationship management program developed by SalesAgility Ltd.
|
||||
* Copyright (C) 2021 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\Command;
|
||||
|
||||
use App\Install\Service\Upgrade\UpgradeHandlerInterface;
|
||||
use Exception;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Question\Question;
|
||||
|
||||
/**
|
||||
* Class UpgradeCommand
|
||||
* @package App\Install\Command
|
||||
*/
|
||||
class UpgradeCommand extends BaseCommand
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected static $defaultName = 'suitecrm:app:upgrade';
|
||||
|
||||
/**
|
||||
* @var UpgradeHandlerInterface
|
||||
*/
|
||||
protected $handler;
|
||||
|
||||
/**
|
||||
* UpgradeCommand constructor.
|
||||
* @param UpgradeHandlerInterface $handler
|
||||
*/
|
||||
public function __construct(UpgradeHandlerInterface $handler)
|
||||
{
|
||||
$this->handler = $handler;
|
||||
|
||||
$this->inputConfig['target-version'] = [
|
||||
'question' => new Question('Please enter the version to move to: '),
|
||||
'argument' => new InputOption(
|
||||
'target-version',
|
||||
't',
|
||||
InputOption::VALUE_REQUIRED,
|
||||
'Target Version'
|
||||
)
|
||||
];
|
||||
|
||||
$this->initSession = true;
|
||||
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @throws Exception
|
||||
*/
|
||||
public function executeCommand(InputInterface $input, OutputInterface $output, array $arguments): int
|
||||
{
|
||||
$output->writeln([
|
||||
'',
|
||||
'SuiteCRM Upgrade',
|
||||
'============',
|
||||
'',
|
||||
]);
|
||||
|
||||
$version = $arguments['target-version'];
|
||||
$context = [
|
||||
'version' => $version
|
||||
];
|
||||
|
||||
$position = 0;
|
||||
$success = true;
|
||||
|
||||
do {
|
||||
$keys = $this->handler->getPositionKeys($position);
|
||||
|
||||
$output->writeln('Running: ' . implode(' | ', $keys));
|
||||
|
||||
$result = $this->handler->runPosition($position, $context);
|
||||
|
||||
foreach ($result->getFeedback() as $key => $feedback) {
|
||||
$this->writeStepFeedback($key, $output, $feedback);
|
||||
}
|
||||
|
||||
$success = $success && $result->isSuccess();
|
||||
|
||||
$position++;
|
||||
|
||||
} while ($success === true && $this->handler->hasPosition($position));
|
||||
|
||||
$output->writeln([
|
||||
'',
|
||||
'============',
|
||||
]);
|
||||
|
||||
if ($success === false) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
protected function configure(): void
|
||||
{
|
||||
parent::configure();
|
||||
|
||||
$this->setDescription('Upgrade the application')
|
||||
->setHelp('This command will upgrade suite 8 and legacy application');
|
||||
}
|
||||
}
|
86
core/backend/Install/Service/Cache/CacheClear.php
Normal file
86
core/backend/Install/Service/Cache/CacheClear.php
Normal file
|
@ -0,0 +1,86 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* SuiteCRM is a customer relationship management program developed by SalesAgility Ltd.
|
||||
* Copyright (C) 2021 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\Cache;
|
||||
|
||||
use App\Engine\Model\Feedback;
|
||||
use Exception;
|
||||
use Symfony\Bundle\FrameworkBundle\Console\Application;
|
||||
use Symfony\Component\Console\Input\ArrayInput;
|
||||
use Symfony\Component\Console\Output\NullOutput;
|
||||
use Symfony\Component\HttpKernel\KernelInterface;
|
||||
|
||||
/**
|
||||
* Class CacheClear
|
||||
* @package App\Install\Service\Cache
|
||||
*/
|
||||
class CacheClear
|
||||
{
|
||||
/**
|
||||
* @var KernelInterface
|
||||
*/
|
||||
protected $kernel;
|
||||
|
||||
/**
|
||||
* CacheClear constructor.
|
||||
* @param KernelInterface $kernel
|
||||
*/
|
||||
public function __construct(KernelInterface $kernel)
|
||||
{
|
||||
$this->kernel = $kernel;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Feedback
|
||||
* @throws Exception
|
||||
*/
|
||||
public function run(): Feedback
|
||||
{
|
||||
$application = new Application($this->kernel);
|
||||
$application->setAutoExit(false);
|
||||
|
||||
$input = new ArrayInput([
|
||||
'command' => 'cache:clear',
|
||||
]);
|
||||
|
||||
$output = new NullOutput();
|
||||
$result = $application->run($input, $output);
|
||||
|
||||
$feedback = new Feedback();
|
||||
|
||||
if ($result === 0) {
|
||||
$feedback->setSuccess(true)->setMessages(['Successfully cleared cache']);
|
||||
|
||||
return $feedback;
|
||||
}
|
||||
|
||||
$feedback->setSuccess(false)->setMessages(['Error clearing cache']);
|
||||
|
||||
return $feedback;
|
||||
}
|
||||
}
|
78
core/backend/Install/Service/Package/PackageHandler.php
Normal file
78
core/backend/Install/Service/Package/PackageHandler.php
Normal file
|
@ -0,0 +1,78 @@
|
|||
<?php
|
||||
/**
|
||||
* SuiteCRM is a customer relationship management program developed by SalesAgility Ltd.
|
||||
* Copyright (C) 2021 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\Package;
|
||||
|
||||
use Symfony\Component\Filesystem\Filesystem;
|
||||
use ZipArchive;
|
||||
|
||||
class PackageHandler
|
||||
{
|
||||
|
||||
/**
|
||||
* @var Filesystem
|
||||
*/
|
||||
protected $filesystem;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->filesystem = new Filesystem();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $path
|
||||
* @return bool
|
||||
*/
|
||||
public function exists(string $path): bool
|
||||
{
|
||||
if (!$this->filesystem->exists($path)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract package to
|
||||
* @param string $packagePath
|
||||
* @param string $outputPath
|
||||
* @return bool
|
||||
*/
|
||||
public function extract(string $packagePath, string $outputPath): bool
|
||||
{
|
||||
$zip = new ZipArchive();
|
||||
|
||||
if ($zip->open($packagePath) !== true) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$result = $zip->extractTo($outputPath);
|
||||
$result = $zip->close() && $result;
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
48
core/backend/Install/Service/Upgrade/UpgradeHandler.php
Normal file
48
core/backend/Install/Service/Upgrade/UpgradeHandler.php
Normal file
|
@ -0,0 +1,48 @@
|
|||
<?php
|
||||
/**
|
||||
* SuiteCRM is a customer relationship management program developed by SalesAgility Ltd.
|
||||
* Copyright (C) 2021 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;
|
||||
|
||||
use App\Engine\Service\ProcessSteps\ProcessStepExecutor;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
class UpgradeHandler extends ProcessStepExecutor implements UpgradeHandlerInterface
|
||||
{
|
||||
/**
|
||||
* UpgradeHandler constructor.
|
||||
* @param iterable $handlers
|
||||
* @param LoggerInterface $upgradeLogger
|
||||
*/
|
||||
public function __construct(
|
||||
iterable $handlers,
|
||||
LoggerInterface $upgradeLogger
|
||||
) {
|
||||
$this->logger = $upgradeLogger;
|
||||
$this->initSteps($handlers, $this->logger);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
<?php
|
||||
/**
|
||||
* SuiteCRM is a customer relationship management program developed by SalesAgility Ltd.
|
||||
* Copyright (C) 2021 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;
|
||||
|
||||
use App\Engine\Service\ProcessSteps\ProcessStepExecutorInterface;
|
||||
|
||||
/**
|
||||
* Interface UpgradeStepInterface
|
||||
* Used to allow extensibility
|
||||
* @package App\Install\Service\Upgrade
|
||||
*/
|
||||
interface UpgradeHandlerInterface extends ProcessStepExecutorInterface
|
||||
{
|
||||
}
|
243
core/backend/Install/Service/Upgrade/UpgradePackageHandler.php
Normal file
243
core/backend/Install/Service/Upgrade/UpgradePackageHandler.php
Normal file
|
@ -0,0 +1,243 @@
|
|||
<?php
|
||||
/**
|
||||
* SuiteCRM is a customer relationship management program developed by SalesAgility Ltd.
|
||||
* Copyright (C) 2021 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;
|
||||
|
||||
use App\Engine\Model\Feedback;
|
||||
use App\Engine\Service\FolderSync\FolderComparatorInterface;
|
||||
use App\Engine\Service\FolderSync\FolderSync;
|
||||
use App\Install\Service\Package\PackageHandler;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
class UpgradePackageHandler extends PackageHandler
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $projectDir;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $upgradePackageDir;
|
||||
|
||||
/**
|
||||
* @var FolderSync
|
||||
*/
|
||||
protected $sync;
|
||||
|
||||
/**
|
||||
* @var FolderComparatorInterface
|
||||
*/
|
||||
protected $compare;
|
||||
|
||||
/**
|
||||
* @var LoggerInterface
|
||||
*/
|
||||
protected $upgradeLogger;
|
||||
|
||||
/**
|
||||
* UpgradeHandler constructor.
|
||||
* @param string $projectDir
|
||||
* @param string $upgradePackageDir
|
||||
* @param FolderSync $sync
|
||||
* @param FolderComparatorInterface $compare
|
||||
* @param LoggerInterface $upgradeLogger
|
||||
* @param array $upgradeConfig
|
||||
*/
|
||||
public function __construct(
|
||||
string $projectDir,
|
||||
string $upgradePackageDir,
|
||||
FolderSync $sync,
|
||||
FolderComparatorInterface $compare,
|
||||
LoggerInterface $upgradeLogger,
|
||||
array $upgradeConfig
|
||||
) {
|
||||
parent::__construct();
|
||||
$this->projectDir = $projectDir;
|
||||
$this->upgradePackageDir = $upgradePackageDir;
|
||||
$this->sync = $sync;
|
||||
$this->compare = $compare;
|
||||
|
||||
$this->compare->setToKeep($upgradeConfig['toKeep']);
|
||||
$this->compare->setPathsToExpand($upgradeConfig['toExpand']);
|
||||
$this->upgradeLogger = $upgradeLogger;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if package exists
|
||||
* @param string $version
|
||||
* @return Feedback
|
||||
*/
|
||||
public function checkPackage(string $version): Feedback
|
||||
{
|
||||
$packagePath = $this->getPackagePath($version);
|
||||
|
||||
$feedback = new Feedback();
|
||||
$feedback->setSuccess(true)->setMessages(['Package found in path']);
|
||||
$feedback->setDebug(['Check package existence in: ' . $packagePath]);
|
||||
|
||||
if (!$this->exists($packagePath)) {
|
||||
$feedback->setSuccess(false)->setMessages(['Package not found in path: ' . $packagePath]);
|
||||
}
|
||||
|
||||
return $feedback;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract package
|
||||
* @param string $version
|
||||
* @return Feedback
|
||||
*/
|
||||
public function extractPackage(string $version): Feedback
|
||||
{
|
||||
$packagePath = $this->getPackagePath($version);
|
||||
$extractPath = $this->getPackageExtractPath($version);
|
||||
|
||||
$feedback = new Feedback();
|
||||
$feedback->setSuccess(true)->setMessages(['Package extracted']);
|
||||
$feedback->setDebug(['Trying to extract to: ' . $extractPath]);
|
||||
|
||||
$extracted = $this->extract($packagePath, $extractPath);
|
||||
|
||||
if ($extracted === false) {
|
||||
$feedback = new Feedback();
|
||||
$feedback->setSuccess(false)->setMessages(['Error while trying to extract package to: ' . $extractPath]);
|
||||
}
|
||||
|
||||
return $feedback;
|
||||
}
|
||||
|
||||
/**
|
||||
* Run compare and check permissions
|
||||
* @param string $version
|
||||
* @return Feedback
|
||||
*/
|
||||
public function checkPermissions(string $version): Feedback
|
||||
{
|
||||
$extractPath = $this->getPackageExtractPath($version);
|
||||
|
||||
$manifest = $this->runCompare($extractPath);
|
||||
|
||||
$messages = [];
|
||||
$success = true;
|
||||
|
||||
foreach ($manifest as $path => $entry) {
|
||||
|
||||
$originAllowed = true;
|
||||
if ($entry->action !== 'delete') {
|
||||
$originResult = $this->sync->checkOriginPermissions($extractPath, $path);
|
||||
$originAllowed = $originResult['allowed'] ?? false;
|
||||
$originPath = $originResult['path'] ?? '';
|
||||
|
||||
if ($originAllowed === false) {
|
||||
$messages[] = 'Insufficient permissions to read from: ' . $originPath;
|
||||
}
|
||||
}
|
||||
|
||||
$destinationResult = $this->sync->checkDestinationPermissions($this->projectDir, $path);
|
||||
$destinationAllowed = $destinationResult['allowed'] ?? false;
|
||||
$destinationPath = $destinationResult['path'] ?? '';
|
||||
|
||||
if ($destinationAllowed === false) {
|
||||
$messages[] = 'Insufficient permissions to read from: ' . $destinationPath;
|
||||
}
|
||||
|
||||
$success = $success && $originAllowed && $destinationAllowed;
|
||||
}
|
||||
|
||||
$feedback = new Feedback();
|
||||
$feedback->setSuccess($success);
|
||||
|
||||
if ($success) {
|
||||
$messages = ['Permissions checked'];
|
||||
}
|
||||
|
||||
$feedback->setMessages($messages);
|
||||
|
||||
return $feedback;
|
||||
}
|
||||
|
||||
/**
|
||||
* Run compare and install package
|
||||
* @param string $version
|
||||
* @return Feedback
|
||||
*/
|
||||
public function install(string $version): Feedback
|
||||
{
|
||||
$extractPath = $this->getPackageExtractPath($version);
|
||||
|
||||
$manifest = $this->runCompare($extractPath);
|
||||
|
||||
$feedback = new Feedback();
|
||||
|
||||
if (empty($manifest)) {
|
||||
$feedback->setSuccess(true)->setMessages(['Sync diff did not return results']);
|
||||
|
||||
return $feedback;
|
||||
}
|
||||
|
||||
$feedback->setDebug([
|
||||
'sync manifest generated: ' . json_encode($manifest, JSON_THROW_ON_ERROR)
|
||||
]);
|
||||
|
||||
$this->sync->run($extractPath, $this->projectDir, $manifest);
|
||||
|
||||
$feedback->setSuccess(true)->setMessages(['Successfully installed package']);
|
||||
|
||||
return $feedback;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $extractPath
|
||||
* @return array
|
||||
*/
|
||||
public function runCompare(string $extractPath): array
|
||||
{
|
||||
return $this->compare->run($extractPath, $this->projectDir);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get package path
|
||||
* @param string $version
|
||||
* @return string
|
||||
*/
|
||||
protected function getPackagePath(string $version): string
|
||||
{
|
||||
return $this->upgradePackageDir . '/' . $version . '.zip';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get package extract output path
|
||||
* @param string $version
|
||||
* @return string
|
||||
*/
|
||||
protected function getPackageExtractPath(string $version): string
|
||||
{
|
||||
return $this->upgradePackageDir . '/' . $version . '-extracted';
|
||||
}
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
<?php
|
||||
/**
|
||||
* SuiteCRM is a customer relationship management program developed by SalesAgility Ltd.
|
||||
* Copyright (C) 2021 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;
|
||||
|
||||
use App\Engine\Model\ProcessStepInterface;
|
||||
|
||||
/**
|
||||
* Interface UpgradeStepInterface
|
||||
* Used to auto-configure upgrade steps
|
||||
* @package App\Install\Service\Upgrade
|
||||
*/
|
||||
interface UpgradeStepInterface extends ProcessStepInterface
|
||||
{
|
||||
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue