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 6: Version class improvements and unit tests #6450

Merged
merged 25 commits into from
Jun 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
f22580b
Version class improvements and more unit tests
bastianallgeier May 17, 2024
57e2e6b
Fix CS issues
bastianallgeier May 21, 2024
57b286a
Return null as modification date if the version does not exist
bastianallgeier May 21, 2024
7d92b5b
Add ::contentFile method
bastianallgeier May 21, 2024
535115d
Refactor unit tests to create more independent test scenarios
bastianallgeier Jun 5, 2024
fc2ba96
Remove language paramater from Version::delete
bastianallgeier Jun 5, 2024
bda2a2a
Remove more unit test dependencies
bastianallgeier Jun 5, 2024
02eb3be
Remove @covers ::deleteLanguage
bastianallgeier Jun 5, 2024
5ed02f4
Add todo as reference for later.
bastianallgeier Jun 11, 2024
a32a662
Return early in ::delete method
bastianallgeier Jun 11, 2024
e0eeeae
Accept a Language object for all language arguments
bastianallgeier Jun 11, 2024
95c0dec
Convert touchLanguage to a protected method
bastianallgeier Jun 11, 2024
99153d3
Use an early return in ::ensure
bastianallgeier Jun 11, 2024
584b05a
Add assertions to cover Version::language
bastianallgeier Jun 11, 2024
71ac631
Add test for touching all languages at once
bastianallgeier Jun 11, 2024
51f26a0
Test Version::move
bastianallgeier Jun 11, 2024
28194ed
Test ::language with invalid language code
bastianallgeier Jun 11, 2024
7b6d287
Remove null as option for ::touch and remove ::touchLanguage
bastianallgeier Jun 11, 2024
6749c2b
Use void as return type for ::ensure
bastianallgeier Jun 11, 2024
af19ca6
Fix @cover hints
bastianallgeier Jun 11, 2024
62aee1b
Mark constructor as covered
bastianallgeier Jun 11, 2024
6e26844
Added test for the default language
bastianallgeier Jun 12, 2024
7c0b030
Add todo as a reference for later.
bastianallgeier Jun 12, 2024
da2c463
Add an early return to avoid further code execution
bastianallgeier Jun 12, 2024
58be7d8
Cover single language code path
lukasbestle Jun 12, 2024
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
150 changes: 94 additions & 56 deletions src/Content/Version.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

namespace Kirby\Content;

use Kirby\Cms\Language;
use Kirby\Cms\ModelWithContent;
use Kirby\Exception\InvalidArgumentException;
use Kirby\Exception\NotFoundException;

/**
Expand All @@ -29,43 +31,52 @@ public function __construct(
/**
* Returns a Content object for the given language
*/
public function content(string $language = 'default'): Content
public function content(Language|string $language = 'default'): Content
{
return new Content(
parent: $this->model,
data: $this->model->storage()->read($this->id, $language),
data: $this->model->storage()->read($this->id, $this->language($language)),
lukasbestle marked this conversation as resolved.
Show resolved Hide resolved
);
}

/**
* Creates a new version for the given language
* Provides simplified access to the absolute content file path.
* This should stay an internal method and be removed as soon as
* the dependency on file storage methods is resolved more clearly.
*
* @internal
*/
public function create(array $fields, string $language = 'default'): void
public function contentFile(Language|string $language = 'default'): string
{
$this->model->storage()->create($this->id, $language, $fields);
return $this->model->storage()->contentFile($this->id, $this->language($language));
}

/**
* Deletes a version by language or for any language
* Creates a new version for the given language
* @todo Convert to a static method that creates the version initially with all relevant languages
*
bastianallgeier marked this conversation as resolved.
Show resolved Hide resolved
* @param array<string, string> $fields Content fields
*/
public function delete(string|null $language = null): void
public function create(array $fields, Language|string $language = 'default'): void
{
// delete all languages
if ($language === null) {
foreach ($this->model->kirby()->languages() as $language) {
$this->model->storage()->delete($this->id, $language->code());
}
}
$this->model->storage()->create($this->id, $this->language($language), $fields);
}

/**
* Deletes a version with all its languages
*/
public function delete(): void
{
// delete the default language in single-language mode
if ($this->model->kirby()->multilang() === false) {
$this->model->storage()->delete($this->id, 'default');
$this->model->storage()->delete($this->id, $this->language('default'));
bastianallgeier marked this conversation as resolved.
Show resolved Hide resolved
return;
}

// delete a single language
$this->model->storage()->delete($this->id, $language);

// delete all languages
foreach ($this->model->kirby()->languages() as $language) {
$this->model->storage()->delete($this->id, $language);
}
}

