diff --git a/src/Content/ContentStorageHandler.php b/src/Content/ContentStorageHandler.php index 75bc2ed22d..dcd5f10821 100644 --- a/src/Content/ContentStorageHandler.php +++ b/src/Content/ContentStorageHandler.php @@ -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; @@ -52,7 +53,10 @@ public function all(): Generator * * @param array $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 @@ -91,6 +95,26 @@ public function dynamicVersions(): array return $versions; } + /** + * Checks if a version/language combination exists and otherwise + * will throw a `NotFoundException` + * + * @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 */ @@ -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 @@ -158,7 +191,20 @@ public function touchLanguage(Language $language): void * * @param array $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 $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; } diff --git a/src/Content/MemoryContentStorageHandler.php b/src/Content/MemoryContentStorageHandler.php new file mode 100644 index 0000000000..668f8d7bed --- /dev/null +++ b/src/Content/MemoryContentStorageHandler.php @@ -0,0 +1,102 @@ + + * @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 + { + return $this->cache->exists($this->cacheId($versionId, $language)); + } + + /** + * 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->modified($this->cacheId($versionId, $language)); + } + + /** + * Returns the stored content fields + * + * @return array + * + * @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)); + } + + /** + * 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); + } + + /** + * Writes the content fields of an existing version + * + * @param array $fields Content fields + */ + protected function write(VersionId $versionId, Language $language, array $fields): void + { + $this->cache->set($this->cacheId($versionId, $language), $fields); + } +} diff --git a/src/Content/PlainTextContentStorageHandler.php b/src/Content/PlainTextContentStorageHandler.php index 9ce36a2388..84328f8855 100644 --- a/src/Content/PlainTextContentStorageHandler.php +++ b/src/Content/PlainTextContentStorageHandler.php @@ -141,18 +141,6 @@ public function contentFiles(VersionId $versionId): array ]; } - /** - * Creates a new version - * - * @param array $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 */ @@ -247,18 +235,6 @@ public function touch(VersionId $versionId, Language $language): void // @codeCoverageIgnoreEnd } - /** - * Updates the content fields of an existing version - * - * @param array $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 * diff --git a/src/Content/Version.php b/src/Content/Version.php index c5395e9293..d9ba0d93a8 100644 --- a/src/Content/Version.php +++ b/src/Content/Version.php @@ -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 @@ -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)); } /** diff --git a/tests/Cache/MemoryCacheTest.php b/tests/Cache/MemoryCacheTest.php index 76c44805d3..6b20b19ada 100644 --- a/tests/Cache/MemoryCacheTest.php +++ b/tests/Cache/MemoryCacheTest.php @@ -116,4 +116,18 @@ public function testFlushWithMultipleInstances() $this->assertTrue($cache2->exists('a')); $this->assertTrue($cache2->exists('b')); } + + /** + * @covers ::modified + */ + public function testModified() + { + $cache = new MemoryCache(); + + $time = time(); + + $cache->set('a', 'A basic value'); + + $this->assertGreaterThanOrEqual($time, $cache->modified('a')); + } } diff --git a/tests/Content/ContentStorageHandlerTest.php b/tests/Content/ContentStorageHandlerTest.php index 527529a276..311a6673f1 100644 --- a/tests/Content/ContentStorageHandlerTest.php +++ b/tests/Content/ContentStorageHandlerTest.php @@ -34,10 +34,18 @@ public function testAllMultiLanguageForFile() $versions = iterator_to_array($handler->all(), false); - // The TestContentStorage handler always returns true - // for every version and language. Thus there should be - // 2 versions for every language. - // + $this->assertCount(0, $versions); + + // create all possible versions + $handler->create(VersionId::published(), $this->app->language('en'), []); + $handler->create(VersionId::published(), $this->app->language('de'), []); + + $handler->create(VersionId::changes(), $this->app->language('en'), []); + $handler->create(VersionId::changes(), $this->app->language('de'), []); + + // count again + $versions = iterator_to_array($handler->all(), false); + // article.en.txt // article.de.txt // _changes/article.en.txt @@ -61,10 +69,15 @@ public function testAllSingleLanguageForFile() $versions = iterator_to_array($handler->all(), false); - // The TestContentStorage handler always returns true - // for every version and language. Thus there should be - // 2 versions in a single language installation. - // + $this->assertCount(0, $versions); + + // create all possible versions + $handler->create(VersionId::published(), Language::single(), []); + $handler->create(VersionId::changes(), Language::single(), []); + + // count again + $versions = iterator_to_array($handler->all(), false); + // article.txt // _changes/article.txt $this->assertCount(2, $versions); @@ -83,6 +96,18 @@ public function testAllMultiLanguageForPage() $versions = iterator_to_array($handler->all(), false); + $this->assertCount(0, $versions); + + // create all possible versions + $handler->create(VersionId::published(), $this->app->language('en'), []); + $handler->create(VersionId::published(), $this->app->language('de'), []); + + $handler->create(VersionId::changes(), $this->app->language('en'), []); + $handler->create(VersionId::changes(), $this->app->language('de'), []); + + // count again + $versions = iterator_to_array($handler->all(), false); + // A page that's not in draft mode can have published and changes versions // and thus should have changes and published for every language $this->assertCount(4, $versions); @@ -101,6 +126,17 @@ public function testAllMultiLanguageForPageDraft() $versions = iterator_to_array($handler->all(), false); + $this->assertCount(0, $versions); + + $handler->create(VersionId::published(), $this->app->language('en'), []); + $handler->create(VersionId::published(), $this->app->language('de'), []); + + $handler->create(VersionId::changes(), $this->app->language('en'), []); + $handler->create(VersionId::changes(), $this->app->language('de'), []); + + // count again + $versions = iterator_to_array($handler->all(), false); + // A draft page has only changes and thus should only have // a changes for every language, but no published versions $this->assertCount(2, $versions); @@ -119,6 +155,15 @@ public function testAllSingleLanguageForPage() $versions = iterator_to_array($handler->all(), false); + $this->assertCount(0, $versions); + + // create all possible versions + $handler->create(VersionId::published(), Language::single(), []); + $handler->create(VersionId::changes(), Language::single(), []); + + // count again + $versions = iterator_to_array($handler->all(), false); + // A page that's not in draft mode can have published and changes versions $this->assertCount(2, $versions); } @@ -136,6 +181,15 @@ public function testAllSingleLanguageForPageDraft() $versions = iterator_to_array($handler->all(), false); + $this->assertCount(0, $versions); + + // create all possible versions + $handler->create(VersionId::published(), Language::single(), []); + $handler->create(VersionId::changes(), Language::single(), []); + + // count again + $versions = iterator_to_array($handler->all(), false); + // A draft page has only changes and thus should only have // a single version in a single language installation $this->assertCount(1, $versions); @@ -148,22 +202,21 @@ public function testDeleteLanguageMultiLanguage() { $this->setUpMultiLanguage(); - // Use the plain text handler, as the abstract class and the test handler do not - // implement the necessary methods to test this. - $handler = new PlainTextContentStorageHandler( + $handler = new TestContentStorageHandler( model: $this->model ); - Data::write($filePublished = $this->model->root() . '/article.de.txt', []); - Data::write($fileChanges = $this->model->root() . '/_changes/article.de.txt', []); + // create two versions for the German language + $handler->create(VersionId::published(), $this->app->language('de'), []); + $handler->create(VersionId::changes(), $this->app->language('de'), []); - $this->assertFileExists($filePublished); - $this->assertFileExists($fileChanges); + $this->assertTrue($handler->exists(VersionId::published(), $this->app->language('de'))); + $this->assertTrue($handler->exists(VersionId::changes(), $this->app->language('de'))); $handler->deleteLanguage($this->app->language('de')); - $this->assertFileDoesNotExist($filePublished); - $this->assertFileDoesNotExist($fileChanges); + $this->assertFalse($handler->exists(VersionId::published(), $this->app->language('de'))); + $this->assertFalse($handler->exists(VersionId::changes(), $this->app->language('de'))); } /** @@ -175,20 +228,23 @@ public function testDeleteLanguageSingleLanguage() // Use the plain text handler, as the abstract class and the test handler do not // implement the necessary methods to test this. - $handler = new PlainTextContentStorageHandler( + $handler = new TestContentStorageHandler( model: $this->model ); - Data::write($filePublished = $this->model->root() . '/article.txt', []); - Data::write($fileChanges = $this->model->root() . '/_changes/article.txt', []); + $language = Language::single(); - $this->assertFileExists($filePublished); - $this->assertFileExists($fileChanges); + // create two versions + $handler->create(VersionId::published(), $language, []); + $handler->create(VersionId::changes(), $language, []); - $handler->deleteLanguage(Language::single()); + $this->assertTrue($handler->exists(VersionId::published(), $language)); + $this->assertTrue($handler->exists(VersionId::changes(), $language)); - $this->assertFileDoesNotExist($filePublished); - $this->assertFileDoesNotExist($fileChanges); + $handler->deleteLanguage($language); + + $this->assertFalse($handler->exists(VersionId::published(), $language)); + $this->assertFalse($handler->exists(VersionId::changes(), $language)); } /** @@ -273,6 +329,60 @@ public function testDynamicVersionsForUser() $this->assertSame(VersionId::PUBLISHED, $versions[1]->value()); } + /** + * @covers ::move + */ + public function testMoveMultiLanguage() + { + $this->setUpMultiLanguage(); + + $handler = new TestContentStorageHandler( + model: $this->model + ); + + $en = $this->app->language('en'); + $de = $this->app->language('de'); + + $handler->create(VersionId::published(), $en, []); + + $this->assertTrue($handler->exists(VersionId::published(), $en)); + $this->assertFalse($handler->exists(VersionId::published(), $de)); + + $handler->move( + VersionId::published(), + $en, + VersionId::published(), + $de + ); + + $this->assertFalse($handler->exists(VersionId::published(), $en)); + $this->assertTrue($handler->exists(VersionId::published(), $de)); + } + + public function testMoveSingleLanguage() + { + $this->setUpSingleLanguage(); + + $handler = new TestContentStorageHandler( + model: $this->model + ); + + $handler->create(VersionId::published(), Language::single(), []); + + $this->assertTrue($handler->exists(VersionId::published(), Language::single())); + $this->assertFalse($handler->exists(VersionId::changes(), Language::single())); + + $handler->move( + VersionId::published(), + Language::single(), + VersionId::changes(), + Language::single() + ); + + $this->assertFalse($handler->exists(VersionId::published(), Language::single())); + $this->assertTrue($handler->exists(VersionId::changes(), Language::single())); + } + /** * @covers ::moveLanguage */ @@ -280,8 +390,8 @@ public function testMoveSingleLanguageToMultiLanguage() { $this->setUpMultiLanguage(); - // Use the plain text handler, as the abstract class and the test handler do not - // implement the necessary methods to test this. + // Use the plain text handler, as it offers the most + // realistic, testable results for this test $handler = new PlainTextContentStorageHandler( model: $this->model ); @@ -311,8 +421,8 @@ public function testMoveMultiLanguageToSingleLanguage() { $this->setUpMultiLanguage(); - // Use the plain text handler, as the abstract class and the test handler do not - // implement the necessary methods to test this. + // Use the plain text handler, as it offers the most + // realistic, testable results for this test $handler = new PlainTextContentStorageHandler( model: $this->model ); diff --git a/tests/Content/MemoryContentStorageHandlerTest.php b/tests/Content/MemoryContentStorageHandlerTest.php new file mode 100644 index 0000000000..2cd1e9c9fc --- /dev/null +++ b/tests/Content/MemoryContentStorageHandlerTest.php @@ -0,0 +1,376 @@ +storage->create($versionId, $language, []); + + $this->assertTrue($this->storage->exists($versionId, $language)); + + $this->storage->delete($versionId, $language); + + $this->assertFalse($this->storage->exists($versionId, $language)); + } + + public function assertCreateAndRead(VersionId $versionId, Language $language): void + { + $fields = [ + 'title' => 'Foo', + 'text' => 'Bar' + ]; + + $this->storage->create($versionId, $language, $fields); + + $this->assertTrue($this->storage->exists($versionId, $language)); + $this->assertSame($fields, $this->storage->read($versionId, $language)); + } + + public function assertCreateAndUpdate(VersionId $versionId, Language $language): void + { + $fields = [ + 'title' => 'Foo', + 'text' => 'Bar' + ]; + + $this->storage->create($versionId, $language, []); + + $this->assertSame([], $this->storage->read($versionId, $language)); + + $this->storage->update($versionId, $language, $fields); + + $this->assertTrue($this->storage->exists($versionId, $language)); + $this->assertSame($fields, $this->storage->read($versionId, $language)); + } + + public function setUpMultiLanguage(): void + { + parent::setUpMultiLanguage(); + + $this->storage = new MemoryContentStorageHandler($this->model); + } + + public function setUpSingleLanguage(): void + { + parent::setUpSingleLanguage(); + + $this->storage = new MemoryContentStorageHandler($this->model); + } + + /** + * @covers ::create + * @covers ::read + * @covers ::write + */ + public function testCreateAndReadChangesMultiLang() + { + $this->setUpMultiLanguage(); + + $versionId = VersionId::changes(); + $language = $this->app->language('en'); + + $this->assertCreateAndRead($versionId, $language); + } + + /** + * @covers ::create + * @covers ::read + * @covers ::write + */ + public function testCreateAndReadChangesSingleLang() + { + $this->setUpSingleLanguage(); + + $versionId = VersionId::changes(); + $language = Language::single(); + + $this->assertCreateAndRead($versionId, $language); + } + + /** + * @covers ::create + * @covers ::read + * @covers ::write + */ + public function testCreateAndReadPublishedMultiLang() + { + $this->setUpMultiLanguage(); + + $versionId = VersionId::published(); + $language = $this->app->language('en'); + + $this->assertCreateAndRead($versionId, $language); + } + + /** + * @covers ::create + * @covers ::read + * @covers ::write + */ + public function testCreateAndReadPublishedSingleLang() + { + $this->setUpSingleLanguage(); + + $versionId = VersionId::published(); + $language = Language::single(); + + $this->assertCreateAndRead($versionId, $language); + } + + /** + * @covers ::delete + * @covers ::exists + */ + public function testDeleteNonExisting() + { + $this->setUpSingleLanguage(); + + $versionId = VersionId::published(); + $language = Language::single(); + + $this->assertFalse($this->storage->exists($versionId, $language)); + + // test idempotency + $this->storage->delete($versionId, $language); + + $this->assertFalse($this->storage->exists($versionId, $language)); + } + + /** + * @covers ::delete + */ + public function testDeleteChangesMultiLang() + { + $this->setUpMultiLanguage(); + + $versionId = VersionId::changes(); + $language = $this->app->language('en'); + + $this->assertCreateAndDelete($versionId, $language); + } + + /** + * @covers ::delete + */ + public function testDeleteChangesSingleLang() + { + $this->setUpSingleLanguage(); + + $versionId = VersionId::changes(); + $language = Language::single(); + + $this->assertCreateAndDelete($versionId, $language); + } + + /** + * @covers ::delete + */ + public function testDeletePublishedMultiLang() + { + $this->setUpMultiLanguage(); + + $versionId = VersionId::published(); + $language = $this->app->language('en'); + + $this->assertCreateAndDelete($versionId, $language); + } + + /** + * @covers ::delete + */ + public function testDeletePublishedSingleLang() + { + $this->setUpSingleLanguage(); + + $versionId = VersionId::published(); + $language = Language::single(); + + $this->assertCreateAndDelete($versionId, $language); + } + + /** + * @covers ::exists + */ + public function testExistsMultiLanguage() + { + $this->setUpMultiLanguage(); + + $versionId = VersionId::published(); + + $this->assertFalse($this->storage->exists($versionId, $this->app->language('en'))); + $this->assertFalse($this->storage->exists($versionId, $this->app->language('de'))); + + $this->storage->create($versionId, $this->app->language('en'), []); + $this->storage->create($versionId, $this->app->language('de'), []); + + $this->assertTrue($this->storage->exists($versionId, $this->app->language('en'))); + $this->assertTrue($this->storage->exists($versionId, $this->app->language('de'))); + } + + /** + * @covers ::exists + */ + public function testExistsSingleLanguage() + { + $this->setUpSingleLanguage(); + + $versionId = VersionId::published(); + $language = Language::single(); + + $this->assertFalse($this->storage->exists($versionId, $language)); + + $this->storage->create($versionId, $language, []); + + $this->assertTrue($this->storage->exists($versionId, $language)); + } + + /** + * @covers ::exists + */ + public function testExistsNoneExistingMultiLanguage() + { + $this->setUpMultiLanguage(); + + $this->assertFalse($this->storage->exists(VersionId::changes(), $this->app->language('en'))); + $this->assertFalse($this->storage->exists(VersionId::changes(), $this->app->language('de'))); + } + + /** + * @covers ::exists + */ + public function testExistsNoneExistingSingleLanguage() + { + $this->setUpSingleLanguage(); + + $this->assertFalse($this->storage->exists(VersionId::changes(), Language::single())); + } + + /** + * @covers ::modified + */ + public function testModifiedNoneExistingMultiLanguage() + { + $this->setUpMultiLanguage(); + + $this->assertNull($this->storage->modified(VersionId::changes(), $this->app->language('en'))); + $this->assertNull($this->storage->modified(VersionId::published(), $this->app->language('en'))); + } + + /** + * @covers ::modified + */ + public function testModifiedNoneExistingSingleLanguage() + { + $this->setUpSingleLanguage(); + + $this->assertNull($this->storage->modified(VersionId::changes(), Language::single())); + $this->assertNull($this->storage->modified(VersionId::published(), Language::single())); + } + + /** + * @covers ::modified + */ + public function testModifiedSomeExistingMultiLanguage() + { + $this->setUpMultiLanguage(); + + $changes = VersionId::changes(); + $language = $this->app->language('en'); + + $this->storage->create($changes, $language, []); + + $this->assertIsInt($this->storage->modified($changes, $language)); + $this->assertNull($this->storage->modified(VersionId::published(), $language)); + } + + /** + * @covers ::modified + */ + public function testModifiedSomeExistingSingleLanguage() + { + $this->setUpSingleLanguage(); + + $changes = VersionId::changes(); + $language = Language::single(); + + $this->storage->create($changes, $language, []); + + $this->assertIsInt($this->storage->modified($changes, $language)); + $this->assertNull($this->storage->modified(VersionId::published(), $language)); + } + + /** + * @covers ::touch + */ + public function testTouchMultiLang() + { + $this->setUpMultiLanguage(); + + $versionId = VersionId::changes(); + $language = $this->app->language('en'); + + $time = time(); + + $this->storage->create($versionId, $language, []); + $this->storage->touch($versionId, $language); + + $this->assertGreaterThanOrEqual($time, $this->storage->modified($versionId, $language)); + } + + /** + * @covers ::touch + */ + public function testTouchSingleLang() + { + $this->setUpSingleLanguage(); + + $versionId = VersionId::changes(); + $language = Language::single(); + + $time = time(); + + $this->storage->create($versionId, $language, []); + $this->storage->touch($versionId, $language); + + $this->assertGreaterThanOrEqual($time, $this->storage->modified($versionId, $language)); + } + + /** + * @covers ::update + * @covers ::write + */ + public function testUpdateMultiLang() + { + $this->setUpMultiLanguage(); + + $versionId = VersionId::changes(); + $language = $this->app->language('en'); + + $this->assertCreateAndUpdate($versionId, $language); + } + + /** + * @covers ::update + * @covers ::write + */ + public function testUpdateSingleLang() + { + $this->setUpSingleLanguage(); + + $versionId = VersionId::changes(); + $language = Language::single(); + + $this->assertCreateAndUpdate($versionId, $language); + } +} diff --git a/tests/Content/PlainTextContentStorageHandlerTest.php b/tests/Content/PlainTextContentStorageHandlerTest.php index 078023baa6..f68ec7d3cc 100644 --- a/tests/Content/PlainTextContentStorageHandlerTest.php +++ b/tests/Content/PlainTextContentStorageHandlerTest.php @@ -410,11 +410,11 @@ public function testUpdateChangesMultiLang() 'text' => 'Bar' ]; - Dir::make(static::TMP . '/_changes'); - Data::write(static::TMP . '/_changes/article.en.txt', $fields); + Dir::make($this->model->root() . '/_changes'); + Data::write($this->model->root() . '/_changes/article.en.txt', $fields); $this->storage->update(VersionId::changes(), $this->app->language('en'), $fields); - $this->assertSame($fields, Data::read(static::TMP . '/_changes/article.en.txt')); + $this->assertSame($fields, Data::read($this->model->root() . '/_changes/article.en.txt')); } /** @@ -429,11 +429,11 @@ public function testUpdateChangesSingleLang() 'text' => 'Bar' ]; - Dir::make(static::TMP . '/_changes'); - Data::write(static::TMP . '/_changes/article.txt', $fields); + Dir::make($this->model->root() . '/_changes'); + Data::write($this->model->root() . '/_changes/article.txt', $fields); $this->storage->update(VersionId::changes(), Language::single(), $fields); - $this->assertSame($fields, Data::read(static::TMP . '/_changes/article.txt')); + $this->assertSame($fields, Data::read($this->model->root() . '/_changes/article.txt')); } /** @@ -448,10 +448,10 @@ public function testUpdatePublishedMultiLang() 'text' => 'Bar' ]; - Data::write(static::TMP . '/article.en.txt', $fields); + Data::write($this->model->root() . '/article.en.txt', $fields); $this->storage->update(VersionId::published(), $this->app->language('en'), $fields); - $this->assertSame($fields, Data::read(static::TMP . '/article.en.txt')); + $this->assertSame($fields, Data::read($this->model->root() . '/article.en.txt')); } /** @@ -466,10 +466,10 @@ public function testUpdatePublishedSingleLang() 'text' => 'Bar' ]; - Data::write(static::TMP . '/article.txt', $fields); + Data::write($this->model->root() . '/article.txt', $fields); $this->storage->update(VersionId::published(), Language::single(), $fields); - $this->assertSame($fields, Data::read(static::TMP . '/article.txt')); + $this->assertSame($fields, Data::read($this->model->root() . '/article.txt')); } /** diff --git a/tests/Content/TestContentStorageHandler.php b/tests/Content/TestContentStorageHandler.php index 363cf13315..451fb4b38d 100644 --- a/tests/Content/TestContentStorageHandler.php +++ b/tests/Content/TestContentStorageHandler.php @@ -2,46 +2,51 @@ namespace Kirby\Content; +use Exception; use Kirby\Cms\Language; +use Kirby\Cms\ModelWithContent; class TestContentStorageHandler extends ContentStorageHandler { - public function create(VersionId $versionId, Language $language, array $fields): void + public array $store = []; + + public function __construct(protected ModelWithContent $model) { + $this->store = []; } public function delete(VersionId $versionId, Language $language): void { + unset($this->store[$this->key($versionId, $language)]); } public function exists(VersionId $versionId, Language $language): bool { - return true; + return isset($this->store[$this->key($versionId, $language)]); } - public function modified(VersionId $versionId, Language $language): int|null + public function key(VersionId $versionId, Language $language): string { - return null; + return $versionId . '/' . $language; } - public function move( - VersionId $fromVersionId, - Language $fromLanguage, - VersionId $toVersionId, - Language $toLanguage - ): void { + public function modified(VersionId $versionId, Language $language): int|null + { + throw new Exception('Not implemented'); } public function read(VersionId $versionId, Language $language): array { - return []; + return $this->store[$this->key($versionId, $language)] ?? []; } public function touch(VersionId $versionId, Language $language): void { + throw new Exception('Not implemented'); } - public function update(VersionId $versionId, Language $language, array $fields): void + public function write(VersionId $versionId, Language $language, array $fields): void { + $this->store[$this->key($versionId, $language)] = $fields; } } diff --git a/tests/Content/mocks.php b/tests/Content/mocks.php new file mode 100644 index 0000000000..36a1f324b3 --- /dev/null +++ b/tests/Content/mocks.php @@ -0,0 +1,19 @@ +