Completed
Push — master ( 25ef41...8b1dcb )
by
unknown
22:51 queued 14s
created
lib/private/AppFramework/Http/Dispatcher.php 1 patch
Indentation   +218 added lines, -218 removed lines patch added patch discarded remove patch
@@ -26,222 +26,222 @@
 block discarded – undo
26 26
  * Class to dispatch the request to the middleware dispatcher
27 27
  */
28 28
 class Dispatcher {
29
-	/** @var MiddlewareDispatcher */
30
-	private $middlewareDispatcher;
31
-
32
-	/** @var Http */
33
-	private $protocol;
34
-
35
-	/** @var ControllerMethodReflector */
36
-	private $reflector;
37
-
38
-	/** @var IRequest */
39
-	private $request;
40
-
41
-	/** @var IConfig */
42
-	private $config;
43
-
44
-	/** @var ConnectionAdapter */
45
-	private $connection;
46
-
47
-	/** @var LoggerInterface */
48
-	private $logger;
49
-
50
-	/** @var IEventLogger */
51
-	private $eventLogger;
52
-
53
-	private ContainerInterface $appContainer;
54
-
55
-	/**
56
-	 * @param Http $protocol the http protocol with contains all status headers
57
-	 * @param MiddlewareDispatcher $middlewareDispatcher the dispatcher which
58
-	 *                                                   runs the middleware
59
-	 * @param ControllerMethodReflector $reflector the reflector that is used to inject
60
-	 *                                             the arguments for the controller
61
-	 * @param IRequest $request the incoming request
62
-	 * @param IConfig $config
63
-	 * @param ConnectionAdapter $connection
64
-	 * @param LoggerInterface $logger
65
-	 * @param IEventLogger $eventLogger
66
-	 */
67
-	public function __construct(Http $protocol,
68
-		MiddlewareDispatcher $middlewareDispatcher,
69
-		ControllerMethodReflector $reflector,
70
-		IRequest $request,
71
-		IConfig $config,
72
-		ConnectionAdapter $connection,
73
-		LoggerInterface $logger,
74
-		IEventLogger $eventLogger,
75
-		ContainerInterface $appContainer) {
76
-		$this->protocol = $protocol;
77
-		$this->middlewareDispatcher = $middlewareDispatcher;
78
-		$this->reflector = $reflector;
79
-		$this->request = $request;
80
-		$this->config = $config;
81
-		$this->connection = $connection;
82
-		$this->logger = $logger;
83
-		$this->eventLogger = $eventLogger;
84
-		$this->appContainer = $appContainer;
85
-	}
86
-
87
-
88
-	/**
89
-	 * Handles a request and calls the dispatcher on the controller
90
-	 * @param Controller $controller the controller which will be called
91
-	 * @param string $methodName the method name which will be called on
92
-	 *                           the controller
93
-	 * @return array $array[0] contains the http status header as a string,
94
-	 *               $array[1] contains response headers as an array,
95
-	 *               $array[2] contains response cookies as an array,
96
-	 *               $array[3] contains the response output as a string,
97
-	 *               $array[4] contains the response object
98
-	 * @throws \Exception
99
-	 */
100
-	public function dispatch(Controller $controller, string $methodName): array {
101
-		$out = [null, [], null];
102
-
103
-		try {
104
-			// prefill reflector with everything that's needed for the
105
-			// middlewares
106
-			$this->reflector->reflect($controller, $methodName);
107
-
108
-			$this->middlewareDispatcher->beforeController($controller,
109
-				$methodName);
110
-
111
-			$databaseStatsBefore = [];
112
-			if ($this->config->getSystemValueBool('debug', false)) {
113
-				$databaseStatsBefore = $this->connection->getInner()->getStats();
114
-			}
115
-
116
-			$response = $this->executeController($controller, $methodName);
117
-
118
-			if (!empty($databaseStatsBefore)) {
119
-				$databaseStatsAfter = $this->connection->getInner()->getStats();
120
-				$numBuilt = $databaseStatsAfter['built'] - $databaseStatsBefore['built'];
121
-				$numExecuted = $databaseStatsAfter['executed'] - $databaseStatsBefore['executed'];
122
-
123
-				if ($numBuilt > 50) {
124
-					$this->logger->debug('Controller {class}::{method} created {count} QueryBuilder objects, please check if they are created inside a loop by accident.', [
125
-						'class' => get_class($controller),
126
-						'method' => $methodName,
127
-						'count' => $numBuilt,
128
-					]);
129
-				}
130
-
131
-				if ($numExecuted > 100) {
132
-					$this->logger->warning('Controller {class}::{method} executed {count} queries.', [
133
-						'class' => get_class($controller),
134
-						'method' => $methodName,
135
-						'count' => $numExecuted,
136
-					]);
137
-				}
138
-			}
139
-
140
-			// if an exception appears, the middleware checks if it can handle the
141
-			// exception and creates a response. If no response is created, it is
142
-			// assumed that there's no middleware who can handle it and the error is
143
-			// thrown again
144
-		} catch (\Exception $exception) {
145
-			$response = $this->middlewareDispatcher->afterException(
146
-				$controller, $methodName, $exception);
147
-		} catch (\Throwable $throwable) {
148
-			$exception = new \Exception($throwable->getMessage() . ' in file \'' . $throwable->getFile() . '\' line ' . $throwable->getLine(), $throwable->getCode(), $throwable);
149
-			$response = $this->middlewareDispatcher->afterException(
150
-				$controller, $methodName, $exception);
151
-		}
152
-
153
-		$response = $this->middlewareDispatcher->afterController(
154
-			$controller, $methodName, $response);
155
-
156
-		// depending on the cache object the headers need to be changed
157
-		$out[0] = $this->protocol->getStatusHeader($response->getStatus());
158
-		$out[1] = array_merge($response->getHeaders());
159
-		$out[2] = $response->getCookies();
160
-		$out[3] = $this->middlewareDispatcher->beforeOutput(
161
-			$controller, $methodName, $response->render()
162
-		);
163
-		$out[4] = $response;
164
-
165
-		return $out;
166
-	}
167
-
168
-
169
-	/**
170
-	 * Uses the reflected parameters, types and request parameters to execute
171
-	 * the controller
172
-	 * @param Controller $controller the controller to be executed
173
-	 * @param string $methodName the method on the controller that should be executed
174
-	 * @return Response
175
-	 */
176
-	private function executeController(Controller $controller, string $methodName): Response {
177
-		$arguments = [];
178
-
179
-		// valid types that will be cast
180
-		$types = ['int', 'integer', 'bool', 'boolean', 'float', 'double'];
181
-
182
-		foreach ($this->reflector->getParameters() as $param => $default) {
183
-			// try to get the parameter from the request object and cast
184
-			// it to the type annotated in the @param annotation
185
-			$value = $this->request->getParam($param, $default);
186
-			$type = $this->reflector->getType($param);
187
-
188
-			// Converted the string `'false'` to false when the controller wants a boolean
189
-			if ($value === 'false' && ($type === 'bool' || $type === 'boolean')) {
190
-				$value = false;
191
-			} elseif ($value !== null && \in_array($type, $types, true)) {
192
-				settype($value, $type);
193
-				$this->ensureParameterValueSatisfiesRange($param, $value);
194
-			} elseif ($value === null && $type !== null && $this->appContainer->has($type)) {
195
-				$value = $this->appContainer->get($type);
196
-			}
197
-
198
-			$arguments[] = $value;
199
-		}
200
-
201
-		$this->eventLogger->start('controller:' . get_class($controller) . '::' . $methodName, 'App framework controller execution');
202
-		$response = \call_user_func_array([$controller, $methodName], $arguments);
203
-		$this->eventLogger->end('controller:' . get_class($controller) . '::' . $methodName);
204
-
205
-		if (!($response instanceof Response)) {
206
-			$this->logger->debug($controller::class . '::' . $methodName . ' returned raw data. Please wrap it in a Response or one of it\'s inheritors.');
207
-		}
208
-
209
-		// format response
210
-		if ($response instanceof DataResponse || !($response instanceof Response)) {
211
-			// get format from the url format or request format parameter
212
-			$format = $this->request->getParam('format');
213
-
214
-			// if none is given try the first Accept header
215
-			if ($format === null) {
216
-				$headers = $this->request->getHeader('Accept');
217
-				$format = $controller->getResponderByHTTPHeader($headers, null);
218
-			}
219
-
220
-			if ($format !== null) {
221
-				$response = $controller->buildResponse($response, $format);
222
-			} else {
223
-				$response = $controller->buildResponse($response);
224
-			}
225
-		}
226
-
227
-		return $response;
228
-	}
229
-
230
-	/**
231
-	 * @psalm-param mixed $value
232
-	 * @throws ParameterOutOfRangeException
233
-	 */
234
-	private function ensureParameterValueSatisfiesRange(string $param, $value): void {
235
-		$rangeInfo = $this->reflector->getRange($param);
236
-		if ($rangeInfo) {
237
-			if ($value < $rangeInfo['min'] || $value > $rangeInfo['max']) {
238
-				throw new ParameterOutOfRangeException(
239
-					$param,
240
-					$value,
241
-					$rangeInfo['min'],
242
-					$rangeInfo['max'],
243
-				);
244
-			}
245
-		}
246
-	}
29
+    /** @var MiddlewareDispatcher */
30
+    private $middlewareDispatcher;
31
+
32
+    /** @var Http */
33
+    private $protocol;
34
+
35
+    /** @var ControllerMethodReflector */
36
+    private $reflector;
37
+
38
+    /** @var IRequest */
39
+    private $request;
40
+
41
+    /** @var IConfig */
42
+    private $config;
43
+
44
+    /** @var ConnectionAdapter */
45
+    private $connection;
46
+
47
+    /** @var LoggerInterface */
48
+    private $logger;
49
+
50
+    /** @var IEventLogger */
51
+    private $eventLogger;
52
+
53
+    private ContainerInterface $appContainer;
54
+
55
+    /**
56
+     * @param Http $protocol the http protocol with contains all status headers
57
+     * @param MiddlewareDispatcher $middlewareDispatcher the dispatcher which
58
+     *                                                   runs the middleware
59
+     * @param ControllerMethodReflector $reflector the reflector that is used to inject
60
+     *                                             the arguments for the controller
61
+     * @param IRequest $request the incoming request
62
+     * @param IConfig $config
63
+     * @param ConnectionAdapter $connection
64
+     * @param LoggerInterface $logger
65
+     * @param IEventLogger $eventLogger
66
+     */
67
+    public function __construct(Http $protocol,
68
+        MiddlewareDispatcher $middlewareDispatcher,
69
+        ControllerMethodReflector $reflector,
70
+        IRequest $request,
71
+        IConfig $config,
72
+        ConnectionAdapter $connection,
73
+        LoggerInterface $logger,
74
+        IEventLogger $eventLogger,
75
+        ContainerInterface $appContainer) {
76
+        $this->protocol = $protocol;
77
+        $this->middlewareDispatcher = $middlewareDispatcher;
78
+        $this->reflector = $reflector;
79
+        $this->request = $request;
80
+        $this->config = $config;
81
+        $this->connection = $connection;
82
+        $this->logger = $logger;
83
+        $this->eventLogger = $eventLogger;
84
+        $this->appContainer = $appContainer;
85
+    }
86
+
87
+
88
+    /**
89
+     * Handles a request and calls the dispatcher on the controller
90
+     * @param Controller $controller the controller which will be called
91
+     * @param string $methodName the method name which will be called on
92
+     *                           the controller
93
+     * @return array $array[0] contains the http status header as a string,
94
+     *               $array[1] contains response headers as an array,
95
+     *               $array[2] contains response cookies as an array,
96
+     *               $array[3] contains the response output as a string,
97
+     *               $array[4] contains the response object
98
+     * @throws \Exception
99
+     */
100
+    public function dispatch(Controller $controller, string $methodName): array {
101
+        $out = [null, [], null];
102
+
103
+        try {
104
+            // prefill reflector with everything that's needed for the
105
+            // middlewares
106
+            $this->reflector->reflect($controller, $methodName);
107
+
108
+            $this->middlewareDispatcher->beforeController($controller,
109
+                $methodName);
110
+
111
+            $databaseStatsBefore = [];
112
+            if ($this->config->getSystemValueBool('debug', false)) {
113
+                $databaseStatsBefore = $this->connection->getInner()->getStats();
114
+            }
115
+
116
+            $response = $this->executeController($controller, $methodName);
117
+
118
+            if (!empty($databaseStatsBefore)) {
119
+                $databaseStatsAfter = $this->connection->getInner()->getStats();
120
+                $numBuilt = $databaseStatsAfter['built'] - $databaseStatsBefore['built'];
121
+                $numExecuted = $databaseStatsAfter['executed'] - $databaseStatsBefore['executed'];
122
+
123
+                if ($numBuilt > 50) {
124
+                    $this->logger->debug('Controller {class}::{method} created {count} QueryBuilder objects, please check if they are created inside a loop by accident.', [
125
+                        'class' => get_class($controller),
126
+                        'method' => $methodName,
127
+                        'count' => $numBuilt,
128
+                    ]);
129
+                }
130
+
131
+                if ($numExecuted > 100) {
132
+                    $this->logger->warning('Controller {class}::{method} executed {count} queries.', [
133
+                        'class' => get_class($controller),
134
+                        'method' => $methodName,
135
+                        'count' => $numExecuted,
136
+                    ]);
137
+                }
138
+            }
139
+
140
+            // if an exception appears, the middleware checks if it can handle the
141
+            // exception and creates a response. If no response is created, it is
142
+            // assumed that there's no middleware who can handle it and the error is
143
+            // thrown again
144
+        } catch (\Exception $exception) {
145
+            $response = $this->middlewareDispatcher->afterException(
146
+                $controller, $methodName, $exception);
147
+        } catch (\Throwable $throwable) {
148
+            $exception = new \Exception($throwable->getMessage() . ' in file \'' . $throwable->getFile() . '\' line ' . $throwable->getLine(), $throwable->getCode(), $throwable);
149
+            $response = $this->middlewareDispatcher->afterException(
150
+                $controller, $methodName, $exception);
151
+        }
152
+
153
+        $response = $this->middlewareDispatcher->afterController(
154
+            $controller, $methodName, $response);
155
+
156
+        // depending on the cache object the headers need to be changed
157
+        $out[0] = $this->protocol->getStatusHeader($response->getStatus());
158
+        $out[1] = array_merge($response->getHeaders());
159
+        $out[2] = $response->getCookies();
160
+        $out[3] = $this->middlewareDispatcher->beforeOutput(
161
+            $controller, $methodName, $response->render()
162
+        );
163
+        $out[4] = $response;
164
+
165
+        return $out;
166
+    }
167
+
168
+
169
+    /**
170
+     * Uses the reflected parameters, types and request parameters to execute
171
+     * the controller
172
+     * @param Controller $controller the controller to be executed
173
+     * @param string $methodName the method on the controller that should be executed
174
+     * @return Response
175
+     */
176
+    private function executeController(Controller $controller, string $methodName): Response {
177
+        $arguments = [];
178
+
179
+        // valid types that will be cast
180
+        $types = ['int', 'integer', 'bool', 'boolean', 'float', 'double'];
181
+
182
+        foreach ($this->reflector->getParameters() as $param => $default) {
183
+            // try to get the parameter from the request object and cast
184
+            // it to the type annotated in the @param annotation
185
+            $value = $this->request->getParam($param, $default);
186
+            $type = $this->reflector->getType($param);
187
+
188
+            // Converted the string `'false'` to false when the controller wants a boolean
189
+            if ($value === 'false' && ($type === 'bool' || $type === 'boolean')) {
190
+                $value = false;
191
+            } elseif ($value !== null && \in_array($type, $types, true)) {
192
+                settype($value, $type);
193
+                $this->ensureParameterValueSatisfiesRange($param, $value);
194
+            } elseif ($value === null && $type !== null && $this->appContainer->has($type)) {
195
+                $value = $this->appContainer->get($type);
196
+            }
197
+
198
+            $arguments[] = $value;
199
+        }
200
+
201
+        $this->eventLogger->start('controller:' . get_class($controller) . '::' . $methodName, 'App framework controller execution');
202
+        $response = \call_user_func_array([$controller, $methodName], $arguments);
203
+        $this->eventLogger->end('controller:' . get_class($controller) . '::' . $methodName);
204
+
205
+        if (!($response instanceof Response)) {
206
+            $this->logger->debug($controller::class . '::' . $methodName . ' returned raw data. Please wrap it in a Response or one of it\'s inheritors.');
207
+        }
208
+
209
+        // format response
210
+        if ($response instanceof DataResponse || !($response instanceof Response)) {
211
+            // get format from the url format or request format parameter
212
+            $format = $this->request->getParam('format');
213
+
214
+            // if none is given try the first Accept header
215
+            if ($format === null) {
216
+                $headers = $this->request->getHeader('Accept');
217
+                $format = $controller->getResponderByHTTPHeader($headers, null);
218
+            }
219
+
220
+            if ($format !== null) {
221
+                $response = $controller->buildResponse($response, $format);
222
+            } else {
223
+                $response = $controller->buildResponse($response);
224
+            }
225
+        }
226
+
227
+        return $response;
228
+    }
229
+
230
+    /**
231
+     * @psalm-param mixed $value
232
+     * @throws ParameterOutOfRangeException
233
+     */
234
+    private function ensureParameterValueSatisfiesRange(string $param, $value): void {
235
+        $rangeInfo = $this->reflector->getRange($param);
236
+        if ($rangeInfo) {
237
+            if ($value < $rangeInfo['min'] || $value > $rangeInfo['max']) {
238
+                throw new ParameterOutOfRangeException(
239
+                    $param,
240
+                    $value,
241
+                    $rangeInfo['min'],
242
+                    $rangeInfo['max'],
243
+                );
244
+            }
245
+        }
246
+    }
247 247
 }
Please login to merge, or discard this patch.