Skip to content

Commit 4e2e442

Browse files
committed
Admin > Settings
1 parent 55064a0 commit 4e2e442

File tree

6 files changed

+135
-3
lines changed

6 files changed

+135
-3
lines changed

public/static/faqoff.css

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -308,4 +308,8 @@ i.color-error {
308308
#admin-contributors-list li {
309309
display: inline-block;
310310
margin-right: 0.5rem;
311-
}
311+
}
312+
#settings-contents {
313+
font-family: monospace;
314+
min-height: 30rem;
315+
}

src/FaqOff/Endpoints/Admin/Settings.php

Lines changed: 76 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,12 @@
33
namespace Soatok\FaqOff\Endpoints\Admin;
44

55
use Interop\Container\Exception\ContainerException;
6+
use ParagonIE\Ionizer\InvalidDataException;
67
use Psr\Http\Message\RequestInterface;
78
use Psr\Http\Message\ResponseInterface;
89
use Soatok\AnthroKit\Endpoint;
10+
use Soatok\FaqOff\Filter\AdminEditSettingsFilter;
11+
use Soatok\FaqOff\MessageOnceTrait;
912
use Twig\Error\LoaderError;
1013
use Twig\Error\RuntimeError;
1114
use Twig\Error\SyntaxError;
@@ -16,12 +19,70 @@
1619
*/
1720
class Settings extends Endpoint
1821
{
22+
use MessageOnceTrait;
23+
24+
private $editable = [
25+
'admins.json',
26+
'anthrokit.php',
27+
'settings.php'
28+
];
29+
30+
/**
31+
* @param RequestInterface $request
32+
* @param string $file
33+
* @return ResponseInterface
34+
* @throws ContainerException
35+
* @throws InvalidDataException
36+
* @throws LoaderError
37+
* @throws RuntimeError
38+
* @throws SyntaxError
39+
*/
40+
protected function editFile(
41+
RequestInterface $request,
42+
string $file
43+
): ResponseInterface {
44+
$filter = new AdminEditSettingsFilter();
45+
$post = $this->post($request, self::TYPE_FORM, $filter);
46+
if ($post) {
47+
$written = file_put_contents(
48+
APP_ROOT . '/local/' . $file,
49+
$post['contents']
50+
);
51+
if (!is_bool($written)) {
52+
$this->messageOnce('File saved successfully!', 'success');
53+
return $this->redirect(
54+
'/admin/settings/edit?' .
55+
http_build_query(['file' => $file])
56+
);
57+
} else {
58+
$contents = $post['contents'];
59+
$this->messageOnce('File could not be saved. Please check its permissions.', 'error');
60+
}
61+
} else {
62+
if (!file_exists(APP_ROOT . '/local/' . $file)) {
63+
touch(APP_ROOT . '/local/' . $file);
64+
}
65+
$contents = file_get_contents(APP_ROOT . '/local/' . $file);
66+
}
67+
if (empty($contents)) {
68+
$contents = '';
69+
}
70+
return $this->view(
71+
'admin/settings-edit.twig',
72+
[
73+
'file' => $file,
74+
'contents' => $contents
75+
]
76+
);
77+
}
78+
1979
/**
2080
* @param RequestInterface $request
2181
* @param ResponseInterface|null $response
2282
* @param array $routerParams
2383
* @return ResponseInterface
2484
* @throws ContainerException
85+
* @throws InvalidDataException
2586
* @throws LoaderError
2687
* @throws RuntimeError
2788
* @throws SyntaxError
@@ -31,6 +92,20 @@ public function __invoke(
3192
?ResponseInterface $response = null,
3293
array $routerParams = []
3394
): ResponseInterface {
34-
return $this->json($routerParams);
95+
$which = $routerParams['which'] ?? '';
96+
switch ($which) {
97+
case 'edit':
98+
$file = $_GET['file'] ?? '';
99+
if ($file) {
100+
if (in_array($file, $this->editable, true)) {
101+
return $this->editFile($request, $file);
102+
}
103+
}
104+
return $this->redirect('/admin/settings');
105+
case '':
106+
return $this->view('admin/settings-index.twig');
107+
default:
108+
return $this->redirect('/admin/settings');
109+
}
35110
}
36111
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?php
2+
declare(strict_types=1);
3+
namespace Soatok\FaqOff\Filter;
4+
5+
use ParagonIE\Ionizer\Filter\StringFilter;
6+
use ParagonIE\Ionizer\InputFilterContainer;
7+
8+
/**
9+
* Class AdminEditSettingsFilter
10+
* @package Soatok\FaqOff\Filter
11+
*/
12+
class AdminEditSettingsFilter extends InputFilterContainer
13+
{
14+
public function __construct()
15+
{
16+
$this->addFilter('contents', new StringFilter());
17+
}
18+
}

src/routes.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
$app->get('/collections', 'admin.collections');
3030
$app->any('/custom[/{action:[^/]+}]', 'admin.custom');
3131
$app->get('/invite-tree', 'admin.invitetree');
32-
$app->get('/settings[/{which:[^/]+}]', 'admin.settings');
32+
$app->any('/settings[/{which:[^/]+}]', 'admin.settings');
3333
$app->any('/theme/{action:[^/]+}/[{id:[0-9]+}]', 'admin.themes');
3434
$app->any('/theme[/{action:[^/]+}]', 'admin.themes');
3535
$app->get('/themes', 'admin.themes');

templates/admin/settings-edit.twig

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
{% extends "base.twig" %}
2+
3+
{% block main %}
4+
<h2>Edit File {{ file }}</h2>
5+
<form method="post">
6+
{{ anti_csrf() }}
7+
<label for="settings-contents">File contents:</label>
8+
<textarea class="form-control" id="settings-contents" name="contents">{{
9+
contents|e('html_attr')
10+
}}</textarea>
11+
<button class="btn btn-verydark form-control" type="submit">
12+
Update Settings
13+
</button>
14+
<a class="btn btn-default" href="/admin/settings">Return to Admin Settings</a>
15+
</form>
16+
{% endblock %}

templates/admin/settings-index.twig

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{% extends "base.twig" %}
2+
3+
{% block main %}
4+
<h1>Site Settings</h1>
5+
<ul>
6+
<li>
7+
<a href="/admin/settings/edit?file=admins%2ejson">Administrators</a> &mdash;
8+
Add/remove user accounts from the administrator roster.
9+
</li>
10+
<li>
11+
<a href="/admin/settings/edit?file=anthrokit%2ephp">AnthroKit Settings</a> &mdash;
12+
Configure AnthroKit (framework plugins used by this software).
13+
</li>
14+
<li>
15+
<a href="/admin/settings/edit?file=settings%2ephp">Global Site Settings</a> &mdash;
16+
Edit settings that affect the entire site at the framework level.
17+
</li>
18+
</ul>
19+
{% endblock %}

0 commit comments

Comments
 (0)