-
-
Notifications
You must be signed in to change notification settings - Fork 171
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #6442 from getkirby/v5/changes/version-class
Changes 3: New Version class
- Loading branch information
Showing
2 changed files
with
365 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,185 @@ | ||
<?php | ||
|
||
namespace Kirby\Content; | ||
|
||
use Kirby\Cms\ModelWithContent; | ||
use Kirby\Exception\NotFoundException; | ||
|
||
/** | ||
* The Version class handles all actions for a single | ||
* version and is identified by a VersionId instance | ||
* | ||
* @internal | ||
* @since 5.0.0 | ||
* | ||
* @package Kirby Content | ||
* @author Bastian Allgeier <[email protected]> | ||
* @link https://getkirby.com | ||
* @copyright Bastian Allgeier | ||
* @license https://getkirby.com/license | ||
*/ | ||
class Version | ||
{ | ||
public function __construct( | ||
protected ModelWithContent $model, | ||
protected VersionId $id | ||
) { | ||
} | ||
|
||
/** | ||
* Returns a Content object for the given language | ||
*/ | ||
public function content(string $language = 'default'): Content | ||
{ | ||
return new Content( | ||
parent: $this->model, | ||
data: $this->model->storage()->read($this->id, $language), | ||
); | ||
} | ||
|
||
/** | ||
* Creates a new version for the given language | ||
*/ | ||
public function create(array $fields, string $language = 'default'): void | ||
{ | ||
$this->model->storage()->create($this->id, $language, $fields); | ||
} | ||
|
||
/** | ||
* Deletes a version by language or for any language | ||
*/ | ||
public function delete(string|null $language = null): void | ||
{ | ||
// delete all languages | ||
if ($language === null) { | ||
foreach ($this->model->kirby()->languages() as $language) { | ||
$this->model->storage()->delete($this->id, $language->code()); | ||
} | ||
} | ||
|
||
// delete the default language in single-language mode | ||
if ($this->model->kirby()->multilang() === false) { | ||
$this->model->storage()->delete($this->id, 'default'); | ||
return; | ||
} | ||
|
||
// delete a single language | ||
$this->model->storage()->delete($this->id, $language); | ||
|
||
} | ||
|
||
/** | ||
* Ensure that the version exists and otherwise | ||
* throw an exception | ||
* | ||
* @throws \Kirby\Exception\NotFoundException if the version does not exist | ||
*/ | ||
public function ensure( | ||
string $language = 'default' | ||
): void { | ||
if ($this->exists($language) !== true) { | ||
throw new NotFoundException('Version "' . $this->id . ' (' . $language . ')" does not already exist'); | ||
} | ||
} | ||
|
||
/** | ||
* Checks if a version exists for the given language | ||
*/ | ||
public function exists(string $language = 'default'): bool | ||
{ | ||
return $this->model->storage()->exists($this->id, $language); | ||
} | ||
|
||
/** | ||
* Returns the VersionId instance for this version | ||
*/ | ||
public function id(): VersionId | ||
{ | ||
return $this->id; | ||
} | ||
|
||
/** | ||
* Returns the parent model | ||
*/ | ||
public function model(): ModelWithContent | ||
{ | ||
return $this->model; | ||
} | ||
|
||
/** | ||
* 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' | ||
): int|null { | ||
$this->ensure($language); | ||
return $this->model->storage()->modified($this->id, $language); | ||
} | ||
|
||
/** | ||
* Moves the version to a new language and/or version | ||
*/ | ||
public function move(string $fromLanguage, VersionId $toVersionId, string $toLanguage): void | ||
{ | ||
$this->ensure($fromLanguage); | ||
$this->model->storage()->move($this->id, $fromLanguage, $toVersionId, $toLanguage); | ||
} | ||
|
||
/** | ||
* Returns the stored content fields | ||
* | ||
* @param string $lang Code `'default'` in a single-lang installation | ||
* @return array<string, string> | ||
*/ | ||
public function read(string $language = 'default'): array | ||
{ | ||
$this->ensure($language); | ||
return $this->model->storage()->read($this->id, $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 | ||
{ | ||
// 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); | ||
} | ||
|
||
/** | ||
* 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 | ||
{ | ||
$this->ensure($language); | ||
$this->model->storage()->update($this->id, $language, $fields); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,180 @@ | ||
<?php | ||
|
||
namespace Kirby\Content; | ||
|
||
use Kirby\Cms\App; | ||
use Kirby\Cms\Page; | ||
use Kirby\Filesystem\Dir; | ||
use Kirby\TestCase; | ||
|
||
/** | ||
* @coversDefaultClass Kirby\Content\Version | ||
*/ | ||
class VersionTest extends TestCase | ||
{ | ||
public const TMP = KIRBY_TMP_DIR . '/Content.Version'; | ||
|
||
protected $model; | ||
|
||
public function setUp(): void | ||
{ | ||
Dir::make(static::TMP); | ||
|
||
$this->model = new Page([ | ||
'kirby' => new App(), | ||
'root' => static::TMP, | ||
'slug' => 'a-page', | ||
'template' => 'article' | ||
]); | ||
} | ||
|
||
public function tearDown(): void | ||
{ | ||
App::destroy(); | ||
Dir::remove(static::TMP); | ||
} | ||
|
||
/** | ||
* @covers ::create | ||
*/ | ||
public function testCreate(): void | ||
{ | ||
$version = new Version( | ||
model: $this->model, | ||
id: VersionId::published() | ||
); | ||
|
||
$this->assertFalse($version->exists()); | ||
|
||
$version->create([ | ||
'title' => 'Test' | ||
]); | ||
|
||
$this->assertTrue($version->exists()); | ||
} | ||
|
||
/** | ||
* @covers ::create | ||
*/ | ||
public function testCreateLanguage(): void | ||
{ | ||
$version = new Version( | ||
model: $this->model, | ||
id: VersionId::published() | ||
); | ||
|
||
$this->assertFalse($version->exists('de')); | ||
|
||
$version->create([ | ||
'title' => 'Test' | ||
], 'de'); | ||
|
||
$this->assertTrue($version->exists('de')); | ||
} | ||
|
||
/** | ||
* @covers ::delete | ||
*/ | ||
public function testDelete(): void | ||
{ | ||
$version = new Version( | ||
model: $this->model, | ||
id: VersionId::published() | ||
); | ||
|
||
$this->assertFalse($version->exists()); | ||
|
||
$version->create([ | ||
'title' => 'Test' | ||
]); | ||
|
||
$this->assertTrue($version->exists()); | ||
|
||
$version->delete(); | ||
|
||
$this->assertFalse($version->exists()); | ||
} | ||
|
||
/** | ||
* @covers ::exists | ||
*/ | ||
public function testExists(): void | ||
{ | ||
$version = new Version( | ||
model: $this->model, | ||
id: VersionId::published() | ||
); | ||
|
||
$this->assertFalse($version->exists()); | ||
|
||
$version->create([]); | ||
|
||
$this->assertTrue($version->exists()); | ||
} | ||
|
||
/** | ||
* @covers ::id | ||
*/ | ||
public function testId(): void | ||
{ | ||
$version = new Version( | ||
model: $this->model, | ||
id: $id = VersionId::published() | ||
); | ||
|
||
$this->assertSame($id, $version->id()); | ||
} | ||
|
||
/** | ||
* @covers ::model | ||
*/ | ||
public function testModel(): void | ||
{ | ||
$version = new Version( | ||
model: $this->model, | ||
id: VersionId::published() | ||
); | ||
|
||
$this->assertSame($this->model, $version->model()); | ||
} | ||
|
||
/** | ||
* @covers ::read | ||
*/ | ||
public function testRead(): void | ||
{ | ||
$version = new Version( | ||
model: $this->model, | ||
id: VersionId::published() | ||
); | ||
|
||
$version->create($content = [ | ||
'title' => 'Test' | ||
]); | ||
|
||
$this->assertSame($content, $version->read()); | ||
} | ||
|
||
/** | ||
* @covers ::update | ||
*/ | ||
public function testUpdate(): void | ||
{ | ||
$version = new Version( | ||
model: $this->model, | ||
id: VersionId::published() | ||
); | ||
|
||
$version->create([ | ||
'title' => 'Test' | ||
]); | ||
|
||
$this->assertSame('Test', $version->read()['title']); | ||
|
||
$version->update([ | ||
'title' => 'Updated Title' | ||
]); | ||
|
||
$this->assertSame('Updated Title', $version->read()['title']); | ||
} | ||
} |