Skip to content

Commit

Permalink
uniformity in Response and Response-like classes
Browse files Browse the repository at this point in the history
  • Loading branch information
donwilson committed Nov 3, 2023
1 parent 536a014 commit f11ba92
Show file tree
Hide file tree
Showing 10 changed files with 198 additions and 226 deletions.
20 changes: 9 additions & 11 deletions src/Magnetar/Helpers/Facades/Response.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,25 +6,23 @@
use Magnetar\Helpers\Facades\Facade;

/**
* @method status(int $code=200): self
* @method responseCode(int $response_code=200): self
* @method body(string $body=''): self
* @method sendBody(): self
* @method setCookie(string $name, ?string $value=null, int $expires=0, string $path='', string $domain='', bool $secure=false, bool $httponly=false): self
* @method redirect(string $path, int $response_code=302): void
* @method setBody(string $body=''): self
* @method json(mixed $body): self
* @method send(): self
* @method sendHeaders(): self
* @method sendBody(): self
* @method body(): string
* @method statusCode(): int
* @method header(string $header, ?string $value=null, int|bool $replace=true, ?int $response_code=0): self|string
* @method setHeaders(array $headers): self
* @method headers(): array
* @method getHeader(string $name): ?string
* @method hasHeader(string $name): bool
* @method setHeaders(array $headers): self
* @method removeHeader(string $name): self
* @method clearHeaders(): self
* @method headersSent(): bool
* @method getHeader(string $name): ?string
* @method hasHeader(string $name): bool
* @method sentHeaders(): bool
* @method sent(): bool
* @method redirect(string $path, int $response_code=302): self
* @method json(mixed $body): self
*
* @see Magnetar\Http\Response
*/
Expand Down
4 changes: 3 additions & 1 deletion src/Magnetar/Helpers/Facades/Router.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@
* @method patch(string $pattern, callable|array|string|null $callback=null): Magnetar\Router\Route
* @method delete(string $pattern, callable|array|string|null $callback=null): Magnetar\Router\Route
* @method options(string $pattern, callable|array|string|null $callback=null): Magnetar\Router\Route
* @method group(string $pathPrefix, callable $callback): void
* @method group(string $pathPrefix, callable $callback): Magnetar\Router\RouteCollection
* @method redirect(string $pattern, string $redirect_path, int $response_code=302): Magnetar\Router\Route
* @method permanentRedirect(string $pattern, string $redirect_path): Magnetar\Router\Route
*
* @see Magnetar\Router\Router
*/
Expand Down
4 changes: 1 addition & 3 deletions src/Magnetar/Http/ExceptionHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ public function render(Request $request, Throwable $e): Response {
$response_status = 404;
}

$response = (new Response())->status($response_status)->setBody(
return (new Response())->responseCode($response_status)->body(
$this->app->make('theme')->tpl($theme_file, [
'request' => $request,
'message' => $e->getMessage(),
Expand All @@ -58,7 +58,5 @@ public function render(Request $request, Throwable $e): Response {
'trace' => $e->getTraceAsString()
])
);

return $response;
}
}
39 changes: 19 additions & 20 deletions src/Magnetar/Http/JsonResponse.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,36 +6,35 @@
use Magnetar\Http\Response;

