HummingBirdAnimeClient/src/AnimeClient/Controller/Settings.php

157 lines
4.0 KiB
PHP

<?php declare(strict_types=1);
/**
* Hummingbird Anime List Client
*
* An API client for Kitsu to manage anime and manga watch lists
*
* PHP version 7.4+
*
* @package HummingbirdAnimeClient
* @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2015 - 2021 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @version 5.2
* @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient
*/
namespace Aviat\AnimeClient\Controller;
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\Di\ContainerInterface;
use Aviat\Ion\Di\Exception\ContainerException;
use Aviat\Ion\Di\Exception\NotFoundException;
/**
* Controller for user settings
*/
final class Settings extends BaseController {
/**
* @var AnilistModel
*/
private AnilistModel $anilistModel;
/**
* @var SettingsModel
*/
private SettingsModel $settingsModel;
/**
* Settings constructor.
*
* @param ContainerInterface $container
* @throws ContainerException
* @throws NotFoundException
*/
public function __construct(ContainerInterface $container)
{
parent::__construct($container);
$this->anilistModel = $container->get('anilist-model');
$this->settingsModel = $container->get('settings-model');
// This is a rare controller where every route is private
$this->checkAuth();
}
/**
* Show the user settings, if logged in
*/
public function index(): void
{
$auth = $this->container->get('auth');
$form = $this->settingsModel->getSettingsForm();
$hasAnilistLogin = $this->config->has(['anilist', 'access_token']);
$this->outputHTML('settings/settings', [
'anilistModel' => $this->anilistModel,
'auth' => $auth,
'form' => $form,
'hasAnilistLogin' => $hasAnilistLogin,
'config' => $this->config,
'title' => $this->config->get('whose_list') . "'s Settings",
]);
}
/**
* Attempt to save the user's settings
*
* @throws RouteNotFound
*/
public function update(): void
{
$post = $this->request->getParsedBody();
unset($post['settings-tabs']);
$saved = $this->settingsModel->saveSettingsFile($post);
$saved
? $this->setFlashMessage('Saved config settings.', 'success')
: $this->setFlashMessage('Failed to save config file.', 'error');
$this->redirect($this->url->generate('settings'), 303);
}
/**
* Redirect to Anilist to start Oauth flow
*/
public function anilistRedirect(): void
{
$query = http_build_query([
'client_id' => $this->config->get(['anilist', 'client_id']),
'redirect_uri' => $this->urlGenerator->url('/anilist-oauth'),
'response_type' => 'code',
]);
$redirectUrl = "https://anilist.co/api/v2/oauth/authorize?{$query}";
$this->redirect($redirectUrl, 303);
}
/**
* Oauth callback for Anilist API
*/
public function anilistCallback(): void
{
$query = $this->request->getQueryParams();
$authCode = $query['code'];
$uri = $this->urlGenerator->url('/anilist-oauth');
$authData = $this->anilistModel->authenticate($authCode, $uri);
$settings = $this->settingsModel->getSettings();
if (array_key_exists('error', $authData))
{
$this->errorPage(400, 'Error Linking Account', $authData['hint']);
return;
}
// Update the override config file
$anilistSettings = [
'access_token' => $authData['access_token'],
'access_token_expires' => (time() - 10) + $authData['expires_in'],
'refresh_token' => $authData['refresh_token'],
];
$newSettings = $settings;
$newSettings['anilist'] = array_merge($settings['anilist'], $anilistSettings);
foreach ($newSettings['config'] as $key => $value)
{
$newSettings[$key] = $value;
}
unset($newSettings['config']);
$saved = $this->settingsModel->saveSettingsFile($newSettings);
$saved
? $this->setFlashMessage('Linked Anilist Account', 'success')
: $this->setFlashMessage('Error Linking Anilist Account', 'error');
$this->redirect($this->url->generate('settings'), 303);
}
}