Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Changes 10: New MemoryContentStorageHandler #6457

Merged
merged 15 commits into from
Jun 24, 2024
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 51 additions & 5 deletions src/Content/ContentStorageHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
use Kirby\Cms\Language;
use Kirby\Cms\ModelWithContent;
use Kirby\Cms\Page;
use Kirby\Exception\NotFoundException;

/**
* Abstract for content storage handlers;
bastianallgeier marked this conversation as resolved.
Show resolved Hide resolved
Expand Down Expand Up @@ -52,7 +53,10 @@ public function all(): Generator
*
* @param array<string, string> $fields Content fields
*/
abstract public function create(VersionId $versionId, Language $language, array $fields): void;
public function create(VersionId $versionId, Language $language, array $fields): void
{
$this->write($versionId, $language, $fields);
}

/**
* Deletes an existing version in an idempotent way if it was already deleted
Expand Down Expand Up @@ -91,6 +95,26 @@ public function dynamicVersions(): array
return $versions;
}

/**
* Checks if a version/language combination exists and otherwise
* will throw a NotFoundException
bastianallgeier marked this conversation as resolved.
Show resolved Hide resolved
*
* @throws \Kirby\Exception\NotFoundException If the version does not exist
*/
public function ensure(VersionId $versionId, Language $language): void
{
if ($this->exists($versionId, $language) === true) {
return;
}

$message = match($this->model->kirby()->multilang()) {
true => 'Version "' . $versionId . ' (' . $language->code() . ')" does not already exist',
false => 'Version "' . $versionId . '" does not already exist',
};

throw new NotFoundException($message);
}

/**
* Checks if a version exists
*/
Expand All @@ -104,12 +128,21 @@ abstract public function modified(VersionId $versionId, Language $language): int
/**
* Moves content from one version-language combination to another
*/
abstract public function move(
public function move(
VersionId $fromVersionId,
Language $fromLanguage,
VersionId $toVersionId,
Language $toLanguage
): void;
): void {
// read the existing fields
$fields = $this->read($fromVersionId, $fromLanguage);

// create the new version
$this->create($toVersionId, $toLanguage, $fields);

// clean up the old version
$this->delete($fromVersionId, $fromLanguage);
}

/**
* Adapts all versions when converting languages
Expand Down Expand Up @@ -158,7 +191,20 @@ public function touchLanguage(Language $language): void
*
* @param array<string, string> $fields Content fields
*
* @throws \Kirby\Exception\NotFoundException If the version does not exist
* @throws \Kirby\Exception\Exception If the file cannot be written
*/
public function update(VersionId $versionId, Language $language, array $fields): void
{
$this->ensure($versionId, $language);
$this->write($versionId, $language, $fields);
}

/**
* Writes the content fields of an existing version
*
* @param array<string, string> $fields Content fields
*
* @throws \Kirby\Exception\Exception If the content cannot be written
*/
abstract public function update(VersionId $versionId, Language $language, array $fields): void;
abstract protected function write(VersionId $versionId, Language $language, array $fields): void;
bastianallgeier marked this conversation as resolved.
Show resolved Hide resolved
}
130 changes: 130 additions & 0 deletions src/Content/MemoryContentStorageHandler.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
<?php

namespace Kirby\Content;

use Kirby\Cache\MemoryCache;
use Kirby\Cms\Language;
use Kirby\Cms\ModelWithContent;

