Completed
Pull Request — master (#246)
by Victor
17:07
created

Application::getLogger()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

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

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.

Loading history...
156
			throw new \RuntimeException('ownCloud in ' . dirname(dirname($file)) . ' is not installed.');
157
		}
158
159
		// version.php should exist
160
		$file = $locator->getPathToVersionFile();
161 View Code Duplication
		if (!file_exists($file) || !is_file($file)){
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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.

Loading history...
162
			throw new \RuntimeException('ownCloud is not found in ' . dirname($file));
163
		}
164
165
		// datadir should exist
166
		$dataDir = $locator->getDataDir();
167
		if (!$fsHelper->fileExists($dataDir)){
168
			throw new \RuntimeException('Datadirectory ' . $dataDir . ' does not exist.');
169
		}
170
171
		// datadir should be writable
172
		if (!$fsHelper->isWritable($dataDir)){
173
			throw new \RuntimeException('Datadirectory ' . $dataDir . ' is not writable.');
174
		}
175
176
		if (!$fsHelper->fileExists($locator->getUpdaterBaseDir())){
177
			$fsHelper->mkdir($locator->getUpdaterBaseDir());
178
		}
179
180
		if (!$fsHelper->fileExists($locator->getDownloadBaseDir())){
181
			$fsHelper->mkdir($locator->getDownloadBaseDir());
182
		}
183
		if (!$fsHelper->fileExists($locator->getCheckpointDir())){
184
			$fsHelper->mkdir($locator->getCheckpointDir());
185
		}
186
	}
187
188
}
189