diff --git a/public_html/data/.gitignore b/public_html/data/.gitignore index 20c21237..402d9491 100644 --- a/public_html/data/.gitignore +++ b/public_html/data/.gitignore @@ -1 +1,2 @@ posts +tags.json diff --git a/src/Dao/AbstractDao.php b/src/Dao/AbstractDao.php index c8fe3395..85d559a8 100644 --- a/src/Dao/AbstractDao.php +++ b/src/Dao/AbstractDao.php @@ -34,18 +34,24 @@ abstract class AbstractDao implements ICrudDao public function save(&$entity) { - if ($entity->getId()) - { - $entity = $this->update($entity); - } - else - { - $entity = $this->create($entity); - } + $entity = $this->upsert($entity); $this->afterSave($entity); + $this->afterBatchSave([$entity]); return $entity; } + public function batchSave(array $entities) + { + foreach ($entities as $key => $entity) + { + $entities[$key] = $this->upsert($entity); + $this->afterSave($entity); + } + if (count($entities) > 0) + $this->afterBatchSave([$entity]); + return $entities; + } + public function findAll() { $query = $this->fpdo->from($this->tableName); @@ -165,6 +171,10 @@ abstract class AbstractDao implements ICrudDao { } + protected function afterBatchSave(array $entities) + { + } + protected function beforeDelete(\Szurubooru\Entities\Entity $entity) { } @@ -247,4 +257,16 @@ abstract class AbstractDao implements ICrudDao $orderByString .= $orderColumn . ' ' . ($orderDir === \Szurubooru\SearchServices\Filters\IFilter::ORDER_DESC ? 'DESC' : 'ASC') . ', '; return substr($orderByString, 0, -2); } + + private function upsert(\Szurubooru\Entities\Entity $entity) + { + if ($entity->getId()) + { + return $this->update($entity); + } + else + { + return $this->create($entity); + } + } } diff --git a/src/Dao/ICrudDao.php b/src/Dao/ICrudDao.php index 9e38b127..5c0f5ed5 100644 --- a/src/Dao/ICrudDao.php +++ b/src/Dao/ICrudDao.php @@ -9,6 +9,8 @@ interface ICrudDao public function save(&$object); + public function batchSave(array $object); + public function deleteById($objectId); public function deleteAll(); diff --git a/src/Dao/PostDao.php b/src/Dao/PostDao.php index 1dfec15b..ee68d59f 100644 --- a/src/Dao/PostDao.php +++ b/src/Dao/PostDao.php @@ -203,6 +203,8 @@ class PostDao extends AbstractDao implements ICrudDao { $this->fpdo->deleteFrom('postTags')->where('postId', $post->getId())->where('tagId', $tagId)->execute(); } + + $this->tagDao->exportJson(); } private function syncPostRelations(\Szurubooru\Entities\Post $post) diff --git a/src/Dao/TagDao.php b/src/Dao/TagDao.php index 8bfa721c..fc16fd36 100644 --- a/src/Dao/TagDao.php +++ b/src/Dao/TagDao.php @@ -3,12 +3,18 @@ namespace Szurubooru\Dao; class TagDao extends AbstractDao implements ICrudDao { - public function __construct(\Szurubooru\DatabaseConnection $databaseConnection) + private $fileService; + + public function __construct( + \Szurubooru\DatabaseConnection $databaseConnection, + \Szurubooru\Services\FileService $fileService) { parent::__construct( $databaseConnection, 'tags', new \Szurubooru\Dao\EntityConverters\TagEntityConverter()); + + $this->fileService = $fileService; } public function findByNames($tagNames) @@ -27,6 +33,17 @@ class TagDao extends AbstractDao implements ICrudDao return $this->findByIds($tagIds); } + public function exportJson() + { + $tags = []; + foreach ($this->findAll() as $tag) + { + $tags[$tag->getName()] = $tag->getUsages(); + } + $json = json_encode($tags); + $this->fileService->save('tags.json', $json); + } + public function createMissingTags(array $tagNames) { $tagNames = array_filter(array_unique($tagNames)); @@ -42,11 +59,19 @@ class TagDao extends AbstractDao implements ICrudDao $tagNamesToCreate = array_udiff($tagNames, $tagNamesNotToCreate, 'strcasecmp'); + $tags = []; foreach ($tagNamesToCreate as $tagName) { $tag = new \Szurubooru\Entities\Tag; $tag->setName($tagName); - $this->save($tag); + $tags[] = $tag; } + $this->batchSave($tags); + } + + protected function afterBatchSave(array $entities) + { + if (count($entities) > 0) + $this->exportJson(); } } diff --git a/src/Upgrades/Upgrade12.php b/src/Upgrades/Upgrade12.php new file mode 100644 index 00000000..ff55c46d --- /dev/null +++ b/src/Upgrades/Upgrade12.php @@ -0,0 +1,17 @@ +tagDao = $tagDao; + } + + public function run(\Szurubooru\DatabaseConnection $databaseConnection) + { + $this->tagDao->exportJson(); + } +} diff --git a/src/di.php b/src/di.php index 41b38339..bb835e0c 100644 --- a/src/di.php +++ b/src/di.php @@ -27,6 +27,7 @@ return [ $container->get(\Szurubooru\Upgrades\Upgrade09::class), $container->get(\Szurubooru\Upgrades\Upgrade10::class), $container->get(\Szurubooru\Upgrades\Upgrade11::class), + $container->get(\Szurubooru\Upgrades\Upgrade12::class), ]; }), diff --git a/tests/AbstractDatabaseTestCase.php b/tests/AbstractDatabaseTestCase.php index 7cd9cf6e..cb5ba04c 100644 --- a/tests/AbstractDatabaseTestCase.php +++ b/tests/AbstractDatabaseTestCase.php @@ -13,8 +13,10 @@ abstract class AbstractDatabaseTestCase extends \Szurubooru\Tests\AbstractTestCa $config->set('database/user', ''); $config->set('database/password', ''); + $fileServiceMock = $this->mock(\Szurubooru\Services\FileService::class); $this->databaseConnection = new \Szurubooru\DatabaseConnection($config); \Szurubooru\Injector::set(\Szurubooru\DatabaseConnection::class, $this->databaseConnection); + \Szurubooru\Injector::set(\Szurubooru\Services\FileService::class, $fileServiceMock); $upgradeRepository = \Szurubooru\Injector::get(\Szurubooru\Upgrades\UpgradeRepository::class); $upgradeService = new \Szurubooru\Services\UpgradeService($config, $this->databaseConnection, $upgradeRepository); diff --git a/tests/Dao/PostDaoTest.php b/tests/Dao/PostDaoTest.php index 5bba25c2..afed77e8 100644 --- a/tests/Dao/PostDaoTest.php +++ b/tests/Dao/PostDaoTest.php @@ -13,7 +13,7 @@ final class PostDaoTest extends \Szurubooru\Tests\AbstractDatabaseTestCase parent::setUp(); $this->fileServiceMock = $this->mock(\Szurubooru\Services\FileService::class); $this->thumbnailServiceMock = $this->mock(\Szurubooru\Services\ThumbnailService::class); - $this->tagDao = new \Szurubooru\Dao\TagDao($this->databaseConnection); + $this->tagDao = new \Szurubooru\Dao\TagDao($this->databaseConnection, $this->fileServiceMock); $this->userDao = new \Szurubooru\Dao\UserDao( $this->databaseConnection, $this->fileServiceMock, @@ -243,9 +243,11 @@ final class PostDaoTest extends \Szurubooru\Tests\AbstractDatabaseTestCase [$post->getThumbnailSourceContentPath()]); $this->fileServiceMock - ->expects($this->once()) + ->expects($this->exactly(2)) ->method('save') - ->with($post->getContentPath(), 'whatever'); + ->withConsecutive( + [$post->getContentPath(), 'whatever'], + ['tags.json', '[]']); $postDao->save($post); } @@ -264,11 +266,12 @@ final class PostDaoTest extends \Szurubooru\Tests\AbstractDatabaseTestCase [$post->getThumbnailSourceContentPath()]); $this->fileServiceMock - ->expects($this->exactly(2)) + ->expects($this->exactly(3)) ->method('save') ->withConsecutive( [$post->getContentPath(), 'whatever'], - [$post->getThumbnailSourceContentPath(), 'an image of sharks']); + [$post->getThumbnailSourceContentPath(), 'an image of sharks'], + ['tags.json', '[]']); $postDao->save($post); } diff --git a/tests/Dao/TagDaoTest.php b/tests/Dao/TagDaoTest.php index 487da63a..a0e8dc5b 100644 --- a/tests/Dao/TagDaoTest.php +++ b/tests/Dao/TagDaoTest.php @@ -3,6 +3,14 @@ namespace Szurubooru\Tests\Dao; final class TagDaoTest extends \Szurubooru\Tests\AbstractDatabaseTestCase { + private $fileServiceMock; + + public function setUp() + { + parent::setUp(); + $this->fileServiceMock = $this->mock(\Szurubooru\Services\FileService::class); + } + public function testFindByPostIds() { $pdo = $this->databaseConnection->getPDO(); @@ -29,8 +37,28 @@ final class TagDaoTest extends \Szurubooru\Tests\AbstractDatabaseTestCase $this->assertEntitiesEqual($expected, $actual); } + public function testExportSingle() + { + $tag1 = new \Szurubooru\Entities\Tag(); + $tag1->setName('test'); + $this->fileServiceMock->expects($this->once())->method('save')->with('tags.json', '{"test":0}'); + $tagDao = $this->getTagDao(); + $tagDao->save($tag1); + } + + public function testExportMultiple() + { + $tag1 = new \Szurubooru\Entities\Tag(); + $tag1->setName('test1'); + $tag2 = new \Szurubooru\Entities\Tag(); + $tag2->setName('test2'); + $this->fileServiceMock->expects($this->once())->method('save')->with('tags.json', '{"test1":0,"test2":0}'); + $tagDao = $this->getTagDao(); + $tagDao->batchSave([$tag1, $tag2]); + } + private function getTagDao() { - return new \Szurubooru\Dao\TagDao($this->databaseConnection); + return new \Szurubooru\Dao\TagDao($this->databaseConnection, $this->fileServiceMock); } }