Passed
Push — master ( fbf25e...f37e15 )
by Christoph
18:24 queued 11s
created

RequestManager.php$0 ➔ getHttpRequest()   A

Complexity

Conditions 1

Size

Total Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
dl 0
loc 2
c 1
b 0
f 0
cc 1
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * @copyright 2020 Christoph Wurst <[email protected]>
7
 *
8
 * @author 2020 Christoph Wurst <[email protected]>
9
 *
10
 * @license GNU AGPL version 3 or any later version
11
 *
12
 * This program is free software: you can redistribute it and/or modify
13
 * it under the terms of the GNU Affero General Public License as
14
 * published by the Free Software Foundation, either version 3 of the
15
 * License, or (at your option) any later version.
16
 *
17
 * This program is distributed in the hope that it will be useful,
18
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20
 * GNU Affero General Public License for more details.
21
 *
22
 * You should have received a copy of the GNU Affero General Public License
23
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
24
 */
25
26
namespace OC\Http\WellKnown;
27
28
use OC\AppFramework\Bootstrap\Coordinator;
29
use OCP\AppFramework\QueryException;
30
use OCP\Http\WellKnown\IHandler;
31
use OCP\Http\WellKnown\IRequestContext;
32
use OCP\Http\WellKnown\IResponse;
33
use OCP\Http\WellKnown\JrdResponse;
34
use OCP\IRequest;
35
use OCP\IServerContainer;
36
use Psr\Log\LoggerInterface;
37
use RuntimeException;
38
use function array_reduce;
39
40
class RequestManager {
41
42
	/** @var Coordinator */
43
	private $coordinator;
44
45
	/** @var IServerContainer */
46
	private $container;
47
48
	/** @var LoggerInterface */
49
	private $logger;
50
51
	public function __construct(Coordinator $coordinator,
52
								IServerContainer $container,
53
								LoggerInterface $logger) {
54
		$this->coordinator = $coordinator;
55
		$this->container = $container;
56
		$this->logger = $logger;
57
	}
58
59
	public function process(string $service, IRequest $request): ?IResponse {
60
		$handlers = $this->loadHandlers();
61
		$context = new class($request) implements IRequestContext {
62
			/** @var IRequest */
63
			private $request;
64
65
			public function __construct(IRequest $request) {
66
				$this->request = $request;
67
			}
68
69
			public function getHttpRequest(): IRequest {
70
				return $this->request;
71
			}
72
		};
73
74
		$subject = $request->getParam('resource');
75
		$initialResponse = new JrdResponse($subject ?? '');
76
		$finalResponse = array_reduce($handlers, function (?IResponse $previousResponse, IHandler $handler) use ($context, $service) {
77
			return $handler->handle($service, $context, $previousResponse);
78
		}, $initialResponse);
79
80
		if ($finalResponse instanceof JrdResponse && $finalResponse->isEmpty()) {
81
			return null;
82
		}
83
84
		return $finalResponse;
85
	}
86
87
	/**
88
	 * @return IHandler[]
89
	 */
90
	private function loadHandlers(): array {
91
		$context = $this->coordinator->getRegistrationContext();
92
93
		if ($context === null) {
94
			throw new RuntimeException("Well known handlers requested before the apps had been fully registered");
95
		}
96
97
		$registrations = $context->getWellKnownHandlers();
98
		$this->logger->debug(count($registrations) . " well known handlers registered");
99
100
		return array_filter(
101
			array_map(function (array $registration) {
102
				$class = $registration['class'];
103
104
				try {
105
					$handler = $this->container->get($class);
106
107
					if (!($handler) instanceof IHandler) {
108
						$this->logger->error("Well known handler $class is invalid");
109
110
						return null;
111
					}
112
113
					return $handler;
114
				} catch (QueryException $e) {
115
					$this->logger->error("Could not load well known handler $class", [
116
						'exception' => $e,
117
					]);
118
119
					return null;
120
				}
121
			}, $registrations)
122
		);
123
	}
124
}
125