[mod] grundlegende Funktionalität
This commit is contained in:
parent
01108c5c01
commit
8a13a1758c
10 changed files with 425 additions and 0 deletions
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
/.geany
|
||||||
|
/build/
|
70
source/helpers.php
Normal file
70
source/helpers.php
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace rosavox\helpers;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
class cache_state
|
||||||
|
{
|
||||||
|
public static array $pool = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
function cache_get(string $key, \Closure $retrieve)
|
||||||
|
{
|
||||||
|
if (\array_key_exists($key, cache_state::$pool))
|
||||||
|
{
|
||||||
|
$value = cache_state::$pool[$key];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$value = ($retrieve)();
|
||||||
|
cache_state::$pool[$key] = $value;
|
||||||
|
}
|
||||||
|
return $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
function string_coin(string $template, array $arguments) : string
|
||||||
|
{
|
||||||
|
$result = $template;
|
||||||
|
foreach ($arguments as $key => $value)
|
||||||
|
{
|
||||||
|
$result = \str_replace(\sprintf('{{%s}}', $key), $value, $result);
|
||||||
|
}
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
function render(string $template_name, array $arguments) : string
|
||||||
|
{
|
||||||
|
return string_coin(
|
||||||
|
cache_get(
|
||||||
|
string_coin(
|
||||||
|
'template.{{name}}',
|
||||||
|
[
|
||||||
|
'name' => $template_name,
|
||||||
|
]
|
||||||
|
),
|
||||||
|
fn() => \file_get_contents(
|
||||||
|
string_coin(
|
||||||
|
'{{directory}}/templates/{{name}}.html.tpl',
|
||||||
|
[
|
||||||
|
'directory' => __DIR__,
|
||||||
|
'name' => $template_name,
|
||||||
|
]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
),
|
||||||
|
$arguments
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
102
source/index.html.php
Normal file
102
source/index.html.php
Normal file
|
@ -0,0 +1,102 @@
|
||||||
|
<?php
|
||||||
|
require_once(__DIR__ . '/helpers.php');
|
||||||
|
require_once(__DIR__ . '/logic.php');
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @todo deactivate
|
||||||
|
*/
|
||||||
|
\rosavox\logic\docs_add_examples();
|
||||||
|
$mode = ($_GET['mode'] ?? 'list');
|
||||||
|
$id_encoded = ($_GET['id'] ?? null);
|
||||||
|
$id = (($id_encoded === null) ? null : \rosavox\logic\docs_id_decode($id_encoded));
|
||||||
|
?>
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8"/>
|
||||||
|
<link rel="stylesheet" type="text/css" href="/style.css"/>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<?php
|
||||||
|
switch ($mode)
|
||||||
|
{
|
||||||
|
case 'list':
|
||||||
|
{
|
||||||
|
echo(
|
||||||
|
\rosavox\helpers\render(
|
||||||
|
'docs-list',
|
||||||
|
[
|
||||||
|
'entries' => \implode(
|
||||||
|
"\n",
|
||||||
|
\array_map(
|
||||||
|
fn ($entry) => \rosavox\helpers\render(
|
||||||
|
'docs-list-entry',
|
||||||
|
[
|
||||||
|
'link' => \rosavox\helpers\string_coin(
|
||||||
|
'?mode=edit&id={{id}}',
|
||||||
|
[
|
||||||
|
'id' => $entry['id'],
|
||||||
|
]
|
||||||
|
),
|
||||||
|
'text' => $entry['doc']['title'],
|
||||||
|
]
|
||||||
|
),
|
||||||
|
\rosavox\logic\docs_list()
|
||||||
|
)
|
||||||
|
),
|
||||||
|
'link_new' => '?mode=make',
|
||||||
|
]
|
||||||
|
)
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'make':
|
||||||
|
{
|
||||||
|
echo(
|
||||||
|
\rosavox\helpers\render(
|
||||||
|
'docs-edit',
|
||||||
|
[
|
||||||
|
'id' => '',
|
||||||
|
'title' => '',
|
||||||
|
'authors' => '',
|
||||||
|
'content' => '',
|
||||||
|
'reasoning' => '',
|
||||||
|
'link_back' => '?mode=list',
|
||||||
|
]
|
||||||
|
)
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'edit':
|
||||||
|
{
|
||||||
|
$doc = \rosavox\logic\docs_read($id);
|
||||||
|
echo(
|
||||||
|
\rosavox\helpers\render(
|
||||||
|
'docs-edit',
|
||||||
|
[
|
||||||
|
'id' => $id_encoded,
|
||||||
|
'title' => $doc['title'],
|
||||||
|
'authors' => \implode(', ', $doc['authors']),
|
||||||
|
'content' => $doc['content'],
|
||||||
|
'reasoning' => $doc['reasoning'],
|
||||||
|
'link_back' => '?mode=list',
|
||||||
|
]
|
||||||
|
)
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'save':
|
||||||
|
{
|
||||||
|
throw (new \Exception('not implemented yet'));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
throw (new \Exception(\sprintf('invalid mode: %s', $mode)));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
</body>
|
||||||
|
</html>
|
129
source/logic.php
Normal file
129
source/logic.php
Normal file
|
@ -0,0 +1,129 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace rosavox\logic;
|
||||||
|
|
||||||
|
require_once(__DIR__ . '/helpers.php');
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
class docs_state
|
||||||
|
{
|
||||||
|
public static int $current_id = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array {record<string,array>}
|
||||||
|
*/
|
||||||
|
public static array $pool = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
function docs_id_encode(int $id) : string
|
||||||
|
{
|
||||||
|
return \sprintf('%u', $id);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
function docs_id_decode(string $id_encoded) : int
|
||||||
|
{
|
||||||
|
return intval($id_encoded);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
function docs_list() : array
|
||||||
|
{
|
||||||
|
return \array_map(
|
||||||
|
fn ($id_encoded) => [
|
||||||
|
'id' => docs_id_decode($id_encoded),
|
||||||
|
'doc' => docs_state::$pool[$id_encoded],
|
||||||
|
],
|
||||||
|
\array_keys(docs_state::$pool)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
function docs_read(int $id) : array
|
||||||
|
{
|
||||||
|
$id_encoded = docs_id_encode($id);
|
||||||
|
if (! \array_key_exists($id_encoded, docs_state::$pool))
|
||||||
|
{
|
||||||
|
throw (new Error('not found'));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return docs_state::$pool[$id_encoded];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
function docs_create(array $doc) : int
|
||||||
|
{
|
||||||
|
docs_state::$current_id += 1;
|
||||||
|
$id = docs_state::$current_id;
|
||||||
|
$id_encoded = docs_id_encode($id);
|
||||||
|
docs_state::$pool[$id_encoded] = $doc;
|
||||||
|
return $id;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
function docs_update(int $id, array $doc) : void
|
||||||
|
{
|
||||||
|
$id_encoded = docs_id_encode($id);
|
||||||
|
if (! \array_key_exists($id_encoded, docs_state::$pool))
|
||||||
|
{
|
||||||
|
throw (new Error('not found'));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
docs_state::$pool[$id_encoded] = $doc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
function docs_delete(int $id) : void
|
||||||
|
{
|
||||||
|
$id_encoded = docs_id_encode($id);
|
||||||
|
if (! \array_key_exists($id_encoded, docs_state::$pool))
|
||||||
|
{
|
||||||
|
throw (new Error('not found'));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
docs_state::$pool[$id_encoded] = null;
|
||||||
|
unset(docs_state::$pool[$id_encoded]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
function docs_add_examples() : void
|
||||||
|
{
|
||||||
|
docs_create(
|
||||||
|
[
|
||||||
|
'title' => 'Freibier bei Parteitagen',
|
||||||
|
'authors' => [
|
||||||
|
'Björn Biernot',
|
||||||
|
'Doreen Dauerdurst',
|
||||||
|
],
|
||||||
|
'content' => 'Wir haben Durst!',
|
||||||
|
'reasoning' => null,
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
72
source/style.css
Normal file
72
source/style.css
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
:root
|
||||||
|
{
|
||||||
|
--hue: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
html
|
||||||
|
{
|
||||||
|
background-color: hsl(var(--hue), 0%, 0%);
|
||||||
|
color: hsl(var(--hue), 0%, 100%);
|
||||||
|
|
||||||
|
font-family: sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
body
|
||||||
|
{
|
||||||
|
max-width: 960px;
|
||||||
|
margin: auto;
|
||||||
|
padding: 16px;
|
||||||
|
|
||||||
|
background-color: hsl(var(--hue), 0%, 12.5%);
|
||||||
|
color: hsl(var(--hue), 0%, 87.5%);
|
||||||
|
}
|
||||||
|
|
||||||
|
a
|
||||||
|
{
|
||||||
|
background-color: hsl(var(--hue), 0%, 12.5%);
|
||||||
|
color: hsl(var(--hue), 50%, 50%);
|
||||||
|
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
a:hover
|
||||||
|
{
|
||||||
|
background-color: hsl(var(--hue), 0%, 12.5%);
|
||||||
|
color: hsl(var(--hue), 50%, 75%);
|
||||||
|
}
|
||||||
|
|
||||||
|
label
|
||||||
|
{
|
||||||
|
display: block;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
label > span
|
||||||
|
{
|
||||||
|
display: block;
|
||||||
|
font-weight: bold;
|
||||||
|
margin-bottom: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type="text"]
|
||||||
|
{
|
||||||
|
min-width: 480px;
|
||||||
|
padding: 4px;
|
||||||
|
|
||||||
|
background-color: hsl(var(--hue), 0%, 25%);
|
||||||
|
color: hsl(var(--hue), 0%, 100%);
|
||||||
|
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
textarea
|
||||||
|
{
|
||||||
|
min-width: 480px;
|
||||||
|
min-height: 120px;
|
||||||
|
padding: 4px;
|
||||||
|
|
||||||
|
background-color: hsl(var(--hue), 0%, 25%);
|
||||||
|
color: hsl(var(--hue), 0%, 100%);
|
||||||
|
|
||||||
|
border: none;
|
||||||
|
}
|
26
source/templates/docs-edit.html.tpl
Normal file
26
source/templates/docs-edit.html.tpl
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
<div id="docs-edit">
|
||||||
|
<form method="GET">
|
||||||
|
<input type="hidden" name="mode" value="save"/>
|
||||||
|
<input type="hidden" name="id" value="{{id}}"/>
|
||||||
|
<label>
|
||||||
|
<span>Titel</span>
|
||||||
|
<input type="text" name="title" value="{{title}}"/>
|
||||||
|
</label>
|
||||||
|
<label>
|
||||||
|
<span>Autoren</span>
|
||||||
|
<input type="text" name="authors" value="{{authors}}"/>
|
||||||
|
</label>
|
||||||
|
<label>
|
||||||
|
<span>Formulierung</span>
|
||||||
|
<textarea name="content">{{content}}</textarea>
|
||||||
|
</label>
|
||||||
|
<label>
|
||||||
|
<span>Begründung</span>
|
||||||
|
<textarea name="reasoning">{{reasoning}}</textarea>
|
||||||
|
</label>
|
||||||
|
<label>
|
||||||
|
<input type="submit" value="Speichern"/>
|
||||||
|
</label>
|
||||||
|
</form>
|
||||||
|
<a href="{{link_back}}">zurück</a>
|
||||||
|
</div>
|
3
source/templates/docs-list-entry.html.tpl
Normal file
3
source/templates/docs-list-entry.html.tpl
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
<li class="docs-list-entry">
|
||||||
|
<a href="{{link}}">{{text}}</a>
|
||||||
|
</li>
|
6
source/templates/docs-list.html.tpl
Normal file
6
source/templates/docs-list.html.tpl
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
<div id="docs-list">
|
||||||
|
<ul>
|
||||||
|
{{entries}}
|
||||||
|
</ul>
|
||||||
|
<a href="{{link_new}}">Neu</a>
|
||||||
|
</div>
|
12
tools/build
Executable file
12
tools/build
Executable file
|
@ -0,0 +1,12 @@
|
||||||
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
|
## consts
|
||||||
|
|
||||||
|
dir_build="build"
|
||||||
|
dir_source="source"
|
||||||
|
|
||||||
|
|
||||||
|
## exec
|
||||||
|
|
||||||
|
mkdir -p ${dir_build}
|
||||||
|
cp -r -u -v ${dir_source}/* ${dir_build}/
|
3
tools/run
Executable file
3
tools/run
Executable file
|
@ -0,0 +1,3 @@
|
||||||
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
|
php -S localhost:8000 -t build
|
Loading…
Add table
Reference in a new issue