Completed
Pull Request — master (#463)
by
unknown
35:46
created

OccRunner   A

Complexity

Total Complexity 16

Size/Duplication

Total Lines 134
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 8

Test Coverage

Coverage 38.32%

Importance

Changes 0
Metric Value
wmc 16
c 0
b 0
f 0
lcom 1
cbo 8
dl 0
loc 134
ccs 23
cts 60
cp 0.3832
rs 10

7 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A setCanUseProcess() 0 3 1
A runJson() 0 11 3
B run() 0 23 6
B runAsRequest() 0 27 2
A getApplication() 0 5 1
A runAsProcess() 0 12 2
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
22
namespace Owncloud\Updater\Utils;
23
24
use GuzzleHttp\Client;
25
use Owncloud\Updater\Console\Application;
26
use Symfony\Component\Process\Process;
27
use Symfony\Component\Process\ProcessUtils;
28
use Symfony\Component\Process\Exception\ProcessFailedException;
29
30
/**
31
 * Class OccRunner
32
 *
33
 * @package Owncloud\Updater\Utils
34
 */
35
class OccRunner {
36
	/**
37
	 * @var Locator $locator
38
	 */
39
	protected $locator;
40
41
	/**
42
	 * @var bool
43
	 */
44
	protected $canUseProcess;
45
46
	/**
47
	 *
48
	 * @param Locator $locator
49
	 * @param bool $canUseProcess
50
	 */
51 2
	public function __construct(Locator $locator, $canUseProcess){
52 2
		$this->locator = $locator;
53 2
		$this->canUseProcess = $canUseProcess;
54 2
	}
55
56
	/**
57
	 * @param bool $canUseProcess
58
	 */
59
	public function setCanUseProcess($canUseProcess){
60
		$this->canUseProcess = $canUseProcess;
61
	}
62
63
	/**
64
	 * @param $command
65
	 * @param array $args
66
	 * @param bool $asJson
67
	 * @return string
68
	 */
69 2
	public function run($command, $args = [], $asJson = false){
70 2
		if ($this->canUseProcess){
71 1
			$extra = $asJson ? '--output=json' : '';
72 1
			$cmdLine = trim($command . ' ' . $extra);
73 1
			foreach ($args as $optionTitle => $optionValue){
74
				if (strpos($optionTitle, '--') === 0){
75
					$line = trim("$optionTitle=$optionValue");
76
				} else {
77
					$line = $optionValue;
78
				}
79
				$escapedLine = ProcessUtils::escapeArgument($line);
80
				$cmdLine .= " $escapedLine";
81
			}
82 1
			return $this->runAsProcess($cmdLine);
83
		} else {
84 1
			if ($asJson){
85 1
				$args['--output'] = 'json';
86
			}
87 1
			$response = $this->runAsRequest($command, $args);
88 1
			$decodedResponse = json_decode($response, true);
89 1
			return $decodedResponse['response'];
90
		}
91
	}
92
93
	/**
94
	 * @param $command
95
	 * @param array $args
96
	 * @return mixed
97
	 */
98 5
	public function runJson($command, $args = []){
99 5
		$plain = $this->run($command, $args, true);
100
		// trim response to always be a valid json. Capture everything between the first and the last curly brace
101 5
		preg_match_all('!(\{.*\})!ms', $plain, $matches);
102 5
		$clean = isset($matches[1][0]) ? $matches[1][0] : '';
103 5
		$decoded = json_decode($clean, true);
104 5
		if (!is_array($decoded)){
105 1
			throw new \UnexpectedValueException('Could not parse a response for ' . $command . '. Please check if the current shell user can run occ command. Raw output: ' . PHP_EOL . $plain);
106
		}
107 4
		return $decoded;
108
	}
109
110
	/**
111
	 * @param $command
112
	 * @param $args
113
	 * @return string
114
	 */
115
	protected function runAsRequest($command, $args){
116
		$application = $this->getApplication();
117
		$client = new Client();
118
		$endpointBase = $application->getEndpoint();
119
		$params = [
120
			'timeout' => 0,
121
			'json' => [
122
				'token' => $application->getAuthToken(),
123
				'params'=> $args
124
			]
125
		];
126
		
127
		// Skip SSL validation for localhost only as localhost never has a valid cert
128
		if (preg_match('/^https:\/\/localhost\/.*/i', $endpointBase)){
129
			$params['verify'] = false;
130
		}
131
		
132
		$request = $client->createRequest(
0 ignored issues
show
Bug introduced by
The method createRequest() does not exist on GuzzleHttp\Client. Did you maybe mean request()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
133
			'POST',
134
			$endpointBase . $command,
135
			$params
136
		);
137
138
		$response = $client->send($request);
139
		$responseBody = $response->getBody()->getContents();
140
		return $responseBody;
141
	}
142
143
	/**
144
	 * @return mixed
145
	 */
146
	protected function getApplication(){
147
		$container = Application::$container;
148
		$application = $container['application'];
149
		return $application;
150
	}
151
152
	/**
153
	 * @param $cmdLine
154
	 * @return string
155
	 */
156
	protected function runAsProcess($cmdLine){
157
		$occPath = $this->locator->getPathToOccFile();
158
		$cmd = "php $occPath --no-warnings $cmdLine";
159
		$process = new Process($cmd);
160
		$process->setTimeout(null);
161
		$process->run();
162
163
		if (!$process->isSuccessful()){
164
			throw new ProcessFailedException($process);
165
		}
166
		return $process->getOutput();
167
	}
168
}
169