/**
Expand All @@ -75,19 +86,26 @@ public function delete(string|null $language = null): void
* @throws \Kirby\Exception\NotFoundException if the version does not exist
*/
public function ensure(
string $language = 'default'
Language|string $language = 'default'
): void {
if ($this->exists($language) !== true) {
throw new NotFoundException('Version "' . $this->id . ' (' . $language . ')" does not already exist');
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);
}

/**
* Checks if a version exists for the given language
*/
public function exists(string $language = 'default'): bool
public function exists(Language|string $language = 'default'): bool
{
return $this->model->storage()->exists($this->id, $language);
return $this->model->storage()->exists($this->id, $this->language($language));
}

/**
Expand All @@ -98,6 +116,33 @@ public function id(): VersionId
return $this->id;
}

/**
* Converts a "user-facing" language code or Language object
* to a `Language` object to be used in storage methods
*
* @throws \Kirby\Exception\InvalidArgumentException if the language code does not match a valid language
*/
protected function language(
Language|string|null $languageCode = null,
): Language {
if ($languageCode instanceof Language) {
return $languageCode;
}

// single language
if ($this->model->kirby()->multilang() === false) {
return Language::single();
}

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

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

/**
* Returns the parent model
*/
Expand All @@ -109,77 +154,70 @@ public function model(): ModelWithContent
/**
* Returns the modification timestamp of a version
* if it exists
*
* @param string $lang Code `'default'` in a single-lang installation
*/
public function modified(
string $language = 'default'
Language|string $language = 'default'
): int|null {
$this->ensure($language);
return $this->model->storage()->modified($this->id, $language);
if ($this->exists($language) === true) {
return $this->model->storage()->modified($this->id, $this->language($language));
}

return null;
}

/**
* Moves the version to a new language and/or version
*
* @throws \Kirby\Exception\NotFoundException If the version does not exist
*/
public function move(string $fromLanguage, VersionId $toVersionId, string $toLanguage): void
{
public function move(
Language|string $fromLanguage,
VersionId $toVersionId,
Language|string $toLanguage
lukasbestle marked this conversation as resolved.
Show resolved Hide resolved
): void {
$this->ensure($fromLanguage);
$this->model->storage()->move($this->id, $fromLanguage, $toVersionId, $toLanguage);
$this->model->storage()->move(
fromVersionId: $this->id,
fromLanguage: $this->language($fromLanguage),
toVersionId: $toVersionId,
toLanguage: $this->language($toLanguage)
);
}

/**
* Returns the stored content fields
*
* @param string $lang Code `'default'` in a single-lang installation
* @return array<string, string>
*
* @throws \Kirby\Exception\NotFoundException If the version does not exist
*/
public function read(string $language = 'default'): array
public function read(Language|string $language = 'default'): array
{
$this->ensure($language);
bastianallgeier marked this conversation as resolved.
Show resolved Hide resolved
return $this->model->storage()->read($this->id, $language);
return $this->model->storage()->read($this->id, $this->language($language));
}

/**
* Updates the modification timestamp of an existing version
*
* @param string $lang Code `'default'` in a single-lang installation
*
* @throws \Kirby\Exception\NotFoundException If the version does not exist
*/
public function touch(string|null $language = null): void
public function touch(Language|string $language = 'default'): void
{
// touch all languages
if ($language === null) {
foreach ($this->model->kirby()->languages() as $language) {
$this->touch($language->code());
}
}

// make sure the version exists
$this->ensure($language);

// touch the default language in single-language mode
if ($this->model->kirby()->multilang() === false) {
$this->model->storage()->touch($this->id, 'default');
return;
}

// touch a single language
$this->model->storage()->touch($this->id, $language);
$this->model->storage()->touch($this->id, $this->language($language));
}

/**
* Updates the content fields of an existing version
*
* @param array<string, string> $fields Content fields
* @param string $lang Code `'default'` in a single-lang installation
*
* @throws \Kirby\Exception\NotFoundException If the version does not exist
*/
public function update(array $fields, string $language = 'default'): void
public function update(array $fields, Language|string $language = 'default'): void
bastianallgeier marked this conversation as resolved.
Show resolved Hide resolved
{
$this->ensure($language);
$this->model->storage()->update($this->id, $language, $fields);
$this->model->storage()->update($this->id, $this->language($language), $fields);
}
}
Loading
Loading