summaryrefslogtreecommitdiffstats
path: root/src/Controller
diff options
context:
space:
mode:
authorArnold Daniels <arnold@jasny.net>2016-11-18 18:28:24 +0100
committerArnold Daniels <arnold@jasny.net>2016-11-18 18:28:24 +0100
commit43c6d835943b322c036e9ee47800d694cb6bb5de (patch)
treef56809890b4e65c2f4790fbd8be9593a3538a72c /src/Controller
parent934b380f473b4e85e807f07d6bf516f4e227e112 (diff)
downloadcontroller-43c6d835943b322c036e9ee47800d694cb6bb5de.zip
controller-43c6d835943b322c036e9ee47800d694cb6bb5de.tar.gz
controller-43c6d835943b322c036e9ee47800d694cb6bb5de.tar.bz2
Refactored CheckRequest and CheckResponse traits
WIP Controller\Output Restructuring the tests (one test per trait)
Diffstat (limited to 'src/Controller')
-rw-r--r--src/Controller/CheckResponse.php23
-rw-r--r--src/Controller/Input.php13
-rw-r--r--src/Controller/Output.php (renamed from src/Controller/Respond.php)125
3 files changed, 135 insertions, 26 deletions
diff --git a/src/Controller/CheckResponse.php b/src/Controller/CheckResponse.php
index 7c02d46..7509778 100644
--- a/src/Controller/CheckResponse.php
+++ b/src/Controller/CheckResponse.php
@@ -18,6 +18,17 @@ trait CheckResponse
/**
+ * Check if response is a 1xx informational
+ *
+ * @return boolean
+ */
+ public function isInformational()
+ {
+ $code = $this->getResponse()->getStatusCode() ?: 200;
+ return $code >= 100 && $code < 200;
+ }
+
+ /**
* Check if response is 2xx succesful, or empty
*
* @return boolean
@@ -25,8 +36,7 @@ trait CheckResponse
public function isSuccessful()
{
$code = $this->getResponse()->getStatusCode() ?: 200;
-
- return !$code || ($code >= 200 && $code < 300);
+ return $code >= 200 && $code < 300;
}
/**
@@ -37,7 +47,6 @@ trait CheckResponse
public function isRedirection()
{
$code = $this->getResponse()->getStatusCode() ?: 200;
-
return $code >= 300 && $code < 400;
}
@@ -49,7 +58,6 @@ trait CheckResponse
public function isClientError()
{
$code = $this->getResponse()->getStatusCode() ?: 200;
-
return $code >= 400 && $code < 500;
}
@@ -60,8 +68,9 @@ trait CheckResponse
*/
public function isServerError()
{
- return $this->getResponse()->getStatusCode() ?: 200 >= 500;
- }
+ $code = $this->getResponse()->getStatusCode() ?: 200;
+ return $code >= 500 && $code < 600;
+ }
/**
* Check if response is 4xx or 5xx error
@@ -71,5 +80,5 @@ trait CheckResponse
public function isError()
{
return $this->isClientError() || $this->isServerError();
- }
+ }
}
diff --git a/src/Controller/Input.php b/src/Controller/Input.php
new file mode 100644
index 0000000..7f5ce35
--- /dev/null
+++ b/src/Controller/Input.php
@@ -0,0 +1,13 @@
+<?php
+
+namespace Jasny\Controller;
+
+use Psr\Http\Message\ServerRequestInterface;
+
+/**
+ * Methods for a controller to read from the request
+ */
+trait Input
+{
+
+}
diff --git a/src/Controller/Respond.php b/src/Controller/Output.php
index 02b2cfb..a6160f1 100644
--- a/src/Controller/Respond.php
+++ b/src/Controller/Output.php
@@ -8,9 +8,14 @@ use Dflydev\ApacheMimeTypes\PhpRepository as ApacheMimeTypes;
/**
* Methods for a controller to send a response
*/
-trait Respond
+trait Output
{
/**
+ * @var string
+ */
+ protected $defaultFormat;
+
+ /**
* Get response. set for controller
*
* @return ResponseInterface
@@ -33,6 +38,17 @@ trait Respond
/**
+ * If a non scalar value is passed without an format, use this format
+ *
+ * @param string $format Format by extention or MIME
+ */
+ public function byDefaultSerializeTo($format)
+ {
+ $this->defaultFormat = $format;
+ }
+
+
+ /**
* Set a response header
*
* @param string $header
@@ -96,40 +112,66 @@ trait Respond
}
/**
- * Response with created 201 code, and optionaly redirect to created location
+ * Response with created 201 code, and optionally the created location
*
* @param string $location Url of created resource
*/
- public function created($location = '')
+ public function created($location = null)
{
$this->respondWith(201);
- if ($location) {
+ if (!empty($location)) {
$this->setResponseHeader('Location', $location);
}
}
/**
+ * Response with 203 Accepted
+ */
+ public function accepted()
+ {
+ $this->respondWith(202);
+ }
+
+ /**
* Response with 204 No Content
+ *
+ * @param int $code 204 (No Content) or 205 (Reset Content)
*/
- public function noContent()
+ public function noContent($code = 204)
{
- $this->respondWith(204);
+ $this->respondWith($code);
+ }
+
+ /**
+ * Respond with a 206 Partial content with `Content-Range` header
+ *
+ * @param int $rangeFrom Beginning of the range in bytes
+ * @param int $rangeTo End of the range in bytes
+ * @param int $totalSize Total size in bytes
+ */
+ public function partialContent($rangeFrom, $rangeTo, $totalSize)
+ {
+ $this->respondWith(206);
+
+ $this->setResponseHeader('Content-Range', "bytes {$rangeFrom}-{$rangeTo}/{$totalSize}");
+ $this->setResponseHeader('Content-Length', $rangeTo - $rangeFrom);
}
+
/**
- * Redirect to url
+ * Redirect to url and output a short message with the link
*
* @param string $url
- * @param int $code 301 (Moved Permanently), 303 (See Other) or 307 (Temporary Redirect)
+ * @param int $code 301 (Moved Permanently), 302 (Found), 303 (See Other) or 307 (Temporary Redirect)
*/
public function redirect($url, $code = 303)
{
- $this->respondWith($code, 'text/html');
+ $this->respondWith($code);
$this->setResponseHeader('Location', $url);
$urlHtml = htmlentities($url);
- $this->output('You are being redirected to <a href="' . $urlHtml . '">' . $urlHtml . '</a>');
+ $this->output('You are being redirected to <a href="' . $urlHtml . '">' . $urlHtml . '</a>', 'text/html');
}
/**
@@ -141,6 +183,14 @@ trait Respond
{
$this->redirect($this->getLocalReferer() ?: '/');
}
+
+ /**
+ * Respond with 304 Not Modified
+ */
+ public function notModified()
+ {
+ $this->respondWith(304);
+ }
/**
@@ -188,7 +238,7 @@ trait Respond
*
* @param string $message
*/
- public function forbidden($message = "Forbidden")
+ public function forbidden($message = "Access denied")
{
$this->respondWith(403);
$this->output($message);
@@ -198,7 +248,7 @@ trait Respond
* Respond with 404 Not Found
*
* @param string $message
- * @param int $code HTTP status code (404 or 405)
+ * @param int $code 404 (Not Found), 405 (Method not allowed) or 410 (Gone)
*/
public function notFound($message = "Not found", $code = 404)
{
@@ -273,16 +323,53 @@ trait Respond
*/
protected function serializeData($data, $contentType)
{
- if ($contentType == 'json') {
- return (is_string($data) && (json_decode($data) !== null || !json_last_error()))
- ? $data : json_encode($data);
+ if (is_scalar($data)) {
+ return (string)$data;
+ }
+
+ $format = preg_replace('~^.+/~', '', $contentType);
+ $method = 'serializeDataTo' . $format;
+
+ if (method_exists($this, $method)) {
+ return $this->$method($data);
+ }
+
+ if (is_object($data) && method_exists($data, '__toString')) {
+ return (string)$data;
+ }
+
+ throw new \Exception("Unable to serialize data to $format");
+ }
+
+ /**
+ * Serialize data to JSON
+ *
+ * @param mixed $data
+ * @return string
+ */
+ private function serializeDataToJson($data)
+ {
+ return json_encode($data);
+ }
+
+ /**
+ * Serialize data to XML
+ *
+ * @param mixed $data
+ * @return string
+ */
+ private function serializeDataToXml($data)
+ {
+ if ($data instanceof \SimpleXMLElement) {
+ return $data->asXML();
}
- if (!is_scalar($data)) {
- throw new \Exception("Unable to serialize data to {$contentType}");
+ if ($data instanceof \DOMNode) {
+ return $data->ownerDocument->saveXML($data);
}
- return $data;
+ $type = (is_object($data) ? get_class($data) . ' ' : '') . gettype($data);
+ throw new \Exception("Unable to serialize $type to XML");
}
/**
@@ -300,7 +387,7 @@ trait Respond
$this->setResponseHeader('Content-Type', $contentType);
}
- $content = $this->serializeData($data, $contentType);
+ $content = $this->serializeData($data, $format);
$this->getResponse()->getBody()->write($content);
}