Completed
Pull Request — master (#355)
by Victor
02:53
created

OccRunner::runAsRequest()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 18
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 18
ccs 0
cts 13
cp 0
rs 9.4285
cc 2
eloc 11
nc 2
nop 2
crap 6
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 Symfony\Component\Process\Process;
26
use Symfony\Component\Process\ProcessUtils;
27
use Symfony\Component\Process\Exception\ProcessFailedException;
28
use Owncloud\Updater\Utils\Locator;
29
30
class OccRunner {
31
	/**
32
	 * @var Locator $locator
33
	 */
34
	protected $locator;
35
36
	/**
37
	 * @var bool
38
	 */
39
	protected $canUseProcess;
40
41
	/**
42
	 *
43
	 * @param Locator $locator
44
	 */
45
	public function __construct(Locator $locator){
46
		$this->locator = $locator;
47
48
		$disabled = explode(',', ini_get('disable_functions'));
49
		$this->canUseProcess = function_exists('proc_open') && !in_array('proc_open', $disabled);
50
		$this->canUseProcess = false;
51
	}
52
53
	public function run($command, $args = [], $extra = ''){
54
		if ($this->canUseProcess){
55
			$cmdLine = trim($command . ' ' . $extra);
56
			foreach ($args as $optionTitle => $optionValue){
57
				if (strpos($optionTitle, '--') === 0){
58
					$line = trim("$optionTitle $optionValue");
59
				} else {
60
					$line = $optionValue;
61
				}
62
				$escapedLine = ProcessUtils::escapeArgument($line);
63
				$cmdLine .= " $escapedLine";
64
			}
65
			return $this->runAsProcess($cmdLine);
66
		} else {
67
			return $this->runAsRequest($command, $args);
68
		}
69
	}
70
71 3
	public function runJson($command, $args = []){
72 3
		$plain = $this->run($command, $args, '--output=json');
73 3
		$decoded = json_decode($plain, true);
74 3
		if (!is_array($decoded)){
75
			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);
76
		}
77 3
		return $decoded;
78
	}
79
80
	private function runAsRequest($command, $args){
81
		$client = new Client();
82
		$request = $client->createRequest(
83
			'POST',
84
			// TODO Get endpoint somehow :-/
85
			'http://localhost/~deo/oc-tmp/index.php/occ/' . $command,
86
			[
87
				'timeout' => 0
88
			]
89
		);
90
91
		$query = $request->getQuery();
92
		foreach ($args as $optionTitle => $optionValue){
93
			$query[$optionTitle] = $optionValue;
94
		}
95
		$response = $client->send($request);
96
		return $response->getBody()->getContents();
97
	}
98
99
	private function runAsProcess($cmdLine){
100
		$occPath = $this->locator->getPathToOccFile();
101
		$cmd = "php $occPath --no-warnings $cmdLine";
102
		$process = new Process($cmd);
103
		$process->setTimeout(null);
104
		$process->run();
105
106
		if (!$process->isSuccessful()){
107
			throw new ProcessFailedException($process);
108
		}
109
		return $process->getOutput();
110
	}
111
}
112