Completed
Push — master ( 097a9e...08268b )
by Lukas
32:42 queued 23:40
created

Application::loadCommands()   F

Complexity

Conditions 17
Paths 880

Size

Total Lines 72
Code Lines 50

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 17
eloc 50
nc 880
nop 2
dl 0
loc 72
rs 2.7777
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * @copyright Copyright (c) 2016, ownCloud, Inc.
4
 *
5
 * @author Joas Schilling <[email protected]>
6
 * @author Lukas Reschke <[email protected]>
7
 * @author Morris Jobke <[email protected]>
8
 * @author Robin McCorkell <[email protected]>
9
 * @author Thomas Müller <[email protected]>
10
 * @author Victor Dubiniuk <[email protected]>
11
 *
12
 * @license AGPL-3.0
13
 *
14
 * This code is free software: you can redistribute it and/or modify
15
 * it under the terms of the GNU Affero General Public License, version 3,
16
 * as published by the Free Software Foundation.
17
 *
18
 * This program is distributed in the hope that it will be useful,
19
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21
 * GNU Affero General Public License for more details.
22
 *
23
 * You should have received a copy of the GNU Affero General Public License, version 3,
24
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
25
 *
26
 */
27
namespace OC\Console;
28
29
use OC\NeedsUpdateException;
30
use OC_App;
31
use OCP\AppFramework\QueryException;
32
use OCP\Console\ConsoleEvent;
33
use OCP\IConfig;
34
use OCP\IRequest;
35
use Symfony\Component\Console\Application as SymfonyApplication;
36
use Symfony\Component\Console\Input\InputInterface;
37
use Symfony\Component\Console\Input\InputOption;
38
use Symfony\Component\Console\Output\OutputInterface;
39
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
40
41
class Application {
42
	/** @var IConfig */
43
	private $config;
44
	/** @var EventDispatcherInterface */
45
	private $dispatcher;
46
	/** @var IRequest */
47
	private $request;
48
49
	/**
50
	 * @param IConfig $config
51
	 * @param EventDispatcherInterface $dispatcher
52
	 * @param IRequest $request
53
	 */
54
	public function __construct(IConfig $config, EventDispatcherInterface $dispatcher, IRequest $request) {
55
		$defaults = \OC::$server->getThemingDefaults();
56
		$this->config = $config;
57
		$this->application = new SymfonyApplication($defaults->getName(), \OC_Util::getVersionString());
0 ignored issues
show
Bug introduced by
The property application does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
58
		$this->dispatcher = $dispatcher;
59
		$this->request = $request;
60
	}
61
62
	/**
63
	 * @param InputInterface $input
64
	 * @param OutputInterface $output
65
	 * @throws \Exception
66
	 */
67
	public function loadCommands(InputInterface $input, OutputInterface $output) {
68
		// $application is required to be defined in the register_command scripts
69
		$application = $this->application;
70
		$inputDefinition = $application->getDefinition();
71
		$inputDefinition->addOption(
72
			new InputOption(
73
				'no-warnings', 
74
				null, 
75
				InputOption::VALUE_NONE, 
76
				'Skip global warnings, show command output only', 
77
				null
78
			)
79
		);
80
		try {
81
			$input->bind($inputDefinition);
82
		} catch (\RuntimeException $e) {
83
			//expected if there are extra options
84
		}
85
		if ($input->getOption('no-warnings')) {
86
			$output->setVerbosity(OutputInterface::VERBOSITY_QUIET);
87
		}
88
		try {
89
			require_once __DIR__ . '/../../../core/register_command.php';
90
			if ($this->config->getSystemValue('installed', false)) {
91
				if (\OCP\Util::needUpgrade()) {
92
					throw new NeedsUpdateException();
93
				} elseif ($this->config->getSystemValue('maintenance', false)) {
94
					if ($input->getArgument('command') !== '_completion') {
95
						$output->writeln("Nextcloud is in maintenance mode - no apps have been loaded");
96
					}
97
				} else {
98
					OC_App::loadApps();
99
					foreach (\OC::$server->getAppManager()->getInstalledApps() as $app) {
100
						$appPath = \OC_App::getAppPath($app);
101
						if ($appPath === false) {
102
							continue;
103
						}
104
						// load commands using info.xml
105
						$info = \OC_App::getAppInfo($app);
106
						if (isset($info['commands'])) {
107
							$this->loadCommandsFromInfoXml($info['commands']);
108
						}
109
						// load from register_command.php
110
						\OC_App::registerAutoloading($app, $appPath);
111
						$file = $appPath . '/appinfo/register_command.php';
112
						if (file_exists($file)) {
113
							require $file;
114
						}
115
					}
116
				}
117
			} else if ($input->getArgument('command') !== '_completion') {
118
				$output->writeln("Nextcloud is not installed - only a limited number of commands are available");
119
			}
120
		} catch(NeedsUpdateException $e) {
121
			if ($input->getArgument('command') !== '_completion') {
122
				$output->writeln("Nextcloud or one of the apps require upgrade - only a limited number of commands are available");
123
				$output->writeln("You may use your browser or the occ upgrade command to do the upgrade");
124
			}
125
		}
126
127
		if ($input->getFirstArgument() !== 'check') {
128
			$errors = \OC_Util::checkServer(\OC::$server->getConfig());
129
			if (!empty($errors)) {
130
				foreach ($errors as $error) {
131
					$output->writeln((string)$error['error']);
132
					$output->writeln((string)$error['hint']);
133
					$output->writeln('');
134
				}
135
				throw new \Exception("Environment not properly prepared.");
136
			}
137
		}
138
	}
139
140
	/**
141
	 * Sets whether to automatically exit after a command execution or not.
142
	 *
143
	 * @param bool $boolean Whether to automatically exit after a command execution or not
144
	 */
145
	public function setAutoExit($boolean) {
146
		$this->application->setAutoExit($boolean);
147
	}
148
149
	/**
150
	 * @param InputInterface $input
151
	 * @param OutputInterface $output
152
	 * @return int
153
	 * @throws \Exception
154
	 */
155
	public function run(InputInterface $input = null, OutputInterface $output = null) {
156
		$this->dispatcher->dispatch(ConsoleEvent::EVENT_RUN, new ConsoleEvent(
157
			ConsoleEvent::EVENT_RUN,
158
			$this->request->server['argv']
0 ignored issues
show
Bug introduced by
Accessing server on the interface OCP\IRequest suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
159
		));
160
		return $this->application->run($input, $output);
161
	}
162
163
	private function loadCommandsFromInfoXml($commands) {
164 View Code Duplication
		foreach ($commands as $command) {
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...
165
			try {
166
				$c = \OC::$server->query($command);
167
			} catch (QueryException $e) {
168
				if (class_exists($command)) {
169
					$c = new $command();
170
				} else {
171
					throw new \Exception("Console command '$command' is unknown and could not be loaded");
172
				}
173
			}
174
175
			$this->application->add($c);
176
		}
177
	}
178
}
179