BashRestController::isHandled()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 4
ccs 2
cts 2
cp 1
rs 10
cc 1
eloc 2
nc 1
nop 2
crap 1
1
<?php
2
3
/**
4
 * This file is part of Lekarna.cz (http://www.lekarna.cz/)
5
 *
6
 * Copyright (c) 2014 Pears Health Cyber, s.r.o. (http://pearshealthcyber.cz)
7
 *
8
 * For the full copyright and license information, please view
9
 * the file LICENSE that was distributed with this source code.
10
 */
11
12
namespace App;
13
14
use App\Exception\ExecutionFailed;
15
use Interop\Container\ContainerInterface;
16
use InvalidArgumentException;
17
use Slim\Http\Request;
18
use Slim\Http\Response;
19
20
21
final class BashRestController
22
{
23
24
	use SecuredTrait;
25
26
	const SECRET_HEADER = 'X-Secret';
27
28
	/**
29
	 * @var Executor
30
	 */
31
	private $executor;
32
33
	/**
34
	 * @var array
35
	 */
36
	private $scripts;
37
38
39 8
	public function __construct(ContainerInterface $ci, Executor $executor)
40
	{
41 8
		$this->executor = $executor;
42 8
		$this->secret = $ci->get('settings')['secret'];
43 8
		$this->scripts = (array) $ci->get('bashREST');
44 8
	}
45
46
47
	/**
48
	 * @param Request $request
49
	 * @param Response $response
50
	 * @param array $args
51
	 * @return Response
52
	 */
53 8
	public function __invoke(Request $request, Response $response, array $args)
54
	{
55 8
		$response = $response->withHeader('Content-Type', 'application/text;charset=utf-8');
56 8
		if ( ! $this->isSecured($request)) {
57 1
			return $response->withStatus(403);
58
		}
59
60 7
		$projectName = $args['group'] . '/' . $args['project'];
61 7
		$action = $args['action'];
62
63 7
		if ( ! $this->isHandled($projectName, $action)) {
64 1
			return $response->withStatus(404);
65
		}
66
67 6
		return $this->handle($request, $response, $projectName, $action);
68
	}
69
70
71
	/**
72
	 * @param array|NULL $data
73
	 * @return array
74
	 */
75 6
	private function flatten($data)
76
	{
77 6
		if ($data === NULL) {
78 1
			return [];
79
		}
80
81 5
		if (is_object($data)) {
82 1
			throw new InvalidArgumentException('Unexpected parser result.');
83
		}
84
85
		$toProcess = [[
86 4
			'data' => $data,
87
			'prefix' => 'HOOK'
88 4
		]];
89
90 4
		$flattened = [];
91
92 4
		while ( ! empty($toProcess)) {
93 4
			$actual = array_pop($toProcess);
94 4
			$this->flattenProcessArray($actual, $flattened, $toProcess);
95 4
		}
96
97 4
		return $flattened;
98
	}
99
100
101
	/**
102
	 * @param string $projectName
103
	 * @param string $action
104
	 * @return bool
105
	 */
106 7
	private function isHandled($projectName, $action)
107
	{
108 7
		return isset($this->scripts[$projectName][$action]);
109
	}
110
111
112
	/**
113
	 * @param array $actual
114
	 * @param array $flattened
115
	 * @param array $toProcess
116
	 * @return array
117
	 */
118 4
	private function flattenProcessArray(array $actual, array &$flattened, array &$toProcess)
119
	{
120 4
		foreach ($actual['data'] as $key => $value) {
121 3
			if (is_scalar($value)) {
122 3
				$flattened[$actual['prefix'] . '_' . $key] = $value;
123 3
			} else {
124 1
				if (is_array($value)) {
125 1
					array_push(
126 1
						$toProcess,
127
						[
128 1
							'data' => $value,
129 1
							'prefix' => $actual['prefix'] . '_' . $key
130 1
						]
131 1
					);
132 1
				}
133
			}
134 4
		}
135 4
	}
136
137
138
	/**
139
	 * @param Request $request
140
	 * @param string $projectName
141
	 * @param string $action
142
	 * @return Response
143
	 */
144 6
	private function handle(Request $request, Response $response, $projectName, $action)
145
	{
146
		try {
147 6
			$defaultEnv = ['HOOK_PROJECT_PATH' => $projectName, 'HOOK_ACTION' => $action];
148 6
			$result = $this->executor->executeCommand(
149 6
				$this->scripts[$projectName][$action],
150 6
				$this->flatten($request->getParsedBody()) + $defaultEnv
151 5
			);
152
153 4
			$body = $response->getBody();
154 4
			$body->rewind();
155 4
			$body->write($result);
156
157 4
			return $response->withStatus(200);
158 2
		} catch (ExecutionFailed $e) {
159
160 1
			$body = $response->getBody();
161 1
			$body->rewind();
162 1
			$body->write($e->getMessage());
163
164 1
			return $response->withStatus(500);
165
		}
166
	}
167
168
}
169