summaryrefslogtreecommitdiffstats
path: root/src/Controller/RouteAction.php
diff options
context:
space:
mode:
Diffstat (limited to 'src/Controller/RouteAction.php')
-rw-r--r--src/Controller/RouteAction.php117
1 files changed, 117 insertions, 0 deletions
diff --git a/src/Controller/RouteAction.php b/src/Controller/RouteAction.php
new file mode 100644
index 0000000..dabd501
--- /dev/null
+++ b/src/Controller/RouteAction.php
@@ -0,0 +1,117 @@
+<?php
+
+namespace Jasny\Controller;
+
+use Psr\Http\Message\ServerRequestInterface;
+use Psr\Http\Message\ResponseInterface;
+
+/**
+ * Execute controller on given route
+ */
+trait RouteAction
+{
+ /**
+ * Get request, set for controller
+ *
+ * @return ServerRequestInterface
+ */
+ abstract public function getRequest();
+
+ /**
+ * Get response. set for controller
+ *
+ * @return ResponseInterface
+ */
+ abstract public function getResponse();
+
+ /**
+ * Run the controller
+ *
+ * @return ResponseInterface
+ */
+ public function run() {
+ $request = $this->getRequest();
+ $route = $request->getAttribute('route');
+ $method = $this->getActionMethod(isset($route->action) ? $route->action : 'default');
+
+ if (!method_exists($this, $method)) {
+ return $this->setResponseError(404, 'Not Found');
+ }
+
+ try {
+ $args = isset($route->args) ?
+ $route->args :
+ $this->getFunctionArgs($route, new \ReflectionMethod($this, $method));
+ } catch (\RuntimeException $e) {
+ return $this->setResponseError(400, 'Bad Request');
+ }
+
+ $response = call_user_func_array([$this, $method], $args);
+
+ return $response ?: $this->getResponse();
+ }
+
+ /**
+ * Get the method name of the action
+ *
+ * @param string $action
+ * @return string
+ */
+ protected function getActionMethod($action)
+ {
+ return \Jasny\camelcase($action) . 'Action';
+ }
+
+ /**
+ * Get the arguments for a function from a route using reflection
+ *
+ * @param object $route
+ * @param \ReflectionFunctionAbstract $refl
+ * @return array
+ */
+ protected function getFunctionArgs($route, \ReflectionFunctionAbstract $refl)
+ {
+ $args = [];
+ $params = $refl->getParameters();
+
+ foreach ($params as $param) {
+ $key = $param->name;
+
+ if (property_exists($route, $key)) {
+ $value = $route->{$key};
+ } else {
+ if (!$param->isOptional()) {
+ $fn = $refl instanceof \ReflectionMethod
+ ? $refl->class . ':' . $refl->name
+ : $refl->name;
+
+ throw new \RuntimeException("Missing argument '$key' for $fn()");
+ }
+
+ $value = $param->isDefaultValueAvailable() ? $param->getDefaultValue() : null;
+ }
+
+ $args[$key] = $value;
+ }
+
+ return $args;
+ }
+
+ /**
+ * Set response to error state
+ *
+ * @param int $code
+ * @param string $message
+ * @return ResponseInterface
+ */
+ protected function setResponseError($code, $message)
+ {
+ $response = $this->getResponse();
+
+ $errorResponse = $response->withStatus($code);
+ $errorResponse->getBody()->write($message);
+
+ return $errorResponse;
+ }
+}
+