<?php namespace Nest\Http\Router; use DOMDocument; use Nest\Application; use Nest\Http\ContentType; use Nest\Http\Header; use Nest\Http\Renderer\Renderer; use Nest\Http\StatusCode; use Nyholm\Psr7\Response; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Message\StreamInterface; use Stringable; /** * An abstract HTTP route controller. */ abstract class Controller { /** * @param Application $app The application. */ public function __construct(protected Application $app) {} /** * Get current request. * @return ServerRequestInterface The request instance. */ public function getRequest(): ServerRequestInterface { return $this->app->http()->getRequest(); } /** * Create a new response with the given status code and data. * @param StatusCode $statusCode The status code to respond. * @param string|null $contentType The content type of the response. * @param string|resource|StreamInterface|null $body The body to respond. * @return ResponseInterface The new response. */ public function newResponse(StatusCode $statusCode = StatusCode::OK, ?string $contentType = null, mixed $body = null): ResponseInterface { // Initialize headers. $headers = []; if (!empty($contentType)) $headers[Header::ContentType->value] = $contentType; return new Response( // Pass the status code. status: $statusCode->value, // Pass headers. headers: $headers, // Pass the raw body. body: $body, ); } /** * Build a text response. * @param string $value The text value to pass. * @param StatusCode $statusCode The status code to send back. OK by default. * @return ResponseInterface Built response. */ public function text(string $value, StatusCode $statusCode = StatusCode::OK): ResponseInterface { return $this->newResponse($statusCode, ContentType::Text->value, $value); } /** * Build a JSON response. * @param mixed $value The value to serialize. * @param StatusCode $statusCode The status code to send back. OK by default. * @return ResponseInterface Built response. */ public function json(mixed $value, StatusCode $statusCode = StatusCode::OK): ResponseInterface { return $this->newResponse($statusCode, ContentType::Json->value, json_encode($value)); } /** * Build an XML response. * @param DOMDocument $value The XML value to serialize. * @param StatusCode $statusCode The status code to send back. OK by default. * @return ResponseInterface Built response. */ public function xml(DOMDocument $value, StatusCode $statusCode = StatusCode::OK): ResponseInterface { return $this->newResponse($statusCode, ContentType::Json->value, $value->saveXML()); } /** * Build a rendered response. * @param Renderer $renderer The renderer instance to use. * @param object $arguments Arguments to use when rendering. * @param StatusCode $statusCode The status code to send back. OK by default. * @param string|null $contentType The content type of the response. * @return ResponseInterface Built response. */ public function render(Renderer $renderer, object $arguments = new \stdClass(), StatusCode $statusCode = StatusCode::OK, ?string $contentType = null): ResponseInterface { return $this->newResponse($statusCode, $contentType ?? null, $renderer->render($arguments)); } }