[mod] Persistenz
This commit is contained in:
parent
aead2342ab
commit
990de81c42
4 changed files with 197 additions and 116 deletions
|
@ -28,6 +28,59 @@ function cache_get(string $key, \Closure $retrieve)
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
*/
|
||||
function database_map_type(string $type)
|
||||
{
|
||||
switch ($type)
|
||||
{
|
||||
case 'integer': return \SQLITE3_INTEGER;
|
||||
case 'string': return \SQLITE3_TEXT;
|
||||
default: throw (new \Exception(\sprintf('unhandled type: %s', $type)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*/
|
||||
function database_get(string $query_template, array $arguments) : array
|
||||
{
|
||||
$connection = new \SQLite3('data.sqlite');
|
||||
$rows = $connection->query($query_template);
|
||||
/*
|
||||
$query = "SELECT * FROM books";
|
||||
$result = $db->query($query);
|
||||
|
||||
while ($row = $result->fetchArray(SQLITE3_ASSOC)) {
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*/
|
||||
function database_put(string $query_template, array $arguments) : int
|
||||
{
|
||||
$connection = new \SQLite3('data.sqlite');
|
||||
$statement = $connection->prepare($query);
|
||||
foreach ($arguments as $key => $value)
|
||||
{
|
||||
$statement->bindValue(
|
||||
\sprintf(':%s', $key),
|
||||
$value['value'],
|
||||
database_map_type($value['type'])
|
||||
);
|
||||
}
|
||||
if ($statement->execute()) {
|
||||
// SELECT last_insert_rowid()
|
||||
echo "Buch erfolgreich hinzugefügt!";
|
||||
}
|
||||
else
|
||||
{
|
||||
echo "Fehler beim Hinzufügen des Buches: " . $db->lastErrorMsg();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*/
|
||||
function string_coin(string $template, array $arguments) : string
|
||||
|
@ -41,6 +94,114 @@ function string_coin(string $template, array $arguments) : string
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
*/
|
||||
class class_crud_jsonfile
|
||||
{
|
||||
private string $path;
|
||||
|
||||
private \Closure $id_encode;
|
||||
|
||||
private \Closure $id_decode;
|
||||
|
||||
public function __construct(
|
||||
string $path,
|
||||
\Closure $id_encode,
|
||||
\Closure $id_decode
|
||||
)
|
||||
{
|
||||
$this->path = $path;
|
||||
$this->id_encode = $id_encode;
|
||||
$this->id_decode = $id_decode;
|
||||
}
|
||||
|
||||
private function get() : array
|
||||
{
|
||||
$content = (\file_exists($this->path) ? \file_get_contents($this->path) : null);
|
||||
return (
|
||||
($content === null)
|
||||
?
|
||||
['last_id' => 0, 'entries' => []]
|
||||
:
|
||||
\json_decode($content, true)
|
||||
);
|
||||
}
|
||||
|
||||
private function put(array $data) : void
|
||||
{
|
||||
$content = \json_encode($data, \JSON_PRETTY_PRINT);
|
||||
\file_put_contents($this->path, $content);
|
||||
}
|
||||
|
||||
public function list_() : array
|
||||
{
|
||||
$data = $this->get();
|
||||
return \array_map(
|
||||
fn ($id_encoded) => [
|
||||
'id' => ($this->id_decode)($id_encoded),
|
||||
'value' => $data['entries'][$id_encoded],
|
||||
],
|
||||
\array_keys($data['entries'])
|
||||
);
|
||||
}
|
||||
|
||||
public function read(int $id)
|
||||
{
|
||||
$data = $this->get();
|
||||
$id_encoded = ($this->id_encode)($id);
|
||||
if (! \array_key_exists($id_encoded, $data['entries']))
|
||||
{
|
||||
throw (new \Exception('not found'));
|
||||
}
|
||||
else
|
||||
{
|
||||
return $data['entries'][$id_encoded];
|
||||
}
|
||||
}
|
||||
|
||||
public function create($value) : int
|
||||
{
|
||||
$data = $this->get();
|
||||
$id = ($data['last_id'] + 1);
|
||||
$id_encoded = ($this->id_encode)($id);
|
||||
$data['last_id'] = $id;
|
||||
$data['entries'][$id_encoded] = $value;
|
||||
$this->put($data);
|
||||
return $id;
|
||||
}
|
||||
|
||||
public function update(int $id, $value) : void
|
||||
{
|
||||
$data = $this->get();
|
||||
$id_encoded = ($this->id_encode)($id);
|
||||
if (! \array_key_exists($id_encoded, $data['entries']))
|
||||
{
|
||||
throw (new \Exception('not found'));
|
||||
}
|
||||
else
|
||||
{
|
||||
$data['entries'][$id_encoded] = $value;
|
||||
$this->put($data);
|
||||
}
|
||||
}
|
||||
|
||||
public function delete(int $id) : void
|
||||
{
|
||||
$data = $this->get();
|
||||
$id_encoded = ($this->id_encode)($id);
|
||||
if (! \array_key_exists($id_encoded, $data['entries']))
|
||||
{
|
||||
throw (new \Exception('not found'));
|
||||
}
|
||||
else
|
||||
{
|
||||
unset($data['entries'][$id_encoded]);
|
||||
$this->put($data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*/
|
||||
function render(string $template_name, array $arguments) : string
|
||||
|
|
|
@ -7,7 +7,7 @@ require_once(__DIR__ . '/logic.php');
|
|||
|
||||
$mode = ($_GET['mode'] ?? 'list');
|
||||
$id_encoded = (! empty($_GET['id']) ? $_GET['id'] : null);
|
||||
$id = (($id_encoded === null) ? null : \rosavox\logic\docs_id_decode($id_encoded));
|
||||
$id = (($id_encoded === null) ? null : \intval($id_encoded));
|
||||
|
||||
|
||||
function nav(string $mode, array $args) : void
|
||||
|
@ -37,15 +37,10 @@ function nav(string $mode, array $args) : void
|
|||
<link rel="stylesheet" type="text/css" href="/style.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<h1>rosavox</h1>
|
||||
<?php
|
||||
switch ($mode)
|
||||
{
|
||||
case 'example':
|
||||
{
|
||||
\rosavox\logic\docs_add_examples();
|
||||
nav('list', []);
|
||||
break;
|
||||
}
|
||||
case 'list':
|
||||
{
|
||||
echo(
|
||||
|
@ -58,13 +53,15 @@ function nav(string $mode, array $args) : void
|
|||
fn ($entry) => \rosavox\helpers\render(
|
||||
'docs-list-entry',
|
||||
[
|
||||
'link' => \rosavox\helpers\string_coin(
|
||||
'link_open' => \rosavox\helpers\string_coin(
|
||||
'?mode=edit&id={{id}}',
|
||||
[
|
||||
'id' => $entry['id'],
|
||||
]
|
||||
),
|
||||
'text' => $entry['doc']['title'],
|
||||
'link_read' => '#not_implemented',
|
||||
'link_hear' => '#not_implemented',
|
||||
'text' => $entry['value']['title'],
|
||||
]
|
||||
),
|
||||
\rosavox\logic\docs_list()
|
||||
|
|
131
source/logic.php
131
source/logic.php
|
@ -9,60 +9,7 @@ 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_push() : void
|
||||
{
|
||||
$path = 'docs.json';
|
||||
$data = [
|
||||
'current_id' => docs_state::$current_id,
|
||||
'pool' => docs_state::$pool,
|
||||
];
|
||||
$content = \json_encode($data, \JSON_PRETTY_PRINT);
|
||||
\file_put_contents($path, $content);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*/
|
||||
function docs_pull() : void
|
||||
{
|
||||
$path = 'docs.json';
|
||||
$content = (\file_exists($path) ? \file_get_contents($path) : null);
|
||||
$data = (
|
||||
($content === null)
|
||||
?
|
||||
['current_id' => 0, 'pool' => []]
|
||||
:
|
||||
\json_decode($content, true)
|
||||
);
|
||||
docs_state::$current_id = $data['current_id'];
|
||||
docs_state::$pool = $data['pool'];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*/
|
||||
function docs_id_encode(int $id) : string
|
||||
{
|
||||
return \sprintf('%u', $id);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*/
|
||||
function docs_id_decode(string $id_encoded) : int
|
||||
{
|
||||
return intval($id_encoded);
|
||||
public static ?\rosavox\helpers\class_crud_jsonfile $crud = null;
|
||||
}
|
||||
|
||||
|
||||
|
@ -70,13 +17,7 @@ function docs_id_decode(string $id_encoded) : int
|
|||
*/
|
||||
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)
|
||||
);
|
||||
return docs_state::$crud->list_();
|
||||
}
|
||||
|
||||
|
||||
|
@ -84,15 +25,7 @@ function docs_list() : array
|
|||
*/
|
||||
function docs_read(int $id) : array
|
||||
{
|
||||
$id_encoded = docs_id_encode($id);
|
||||
if (! \array_key_exists($id_encoded, docs_state::$pool))
|
||||
{
|
||||
throw (new \Exception('not found'));
|
||||
}
|
||||
else
|
||||
{
|
||||
return docs_state::$pool[$id_encoded];
|
||||
}
|
||||
return docs_state::$crud->read($id);
|
||||
}
|
||||
|
||||
|
||||
|
@ -100,12 +33,7 @@ function docs_read(int $id) : array
|
|||
*/
|
||||
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;
|
||||
docs_push();
|
||||
return $id;
|
||||
return docs_state::$crud->create($doc);
|
||||
}
|
||||
|
||||
|
||||
|
@ -113,16 +41,7 @@ function docs_create(array $doc) : int
|
|||
*/
|
||||
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 \Exception('not found'));
|
||||
}
|
||||
else
|
||||
{
|
||||
docs_state::$pool[$id_encoded] = $doc;
|
||||
docs_push();
|
||||
}
|
||||
docs_state::$crud->update($id, $doc);
|
||||
}
|
||||
|
||||
|
||||
|
@ -130,25 +49,7 @@ function docs_update(int $id, array $doc) : void
|
|||
*/
|
||||
function docs_delete(int $id) : void
|
||||
{
|
||||
$id_encoded = docs_id_encode($id);
|
||||
if (! \array_key_exists($id_encoded, docs_state::$pool))
|
||||
{
|
||||
throw (new \Exception('not found'));
|
||||
}
|
||||
else
|
||||
{
|
||||
docs_state::$pool[$id_encoded] = null;
|
||||
unset(docs_state::$pool[$id_encoded]);
|
||||
docs_push();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*/
|
||||
function docs_init() : void
|
||||
{
|
||||
docs_pull();
|
||||
docs_state::$crud->delete($id);
|
||||
}
|
||||
|
||||
|
||||
|
@ -169,4 +70,24 @@ function docs_add_examples() : void
|
|||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*/
|
||||
function docs_init() : void
|
||||
{
|
||||
docs_state::$crud = new \rosavox\helpers\class_crud_jsonfile(
|
||||
'docs.json',
|
||||
fn ($id) => \sprintf('%u', $id),
|
||||
fn ($id_encoded) => \intval($id_encoded)
|
||||
);
|
||||
if (empty(docs_state::$crud->list_()))
|
||||
{
|
||||
docs_add_examples();
|
||||
}
|
||||
else
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
<li class="docs-list-entry">
|
||||
<a href="{{link}}">{{text}}</a>
|
||||
<a href="{{link_open}}">{{text}}</a>
|
||||
| <a href="{{link_read}}">[lesen]</a>
|
||||
| <a href="{{link_hear}}">[hören]</a>
|
||||
</li>
|
||||
|
|
Loading…
Add table
Reference in a new issue