/**
* @package Kirby Content
* @author Bastian Allgeier <[email protected]>
* @link https://getkirby.com
* @copyright Bastian Allgeier
* @license https://getkirby.com/license
*/
class MemoryContentStorageHandler extends ContentStorageHandler
{
/**
* Cache instance, used to store content in memory
*/
protected MemoryCache $cache;

/**
* Sets up the cache instance
*/
public function __construct(protected ModelWithContent $model)
{
parent::__construct($model);
$this->cache = new MemoryCache();
}

/**
* Returns a unique id for a combination
* of the version id, the language code and the model id
*/
protected function cacheId(VersionId $versionId, Language $language): string
{
return $versionId->value() . '/' . $language->code() . '/' . $this->model->id();
}

/**
* Deletes an existing version in an idempotent way if it was already deleted
*/
public function delete(VersionId $versionId, Language $language): void
{
$this->cache->remove($this->cacheId($versionId, $language));
}

/**
* Checks if a version exists
*/
public function exists(VersionId $versionId, Language $language): bool
{
$data = $this->cache->get($this->cacheId($versionId, $language));

// validate the cached data
if (
isset($data['fields']) === true &&
is_array($data['fields']) === true &&
isset($data['modified']) === true &&
is_int($data['modified']) === true
) {
return true;
}

return false;
}

/**
* Returns the modification timestamp of a version if it exists
*/
public function modified(VersionId $versionId, Language $language): int|null
{
if ($this->exists($versionId, $language) === false) {
return null;
}

return $this->cache->get($this->cacheId($versionId, $language))['modified'];
bastianallgeier marked this conversation as resolved.
Show resolved Hide resolved
}

/**
* Returns the stored content fields
*
* @return array<string, string>
*
* @throws \Kirby\Exception\NotFoundException If the version does not exist
*/
public function read(VersionId $versionId, Language $language): array
{
$this->ensure($versionId, $language);
return $this->cache->get($this->cacheId($versionId, $language))['fields'];
}

/**
* Updates the modification timestamp of an existing version
*
* @throws \Kirby\Exception\NotFoundException If the version does not exist
*/
public function touch(VersionId $versionId, Language $language): void
{
$fields = $this->read($versionId, $language);
$this->write($versionId, $language, $fields);
bastianallgeier marked this conversation as resolved.
Show resolved Hide resolved
}

/**
* Updates the content fields of an existing version
*
* @param array<string, string> $fields Content fields
*
* @throws \Kirby\Exception\NotFoundException If the version does not exist
*/
public function update(VersionId $versionId, Language $language, array $fields): void
{
$this->ensure($versionId, $language);
$this->write($versionId, $language, $fields);
}

bastianallgeier marked this conversation as resolved.
Show resolved Hide resolved
/**
* Writes the content fields of an existing version
*
* @param array<string, string> $fields Content fields
*/
protected function write(VersionId $versionId, Language $language, array $fields): void
{
$this->cache->set($this->cacheId($versionId, $language), [
'fields' => $fields,
'modified' => time()
]);
}
}
24 changes: 0 additions & 24 deletions src/Content/PlainTextContentStorageHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -141,18 +141,6 @@ public function contentFiles(VersionId $versionId): array
];
}

/**
* Creates a new version
*
* @param array<string, string> $fields Content fields
*
* @throws \Kirby\Exception\Exception If the file cannot be written
*/
public function create(VersionId $versionId, Language $language, array $fields): void
{
$this->write($versionId, $language, $fields);
}

/**
* Deletes an existing version in an idempotent way if it was already deleted
*/
Expand Down Expand Up @@ -247,18 +235,6 @@ public function touch(VersionId $versionId, Language $language): void
// @codeCoverageIgnoreEnd
}

/**
* Updates the content fields of an existing version
*
* @param array<string, string> $fields Content fields
*
* @throws \Kirby\Exception\Exception If the file cannot be written
*/
public function update(VersionId $versionId, Language $language, array $fields): void
{
$this->write($versionId, $language, $fields);
}

/**
* Writes the content fields of an existing version
*
Expand Down
12 changes: 1 addition & 11 deletions src/Content/Version.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
use Kirby\Cms\Language;
use Kirby\Cms\ModelWithContent;
use Kirby\Exception\InvalidArgumentException;
use Kirby\Exception\NotFoundException;

/**
* The Version class handles all actions for a single
Expand Down Expand Up @@ -88,16 +87,7 @@ public function delete(): void
public function ensure(
Language|string $language = 'default'
): void {
if ($this->exists($language) === true) {
return;
}

$message = match($this->model->kirby()->multilang()) {
true => 'Version "' . $this->id . ' (' . $language . ')" does not already exist',
false => 'Version "' . $this->id . '" does not already exist',
};

throw new NotFoundException($message);
$this->model->storage()->ensure($this->id, $this->language($language));
}

/**
Expand Down
Loading
Loading