Version 5.1 - All the GraphQL #32
@ -53,13 +53,13 @@ return (new Config())
|
|||||||
'yield_from',
|
'yield_from',
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
'braces' => [
|
// 'braces' => [
|
||||||
'allow_single_line_anonymous_class_with_empty_body' => true,
|
// 'allow_single_line_anonymous_class_with_empty_body' => true,
|
||||||
'allow_single_line_closure' => true,
|
// 'allow_single_line_closure' => true,
|
||||||
'position_after_anonymous_constructs' => 'same',
|
// 'position_after_anonymous_constructs' => 'same',
|
||||||
'position_after_control_structures' => 'next',
|
// 'position_after_control_structures' => 'next',
|
||||||
'position_after_functions_and_oop_constructs' => 'next',
|
// 'position_after_functions_and_oop_constructs' => 'next',
|
||||||
],
|
// ],
|
||||||
'cast_spaces' => ['space' => 'single'],
|
'cast_spaces' => ['space' => 'single'],
|
||||||
'class_attributes_separation' => [
|
'class_attributes_separation' => [
|
||||||
'elements' => [
|
'elements' => [
|
||||||
@ -93,7 +93,16 @@ return (new Config())
|
|||||||
'compact_nullable_typehint' => true,
|
'compact_nullable_typehint' => true,
|
||||||
'concat_space' => ['spacing' => 'one'],
|
'concat_space' => ['spacing' => 'one'],
|
||||||
'constant_case' => ['case' => 'upper'],
|
'constant_case' => ['case' => 'upper'],
|
||||||
|
'control_structure_braces' => true,
|
||||||
'control_structure_continuation_position' => ['position' => 'next_line'],
|
'control_structure_continuation_position' => ['position' => 'next_line'],
|
||||||
|
'curly_braces_position' => [
|
||||||
|
'allow_single_line_anonymous_functions' => true,
|
||||||
|
'allow_single_line_empty_anonymous_classes' => true,
|
||||||
|
'anonymous_functions_opening_brace' => 'same_line',
|
||||||
|
'classes_opening_brace' => 'next_line_unless_newline_at_signature_end',
|
||||||
|
'control_structures_opening_brace' => 'next_line_unless_newline_at_signature_end',
|
||||||
|
'functions_opening_brace' => 'next_line_unless_newline_at_signature_end',
|
||||||
|
],
|
||||||
'date_time_immutable' => false,
|
'date_time_immutable' => false,
|
||||||
'declare_equal_normalize' => ['space' => 'none'],
|
'declare_equal_normalize' => ['space' => 'none'],
|
||||||
'declare_parentheses' => true,
|
'declare_parentheses' => true,
|
||||||
@ -108,7 +117,7 @@ return (new Config())
|
|||||||
'long_function' => 'echo',
|
'long_function' => 'echo',
|
||||||
'shorten_simple_statements_only' => false,
|
'shorten_simple_statements_only' => false,
|
||||||
],
|
],
|
||||||
'elseif' => true,
|
'elseif' => false,
|
||||||
'empty_loop_body' => ['style' => 'braces'],
|
'empty_loop_body' => ['style' => 'braces'],
|
||||||
'empty_loop_condition' => ['style' => 'while'],
|
'empty_loop_condition' => ['style' => 'while'],
|
||||||
'encoding' => true,
|
'encoding' => true,
|
||||||
@ -429,8 +438,8 @@ return (new Config())
|
|||||||
'single_line_comment_style' => ['comment_types' => ['asterisk', 'hash']],
|
'single_line_comment_style' => ['comment_types' => ['asterisk', 'hash']],
|
||||||
'single_line_throw' => false,
|
'single_line_throw' => false,
|
||||||
'single_quote' => ['strings_containing_single_quote_chars' => false],
|
'single_quote' => ['strings_containing_single_quote_chars' => false],
|
||||||
'single_space_after_construct' => [
|
'single_space_around_construct' => [
|
||||||
'constructs' => [
|
'constructs_followed_by_a_single_space' => [
|
||||||
'abstract',
|
'abstract',
|
||||||
'as',
|
'as',
|
||||||
'attribute',
|
'attribute',
|
||||||
@ -493,6 +502,7 @@ return (new Config())
|
|||||||
'space_after_semicolon' => ['remove_in_empty_for_expressions' => true],
|
'space_after_semicolon' => ['remove_in_empty_for_expressions' => true],
|
||||||
'standardize_increment' => true,
|
'standardize_increment' => true,
|
||||||
'standardize_not_equals' => true,
|
'standardize_not_equals' => true,
|
||||||
|
'statement_indentation' => true,
|
||||||
'static_lambda' => true,
|
'static_lambda' => true,
|
||||||
'strict_comparison' => true,
|
'strict_comparison' => true,
|
||||||
'strict_param' => true,
|
'strict_param' => true,
|
||||||
|
@ -13,8 +13,8 @@
|
|||||||
"autoload": {
|
"autoload": {
|
||||||
"files": [
|
"files": [
|
||||||
"src/Ion/functions.php",
|
"src/Ion/functions.php",
|
||||||
"src/AnimeClient/constants.php",
|
"src/AnimeClient.php",
|
||||||
"src/AnimeClient/AnimeClient.php"
|
"src/AnimeClient/constants.php"
|
||||||
],
|
],
|
||||||
"psr-4": {
|
"psr-4": {
|
||||||
"Aviat\\": "src/"
|
"Aviat\\": "src/"
|
||||||
|
@ -18,7 +18,7 @@ use Amp\Http\Client\{HttpClient, HttpClientBuilder, Request, Response};
|
|||||||
|
|
||||||
use Aviat\Ion\{ConfigInterface, ImageBuilder};
|
use Aviat\Ion\{ConfigInterface, ImageBuilder};
|
||||||
use DateTimeImmutable;
|
use DateTimeImmutable;
|
||||||
use Psr\SimpleCache\CacheInterface;
|
use Psr\SimpleCache\{CacheInterface, InvalidArgumentException};
|
||||||
use Throwable;
|
use Throwable;
|
||||||
|
|
||||||
use Yosymfony\Toml\{Toml, TomlBuilder};
|
use Yosymfony\Toml\{Toml, TomlBuilder};
|
||||||
@ -218,7 +218,7 @@ function getResponse(Request|string $request): Response
|
|||||||
*/
|
*/
|
||||||
function getLocalImg(string $kitsuUrl, bool $webp = TRUE): string
|
function getLocalImg(string $kitsuUrl, bool $webp = TRUE): string
|
||||||
{
|
{
|
||||||
if (empty($kitsuUrl) || ( ! is_string($kitsuUrl)))
|
if (empty($kitsuUrl))
|
||||||
{
|
{
|
||||||
return 'images/placeholder.webp';
|
return 'images/placeholder.webp';
|
||||||
}
|
}
|
||||||
@ -276,6 +276,7 @@ function colNotEmpty(array $search, string $key): bool
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Clear the cache, but save user auth data
|
* Clear the cache, but save user auth data
|
||||||
|
* @throws InvalidArgumentException
|
||||||
*/
|
*/
|
||||||
function clearCache(CacheInterface $cache): bool
|
function clearCache(CacheInterface $cache): bool
|
||||||
{
|
{
|
@ -16,16 +16,14 @@ namespace Aviat\AnimeClient\API;
|
|||||||
|
|
||||||
// use Amp\Http\Client\Form;
|
// use Amp\Http\Client\Form;
|
||||||
use Amp\Http\Client\Body\FormBody;
|
use Amp\Http\Client\Body\FormBody;
|
||||||
use Amp\Http\Client\HttpClientBuilder;
|
use Amp\Http\Client\{HttpClientBuilder, HttpException, Request};
|
||||||
use Amp\Http\Client\HttpException;
|
|
||||||
use Amp\Http\Client\Request;
|
|
||||||
use Aviat\Ion\Json;
|
use Aviat\Ion\Json;
|
||||||
|
|
||||||
use Error;
|
|
||||||
use InvalidArgumentException;
|
use InvalidArgumentException;
|
||||||
use Psr\Log\LoggerAwareTrait;
|
use Psr\Log\LoggerAwareTrait;
|
||||||
use Throwable;
|
use Throwable;
|
||||||
use TypeError;
|
// use function Amp\async;
|
||||||
|
// use function Amp\Future\await;
|
||||||
use function Amp\Promise\wait;
|
use function Amp\Promise\wait;
|
||||||
use function Aviat\AnimeClient\getResponse;
|
use function Aviat\AnimeClient\getResponse;
|
||||||
use const Aviat\AnimeClient\USER_AGENT;
|
use const Aviat\AnimeClient\USER_AGENT;
|
||||||
@ -221,8 +219,6 @@ abstract class APIRequestBuilder
|
|||||||
/**
|
/**
|
||||||
* Get the data from the response of the passed request
|
* Get the data from the response of the passed request
|
||||||
*
|
*
|
||||||
* @param Request $request
|
|
||||||
* @return mixed
|
|
||||||
* @throws Throwable
|
* @throws Throwable
|
||||||
*/
|
*/
|
||||||
public function getResponseData(Request $request): mixed
|
public function getResponseData(Request $request): mixed
|
||||||
|
@ -38,7 +38,6 @@ abstract class AbstractListItem
|
|||||||
* Retrieve a list item
|
* Retrieve a list item
|
||||||
*
|
*
|
||||||
* @param string $id - The id of the list item
|
* @param string $id - The id of the list item
|
||||||
* @return mixed[]
|
|
||||||
*/
|
*/
|
||||||
abstract public function get(string $id): array;
|
abstract public function get(string $id): array;
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
|
|
||||||
namespace Aviat\AnimeClient\API;
|
namespace Aviat\AnimeClient\API;
|
||||||
|
|
||||||
use Psr\SimpleCache\CacheInterface;
|
use Psr\SimpleCache\{CacheInterface, InvalidArgumentException};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper methods for dealing with the Cache
|
* Helper methods for dealing with the Cache
|
||||||
@ -44,6 +44,7 @@ trait CacheTrait
|
|||||||
/**
|
/**
|
||||||
* Get the cached value if it exists, otherwise set the cache value
|
* Get the cached value if it exists, otherwise set the cache value
|
||||||
* and return it.
|
* and return it.
|
||||||
|
* @throws InvalidArgumentException
|
||||||
*/
|
*/
|
||||||
public function getCached(string $key, callable $primer, ?array $primeArgs = []): mixed
|
public function getCached(string $key, callable $primer, ?array $primeArgs = []): mixed
|
||||||
{
|
{
|
||||||
|
@ -16,7 +16,6 @@ namespace Aviat\AnimeClient\API\Kitsu;
|
|||||||
|
|
||||||
use Amp\Http\Client\{Request, Response};
|
use Amp\Http\Client\{Request, Response};
|
||||||
use Aviat\AnimeClient\API\APIRequestBuilder;
|
use Aviat\AnimeClient\API\APIRequestBuilder;
|
||||||
use Aviat\AnimeClient\Enum\EventType;
|
|
||||||
use Aviat\AnimeClient\Kitsu as K;
|
use Aviat\AnimeClient\Kitsu as K;
|
||||||
use Aviat\Ion\Di\{ContainerAware, ContainerInterface};
|
use Aviat\Ion\Di\{ContainerAware, ContainerInterface};
|
||||||
use Aviat\Ion\{Event, Json, JsonException};
|
use Aviat\Ion\{Event, Json, JsonException};
|
||||||
|
@ -54,7 +54,7 @@ final class MangaTransformer extends AbstractTransformer
|
|||||||
}
|
}
|
||||||
|
|
||||||
$details = $rawCharacter['character'];
|
$details = $rawCharacter['character'];
|
||||||
if (array_key_exists($details['id'], (array)$characters[$type]))
|
if (array_key_exists($details['id'], (array) $characters[$type]))
|
||||||
{
|
{
|
||||||
$characters[$type][$details['id']] = [
|
$characters[$type][$details['id']] = [
|
||||||
'image' => Kitsu::getImage($details),
|
'image' => Kitsu::getImage($details),
|
||||||
|
@ -14,11 +14,12 @@
|
|||||||
|
|
||||||
namespace Aviat\AnimeClient\API;
|
namespace Aviat\AnimeClient\API;
|
||||||
|
|
||||||
use Amp\Http\Client\Request;
|
use Amp\Http\Client\{HttpException, Request};
|
||||||
use Generator;
|
use Generator;
|
||||||
use Throwable;
|
use Throwable;
|
||||||
use function Amp\call;
|
use function Amp\call;
|
||||||
|
|
||||||
|
// use function Amp\Future\{async, await};
|
||||||
use function Amp\Promise\{all, wait};
|
use function Amp\Promise\{all, wait};
|
||||||
use function Aviat\AnimeClient\getApiClient;
|
use function Aviat\AnimeClient\getApiClient;
|
||||||
|
|
||||||
@ -65,9 +66,23 @@ final class ParallelAPIRequest
|
|||||||
* Make the requests, and return the body for each
|
* Make the requests, and return the body for each
|
||||||
*
|
*
|
||||||
* @throws Throwable
|
* @throws Throwable
|
||||||
* @return mixed[]
|
|
||||||
*/
|
*/
|
||||||
public function makeRequests(): array
|
public function makeRequests(): array
|
||||||
|
{
|
||||||
|
return $this->makeRequestOld();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make the requests and return the response objects
|
||||||
|
*
|
||||||
|
* @throws Throwable
|
||||||
|
*/
|
||||||
|
public function getResponses(): array
|
||||||
|
{
|
||||||
|
return $this->getResponsesOld();
|
||||||
|
}
|
||||||
|
|
||||||
|
private function makeRequestOld(): array
|
||||||
{
|
{
|
||||||
$client = getApiClient();
|
$client = getApiClient();
|
||||||
|
|
||||||
@ -84,13 +99,19 @@ final class ParallelAPIRequest
|
|||||||
return wait(all($promises));
|
return wait(all($promises));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private function makeRequestsNew(): array
|
||||||
* Make the requests and return the response objects
|
{
|
||||||
*
|
$futures = [];
|
||||||
* @throws Throwable
|
|
||||||
* @return mixed[]
|
foreach ($this->requests as $key => $url)
|
||||||
*/
|
{
|
||||||
public function getResponses(): array
|
$futures[$key] = async(static fn () => self::bodyHandler($url));
|
||||||
|
}
|
||||||
|
|
||||||
|
return await($futures);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getResponsesOld(): array
|
||||||
{
|
{
|
||||||
$client = getApiClient();
|
$client = getApiClient();
|
||||||
|
|
||||||
@ -103,4 +124,41 @@ final class ParallelAPIRequest
|
|||||||
|
|
||||||
return wait(all($promises));
|
return wait(all($promises));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function getResponsesNew(): array
|
||||||
|
{
|
||||||
|
$futures = [];
|
||||||
|
|
||||||
|
foreach ($this->requests as $key => $url)
|
||||||
|
{
|
||||||
|
$futures[$key] = async(static fn () => self::responseHandler($url));
|
||||||
|
}
|
||||||
|
|
||||||
|
return await($futures);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function bodyHandler(string|Request $uri): string
|
||||||
|
{
|
||||||
|
$client = getApiClient();
|
||||||
|
|
||||||
|
if (is_string($uri))
|
||||||
|
{
|
||||||
|
$uri = new Request($uri);
|
||||||
|
}
|
||||||
|
$response = $client->request($uri);
|
||||||
|
|
||||||
|
return $response->getBody()->buffer();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function responseHandler(string|Request $uri)
|
||||||
|
{
|
||||||
|
$client = getApiClient();
|
||||||
|
|
||||||
|
if (is_string($uri))
|
||||||
|
{
|
||||||
|
$uri = new Request($uri);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $client->request($uri);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -120,194 +120,185 @@ class Controller
|
|||||||
Event::on(EventType::RESET_CACHE_KEY, fn (string $key) => $this->cache->delete($key));
|
Event::on(EventType::RESET_CACHE_KEY, fn (string $key) => $this->cache->delete($key));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the current url in the session as the target of a future redirect
|
* Set the current url in the session as the target of a future redirect
|
||||||
*
|
*
|
||||||
* @throws ContainerException
|
* @throws ContainerException
|
||||||
* @throws NotFoundException
|
* @throws NotFoundException
|
||||||
*/
|
*/
|
||||||
#[\PHPUnit\Framework\Attributes\CodeCoverageIgnore]
|
public function setSessionRedirect(?string $url = NULL): void
|
||||||
public function setSessionRedirect(?string $url = NULL): void
|
{
|
||||||
{
|
$serverParams = $this->request->getServerParams();
|
||||||
$serverParams = $this->request->getServerParams();
|
|
||||||
|
|
||||||
if ( ! array_key_exists('HTTP_REFERER', $serverParams))
|
if ( ! array_key_exists('HTTP_REFERER', $serverParams))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$util = $this->container->get('util');
|
$util = $this->container->get('util');
|
||||||
$doubleFormPage = $serverParams['HTTP_REFERER'] === $this->request->getUri();
|
$doubleFormPage = $serverParams['HTTP_REFERER'] === $this->request->getUri();
|
||||||
$isLoginPage = str_contains($serverParams['HTTP_REFERER'], 'login');
|
$isLoginPage = str_contains($serverParams['HTTP_REFERER'], 'login');
|
||||||
|
|
||||||
// Don't attempt to set the redirect url if
|
// Don't attempt to set the redirect url if
|
||||||
// the page is one of the form type pages,
|
// the page is one of the form type pages,
|
||||||
// and the previous page is also a form type
|
// and the previous page is also a form type
|
||||||
if ($doubleFormPage || $isLoginPage)
|
if ($doubleFormPage || $isLoginPage)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (NULL === $url)
|
if (NULL === $url)
|
||||||
{
|
{
|
||||||
$url = $util->isViewPage()
|
$url = $util->isViewPage()
|
||||||
? (string) $this->request->getUri()
|
? (string) $this->request->getUri()
|
||||||
: $serverParams['HTTP_REFERER'];
|
: $serverParams['HTTP_REFERER'];
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->session->set('redirect_url', $url);
|
$this->session->set('redirect_url', $url);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Redirect to the url previously set in the session
|
* Redirect to the url previously set in the session
|
||||||
*
|
*
|
||||||
* If one is not set, redirect to default url
|
* If one is not set, redirect to default url
|
||||||
*
|
*
|
||||||
* @throws InvalidArgumentException
|
* @throws InvalidArgumentException
|
||||||
*/
|
*/
|
||||||
#[\PHPUnit\Framework\Attributes\CodeCoverageIgnore]
|
public function sessionRedirect(): void
|
||||||
public function sessionRedirect(): void
|
{
|
||||||
{
|
$target = $this->session->get('redirect_url') ?? '/';
|
||||||
$target = $this->session->get('redirect_url') ?? '/';
|
|
||||||
|
|
||||||
$this->redirect($target, 303);
|
$this->redirect($target, 303);
|
||||||
$this->session->set('redirect_url', NULL);
|
$this->session->set('redirect_url', NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if the current user is authenticated, else error and exit
|
* Check if the current user is authenticated, else error and exit
|
||||||
*/
|
*/
|
||||||
#[\PHPUnit\Framework\Attributes\CodeCoverageIgnore]
|
protected function checkAuth(): void
|
||||||
protected function checkAuth(): void
|
{
|
||||||
{
|
if ( ! $this->auth->isAuthenticated())
|
||||||
if ( ! $this->auth->isAuthenticated())
|
{
|
||||||
{
|
$this->errorPage(
|
||||||
$this->errorPage(
|
403,
|
||||||
403,
|
'Forbidden',
|
||||||
'Forbidden',
|
'You must <a href="/login">log in</a> to perform this action.'
|
||||||
'You must <a href="/login">log in</a> to perform this action.'
|
);
|
||||||
);
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the string output of a partial template
|
* Get the string output of a partial template
|
||||||
*/
|
*/
|
||||||
#[\PHPUnit\Framework\Attributes\CodeCoverageIgnore]
|
protected function loadPartial(HtmlView $view, string $template, array $data = []): string
|
||||||
protected function loadPartial(HtmlView $view, string $template, array $data = []): string
|
{
|
||||||
{
|
$router = $this->container->get('dispatcher');
|
||||||
$router = $this->container->get('dispatcher');
|
|
||||||
|
|
||||||
if (isset($this->baseData))
|
if (isset($this->baseData))
|
||||||
{
|
{
|
||||||
$data = array_merge($this->baseData, $data);
|
$data = array_merge($this->baseData, $data);
|
||||||
}
|
}
|
||||||
|
|
||||||
$route = $router->getRoute();
|
$route = $router->getRoute();
|
||||||
$data['route_path'] = $route !== FALSE ? $route->path : '';
|
$data['route_path'] = $route !== FALSE ? $route->path : '';
|
||||||
|
|
||||||
$templatePath = _dir($this->config->get('view_path'), "{$template}.php");
|
$templatePath = _dir($this->config->get('view_path'), "{$template}.php");
|
||||||
|
|
||||||
if ( ! is_file($templatePath))
|
if ( ! is_file($templatePath))
|
||||||
{
|
{
|
||||||
throw new InvalidArgumentException("Invalid template : {$template}");
|
throw new InvalidArgumentException("Invalid template : {$template}");
|
||||||
}
|
}
|
||||||
|
|
||||||
return $view->renderTemplate($templatePath, $data);
|
return $view->renderTemplate($templatePath, $data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Render a template with header and footer
|
* Render a template with header and footer
|
||||||
*/
|
*/
|
||||||
#[\PHPUnit\Framework\Attributes\CodeCoverageIgnore]
|
protected function renderFullPage(HtmlView $view, string $template, array $data): HtmlView
|
||||||
protected function renderFullPage(HtmlView $view, string $template, array $data): HtmlView
|
{
|
||||||
{
|
$csp = [
|
||||||
$csp = [
|
"default-src 'self' media.kitsu.io kitsu-production-media.s3.us-west-002.backblazeb2.com",
|
||||||
"default-src 'self' media.kitsu.io kitsu-production-media.s3.us-west-002.backblazeb2.com",
|
"object-src 'none'",
|
||||||
"object-src 'none'",
|
"child-src 'self' *.youtube.com polyfill.io",
|
||||||
"child-src 'self' *.youtube.com polyfill.io",
|
];
|
||||||
];
|
|
||||||
|
|
||||||
$view->addHeader('Content-Security-Policy', implode('; ', $csp));
|
$view->addHeader('Content-Security-Policy', implode('; ', $csp));
|
||||||
$view->appendOutput($this->loadPartial($view, 'header', $data));
|
$view->appendOutput($this->loadPartial($view, 'header', $data));
|
||||||
|
|
||||||
if (array_key_exists('message', $data) && is_array($data['message']))
|
if (array_key_exists('message', $data) && is_array($data['message']))
|
||||||
{
|
{
|
||||||
$view->appendOutput($this->loadPartial($view, 'message', $data['message']));
|
$view->appendOutput($this->loadPartial($view, 'message', $data['message']));
|
||||||
}
|
}
|
||||||
|
|
||||||
$view->appendOutput($this->loadPartial($view, $template, $data));
|
$view->appendOutput($this->loadPartial($view, $template, $data));
|
||||||
$view->appendOutput($this->loadPartial($view, 'footer', $data));
|
$view->appendOutput($this->loadPartial($view, 'footer', $data));
|
||||||
|
|
||||||
return $view;
|
return $view;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 404 action
|
* 404 action
|
||||||
*
|
*
|
||||||
* @throws InvalidArgumentException
|
* @throws InvalidArgumentException
|
||||||
*/
|
*/
|
||||||
#[\PHPUnit\Framework\Attributes\CodeCoverageIgnore]
|
public function notFound(
|
||||||
public function notFound(
|
string $title = 'Sorry, page not found',
|
||||||
string $title = 'Sorry, page not found',
|
string $message = 'Page Not Found'
|
||||||
string $message = 'Page Not Found'
|
): never {
|
||||||
): never {
|
$this->outputHTML('404', [
|
||||||
$this->outputHTML('404', [
|
'title' => $title,
|
||||||
'title' => $title,
|
'message' => $message,
|
||||||
'message' => $message,
|
], NULL, 404);
|
||||||
], NULL, 404);
|
|
||||||
|
|
||||||
exit();
|
exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Display a generic error page
|
* Display a generic error page
|
||||||
*
|
*
|
||||||
* @throws InvalidArgumentException
|
* @throws InvalidArgumentException
|
||||||
*/
|
*/
|
||||||
#[\PHPUnit\Framework\Attributes\CodeCoverageIgnore]
|
public function errorPage(int $httpCode, string $title, string $message, string $longMessage = ''): void
|
||||||
public function errorPage(int $httpCode, string $title, string $message, string $longMessage = ''): void
|
{
|
||||||
{
|
$this->outputHTML('error', [
|
||||||
$this->outputHTML('error', [
|
'title' => $title,
|
||||||
'title' => $title,
|
'message' => $message,
|
||||||
'message' => $message,
|
'long_message' => $longMessage,
|
||||||
'long_message' => $longMessage,
|
], NULL, $httpCode);
|
||||||
], NULL, $httpCode);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Redirect to the default controller/url from an empty path
|
* Redirect to the default controller/url from an empty path
|
||||||
*
|
*
|
||||||
* @throws InvalidArgumentException
|
* @throws InvalidArgumentException
|
||||||
*/
|
*/
|
||||||
#[\PHPUnit\Framework\Attributes\CodeCoverageIgnore]
|
public function redirectToDefaultRoute(): void
|
||||||
public function redirectToDefaultRoute(): void
|
{
|
||||||
{
|
$defaultType = $this->config->get('default_list');
|
||||||
$defaultType = $this->config->get('default_list');
|
$this->redirect($this->urlGenerator->defaultUrl($defaultType), 303);
|
||||||
$this->redirect($this->urlGenerator->defaultUrl($defaultType), 303);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set a session flash variable to display a message on
|
* Set a session flash variable to display a message on
|
||||||
* next page load
|
* next page load
|
||||||
*/
|
*/
|
||||||
#[\PHPUnit\Framework\Attributes\CodeCoverageIgnore]
|
public function setFlashMessage(string $message, string $type = 'info'): void
|
||||||
public function setFlashMessage(string $message, string $type = 'info'): void
|
{
|
||||||
{
|
static $messages;
|
||||||
static $messages;
|
|
||||||
|
|
||||||
if ( ! $messages)
|
if ( ! $messages)
|
||||||
{
|
{
|
||||||
$messages = [];
|
$messages = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
$messages[] = [
|
$messages[] = [
|
||||||
'message_type' => $type,
|
'message_type' => $type,
|
||||||
'message' => $message,
|
'message' => $message,
|
||||||
];
|
];
|
||||||
|
|
||||||
$this->session->setFlash('message', $messages);
|
$this->session->setFlash('message', $messages);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper for consistent page titles
|
* Helper for consistent page titles
|
||||||
@ -319,62 +310,58 @@ class Controller
|
|||||||
return implode(' · ', $parts);
|
return implode(' · ', $parts);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a message box to the page
|
* Add a message box to the page
|
||||||
*
|
*
|
||||||
* @throws InvalidArgumentException
|
* @throws InvalidArgumentException
|
||||||
*/
|
*/
|
||||||
#[\PHPUnit\Framework\Attributes\CodeCoverageIgnore]
|
protected function showMessage(HtmlView $view, string $type, string $message): string
|
||||||
protected function showMessage(HtmlView $view, string $type, string $message): string
|
{
|
||||||
{
|
return $this->loadPartial($view, 'message', [
|
||||||
return $this->loadPartial($view, 'message', [
|
'message_type' => $type,
|
||||||
'message_type' => $type,
|
'message' => $message,
|
||||||
'message' => $message,
|
]);
|
||||||
]);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Output a template to HTML, using the provided data
|
* Output a template to HTML, using the provided data
|
||||||
*
|
*
|
||||||
* @throws InvalidArgumentException
|
* @throws InvalidArgumentException
|
||||||
*/
|
*/
|
||||||
#[\PHPUnit\Framework\Attributes\CodeCoverageIgnore]
|
protected function outputHTML(string $template, array $data = [], ?HtmlView $view = NULL, int $code = 200): void
|
||||||
protected function outputHTML(string $template, array $data = [], ?HtmlView $view = NULL, int $code = 200): void
|
{
|
||||||
{
|
if (NULL === $view)
|
||||||
if (NULL === $view)
|
{
|
||||||
{
|
$view = new HtmlView($this->container);
|
||||||
$view = new HtmlView($this->container);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
$view->setStatusCode($code);
|
$view->setStatusCode($code);
|
||||||
$this->renderFullPage($view, $template, $data)->send();
|
$this->renderFullPage($view, $template, $data)->send();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Output a JSON Response
|
* Output a JSON Response
|
||||||
*
|
*
|
||||||
* @param int $code - the http status code
|
* @param int $code - the http status code
|
||||||
* @throws DoubleRenderException
|
* @throws DoubleRenderException
|
||||||
*/
|
*/
|
||||||
#[\PHPUnit\Framework\Attributes\CodeCoverageIgnore]
|
protected function outputJSON(mixed $data, int $code): void
|
||||||
protected function outputJSON(mixed $data, int $code): void
|
{
|
||||||
{
|
JsonView::new()
|
||||||
JsonView::new()
|
->setOutput($data)
|
||||||
->setOutput($data)
|
->setStatusCode($code)
|
||||||
->setStatusCode($code)
|
->send();
|
||||||
->send();
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Redirect to the selected page
|
* Redirect to the selected page
|
||||||
*/
|
*/
|
||||||
#[\PHPUnit\Framework\Attributes\CodeCoverageIgnore]
|
protected function redirect(string $url, int $code): void
|
||||||
protected function redirect(string $url, int $code): void
|
{
|
||||||
{
|
HttpView::new()
|
||||||
HttpView::new()
|
->redirect($url, $code)
|
||||||
->redirect($url, $code)
|
->send();
|
||||||
->send();
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// End of BaseController.php
|
// End of BaseController.php
|
||||||
|
@ -214,8 +214,6 @@ final class Dispatcher extends RoutingBase
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the list of controllers in the default namespace
|
* Get the list of controllers in the default namespace
|
||||||
*
|
|
||||||
* @return array
|
|
||||||
*/
|
*/
|
||||||
public function getControllerList(): array
|
public function getControllerList(): array
|
||||||
{
|
{
|
||||||
|
@ -98,9 +98,7 @@ class UrlGenerator extends RoutingBase
|
|||||||
|
|
||||||
if ($defaultPath !== NULL)
|
if ($defaultPath !== NULL)
|
||||||
{
|
{
|
||||||
// @codeCoverageIgnoreStart
|
|
||||||
return $this->url("{$type}/{$defaultPath}");
|
return $this->url("{$type}/{$defaultPath}");
|
||||||
// @codeCoverageIgnoreEnd
|
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new InvalidArgumentException("Invalid default type: '{$type}'");
|
throw new InvalidArgumentException("Invalid default type: '{$type}'");
|
||||||
|
@ -25,10 +25,7 @@ class Json
|
|||||||
/**
|
/**
|
||||||
* Encode data in json format
|
* Encode data in json format
|
||||||
*
|
*
|
||||||
* @param mixed $data
|
|
||||||
* @param int $options
|
|
||||||
* @param int<1, max> $depth
|
* @param int<1, max> $depth
|
||||||
* @return string
|
|
||||||
*/
|
*/
|
||||||
public static function encode(mixed $data, int $options = 0, int $depth = 512): string
|
public static function encode(mixed $data, int $options = 0, int $depth = 512): string
|
||||||
{
|
{
|
||||||
@ -57,11 +54,7 @@ class Json
|
|||||||
/**
|
/**
|
||||||
* Decode data from json
|
* Decode data from json
|
||||||
*
|
*
|
||||||
* @param string|null $json
|
|
||||||
* @param bool $assoc
|
|
||||||
* @param int<1, max> $depth
|
* @param int<1, max> $depth
|
||||||
* @param int $options
|
|
||||||
* @return mixed
|
|
||||||
*/
|
*/
|
||||||
public static function decode(?string $json, bool $assoc = TRUE, int $depth = 512, int $options = 0): mixed
|
public static function decode(?string $json, bool $assoc = TRUE, int $depth = 512, int $options = 0): mixed
|
||||||
{
|
{
|
||||||
@ -81,11 +74,7 @@ class Json
|
|||||||
/**
|
/**
|
||||||
* Decode json data loaded from the passed filename
|
* Decode json data loaded from the passed filename
|
||||||
*
|
*
|
||||||
* @param string $filename
|
|
||||||
* @param bool $assoc
|
|
||||||
* @param int<1, max> $depth
|
* @param int<1, max> $depth
|
||||||
* @param int $options
|
|
||||||
* @return mixed
|
|
||||||
*/
|
*/
|
||||||
public static function decodeFile(string $filename, bool $assoc = TRUE, int $depth = 512, int $options = 0): mixed
|
public static function decodeFile(string $filename, bool $assoc = TRUE, int $depth = 512, int $options = 0): mixed
|
||||||
{
|
{
|
||||||
|
@ -2138,7 +2138,7 @@ abstract class Stringy implements Countable, IteratorAggregate, ArrayAccess
|
|||||||
return mb_regex_encoding(...$args);
|
return mb_regex_encoding(...$args);
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function supportsEncoding(): bool|null
|
protected function supportsEncoding(): bool|null
|
||||||
|
@ -15,8 +15,7 @@
|
|||||||
namespace Aviat\Ion\Tests;
|
namespace Aviat\Ion\Tests;
|
||||||
|
|
||||||
use Aviat\Ion\Config;
|
use Aviat\Ion\Config;
|
||||||
use PHPUnit\Framework\Attributes\DataProvider;
|
use PHPUnit\Framework\Attributes\{DataProvider, IgnoreMethodForCodeCoverage};
|
||||||
use PHPUnit\Framework\Attributes\IgnoreMethodForCodeCoverage;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @internal
|
* @internal
|
||||||
|
@ -15,11 +15,8 @@
|
|||||||
namespace Aviat\Ion\Tests\Type;
|
namespace Aviat\Ion\Tests\Type;
|
||||||
|
|
||||||
use Aviat\Ion\Tests\IonTestCase;
|
use Aviat\Ion\Tests\IonTestCase;
|
||||||
use Aviat\Ion\Type\StringType;
|
use Aviat\Ion\Type\{StringType, Stringy};
|
||||||
use Aviat\Ion\Type\Stringy;
|
use PHPUnit\Framework\Attributes\{DataProvider, IgnoreClassForCodeCoverage, Test};
|
||||||
use PHPUnit\Framework\Attributes\DataProvider;
|
|
||||||
use PHPUnit\Framework\Attributes\IgnoreClassForCodeCoverage;
|
|
||||||
use PHPUnit\Framework\Attributes\Test;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @internal
|
* @internal
|
||||||
|
@ -14,8 +14,7 @@
|
|||||||
|
|
||||||
namespace Aviat\Ion\Tests;
|
namespace Aviat\Ion\Tests;
|
||||||
|
|
||||||
use PHPUnit\Framework\Attributes\IgnoreClassForCodeCoverage;
|
use PHPUnit\Framework\Attributes\{IgnoreClassForCodeCoverage, Test};
|
||||||
use PHPUnit\Framework\Attributes\Test;
|
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
|
|
||||||
use function Aviat\Ion\_dir;
|
use function Aviat\Ion\_dir;
|
||||||
|
Loading…
Reference in New Issue
Block a user