Passed
Push — master ( f17d1c...327bdc )
by Jan
02:49
created

BashRestController::__invoke()   B

Complexity

Conditions 6
Paths 9

Size

Total Lines 28
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 20
CRAP Score 6

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 28
ccs 20
cts 20
cp 1
rs 8.439
cc 6
eloc 16
nc 9
nop 3
crap 6
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 Interop\Container\ContainerInterface;
15
use InvalidArgumentException;
16
use Slim\Http\Request;
17
use Slim\Http\Response;
18
19
20
final class BashRestController
21
{
22
23
	const SECRET_HEADER = 'X-Secret';
24
25
	/**
26
	 * @var Executor
27
	 */
28
	private $executor;
29
30
	/**
31
	 * @var string
32
	 */
33
	private $secret;
34
35
	/**
36
	 * @var array
37
	 */
38
	private $scripts;
39
40 5
	public function __construct(ContainerInterface $ci, Executor $executor)
41
	{
42 5
		$this->executor = $executor;
43 5
		$this->secret = $ci->get('settings')['secret'];
44 5
		$this->scripts = $ci->get('bashREST');
0 ignored issues
show
Documentation Bug introduced by
It seems like $ci->get('bashREST') of type * is incompatible with the declared type array of property $scripts.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
45 5
	}
46
47
48 5
	public function __invoke(Request $request, Response $response, array $args)
49
	{
50 5
		$secured = FALSE;
51 5
		foreach ($request->getHeader(self::SECRET_HEADER) as $secret) {
52 4
			if ($secret == $this->secret) { // allow cast
53 4
				$secured = TRUE;
54 4
			}
55 5
		}
56
57 5
		if ($this->secret !== NULL && ! $secured) {
58 1
			return $response->withStatus(403);
59
		}
60
61 4
		$projectName = $args['group'] . '/' . $args['project'];
62 4
		$action = $args['action'];
63
64 4
		if ( ! isset($this->scripts[$projectName][$action])) {
65 1
			return $response->withStatus(404);
66
		}
67
68 3
		return $response->withStatus(200)
69 3
			->withJson([
70 3
				'result' => $this->executor->executeCommand(
71 3
					$this->scripts[$projectName][$action],
72 3
					$this->flatten($request->getParsedBody())
73 3
				)
74 3
			]);
75
	}
76
77
78 3
	private function flatten($data)
79
	{
80 3
		if ($data === NULL) {
81
			return [];
82
		}
83
84 3
		if ( is_object($data)) {
85
			throw new InvalidArgumentException('Unexpected parser result.');
86
		}
87
88
		$toProcess = [[
89 3
			'data' => $data,
90
			'prefix' => 'HOOK'
91 3
		]];
92
93 3
		$flattened = [];
94
95 3
		while ( ! empty($toProcess)) {
96 3
			$actual = array_pop($toProcess);
97 3
			foreach ($actual['data'] as $key => $value) {
98 1
				if (is_scalar($value)) {
99 1
					$flattened[$actual['prefix'] . '_' . $key] = $value;
100 1
				} else if (is_array($value)) {
101 1
					array_push($toProcess, [
102 1
						'data' => $value,
103 1
						'prefix' => $actual['prefix'] . '_' . $key
104 1
					]);
105 1
				}
106 3
			}
107 3
		}
108
109 3
		return $flattened;
110
	}
111
112
}
113