1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* @author Victor Dubiniuk <[email protected]> |
4
|
|
|
* |
5
|
|
|
* @copyright Copyright (c) 2015, ownCloud, Inc. |
6
|
|
|
* @license AGPL-3.0 |
7
|
|
|
* |
8
|
|
|
* This code is free software: you can redistribute it and/or modify |
9
|
|
|
* it under the terms of the GNU Affero General Public License, version 3, |
10
|
|
|
* as published by the Free Software Foundation. |
11
|
|
|
* |
12
|
|
|
* This program is distributed in the hope that it will be useful, |
13
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
14
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
15
|
|
|
* GNU Affero General Public License for more details. |
16
|
|
|
* |
17
|
|
|
* You should have received a copy of the GNU Affero General Public License, version 3, |
18
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/> |
19
|
|
|
* |
20
|
|
|
*/ |
21
|
|
|
namespace Owncloud\Updater\Console; |
22
|
|
|
|
23
|
|
|
use Owncloud\Updater\Utils\Locator; |
24
|
|
|
use Pimple\Container; |
25
|
|
|
use Symfony\Component\Console\Output\StreamOutput; |
26
|
|
|
use Symfony\Component\Console\Input\InputInterface; |
27
|
|
|
use Symfony\Component\Console\Output\BufferedOutput; |
28
|
|
|
use Symfony\Component\Console\Output\OutputInterface; |
29
|
|
|
use Symfony\Component\Console\Command\Command; |
30
|
|
|
use \Symfony\Component\Process\Exception\ProcessFailedException; |
31
|
|
|
|
32
|
|
|
class Application extends \Symfony\Component\Console\Application { |
33
|
|
|
|
34
|
|
|
/** @var Container */ |
35
|
|
|
public static $container; |
36
|
|
|
|
37
|
|
|
|
38
|
|
|
/** @var Container */ |
39
|
|
|
protected $diContainer; |
40
|
|
|
|
41
|
|
|
/** |
42
|
|
|
* Pass Pimple container into application |
43
|
|
|
* @param Container $container |
44
|
|
|
*/ |
45
|
|
|
public function setContainer(Container $container){ |
46
|
|
|
$this->diContainer = $container; |
47
|
|
|
self::$container = $container; |
48
|
|
|
} |
49
|
|
|
|
50
|
|
|
/** |
51
|
|
|
* Get Pimple container |
52
|
|
|
* @return Container |
53
|
|
|
*/ |
54
|
|
|
public function getContainer(){ |
55
|
|
|
return $this->diContainer; |
56
|
|
|
} |
57
|
|
|
|
58
|
|
|
/** |
59
|
|
|
* Get logger instance |
60
|
|
|
* @return \Psr\Log\LoggerInterface |
61
|
|
|
*/ |
62
|
|
|
public function getLogger(){ |
63
|
|
|
return $this->diContainer['logger']; |
64
|
|
|
} |
65
|
|
|
|
66
|
|
|
/** |
67
|
|
|
* Log exception with trace |
68
|
|
|
* @param \Exception $e |
69
|
|
|
*/ |
70
|
|
|
public function logException($e){ |
71
|
|
|
$buffer = new BufferedOutput(OutputInterface::VERBOSITY_VERBOSE); |
72
|
|
|
$this->renderException($e, $buffer); |
73
|
|
|
$this->getLogger()->error($buffer->fetch()); |
74
|
|
|
} |
75
|
|
|
|
76
|
|
|
public function doRun(InputInterface $input, OutputInterface $output){ |
77
|
|
|
if (!($this->diContainer['logger.output'] instanceof StreamOutput)){ |
78
|
|
|
$output->writeln('[Warning] Failed to init logger. Logging is disabled.'); |
79
|
|
|
} |
80
|
|
|
try { |
81
|
|
|
// TODO: check if the current command needs a valid OC instance |
82
|
|
|
$this->assertOwnCloudFound(); |
83
|
|
|
$this->initDirectoryStructure(); |
84
|
|
|
|
85
|
|
|
$configReader = $this->diContainer['utils.configReader']; |
86
|
|
|
$commandName = $this->getCommandName($input); |
87
|
|
|
if (!in_array( |
88
|
|
|
$commandName, |
89
|
|
|
['upgrade:executeCoreUpgradeScripts', 'upgrade:checkpoint', 'upgrade:maintenanceMode', 'help', 'list'] |
90
|
|
|
) |
91
|
|
|
){ |
92
|
|
|
try { |
93
|
|
|
$configReader->init(); |
94
|
|
|
} catch (ProcessFailedException $e){ |
95
|
|
|
$this->logException($e); |
96
|
|
|
$output->writeln("<error>Initialization failed with message:</error>"); |
97
|
|
|
$output->writeln($e->getProcess()->getOutput()); |
98
|
|
|
$output->writeln('<info>Use upgrade:checkpoint --list to view a list of checkpoints</info>'); |
99
|
|
|
$output->writeln('<info>upgrade:checkpoint --restore [checkpointid] to revert to the last checkpoint</info>'); |
100
|
|
|
$output->writeln('Please attach your update.log to the issues you reporting.'); |
101
|
|
|
return 1; |
102
|
|
|
} |
103
|
|
|
|
104
|
|
|
} |
105
|
|
|
return parent::doRun($input, $output); |
106
|
|
|
} catch (\Exception $e) { |
107
|
|
|
$this->logException($e); |
108
|
|
|
throw $e; |
109
|
|
|
} |
110
|
|
|
} |
111
|
|
|
|
112
|
|
|
protected function doRunCommand(Command $command, InputInterface $input, OutputInterface $output){ |
113
|
|
|
if ($command instanceof \Owncloud\Updater\Command\Command){ |
114
|
|
|
$command->setContainer($this->getContainer()); |
115
|
|
|
$commandName = $this->getCommandName($input); |
116
|
|
|
$this->getLogger()->info('Execution of ' . $commandName . ' command started'); |
117
|
|
|
if (!empty($command->getMessage())){ |
118
|
|
|
$message = sprintf('<info>%s</info>', $command->getMessage()); |
119
|
|
|
$output->writeln($message); |
120
|
|
|
} |
121
|
|
|
$exitCode = parent::doRunCommand($command, $input, $output); |
122
|
|
|
$this->getLogger()->info( |
123
|
|
|
'Execution of ' . $commandName . ' command stopped. Exit code is ' . $exitCode |
124
|
|
|
); |
125
|
|
|
} else { |
126
|
|
|
$exitCode = parent::doRunCommand($command, $input, $output); |
127
|
|
|
} |
128
|
|
|
return $exitCode; |
129
|
|
|
} |
130
|
|
|
|
131
|
|
|
/** |
132
|
|
|
* Check for owncloud instance |
133
|
|
|
* @throws \RuntimeException |
134
|
|
|
*/ |
135
|
|
|
protected function assertOwnCloudFound(){ |
136
|
|
|
$container = $this->getContainer(); |
137
|
|
|
/** @var Locator $locator */ |
138
|
|
|
$locator = $container['utils.locator']; |
139
|
|
|
|
140
|
|
|
$file = $locator->getPathToVersionFile(); |
141
|
|
View Code Duplication |
if (!file_exists($file) || !is_file($file)){ |
|
|
|
|
142
|
|
|
throw new \RuntimeException('ownCloud is not found in ' . dirname($file)); |
143
|
|
|
} |
144
|
|
|
|
145
|
|
|
// assert minimum version |
146
|
|
|
$installedVersion = implode('.', $locator->getInstalledVersion()); |
147
|
|
|
if (version_compare($installedVersion, '9.0.0', '<')) { |
148
|
|
|
throw new \RuntimeException("Minimum ownCloud version 9.0.0 is required for the updater - $installedVersion was found in " . $locator->getOwncloudRootPath()); |
149
|
|
|
} |
150
|
|
|
|
151
|
|
|
// has to be installed |
152
|
|
|
$file = $locator->getPathtoConfigFile(); |
153
|
|
View Code Duplication |
if (!file_exists($file) || !is_file($file)){ |
|
|
|
|
154
|
|
|
throw new \RuntimeException('ownCloud in ' . dirname($file) . ' is not installed.'); |
155
|
|
|
} |
156
|
|
|
} |
157
|
|
|
|
158
|
|
|
/** |
159
|
|
|
* Create proper directory structure to store data |
160
|
|
|
*/ |
161
|
|
|
protected function initDirectoryStructure(){ |
162
|
|
|
$container = $this->getContainer(); |
163
|
|
|
$locator = $container['utils.locator']; |
164
|
|
|
$fsHelper = $container['utils.filesystemhelper']; |
165
|
|
|
if (!file_exists($locator->getDataDir())){ |
166
|
|
|
$fsHelper->mkdir($locator->getDataDir()); |
167
|
|
|
} |
168
|
|
|
if (!file_exists($locator->getDownloadBaseDir())){ |
169
|
|
|
$fsHelper->mkdir($locator->getDownloadBaseDir()); |
170
|
|
|
} |
171
|
|
|
if (!file_exists($locator->getCheckpointDir())){ |
172
|
|
|
$fsHelper->mkdir($locator->getCheckpointDir()); |
173
|
|
|
} |
174
|
|
|
} |
175
|
|
|
|
176
|
|
|
} |
177
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.