Add Routing attributes to controllers for a potential future refactoring
timw4mail/HummingBirdAnimeClient/pipeline/head This commit looks good Details

This commit is contained in:
Timothy Warren 2023-03-16 13:04:55 -04:00
parent 581fad9ccc
commit 8dcffe9cd2
11 changed files with 172 additions and 48 deletions

View File

@ -340,7 +340,7 @@ class Controller
* Output a template to HTML, using the provided data
*
* @codeCoverageIgnore
*@throws InvalidArgumentException
* @throws InvalidArgumentException
*/
protected function outputHTML(string $template, array $data = [], ?HtmlView $view = NULL, int $code = 200): void
{
@ -362,7 +362,7 @@ class Controller
*/
protected function outputJSON(mixed $data, int $code): void
{
(new JsonView())
JsonView::new()
->setOutput($data)
->setStatusCode($code)
->send();
@ -375,13 +375,9 @@ class Controller
*/
protected function redirect(string $url, int $code): void
{
try
{
(new HttpView())->redirect($url, $code)->send();
}
catch (\Throwable)
{
}
HttpView::new()
->redirect($url, $code)
->send();
}
}

View File

@ -21,6 +21,8 @@ use Aviat\AnimeClient\API\Mapping\AnimeWatchingStatus;
use Aviat\AnimeClient\Controller as BaseController;
use Aviat\AnimeClient\Model\Anime as AnimeModel;
use Aviat\AnimeClient\Types\FormItem;
use Aviat\Ion\Attribute\Controller;
use Aviat\Ion\Attribute\Route;
use Aviat\Ion\Di\ContainerInterface;
use Aviat\Ion\Di\Exception\{ContainerException, NotFoundException};
use Aviat\Ion\Json;
@ -32,6 +34,7 @@ use TypeError;
/**
* Controller for Anime-related pages
*/
#[Controller('anime')]
final class Anime extends BaseController
{
/**
@ -66,6 +69,7 @@ final class Anime extends BaseController
* @throws InvalidArgumentException
* @throws Throwable
*/
#[Route('anime.list', '/anime/{status}{/view}')]
public function index(int|string $status = KitsuWatchingStatus::WATCHING, ?string $view = NULL): void
{
if ( ! in_array($status, [
@ -111,6 +115,7 @@ final class Anime extends BaseController
* @throws RouteNotFound
* @throws Throwable
*/
#[Route('anime.add.get', '/anime/add')]
public function addForm(): void
{
$this->checkAuth();
@ -131,6 +136,7 @@ final class Anime extends BaseController
*
* @throws Throwable
*/
#[Route('anime.add.post', '/anime/add', Route::POST)]
public function add(): void
{
$this->checkAuth();
@ -165,6 +171,7 @@ final class Anime extends BaseController
/**
* Form to edit details about a series
*/
#[Route('anime.edit', '/anime/edit/{id}/{status}')]
public function edit(string $id, string $status = 'all'): void
{
$this->checkAuth();
@ -188,6 +195,7 @@ final class Anime extends BaseController
/**
* Search for anime
*/
#[Route('anime.search', '/anime/search')]
public function search(): void
{
$queryParams = $this->request->getQueryParams();
@ -200,6 +208,7 @@ final class Anime extends BaseController
*
* @throws Throwable
*/
#[Route('anime.update.post', '/anime/update_form', Route::POST)]
public function formUpdate(): void
{
$this->checkAuth();
@ -230,18 +239,14 @@ final class Anime extends BaseController
*
* @throws Throwable
*/
#[Route('anime.increment', '/anime/increment', Route::POST)]
public function increment(): void
{
$this->checkAuth();
if (str_contains($this->request->getHeader('content-type')[0], 'application/json'))
{
$data = Json::decode((string) $this->request->getBody());
}
else
{
$data = (array) $this->request->getParsedBody();
}
$data = str_contains($this->request->getHeader('content-type')[0], 'application/json')
? Json::decode((string) $this->request->getBody())
: (array) $this->request->getParsedBody();
if (empty($data))
{
@ -261,6 +266,7 @@ final class Anime extends BaseController
*
* @throws Throwable
*/
#[Route('anime.delete', '/anime/delete', Route::POST)]
public function delete(): void
{
$this->checkAuth();
@ -286,6 +292,7 @@ final class Anime extends BaseController
*
* @throws InvalidArgumentException
*/
#[Route('anime.details', '/anime/details/{id}')]
public function details(string $id): void
{
try
@ -324,6 +331,7 @@ final class Anime extends BaseController
}
}
#[Route('anime.random', '/anime/details/random')]
public function random(): void
{
try

View File

@ -20,8 +20,11 @@ use Aviat\AnimeClient\Model\{
Anime as AnimeModel,
AnimeCollection as AnimeCollectionModel
};
use Aviat\Ion\Attribute\Controller;
use Aviat\Ion\Attribute\Route;
use Aviat\Ion\Di\ContainerInterface;
use Aviat\Ion\Di\Exception\{ContainerException, NotFoundException};
use Aviat\Ion\Json;
use Aviat\Ion\Exception\DoubleRenderException;
use InvalidArgumentException;
@ -29,6 +32,7 @@ use InvalidArgumentException;
/**
* Controller for Anime collection pages
*/
#[Controller('anime.collection')]
final class AnimeCollection extends BaseController
{
/**
@ -61,6 +65,8 @@ final class AnimeCollection extends BaseController
]);
}
#[Route('anime.collection.redirect', '/anime-collection')]
#[Route('anime.collection.redirect2', '/anime-collection/')]
public function index(): void
{
$this->redirect('/anime-collection/view', 303);
@ -71,6 +77,7 @@ final class AnimeCollection extends BaseController
*
* @throws DoubleRenderException
*/
#[Route('anime.collection.search', '/anime-collection/search')]
public function search(): void
{
$queryParams = $this->request->getQueryParams();
@ -85,6 +92,7 @@ final class AnimeCollection extends BaseController
* @throws InvalidArgumentException
* @throws NotFoundException
*/
#[Route('anime.collection.view', '/anime-collection/view{/view}')]
public function view(?string $view = ''): void
{
$viewMap = [
@ -112,7 +120,9 @@ final class AnimeCollection extends BaseController
* @throws NotFoundException
* @throws RouteNotFound
*/
public function form($id = NULL): void
#[Route('anime.collection.add.get', '/anime-collection/add')]
#[Route('anime.collection.edit.get', '/anime-collection/edit/{id}')]
public function form(?int $id = NULL): void
{
$this->checkAuth();
@ -140,6 +150,7 @@ final class AnimeCollection extends BaseController
* @throws InvalidArgumentException
* @throws NotFoundException
*/
#[Route('anime.collection.edit.post', '/anime-collection/edit', Route::POST)]
public function edit(): void
{
$this->checkAuth();
@ -153,6 +164,7 @@ final class AnimeCollection extends BaseController
* @throws InvalidArgumentException
* @throws NotFoundException
*/
#[Route('anime.collection.add.post', '/anime-collection/add', Route::POST)]
public function add(): void
{
$this->checkAuth();
@ -202,6 +214,7 @@ final class AnimeCollection extends BaseController
/**
* Remove a collection item
*/
#[Route('anime.collection.delete', '/anime-collection/delete', Route::POST)]
public function delete(): void
{
$this->checkAuth();

View File

@ -18,12 +18,15 @@ use Aviat\AnimeClient\API\Kitsu\Model;
use Aviat\AnimeClient\API\Kitsu\Transformer\CharacterTransformer;
use Aviat\AnimeClient\Controller as BaseController;
use Aviat\Ion\Attribute\Controller;
use Aviat\Ion\Attribute\Route;
use Aviat\Ion\Di\ContainerInterface;
use Aviat\Ion\Di\Exception\{ContainerException, NotFoundException};
/**
* Controller for character description pages
*/
#[Controller]
final class Character extends BaseController
{
private Model $model;
@ -43,6 +46,7 @@ final class Character extends BaseController
/**
* Show information about a character
*/
#[Route('character', '/character/{slug}')]
public function index(string $slug): void
{
$rawData = $this->model->getCharacter($slug);

View File

@ -14,6 +14,8 @@
namespace Aviat\AnimeClient\Controller;
use Aviat\Ion\Attribute\Controller;
use Aviat\Ion\Attribute\Route;
use Aviat\AnimeClient\{Controller as BaseController, Model};
use Aviat\Ion\Di\ContainerInterface;
use Aviat\Ion\Di\Exception\{ContainerException, NotFoundException};
@ -21,6 +23,7 @@ use Aviat\Ion\Di\Exception\{ContainerException, NotFoundException};
/**
* Controller for Anime-related pages
*/
#[Controller]
final class History extends BaseController
{
/**
@ -47,6 +50,7 @@ final class History extends BaseController
$this->mangaModel = $container->get('manga-model');
}
#[Route('history', '/history/{type}')]
public function index(string $type = 'anime'): void
{
if (method_exists($this, $type))

View File

@ -15,6 +15,8 @@
namespace Aviat\AnimeClient\Controller;
use Aviat\AnimeClient\Controller as BaseController;
use Aviat\Ion\Attribute\Controller;
use Aviat\Ion\Attribute\Route;
use Throwable;
use function Amp\Promise\wait;
use function Aviat\AnimeClient\{createPlaceholderImage, getResponse};
@ -25,6 +27,7 @@ use function in_array;
/**
* Controller for handling routes that don't fit elsewhere
*/
#[Controller]
final class Images extends BaseController
{
/**
@ -35,6 +38,7 @@ final class Images extends BaseController
* @param bool $display Whether to output the image to the server
* @throws Throwable
*/
#[Route('image_proxy', '/public/images/{type}/{file}')]
public function cache(string $type, string $file, bool $display = TRUE): void
{
$currentUrl = (string) $this->request->getUri();

View File

@ -17,9 +17,11 @@ namespace Aviat\AnimeClient\Controller;
use Aura\Router\Exception\RouteNotFound;
use Aviat\AnimeClient\API\Kitsu\Transformer\MangaListTransformer;
use Aviat\AnimeClient\API\Mapping\MangaReadingStatus;
use Aviat\AnimeClient\Controller;
use Aviat\AnimeClient\Controller as BaseController;
use Aviat\AnimeClient\Model\Manga as MangaModel;
use Aviat\AnimeClient\Types\FormItem;
use Aviat\Ion\Attribute\Controller;
use Aviat\Ion\Attribute\Route;
use Aviat\Ion\Di\ContainerInterface;
use Aviat\Ion\Di\Exception\{ContainerException, NotFoundException};
use Aviat\Ion\Json;
@ -30,7 +32,8 @@ use Throwable;
/**
* Controller for manga list
*/
final class Manga extends Controller
#[Controller('manga')]
final class Manga extends BaseController
{
/**
* The manga model
@ -57,10 +60,8 @@ final class Manga extends Controller
/**
* Get a section of the manga list
*
* @param string $view
*@throws InvalidArgumentException
*/
#[Route('manga.list', '/list/{status}{/view}')]
public function index(string $status = 'all', ?string $view = ''): void
{
if ( ! in_array($status, [
@ -98,13 +99,9 @@ final class Manga extends Controller
}
/**
* Form to add an manga
*
* @throws ContainerException
* @throws InvalidArgumentException
* @throws NotFoundException
* @throws RouteNotFound
* Form to add a manga
*/
#[Route('manga.add.get', '/manga/add')]
public function addForm(): void
{
$this->checkAuth();
@ -123,10 +120,9 @@ final class Manga extends Controller
}
/**
* Add an manga to the list
*
* @throws Throwable
* Add a manga to the list
*/
#[Route('manage.add.post', '/manga/add', Route::POST)]
public function add(): void
{
$this->checkAuth();
@ -159,12 +155,8 @@ final class Manga extends Controller
/**
* Show the manga edit form
*
* @throws ContainerException
* @throws InvalidArgumentException
* @throws NotFoundException
* @throws RouteNotFound
*/
#[Route('manga.edit', '/manga/edit/{id}/{status}')]
public function edit(string $id, string $status = 'All'): void
{
$this->checkAuth();
@ -189,6 +181,7 @@ final class Manga extends Controller
/**
* Search for a manga to add to the list
*/
#[Route('manga.search', '/manga/search')]
public function search(): void
{
$queryParams = $this->request->getQueryParams();
@ -198,9 +191,8 @@ final class Manga extends Controller
/**
* Update an manga item via a form submission
*
* @throws Throwable
*/
#[Route('manga.update.post', '/manga/update', Route::POST)]
public function formUpdate(): void
{
$this->checkAuth();
@ -228,8 +220,8 @@ final class Manga extends Controller
/**
* Increment the progress of a manga item
* @throws Throwable
*/
#[Route('manga.increment', '/manga/increment', Route::POST)]
public function increment(): void
{
$this->checkAuth();
@ -253,9 +245,8 @@ final class Manga extends Controller
/**
* Remove an manga from the list
*
* @throws Throwable
*/
#[Route('manga.delete', '/manga/delete', Route::POST)]
public function delete(): void
{
$this->checkAuth();
@ -278,10 +269,8 @@ final class Manga extends Controller
/**
* View details of an manga
*
* @throws InvalidArgumentException
* @throws Throwable
*/
#[Route('manga.details', '/manga/details/{id}')]
public function details(string $id): void
{
$data = $this->model->getManga($id);
@ -309,10 +298,8 @@ final class Manga extends Controller
/**
* View details of a random manga
*
* @throws InvalidArgumentException
* @throws Throwable
*/
#[Route('manga.random', '/manga/details/random')]
public function random(): void
{
$data = $this->model->getRandomManga();

View File

@ -14,19 +14,44 @@
namespace Aviat\AnimeClient\Controller;
use Aviat\AnimeClient\API\Kitsu\Model;
use Aviat\AnimeClient\API\Kitsu\Transformer\CharacterTransformer;
use Aviat\AnimeClient\API\Kitsu\Transformer\PersonTransformer;
use Aviat\AnimeClient\Controller as BaseController;
use Aviat\AnimeClient\Enum\EventType;
use Aviat\Ion\Attribute\DefaultController;
use Aviat\Ion\Attribute\Route;
use Aviat\Ion\Di\ContainerInterface;
use Aviat\Ion\Event;
use Aviat\Ion\View\HtmlView;
/**
* Controller for handling routes that don't fit elsewhere
*/
#[DefaultController]
final class Misc extends BaseController
{
private Model $model;
public function __construct(ContainerInterface $container)
{
parent::__construct($container);
$this->model = $container->get('kitsu-model');
}
/**
* Redirect to the default controller/url from an empty path
*/
#[Route('index_redirect', '/')]
public function index(): void
{
parent::redirectToDefaultRoute();
}
/**
* Purges the API cache
*/
#[Route('cache_purge', '/cache_purge')]
public function clearCache(): void
{
$this->checkAuth();
@ -41,6 +66,7 @@ final class Misc extends BaseController
/**
* Show the login form
*/
#[Route('login', '/login')]
public function login(string $status = ''): void
{
$message = '';
@ -64,6 +90,7 @@ final class Misc extends BaseController
/**
* Attempt login authentication
*/
#[Route('login.post', '/login', Route::POST)]
public function loginAction(): void
{
$post = (array) $this->request->getParsedBody();
@ -86,6 +113,7 @@ final class Misc extends BaseController
/**
* Deauthorize the current user
*/
#[Route('logout', '/logout')]
public function logout(): void
{
$this->auth->logout();
@ -96,8 +124,72 @@ final class Misc extends BaseController
/**
* Check if the current user is logged in
*/
#[Route('heartbeat', '/heartbeat')]
public function heartbeat(): void
{
$this->outputJSON(['hasAuth' => $this->auth->isAuthenticated()], 200);
}
/**
* Show information about a character
*/
#[Route('character', '/character/{slug}')]
public function character(string $slug): void
{
$rawData = $this->model->getCharacter($slug);
if (( ! array_key_exists('data', $rawData)) || empty($rawData['data']))
{
$this->notFound(
$this->formatTitle(
'Characters',
'Character not found'
),
'Character Not Found'
);
return;
}
$data = (new CharacterTransformer())->transform($rawData)->toArray();
$this->outputHTML('character/details', [
'title' => $this->formatTitle(
'Characters',
$data['name']
),
'data' => $data,
]);
}
/**
* Show information about a person
*/
#[Route('person', '/people/{slug}')]
public function person(string $slug): void
{
$rawData = $this->model->getPerson($slug);
$data = (new PersonTransformer())->transform($rawData)->toArray();
if (( ! array_key_exists('data', $rawData)) || empty($rawData['data']))
{
$this->notFound(
$this->formatTitle(
'People',
'Person not found'
),
'Person Not Found'
);
return;
}
$this->outputHTML('person/details', [
'title' => $this->formatTitle(
'People',
$data['name']
),
'data' => $data,
]);
}
}

View File

@ -18,12 +18,15 @@ use Aviat\AnimeClient\API\Kitsu\Model;
use Aviat\AnimeClient\API\Kitsu\Transformer\PersonTransformer;
use Aviat\AnimeClient\Controller as BaseController;
use Aviat\Ion\Attribute\Controller;
use Aviat\Ion\Attribute\Route;
use Aviat\Ion\Di\ContainerInterface;
use Aviat\Ion\Di\Exception\{ContainerException, NotFoundException};
/**
* Controller for People pages
*/
#[Controller]
final class People extends BaseController
{
private Model $model;
@ -43,6 +46,7 @@ final class People extends BaseController
/**
* Show information about a person
*/
#[Route('person', '/people/{slug}')]
public function index(string $slug): void
{
$rawData = $this->model->getPerson($slug);

View File

@ -18,12 +18,15 @@ use Aura\Router\Exception\RouteNotFound;
use Aviat\AnimeClient\API\Anilist\Model as AnilistModel;
use Aviat\AnimeClient\Controller as BaseController;
use Aviat\AnimeClient\Model\Settings as SettingsModel;
use Aviat\Ion\Attribute\Controller;
use Aviat\Ion\Attribute\Route;
use Aviat\Ion\Di\ContainerInterface;
use Aviat\Ion\Di\Exception\{ContainerException, NotFoundException};
/**
* Controller for user settings
*/
#[Controller]
final class Settings extends BaseController
{
private AnilistModel $anilistModel;
@ -49,6 +52,7 @@ final class Settings extends BaseController
/**
* Show the user settings, if logged in
*/
#[Route('settings', '/settings')]
public function index(): void
{
$auth = $this->container->get('auth');
@ -71,6 +75,7 @@ final class Settings extends BaseController
*
* @throws RouteNotFound
*/
#[Route('settings-post', '/settings/update', Route::POST)]
public function update(): void
{
$post = (array) $this->request->getParsedBody();
@ -91,6 +96,7 @@ final class Settings extends BaseController
/**
* Redirect to Anilist to start Oauth flow
*/
#[Route('anilist-redirect', '/anilist-redirect')]
public function anilistRedirect(): void
{
$query = http_build_query([
@ -107,6 +113,7 @@ final class Settings extends BaseController
/**
* Oauth callback for Anilist API
*/
#[Route('anilist-callback', '/anilist-oauth')]
public function anilistCallback(): void
{
$query = $this->request->getQueryParams();

View File

@ -18,12 +18,15 @@ use Aviat\AnimeClient\API\Kitsu\Model;
use Aviat\AnimeClient\API\Kitsu\Transformer\UserTransformer;
use Aviat\AnimeClient\Controller as BaseController;
use Aviat\Ion\Attribute\Controller;
use Aviat\Ion\Attribute\Route;
use Aviat\Ion\Di\ContainerInterface;
use Aviat\Ion\Di\Exception\{ContainerException, NotFoundException};
/**
* Controller for handling routes that don't fit elsewhere
*/
#[Controller]
final class User extends BaseController
{
private Model $kitsuModel;
@ -44,6 +47,7 @@ final class User extends BaseController
/**
* Show the user profile page for the configured user
*/
#[Route('default_user_info', '/me')]
public function me(): void
{
$this->about('me');
@ -52,6 +56,7 @@ final class User extends BaseController
/**
* Show the user profile page
*/
#[Route('user_info', '/user/{username}')]
public function about(string $username): void
{
$isMainUser = $username === 'me';