class JsonResponse extends Response {
/**
* Constructor method
*
* @note Sets the default Content-Type header to application/json
*/
public function __construct() {
parent::__construct();

// set default content type to JSON
$this->header('Content-Type', 'application/json');
}

/**
* Set the response data. This will be encoded to JSON
* @param mixed $body
* @return self
*
* @note Intentionally overrides the json method in the Response class
*/
public function setData(mixed $data): self {
$this->body = json_encode($data);

return $this;
public function json(mixed $data): self {
return $this->body( json_encode($data) );
}

/**
* Set the raw JSON response body. Expects a JSON string
* @param string $json_body
* @param string $json The JSON string to set as the response body
* @return self
*/
public function setJson(string $json): self {
$this->body = $json;

return $this;
}

public function send(): self {
$this->header('Content-Type', 'application/json; charset=UTF-8', true);

$this->sendHeaders();
$this->sendBody();

$this->sent = true;

return $this;
public function rawJson(string $json): self {
return $this->body($json);
}
}
8 changes: 2 additions & 6 deletions src/Magnetar/Http/Kernel.php
Original file line number Diff line number Diff line change
Expand Up @@ -192,16 +192,14 @@ protected function parseMiddlewareString(string $middleware): array {
*/
protected function panic(Exception $e): Response {
// send 503 response
$response = (new Response())->status(503)->setBody(
return (new Response())->responseCode(503)->body(
$this->app->make('theme')->tpl('errors/503', [
'message' => $e->getMessage(),
'file' => $e->getFile(),
'line' => $e->getLine(),
'trace' => $e->getTraceAsString()
])
);

return $response;
}

/**
Expand All @@ -211,13 +209,11 @@ protected function panic(Exception $e): Response {
*/
public function handle404(string $message=''): Response {
// send 404 response
$response = (new Response())->status(404)->setBody(
return (new Response())->responseCode(404)->body(
$this->app->make('theme')->tpl('errors/404', [
'message' => $message
])
);

return $response;
}

/**
Expand Down
82 changes: 36 additions & 46 deletions src/Magnetar/Http/RedirectResponse.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,25 +19,17 @@ class RedirectResponse extends Response {
protected string|null $url = null;

/**
* The HTTP Response Code
* How many seconds to delay the redirect, showing a "Redirecting..." page during instead of an instant redirect
* @var int
*/
protected int $statusCode = 307;
protected int $delay_seconds = 0;

/**
* How long to delay the redirect in seconds, showing a "Redirecting..." page during the delay
* @var int
*/
protected int $delaySeconds = 0;

/**
* Set the redirect URL
* @param string $url The URL to redirect to. If it does not start with http:// or https://, it will be prepended with the current domain
* Simplified alias for setURL()
* @param string $url The URL to redirect to
* @return self
*
* @throws InvalidRedirectURLException
*/
public function setURL(string $url): self {
public function to(string $url): self {
if(!preg_match('/^https?:\/\//', $url)) {
$url = URL::to($url);
}
Expand All @@ -52,47 +44,44 @@ public function setURL(string $url): self {
}

/**
* Simplified alias for setURL()
* @param string $url The URL to redirect to
* Set the redirect URL
* @param string $url The URL to redirect to. If it does not start with http:// or https://, it will be prepended with the current domain
* @return self
*
* @throws InvalidRedirectURLException
*/
public function to(string $url): self {
return $this->setURL($url);
public function url(string $url): self {
return $this->to($url);
}

/**
* Set the response code
* @param int $code The HTTP Response Code for the redirect. Only allows 301, 302, and 307. Defaults to 307
* @return self
* {@inheritDoc}
*
* @throws InvalidResponseCodeException
*/
public function setCode(int $code=307): self {
if(!in_array($code, [301, 302, 307])) {
public function responseCode(int $response_code=307): self {
// sanitize response code
if(!in_array($response_code, [300, 301, 302, 303, 304, 307, 308])) {
throw new InvalidResponseCodeException('Invalid redirect code');
}

return $this;
return parent::responseCode($response_code);
}

/**
* Set the response code to 301 (permanent redirect)
* @return self
*/
public function permanent(): self {
$this->statusCode = 301;

return $this;
return $this->responseCode(301);
}

/**
* Set the response code to 307 (temporary redirect)
* @return self
*/
public function temporary(): self {
$this->statusCode = 307;

return $this;
return $this->responseCode(307);
}

/**
Expand All @@ -101,7 +90,7 @@ public function temporary(): self {
* @return self
*/
public function delay(int $seconds=0): self {
$this->delaySeconds = abs($seconds);
$this->delay_seconds = abs($seconds);

return $this;
}
Expand All @@ -110,45 +99,46 @@ public function delay(int $seconds=0): self {
* Resets the delay to the default of 0 seconds
* @return self
*/
public function nodelay(): self {
$this->delaySeconds = 0;
public function noDelay(): self {
$this->delay_seconds = 0;

return $this;
}

/**
* {@inheritDoc}
*
* @throws InvalidRedirectURLException
*/
public function send(): self {
// check for valid URL
if(null === $this->url) {
throw new \Exception('No URL set');
throw new InvalidRedirectURLException('No URL set');
}

// send the redirect header if there is no delay
if(0 === $this->delaySeconds) {
$this->header('Location', $this->url, true, $this->statusCode);
if(0 === $this->delay_seconds) {
$this->header(
'Location',
$this->url,
true,
$this->response_code
);
}

// set body to a basic redirect page
$this->setBody(
$this->generateRedirecPage($this->url)
);
$this->body( $this->generateRedirecHTMLPage($this->url) );

$this->sendHeaders();
$this->sendBody();

$this->sent = true;

return $this;
// send the response
return parent::send();
}

/**
* Generate the redirect HTML page
* @param string|null $url The URL to redirect to. Defaults to the URL set in the response
* @return string
*/
protected function generateRedirecPage(string|null $url=null): string {
protected function generateRedirecHTMLPage(string|null $url=null): string {
// sanitize url
$url ??= $this->url;

Expand All @@ -161,7 +151,7 @@ protected function generateRedirecPage(string|null $url=null): string {
<html>
<head>
<title>Redirecting...</title>
<meta http-equiv="refresh" content="{$this->delaySeconds};url={$escaped_url}">
<meta http-equiv="refresh" content="{$this->delay_seconds};url={$escaped_url}">
<meta name="robots" content="noindex,follow">
</head>
<body>
Expand Down
Loading

0 comments on commit f11ba92

Please sign in to comment.