Settings control panel saves to admin-override.toml in the app/config directory, resolves #7

This commit is contained in:
Timothy Warren 2018-10-08 15:45:46 -04:00
parent b625f22d6a
commit 88b68b847c
9 changed files with 142 additions and 37 deletions

View File

@ -1,5 +1,11 @@
# Changelog # Changelog
## Version 4.1
* Removed MAL integration, added Anilist Integration
* Now uses WebP cache images when the browser supports it
* Replaces JS minifier with pre-minified scripts (Removes the need for one caching folder, too)
* Updated console command to sync Kitsu and Anilist data
## Version 4 ## Version 4
* Updated to use Kitsu API after discontinuation of Hummingbird * Updated to use Kitsu API after discontinuation of Hummingbird
* Added streaming links to list entries from the Kitsu API * Added streaming links to list entries from the Kitsu API

View File

@ -216,8 +216,8 @@ return [
'verb' => 'get', 'verb' => 'get',
], ],
'settings-post' => [ 'settings-post' => [
'path' => '/settings', 'path' => '/settings-save',
'action' => 'settings', 'action' => 'settings_post',
'controller' => DEFAULT_CONTROLLER, 'controller' => DEFAULT_CONTROLLER,
'verb' => 'post', 'verb' => 'post',
], ],

View File

