feat(demo): add story 1 — Sorano: Rock and Time
This commit is contained in:
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Grav\Plugin\Api\Exceptions;
|
||||
|
||||
use RuntimeException;
|
||||
|
||||
class ApiException extends RuntimeException
|
||||
{
|
||||
public function __construct(
|
||||
protected readonly int $statusCode,
|
||||
protected readonly string $errorTitle,
|
||||
string $detail = '',
|
||||
protected readonly array $headers = [],
|
||||
?\Throwable $previous = null,
|
||||
) {
|
||||
parent::__construct($detail, $statusCode, $previous);
|
||||
}
|
||||
|
||||
public function getStatusCode(): int
|
||||
{
|
||||
return $this->statusCode;
|
||||
}
|
||||
|
||||
public function getErrorTitle(): string
|
||||
{
|
||||
return $this->errorTitle;
|
||||
}
|
||||
|
||||
public function getHeaders(): array
|
||||
{
|
||||
return $this->headers;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Grav\Plugin\Api\Exceptions;
|
||||
|
||||
class ConflictException extends ApiException
|
||||
{
|
||||
public function __construct(string $detail = 'The resource has been modified. Refresh and try again.', ?\Throwable $previous = null)
|
||||
{
|
||||
parent::__construct(409, 'Conflict', $detail, [], $previous);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Grav\Plugin\Api\Exceptions;
|
||||
|
||||
class ForbiddenException extends ApiException
|
||||
{
|
||||
public function __construct(string $detail = 'You do not have permission to perform this action.', ?\Throwable $previous = null)
|
||||
{
|
||||
parent::__construct(403, 'Forbidden', $detail, [], $previous);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Grav\Plugin\Api\Exceptions;
|
||||
|
||||
class NotFoundException extends ApiException
|
||||
{
|
||||
public function __construct(string $detail = 'The requested resource was not found.', ?\Throwable $previous = null)
|
||||
{
|
||||
parent::__construct(404, 'Not Found', $detail, [], $previous);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Grav\Plugin\Api\Exceptions;
|
||||
|
||||
class TooManyRequestsException extends ApiException
|
||||
{
|
||||
public function __construct(string $detail = 'Too many requests.', int $retryAfter = 0, ?\Throwable $previous = null)
|
||||
{
|
||||
$headers = [];
|
||||
if ($retryAfter > 0) {
|
||||
$headers['Retry-After'] = (string) $retryAfter;
|
||||
}
|
||||
parent::__construct(429, 'Too Many Requests', $detail, $headers, $previous);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Grav\Plugin\Api\Exceptions;
|
||||
|
||||
/**
|
||||
* 403 forbidden, dedicated to the `security.twig_content.*` gate. The
|
||||
* `errorTitle` field carries a stable machine-readable reason code that
|
||||
* Admin Next can switch on to render the right toast.
|
||||
*/
|
||||
class TwigContentForbiddenException extends ApiException
|
||||
{
|
||||
/** Site-wide gate is off; nobody can enable Twig in content. */
|
||||
public const REASON_DISABLED = 'TWIG_CONTENT_DISABLED';
|
||||
|
||||
/** Gate is on, but the current user is not allowed to toggle Twig on pages. */
|
||||
public const REASON_FORBIDDEN = 'TWIG_CONTENT_FORBIDDEN';
|
||||
|
||||
/** Page already has process.twig:true; the current user cannot edit it. */
|
||||
public const REASON_PAGE_FORBIDDEN = 'TWIG_CONTENT_PAGE_FORBIDDEN';
|
||||
|
||||
public function __construct(string $reason, string $detail = '', ?\Throwable $previous = null)
|
||||
{
|
||||
if ($detail === '') {
|
||||
$detail = match ($reason) {
|
||||
self::REASON_DISABLED => 'Twig processing in page content is disabled site-wide. An administrator can enable it under Configuration > Security > Twig in Content.',
|
||||
self::REASON_FORBIDDEN => "You don't have permission to enable Twig processing on pages.",
|
||||
self::REASON_PAGE_FORBIDDEN => "This page has Twig processing enabled in its content. You don't have permission to edit pages with Twig enabled.",
|
||||
default => 'Twig in content is not allowed.',
|
||||
};
|
||||
}
|
||||
|
||||
parent::__construct(403, $reason, $detail, [], $previous);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Grav\Plugin\Api\Exceptions;
|
||||
|
||||
class UnauthorizedException extends ApiException
|
||||
{
|
||||
public function __construct(string $detail = 'Authentication is required.', ?\Throwable $previous = null)
|
||||
{
|
||||
parent::__construct(401, 'Unauthorized', $detail, ['WWW-Authenticate' => 'Bearer'], $previous);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Grav\Plugin\Api\Exceptions;
|
||||
|
||||
class ValidationException extends ApiException
|
||||
{
|
||||
public function __construct(
|
||||
string $detail = 'The request data is invalid.',
|
||||
protected readonly array $errors = [],
|
||||
?\Throwable $previous = null,
|
||||
) {
|
||||
parent::__construct(422, 'Unprocessable Entity', $detail, [], $previous);
|
||||
}
|
||||
|
||||
public function getValidationErrors(): array
|
||||
{
|
||||
return $this->errors;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user