1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
namespace Magento\Setup\Console\Command;
use Magento\Framework\App\Console\MaintenanceModeEnabler;
use Magento\Framework\App\DeploymentConfig;
use Magento\Framework\App\MaintenanceMode;
use Magento\Framework\Backup\Factory;
use Magento\Framework\ObjectManagerInterface;
use Magento\Framework\Setup\BackupRollbackFactory;
use Magento\Setup\Model\ObjectManagerProvider;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Question\ConfirmationQuestion;
/**
* Command to rollback code, media and DB
*
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
*/
class RollbackCommand extends AbstractSetupCommand
{
/**
* Name of input arguments or options
*/
const INPUT_KEY_CODE_BACKUP_FILE = 'code-file';
const INPUT_KEY_MEDIA_BACKUP_FILE = 'media-file';
const INPUT_KEY_DB_BACKUP_FILE = 'db-file';
/**
* Object Manager
*
* @var ObjectManagerInterface
*/
private $objectManager;
/**
* @var BackupRollbackFactory
*/
private $backupRollbackFactory;
/**
* Existing deployment config
*
* @var DeploymentConfig
*/
private $deploymentConfig;
/**
* @var MaintenanceModeEnabler
*/
private $maintenanceModeEnabler;
/**
* Constructor
*
* @param ObjectManagerProvider $objectManagerProvider
* @param MaintenanceMode $maintenanceMode deprecated, use $maintenanceModeEnabler instead
* @param DeploymentConfig $deploymentConfig
* @param MaintenanceModeEnabler $maintenanceModeEnabler
*
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
*/
public function __construct(
ObjectManagerProvider $objectManagerProvider,
MaintenanceMode $maintenanceMode,
DeploymentConfig $deploymentConfig,
MaintenanceModeEnabler $maintenanceModeEnabler = null
) {
$this->objectManager = $objectManagerProvider->get();
$this->backupRollbackFactory = $this->objectManager->get(\Magento\Framework\Setup\BackupRollbackFactory::class);
$this->deploymentConfig = $deploymentConfig;
$this->maintenanceModeEnabler =
$maintenanceModeEnabler ?: $this->objectManager->get(MaintenanceModeEnabler::class);
parent::__construct();
}
/**
* {@inheritdoc}
*/
protected function configure()
{
$options = [
new InputOption(
self::INPUT_KEY_CODE_BACKUP_FILE,
'c',
InputOption::VALUE_REQUIRED,
'Basename of the code backup file in var/backups'
),
new InputOption(
self::INPUT_KEY_MEDIA_BACKUP_FILE,
'm',
InputOption::VALUE_REQUIRED,
'Basename of the media backup file in var/backups'
),
new InputOption(
self::INPUT_KEY_DB_BACKUP_FILE,
'd',
InputOption::VALUE_REQUIRED,
'Basename of the db backup file in var/backups'
),
];
$this->setName('setup:rollback')
->setDescription('Rolls back Magento Application codebase, media and database')
->setDefinition($options);
parent::configure();
}
/**
* {@inheritdoc}
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
if (!$this->deploymentConfig->isAvailable() && ($input->getOption(self::INPUT_KEY_MEDIA_BACKUP_FILE)
|| $input->getOption(self::INPUT_KEY_DB_BACKUP_FILE))
) {
$output->writeln("<info>No information is available: the Magento application is not installed.</info>");
// we must have an exit code higher than zero to indicate something was wrong
return \Magento\Framework\Console\Cli::RETURN_FAILURE;
}
$returnValue = $this->maintenanceModeEnabler->executeInMaintenanceMode(
function () use ($input, $output, &$returnValue) {
try {
$helper = $this->getHelper('question');
$question = new ConfirmationQuestion(
'<info>You are about to remove current code and/or database tables. Are you sure?[y/N]<info>',
false
);
if (!$helper->ask($input, $output, $question) && $input->isInteractive()) {
return \Magento\Framework\Console\Cli::RETURN_FAILURE;
}
$questionKeep = new ConfirmationQuestion(
'<info>Do you want to keep the backups?[y/N]<info>',
false
);
$keepSourceFile = $helper->ask($input, $output, $questionKeep);
$this->doRollback($input, $output, $keepSourceFile);
$output->writeln('<info>Please set file permission of bin/magento to executable</info>');
return \Magento\Framework\Console\Cli::RETURN_SUCCESS;
} catch (\Exception $e) {
$output->writeln('<error>' . $e->getMessage() . '</error>');
// we must have an exit code higher than zero to indicate something was wrong
return \Magento\Framework\Console\Cli::RETURN_FAILURE;
}
},
$output,
false
);
return $returnValue;
}
/**
* Check rollback options and rolls back appropriately
*
* @param InputInterface $input
* @param OutputInterface $output
* @param boolean $keepSourceFile
* @return void
* @throws \InvalidArgumentException
*/
private function doRollback(InputInterface $input, OutputInterface $output, $keepSourceFile)
{
$inputOptionProvided = false;
$rollbackHandler = $this->backupRollbackFactory->create($output);
if ($input->getOption(self::INPUT_KEY_CODE_BACKUP_FILE)) {
$rollbackHandler->codeRollback(
$input->getOption(self::INPUT_KEY_CODE_BACKUP_FILE),
Factory::TYPE_FILESYSTEM,
$keepSourceFile
);
$inputOptionProvided = true;
}
if ($input->getOption(self::INPUT_KEY_MEDIA_BACKUP_FILE)) {
$rollbackHandler->codeRollback(
$input->getOption(self::INPUT_KEY_MEDIA_BACKUP_FILE),
Factory::TYPE_MEDIA,
$keepSourceFile
);
$inputOptionProvided = true;
}
if ($input->getOption(self::INPUT_KEY_DB_BACKUP_FILE)) {
$this->setAreaCode();
$rollbackHandler->dbRollback($input->getOption(self::INPUT_KEY_DB_BACKUP_FILE), $keepSourceFile);
$inputOptionProvided = true;
}
if (!$inputOptionProvided) {
throw new \InvalidArgumentException(
'Not enough information provided to roll back.'
);
}
}
/**
* Sets area code to start a session for database backup and rollback
*
* @return void
*/
private function setAreaCode()
{
$areaCode = 'adminhtml';
/** @var \Magento\Framework\App\State $appState */
$appState = $this->objectManager->get(\Magento\Framework\App\State::class);
$appState->setAreaCode($areaCode);
/** @var \Magento\Framework\ObjectManager\ConfigLoaderInterface $configLoader */
$configLoader = $this->objectManager->get(\Magento\Framework\ObjectManager\ConfigLoaderInterface::class);
$this->objectManager->configure($configLoader->load($areaCode));
}
}