@ -6,6 +6,7 @@ if ( ! $auth->isAuthenticated())
} }
$sectionMapping = [ $sectionMapping = [
'anilist' => 'Anilist API Integration',
'config' => 'General Settings', 'config' => 'General Settings',
'cache' => 'Caching', 'cache' => 'Caching',
'database' => 'Collection Database Settings', 'database' => 'Collection Database Settings',
@ -15,9 +16,7 @@ $hiddenFields = [];
$nestedPrefix = 'config'; $nestedPrefix = 'config';
?> ?>
<pre><?= print_r($_POST, TRUE) ?></pre> <form action="<?= $url->generate('settings-post') ?>" method="POST">
<form action="<?= $_SERVER['REQUEST_URI'] ?>" method="POST">
<main class='form'> <main class='form'>
<button type="submit">Save Changes</button> <button type="submit">Save Changes</button>
<br /> <br />

View File

@ -49,7 +49,13 @@ $baseConfig = require $APPCONF_DIR . '/base_config.php';
$di = require $APP_DIR . '/bootstrap.php'; $di = require $APP_DIR . '/bootstrap.php';
$config = loadToml($CONF_DIR); $config = loadToml($CONF_DIR);
$configArray = array_merge($baseConfig, $config);
$overrideFile = $CONF_DIR . '/admin-override.toml';
$overrideConfig = file_exists($overrideFile)
? loadTomlFile($overrideFile)
: [];
$configArray = array_merge($baseConfig, $config, $overrideConfig);
$checkedConfig = (new ConfigType($configArray))->toArray(); $checkedConfig = (new ConfigType($configArray))->toArray();
$container = $di($checkedConfig); $container = $di($checkedConfig);

View File

@ -33,6 +33,11 @@ function loadToml(string $path): array
foreach ($files as $file) foreach ($files as $file)
{ {
$key = str_replace('.toml', '', basename($file)); $key = str_replace('.toml', '', basename($file));
if ($key === 'admin-override')
{
continue;
}
$config = Toml::parseFile($file); $config = Toml::parseFile($file);
if ($key === 'config') if ($key === 'config')
@ -71,6 +76,17 @@ function loadTomlByFile(string $path): array
return $output; return $output;
} }
/**
* Load config from one specific TOML file
*
* @param string $filename
* @return array
*/
function loadTomlFile(string $filename): array
{
return Toml::parseFile($filename);
}
/** /**
* Is the array sequential, not associative? * Is the array sequential, not associative?
* *

View File

@ -39,9 +39,6 @@ final class Index extends BaseController {
/** /**
* Purges the API cache * Purges the API cache
* *
* @throws \Aviat\Ion\Di\ContainerException
* @throws \Aviat\Ion\Di\NotFoundException
* @throws \InvalidArgumentException
* @return void * @return void
*/ */
public function clearCache() public function clearCache()
@ -56,9 +53,6 @@ final class Index extends BaseController {
* Show the login form * Show the login form
* *
* @param string $status * @param string $status
* @throws \Aviat\Ion\Di\ContainerException
* @throws \Aviat\Ion\Di\NotFoundException
* @throws \InvalidArgumentException
* @return void * @return void
*/ */
public function login(string $status = '') public function login(string $status = '')
@ -109,10 +103,6 @@ final class Index extends BaseController {
/** /**
* Attempt login authentication * Attempt login authentication
* *
* @throws \Aviat\Ion\Di\ContainerException
* @throws \Aviat\Ion\Di\NotFoundException
* @throws \Aura\Router\Exception\RouteNotFound
* @throws \InvalidArgumentException
* @return void * @return void
*/ */
public function loginAction() public function loginAction()
@ -133,9 +123,6 @@ final class Index extends BaseController {
/** /**
* Deauthorize the current user * Deauthorize the current user
* *
* @throws \Aviat\Ion\Di\ContainerException
* @throws \Aviat\Ion\Di\NotFoundException
* @throws \InvalidArgumentException
* @return void * @return void
*/ */
public function logout() public function logout()
@ -149,9 +136,6 @@ final class Index extends BaseController {
/** /**
* Show the user profile page * Show the user profile page
* *
* @throws \Aviat\Ion\Di\ContainerException
* @throws \Aviat\Ion\Di\NotFoundException
* @throws \InvalidArgumentException
* @return void * @return void
*/ */
public function me() public function me()
@ -188,14 +172,28 @@ final class Index extends BaseController {
]); ]);
} }
/**
* Attempt to save the user's settings
*
* @throws \Aura\Router\Exception\RouteNotFound
*/
public function settings_post() public function settings_post()
{ {
$auth = $this->container->get('auth'); $post = $this->request->getParsedBody();
$this->outputHTML('settings', [
'auth' => $auth, // dump($post);
'config' => $this->config, $saved = $this->settingsModel->saveSettingsFile($post);
'title' => $this->config->get('whose_list') . "'s Settings",
]); if ($saved)
{
$this->setFlashMessage('Saved config settings.', 'success');
}
else
{
$this->setFlashMessage('Failed to save config file.', 'error');
}
$this->redirect($this->url->generate('settings'), 303);
} }
/** /**
@ -250,7 +248,7 @@ final class Index extends BaseController {
$baseSavePath = $this->config->get('img_cache_path'); $baseSavePath = $this->config->get('img_cache_path');
$filePrefix = "{$baseSavePath}/{$type}/{$id}"; $filePrefix = "{$baseSavePath}/{$type}/{$id}";
[$origWidth, $origHeight] = getimagesizefromstring($data); [$origWidth] = getimagesizefromstring($data);
$gdImg = imagecreatefromstring($data); $gdImg = imagecreatefromstring($data);
$resizedImg = imagescale($gdImg, $width ?? $origWidth); $resizedImg = imagescale($gdImg, $width ?? $origWidth);

View File

@ -83,7 +83,7 @@ final class FormGenerator {
$params['attribs']['label'] = $form['description']; $params['attribs']['label'] = $form['description'];
$params['attribs']['value'] = TRUE; $params['attribs']['value'] = TRUE;
$params['attribs']['value_unchecked'] = '0'; */ $params['attribs']['value_unchecked'] = '0'; */
$params['type'] = 'radio'; $params['type'] = 'radio';
$params['options'] = [ $params['options'] = [
'1' => 'Yes', '1' => 'Yes',

View File

@ -16,6 +16,9 @@
namespace Aviat\AnimeClient\Model; namespace Aviat\AnimeClient\Model;
use function Aviat\AnimeClient\arrayToToml;
use function Aviat\Ion\_dir;
use Aviat\AnimeClient\Types\{Config, UndefinedPropertyException}; use Aviat\AnimeClient\Types\{Config, UndefinedPropertyException};
use Aviat\Ion\ConfigInterface; use Aviat\Ion\ConfigInterface;
@ -36,7 +39,12 @@ final class Settings {
*/ */
private const SETTINGS_MAP = [ private const SETTINGS_MAP = [
'anilist' => [ 'anilist' => [
'enabled' => [
'type' => 'boolean',
'title' => 'Enable Anilist Integration',
'default' => FALSE,
'description' => 'Enable syncing data between Kitsu and Anilist. Requires appropriate API keys to be set in config',
],
], ],
'config' => [ 'config' => [
'kitsu_username' => [ 'kitsu_username' => [
@ -265,22 +273,88 @@ final class Settings {
return $output; return $output;
} }
public function validateSettings(array $settings): bool public function validateSettings(array $settings)
{ {
$config = (new Config($settings))->toArray();
$looseConfig = [];
$keyedConfig = [];
// Convert 'boolean' values to true and false
// Also order keys so they can be saved properly
foreach ($config as $key => $val)
{
if (is_scalar($val))
{
if ($val === '1')
{
$looseConfig[$key] = TRUE;
}
elseif ($val === '0')
{
$looseConfig[$key] = FALSE;
}
else
{
$looseConfig[$key] = $val;
}
}
elseif (is_array($val))
{
foreach($val as $k => $v)
{
if ($v === '1')
{
$keyedConfig[$key][$k] = TRUE;
}
elseif($v === '0')
{
$keyedConfig[$key][$k] = FALSE;
}
else
{
$keyedConfig[$key][$k] = $v;
}
}
}
}
ksort($looseConfig);
ksort($keyedConfig);
$output = [];
foreach($looseConfig as $k => $v)
{
$output[$k] = $v;
}
foreach($keyedConfig as $k => $v)
{
$output[$k] = $v;
}
return $output;
}
public function saveSettingsFile(array $settings): bool
{
$settings = $settings['config'];
try try
{ {
new Config($settings); $settings = $this->validateSettings($settings);
} }
catch (UndefinedPropertyException $e) catch (UndefinedPropertyException $e)
{ {
return FALSE; return FALSE;
} }
return TRUE; $savePath = realpath(_dir(__DIR__, '..', '..', 'app', 'config'));
} $saveFile = _dir($savePath, 'admin-override.toml');
public function saveSettingsFile() $saved = file_put_contents($saveFile, arrayToToml($settings));
{
return $saved !== FALSE;
} }
} }

6
sw.js
View File

@ -61,6 +61,12 @@ self.addEventListener('activate', event => {
// Pull css, images, and javascript from cache // Pull css, images, and javascript from cache
self.addEventListener('fetch', event => { self.addEventListener('fetch', event => {
// Only cache things with a file extension,
// Ignore other requests
if ( ! event.request.url.includes('/public/')) {
return;
}
fromCache(event.request).then(cached => { fromCache(event.request).then(cached => {
if (cached !== undefined) { if (cached !== undefined) {
event.respondWith(cached); event.respondWith(cached);