Skip to content

Commit

Permalink
Always use a full Language object in the content storage handlers
Browse files Browse the repository at this point in the history
  • Loading branch information
bastianallgeier committed May 17, 2024
1 parent 3a3b659 commit ea67992
Show file tree
Hide file tree
Showing 6 changed files with 380 additions and 277 deletions.
44 changes: 19 additions & 25 deletions src/Content/ContentStorage.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace Kirby\Content;

use Generator;
use Kirby\Cms\Language;
use Kirby\Cms\ModelWithContent;
use Kirby\Cms\Page;
use Kirby\Exception\InvalidArgumentException;
Expand Down Expand Up @@ -73,9 +74,8 @@ public function all(): Generator
public function contentFile(
VersionId $versionId,
string $lang,
bool $force = false
): string {
$lang = $this->language($lang, $force);
$lang = $this->language($lang);
return $this->handler->contentFile($versionId, $lang);
}

Expand Down Expand Up @@ -116,9 +116,8 @@ public function create(
public function delete(
VersionId $versionId,
string|null $lang = null,
bool $force = false
): void {
$lang = $this->language($lang, $force);
$lang = $this->language($lang);
$this->handler->delete($versionId, $lang);
}

Expand Down Expand Up @@ -253,7 +252,13 @@ protected function ensureExistingVersion(
string $lang
): void {
if ($this->exists($versionId, $lang) !== true) {
throw new NotFoundException('Version "' . $versionId . ' (' . $lang . ')" does not already exist');

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

throw new NotFoundException($message);
}
}

Expand All @@ -262,32 +267,21 @@ protected function ensureExistingVersion(
* used for storage
*
* @param bool $force If set to `true`, the language code is not validated
* @return string Language code
*/
protected function language(
string|null $languageCode = null,
bool $force = false
): string {
// in force mode, use the provided language code even in single-lang for
// compatibility with the previous behavior in `$model->contentFile()`
if ($force === true) {
return $languageCode ?? 'default';
): Language {
// single language
if ($this->model->kirby()->multilang() === false) {
return Language::single();
}

// in multi-lang, …
if ($this->model->kirby()->multilang() === true) {
// look up the actual language object if possible
$language = $this->model->kirby()->language($languageCode);

// validate the language code
if ($language === null) {
throw new InvalidArgumentException('Invalid language: ' . $languageCode);
}

return $language->code();
// look up the actual language object if possible
if ($language = $this->model->kirby()->language($languageCode)) {
return $language;
}

// otherwise use hardcoded "default" code for single lang
return 'default';
// validate the language code
throw new InvalidArgumentException('Invalid language: ' . $languageCode);
}
}
3 changes: 1 addition & 2 deletions src/Content/ContentTranslation.php
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,7 @@ public function contentFile(): string
{
return $this->contentFile = $this->parent->storage()->contentFile(
VersionId::default($this->parent),
$this->code,
true
$this->code
);
}

Expand Down
103 changes: 39 additions & 64 deletions src/Content/PlainTextContentStorageHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace Kirby\Content;

use Kirby\Cms\File;
use Kirby\Cms\Language;
use Kirby\Cms\ModelWithContent;
use Kirby\Cms\Page;
use Kirby\Cms\Site;
Expand Down Expand Up @@ -53,17 +54,15 @@ public function contentDirectory(VersionId $versionId): string
/**
* Returns the absolute path to the content file
* @internal To be made `protected` when the CMS core no longer relies on it
*
* @param string $lang Code `'default'` in a single-lang installation
*/
public function contentFile(VersionId $versionId, string $lang): string
public function contentFile(VersionId $versionId, Language $language): string
{
// get the filename without extension and language code
return match (true) {
$this->model instanceof File => $this->contentFileForFile($this->model, $versionId, $lang),
$this->model instanceof Page => $this->contentFileForPage($this->model, $versionId, $lang),
$this->model instanceof Site => $this->contentFileForSite($this->model, $versionId, $lang),
$this->model instanceof User => $this->contentFileForUser($this->model, $versionId, $lang),
$this->model instanceof File => $this->contentFileForFile($this->model, $versionId, $language),
$this->model instanceof Page => $this->contentFileForPage($this->model, $versionId, $language),
$this->model instanceof Site => $this->contentFileForSite($this->model, $versionId, $language),
$this->model instanceof User => $this->contentFileForUser($this->model, $versionId, $language),
// @codeCoverageIgnoreStart
default => throw new LogicException('Cannot determine content file for model type "' . $this->model::CLASS_ALIAS . '"')
// @codeCoverageIgnoreEnd
Expand All @@ -72,20 +71,16 @@ public function contentFile(VersionId $versionId, string $lang): string

/**
* Returns the absolute path to the content file of a file model
*
* @param string $lang Code `'default'` in a single-lang installation
*/
protected function contentFileForFile(File $model, VersionId $versionId, string $lang): string
protected function contentFileForFile(File $model, VersionId $versionId, Language $language): string
{
return $this->contentDirectory($versionId) . '/' . $this->contentFilename($model->filename(), $lang);
return $this->contentDirectory($versionId) . '/' . $this->contentFilename($model->filename(), $language);
}

/**
* Returns the absolute path to the content file of a page model
*
* @param string $lang Code `'default'` in a single-lang installation
*/
protected function contentFileForPage(Page $model, VersionId $versionId, string $lang): string
protected function contentFileForPage(Page $model, VersionId $versionId, Language $language): string
{
$directory = $this->contentDirectory($versionId);

Expand All @@ -99,42 +94,36 @@ protected function contentFileForPage(Page $model, VersionId $versionId, string
$directory = $this->model->root();
}

return $directory . '/' . $this->contentFilename($model->intendedTemplate()->name(), $lang);
return $directory . '/' . $this->contentFilename($model->intendedTemplate()->name(), $language);
}

/**
* Returns the absolute path to the content file of a site model
*
* @param string $lang Code `'default'` in a single-lang installation
*/
protected function contentFileForSite(Site $model, VersionId $versionId, string $lang): string
protected function contentFileForSite(Site $model, VersionId $versionId, Language $language): string
{
return $this->contentDirectory($versionId) . '/' . $this->contentFilename('site', $lang);
return $this->contentDirectory($versionId) . '/' . $this->contentFilename('site', $language);
}

/**
* Returns the absolute path to the content file of a user model
*
* @param string $lang Code `'default'` in a single-lang installation
*/
protected function contentFileForUser(User $model, VersionId $versionId, string $lang): string
protected function contentFileForUser(User $model, VersionId $versionId, Language $language): string
{
return $this->contentDirectory($versionId) . '/' . $this->contentFilename('user', $lang);
return $this->contentDirectory($versionId) . '/' . $this->contentFilename('user', $language);
}

/**
* Creates a filename with extension and optional language code
* in a multi-language installation
*
* @param string $lang Code `'default'` in a single-lang installation
*/
public function contentFilename(string $name, string $lang): string
public function contentFilename(string $name, Language $language): string
{
$kirby = $this->model->kirby();
$extension = $kirby->contentExtension();

if ($lang !== 'default') {
return $name . '.' . $lang . '.' . $extension;
if ($kirby->multilang() === true) {
return $name . '.' . $language->code() . '.' . $extension;
}

return $name . '.' . $extension;
Expand All @@ -148,36 +137,33 @@ public function contentFiles(VersionId $versionId): array
{
if ($this->model->kirby()->multilang() === true) {
return $this->model->kirby()->languages()->values(
fn ($lang) => $this->contentFile($versionId, $lang)
fn ($language) => $this->contentFile($versionId, $language)
);
}

return [
$this->contentFile($versionId, 'default')
$this->contentFile($versionId, Language::single())
];
}

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

/**
* Deletes an existing version in an idempotent way if it was already deleted
*
* @param string $lang Code `'default'` in a single-lang installation
*/
public function delete(VersionId $versionId, string $lang): void
public function delete(VersionId $versionId, Language $language): void
{
$contentFile = $this->contentFile($versionId, $lang);
$contentFile = $this->contentFile($versionId, $language);
$success = F::unlink($contentFile);

// @codeCoverageIgnoreStart
Expand All @@ -204,23 +190,19 @@ public function delete(VersionId $versionId, string $lang): void

/**
* Checks if a version exists
*
* @param string|null $lang Code `'default'` in a single-lang installation
*/
public function exists(VersionId $versionId, string $lang): bool
public function exists(VersionId $versionId, Language $language): bool
{
return is_file($this->contentFile($versionId, $lang)) === true;
return is_file($this->contentFile($versionId, $language)) === true;
}

/**
* Returns the modification timestamp of a version
* if it exists
*
* @param string $lang Code `'default'` in a single-lang installation
*/
public function modified(VersionId $versionId, string $lang): int|null
public function modified(VersionId $versionId, Language $language): int|null
{
$modified = F::modified($this->contentFile($versionId, $lang));
$modified = F::modified($this->contentFile($versionId, $language));

if (is_int($modified) === true) {
return $modified;
Expand All @@ -231,43 +213,37 @@ public function modified(VersionId $versionId, string $lang): int|null

/**
* Moves content from one version-language combination to another
*
* @param string $fromLang Code `'default'` in a single-lang installation
* @param string $toLang Code `'default'` in a single-lang installation
*/
public function move(
VersionId $fromVersionId,
string $fromLang,
Language $fromLanguage,
VersionId $toVersionId,
string $toLang
Language $toLanguage
): void {
F::move(
$this->contentFile($fromVersionId, $fromLang),
$this->contentFile($toVersionId, $toLang)
$this->contentFile($fromVersionId, $fromLanguage),
$this->contentFile($toVersionId, $toLanguage)
);
}

/**
* Returns the stored content fields
*
* @param string $lang Code `'default'` in a single-lang installation
* @return array<string, string>
*/
public function read(VersionId $versionId, string $lang): array
public function read(VersionId $versionId, Language $language): array
{
return Data::read($this->contentFile($versionId, $lang));
return Data::read($this->contentFile($versionId, $language));
}

/**
* Updates the modification timestamp of an existing version
*
* @param string $lang Code `'default'` in a single-lang installation
*
* @throws \Kirby\Exception\Exception If the file cannot be touched
*/
public function touch(VersionId $versionId, string $lang): void
public function touch(VersionId $versionId, Language $language): void
{
$success = touch($this->contentFile($versionId, $lang));
$success = touch($this->contentFile($versionId, $language));

// @codeCoverageIgnoreStart
if ($success !== true) {
Expand All @@ -279,14 +255,13 @@ public function touch(VersionId $versionId, string $lang): void
/**
* Updates the content fields of an existing version
*
* @param string $lang Code `'default'` in a single-lang installation
* @param array<string, string> $fields Content fields
*
* @throws \Kirby\Exception\Exception If the file cannot be written
*/
public function update(VersionId $versionId, string $lang, array $fields): void
public function update(VersionId $versionId, Language $language, array $fields): void
{
$this->write($versionId, $lang, $fields);
$this->write($versionId, $language, $fields);
}

/**
Expand All @@ -296,9 +271,9 @@ public function update(VersionId $versionId, string $lang, array $fields): void
*
* @throws \Kirby\Exception\Exception If the content cannot be written
*/
protected function write(VersionId $versionId, string $lang, array $fields): void
protected function write(VersionId $versionId, Language $language, array $fields): void
{
$success = Data::write($this->contentFile($versionId, $lang), $fields);
$success = Data::write($this->contentFile($versionId, $language), $fields);

// @codeCoverageIgnoreStart
if ($success !== true) {
Expand Down
Loading

0 comments on commit ea67992

Please sign in to comment.