szurubooru/src/Dao/PostDao.php

283 lines
7.2 KiB
PHP
Raw Normal View History

<?php
namespace Szurubooru\Dao;
use Szurubooru\Dao\EntityConverters\PostEntityConverter;
use Szurubooru\Dao\PublicFileDao;
use Szurubooru\Dao\TagDao;
use Szurubooru\Dao\UserDao;
use Szurubooru\DatabaseConnection;
use Szurubooru\Entities\Entity;
use Szurubooru\Entities\Post;
use Szurubooru\SearchServices\Filters\PostFilter;
use Szurubooru\SearchServices\Requirements\Requirement;
use Szurubooru\Services\ThumbnailService;
2014-09-15 11:38:24 +02:00
class PostDao extends AbstractDao implements ICrudDao
{
2014-09-21 09:35:43 +02:00
private $tagDao;
2014-09-21 18:21:54 +02:00
private $userDao;
private $fileDao;
private $thumbnailService;
public function __construct(
DatabaseConnection $databaseConnection,
TagDao $tagDao,
UserDao $userDao,
PublicFileDao $fileDao,
ThumbnailService $thumbnailService)
{
parent::__construct(
$databaseConnection,
'posts',
new PostEntityConverter());
2014-09-21 09:35:43 +02:00
$this->tagDao = $tagDao;
2014-09-21 18:21:54 +02:00
$this->userDao = $userDao;
$this->fileDao = $fileDao;
$this->thumbnailService = $thumbnailService;
}
2014-09-15 11:38:24 +02:00
2014-09-25 11:45:46 +02:00
public function getCount()
{
return count($this->pdo->from($this->tableName));
2014-09-25 11:45:46 +02:00
}
public function getTotalFileSize()
{
$query = $this->pdo->from($this->tableName)->select('SUM(originalFileSize) AS __sum');
2014-09-25 11:45:46 +02:00
return intval(iterator_to_array($query)[0]['__sum']);
}
2014-09-15 11:38:24 +02:00
public function findByName($name)
{
return $this->findOneBy('name', $name);
}
2014-10-10 09:53:05 +02:00
public function findByTagName($tagName)
{
$query = $this->pdo->from('posts')
->innerJoin('postTags', 'postTags.postId = posts.id')
->innerJoin('tags', 'postTags.tagId = tags.id')
2014-10-10 09:53:05 +02:00
->where('tags.name', $tagName);
$arrayEntities = iterator_to_array($query);
return $this->arrayToEntities($arrayEntities);
}
2014-09-15 11:38:24 +02:00
public function findByContentChecksum($checksum)
{
return $this->findOneBy('contentChecksum', $checksum);
}
protected function afterLoad(Entity $post)
2014-09-15 11:38:24 +02:00
{
$post->setLazyLoader(
Post::LAZY_LOADER_CONTENT,
function (Post $post)
{
return $this->fileDao->load($post->getContentPath());
});
$post->setLazyLoader(
Post::LAZY_LOADER_THUMBNAIL_SOURCE_CONTENT,
function (Post $post)
{
return $this->fileDao->load($post->getThumbnailSourceContentPath());
});
2014-09-21 18:21:54 +02:00
$post->setLazyLoader(
Post::LAZY_LOADER_USER,
function (Post $post)
2014-09-21 18:21:54 +02:00
{
return $this->getUser($post);
});
$post->setLazyLoader(
Post::LAZY_LOADER_TAGS,
function (Post $post)
2014-09-15 11:38:24 +02:00
{
return $this->getTags($post);
});
2014-09-25 23:53:47 +02:00
$post->setLazyLoader(
Post::LAZY_LOADER_RELATED_POSTS,
function (Post $post)
2014-09-25 23:53:47 +02:00
{
return $this->getRelatedPosts($post);
});
2014-09-15 11:38:24 +02:00
}
protected function afterSave(Entity $post)
2014-09-15 11:38:24 +02:00
{
$this->syncContent($post);
$this->syncThumbnailSourceContent($post);
2014-09-21 09:35:43 +02:00
$this->syncTags($post);
2014-09-25 23:53:47 +02:00
$this->syncPostRelations($post);
2014-09-15 11:38:24 +02:00
}
protected function decorateQueryFromRequirement($query, Requirement $requirement)
2014-09-27 10:59:37 +02:00
{
if ($requirement->getType() === PostFilter::REQUIREMENT_TAG)
2014-09-27 10:59:37 +02:00
{
2014-10-10 20:05:32 +02:00
$tagName = $requirement->getValue()->getValue();
$tag = $this->tagDao->findByName($tagName);
if (!$tag)
throw new \DomainException('Invalid tag: "' . $tagName . '"');
2014-09-27 10:59:37 +02:00
$sql = 'EXISTS (
SELECT 1 FROM postTags
WHERE postTags.postId = posts.id
2014-10-10 20:05:32 +02:00
AND postTags.tagId = ?)';
2014-09-27 10:59:37 +02:00
if ($requirement->isNegated())
$sql = 'NOT ' . $sql;
2014-10-10 20:05:32 +02:00
$query->where($sql, $tag->getId());
2014-09-27 10:59:37 +02:00
return;
}
elseif ($requirement->getType() === PostFilter::REQUIREMENT_FAVORITE)
2014-10-01 14:34:49 +02:00
{
2014-10-19 21:15:25 +02:00
$query->innerJoin('favorites _fav', '_fav.postId = posts.id');
$query->innerJoin('users favoritedBy', 'favoritedBy.id = _fav.userId');
}
elseif ($requirement->getType() === PostFilter::REQUIREMENT_COMMENT)
{
2014-10-19 21:15:25 +02:00
$query->innerJoin('comments _comment', '_comment.postId = posts.id');
$query->innerJoin('users commentedBy', 'commentedBy.id = _comment.userId');
2014-10-01 14:34:49 +02:00
}
elseif ($requirement->getType() === PostFilter::REQUIREMENT_UPLOADER)
{
2014-10-19 21:15:25 +02:00
$query->innerJoin('users uploader', 'uploader.id = posts.userId');
}
elseif ($requirement->getType() === PostFilter::REQUIREMENT_USER_SCORE)
{
$values = $requirement->getValue()->getValues();
$userName = $values[0];
$score = $values[1];
$sql = 'EXISTS (
SELECT 1 FROM scores
INNER JOIN users ON scores.userId = users.id
WHERE scores.postId = posts.id
AND LOWER(users.name) = LOWER(?)
AND scores.score = ?)';
if ($requirement->isnegated())
$sql = 'NOT ' . $sql;
$query->where($sql, [$userName, $score]);
return;
}
2014-09-27 10:59:37 +02:00
parent::decorateQueryFromRequirement($query, $requirement);
}
private function getTags(Post $post)
2014-09-15 11:38:24 +02:00
{
2014-09-21 09:35:43 +02:00
return $this->tagDao->findByPostId($post->getId());
2014-09-15 11:38:24 +02:00
}
private function getUser(Post $post)
2014-09-21 18:21:54 +02:00
{
return $this->userDao->findById($post->getUserId());
}
private function getRelatedPosts(Post $post)
2014-09-25 23:53:47 +02:00
{
$relatedPostIds = [];
foreach ($this->pdo->from('postRelations')->where('post1id', $post->getId()) as $arrayEntity)
{
$postId = intval($arrayEntity['post2id']);
if ($postId !== $post->getId())
$relatedPostIds[] = $postId;
}
foreach ($this->pdo->from('postRelations')->where('post2id', $post->getId()) as $arrayEntity)
2014-09-25 23:53:47 +02:00
{
$postId = intval($arrayEntity['post1id']);
if ($postId !== $post->getId())
$relatedPostIds[] = $postId;
2014-09-25 23:53:47 +02:00
}
return $this->findByIds($relatedPostIds);
}
private function syncContent(Post $post)
{
$targetPath = $post->getContentPath();
$content = $post->getContent();
if ($content)
$this->fileDao->save($targetPath, $content);
else
$this->fileDao->delete($targetPath, $content);
$this->thumbnailService->deleteUsedThumbnails($targetPath);
}
private function syncThumbnailSourceContent(Post $post)
{
$targetPath = $post->getThumbnailSourceContentPath();
$content = $post->getThumbnailSourceContent();
if ($content)
$this->fileDao->save($targetPath, $content);
else
$this->fileDao->delete($targetPath);
$this->thumbnailService->deleteUsedThumbnails($targetPath);
}
private function syncTags(Post $post)
2014-09-15 11:38:24 +02:00
{
2014-09-21 09:35:43 +02:00
$tagIds = array_map(
2014-09-27 21:33:31 +02:00
function ($tag)
2014-09-21 09:35:43 +02:00
{
if (!$tag->getId())
throw new \RuntimeException('Unsaved entities found');
2014-09-21 09:35:43 +02:00
return $tag->getId();
},
$post->getTags());
2014-09-15 11:38:24 +02:00
2014-09-21 09:35:43 +02:00
$existingTagRelationIds = array_map(
2014-09-27 21:33:31 +02:00
function ($arrayEntity)
2014-09-15 11:38:24 +02:00
{
2014-09-21 09:35:43 +02:00
return $arrayEntity['tagId'];
2014-09-15 11:38:24 +02:00
},
iterator_to_array($this->pdo->from('postTags')->where('postId', $post->getId())));
2014-09-15 11:38:24 +02:00
2014-09-21 09:35:43 +02:00
$tagRelationsToInsert = array_diff($tagIds, $existingTagRelationIds);
$tagRelationsToDelete = array_diff($existingTagRelationIds, $tagIds);
2014-09-15 11:38:24 +02:00
2014-09-21 09:35:43 +02:00
foreach ($tagRelationsToInsert as $tagId)
{
$this->pdo->insertInto('postTags')->values(['postId' => $post->getId(), 'tagId' => $tagId])->execute();
2014-09-21 09:35:43 +02:00
}
foreach ($tagRelationsToDelete as $tagId)
2014-09-15 11:38:24 +02:00
{
$this->pdo->deleteFrom('postTags')->where('postId', $post->getId())->where('tagId', $tagId)->execute();
2014-09-15 11:38:24 +02:00
}
}
2014-09-25 23:53:47 +02:00
private function syncPostRelations(Post $post)
2014-09-25 23:53:47 +02:00
{
$this->pdo->deleteFrom('postRelations')->where('post1id', $post->getId())->execute();
$this->pdo->deleteFrom('postRelations')->where('post2id', $post->getId())->execute();
2014-09-25 23:53:47 +02:00
$relatedPostIds = array_filter(array_unique(array_map(
function ($post)
{
if (!$post->getId())
throw new \RuntimeException('Unsaved entities found');
return $post->getId();
},
$post->getRelatedPosts())));
foreach ($relatedPostIds as $postId)
{
$this->pdo
2014-09-25 23:53:47 +02:00
->insertInto('postRelations')
->values([
'post1id' => $post->getId(),
'post2id' => $postId])
->execute();
}
}
}