Abandoned FPDO
Also, fixed tag search by categories
This commit is contained in:
parent
c55c0833ea
commit
c52ed6a455
23 changed files with 740 additions and 61 deletions
|
@ -1,7 +1,6 @@
|
||||||
{
|
{
|
||||||
"require": {
|
"require": {
|
||||||
"mnapoli/php-di": "~4.0",
|
"mnapoli/php-di": "~4.0"
|
||||||
"lichtner/fluentpdo": "dev-master"
|
|
||||||
},
|
},
|
||||||
|
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
|
|
|
@ -13,7 +13,6 @@ use Szurubooru\SearchServices\Result;
|
||||||
abstract class AbstractDao implements ICrudDao, IBatchDao
|
abstract class AbstractDao implements ICrudDao, IBatchDao
|
||||||
{
|
{
|
||||||
protected $pdo;
|
protected $pdo;
|
||||||
protected $fpdo;
|
|
||||||
protected $tableName;
|
protected $tableName;
|
||||||
protected $entityConverter;
|
protected $entityConverter;
|
||||||
protected $driver;
|
protected $driver;
|
||||||
|
@ -64,7 +63,7 @@ abstract class AbstractDao implements ICrudDao, IBatchDao
|
||||||
|
|
||||||
public function findAll()
|
public function findAll()
|
||||||
{
|
{
|
||||||
$query = $this->fpdo->from($this->tableName)->disableSmartJoin();
|
$query = $this->pdo->from($this->tableName);
|
||||||
$arrayEntities = iterator_to_array($query);
|
$arrayEntities = iterator_to_array($query);
|
||||||
return $this->arrayToEntities($arrayEntities);
|
return $this->arrayToEntities($arrayEntities);
|
||||||
}
|
}
|
||||||
|
@ -81,7 +80,7 @@ abstract class AbstractDao implements ICrudDao, IBatchDao
|
||||||
|
|
||||||
public function findFiltered(IFilter $searchFilter)
|
public function findFiltered(IFilter $searchFilter)
|
||||||
{
|
{
|
||||||
$query = $this->fpdo->from($this->tableName)->disableSmartJoin();
|
$query = $this->pdo->from($this->tableName);
|
||||||
|
|
||||||
$orderByString = self::compileOrderBy($searchFilter->getOrder());
|
$orderByString = self::compileOrderBy($searchFilter->getOrder());
|
||||||
if ($orderByString)
|
if ($orderByString)
|
||||||
|
@ -95,7 +94,7 @@ abstract class AbstractDao implements ICrudDao, IBatchDao
|
||||||
}
|
}
|
||||||
$entities = $this->arrayToEntities(iterator_to_array($query));
|
$entities = $this->arrayToEntities(iterator_to_array($query));
|
||||||
|
|
||||||
$query = $this->fpdo->from($this->tableName)->disableSmartJoin();
|
$query = $this->pdo->from($this->tableName);
|
||||||
$this->decorateQueryFromFilter($query, $searchFilter);
|
$this->decorateQueryFromFilter($query, $searchFilter);
|
||||||
$totalRecords = count($query);
|
$totalRecords = count($query);
|
||||||
|
|
||||||
|
@ -114,7 +113,7 @@ abstract class AbstractDao implements ICrudDao, IBatchDao
|
||||||
{
|
{
|
||||||
$this->beforeDelete($entity);
|
$this->beforeDelete($entity);
|
||||||
}
|
}
|
||||||
$this->fpdo->deleteFrom($this->tableName)->execute();
|
$this->pdo->deleteFrom($this->tableName)->execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function deleteById($entityId)
|
public function deleteById($entityId)
|
||||||
|
@ -125,14 +124,15 @@ abstract class AbstractDao implements ICrudDao, IBatchDao
|
||||||
public function update(Entity $entity)
|
public function update(Entity $entity)
|
||||||
{
|
{
|
||||||
$arrayEntity = $this->entityConverter->toArray($entity);
|
$arrayEntity = $this->entityConverter->toArray($entity);
|
||||||
$this->fpdo->update($this->tableName)->set($arrayEntity)->where($this->getIdColumn(), $entity->getId())->execute();
|
unset($arrayEntity['id']);
|
||||||
|
$this->pdo->update($this->tableName)->set($arrayEntity)->where($this->getIdColumn(), $entity->getId())->execute();
|
||||||
return $entity;
|
return $entity;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function create(Entity $entity)
|
public function create(Entity $entity)
|
||||||
{
|
{
|
||||||
$arrayEntity = $this->entityConverter->toArray($entity);
|
$arrayEntity = $this->entityConverter->toArray($entity);
|
||||||
$this->fpdo->insertInto($this->tableName)->values($arrayEntity)->execute();
|
$this->pdo->insertInto($this->tableName)->values($arrayEntity)->execute();
|
||||||
$entity->setId(intval($this->pdo->lastInsertId()));
|
$entity->setId(intval($this->pdo->lastInsertId()));
|
||||||
return $entity;
|
return $entity;
|
||||||
}
|
}
|
||||||
|
@ -144,14 +144,14 @@ abstract class AbstractDao implements ICrudDao, IBatchDao
|
||||||
|
|
||||||
protected function hasAnyRecords()
|
protected function hasAnyRecords()
|
||||||
{
|
{
|
||||||
return count(iterator_to_array($this->fpdo->from($this->tableName)->limit(1))) > 0;
|
return count(iterator_to_array($this->pdo->from($this->tableName)->limit(1))) > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function findBy($columnName, $value)
|
protected function findBy($columnName, $value)
|
||||||
{
|
{
|
||||||
if (is_array($value) and empty($value))
|
if (is_array($value) and empty($value))
|
||||||
return [];
|
return [];
|
||||||
$query = $this->fpdo->from($this->tableName)->disableSmartJoin()->where($columnName, $value);
|
$query = $this->pdo->from($this->tableName)->where($columnName, $value);
|
||||||
$arrayEntities = iterator_to_array($query);
|
$arrayEntities = iterator_to_array($query);
|
||||||
return $this->arrayToEntities($arrayEntities);
|
return $this->arrayToEntities($arrayEntities);
|
||||||
}
|
}
|
||||||
|
@ -170,7 +170,7 @@ abstract class AbstractDao implements ICrudDao, IBatchDao
|
||||||
{
|
{
|
||||||
$this->beforeDelete($entity);
|
$this->beforeDelete($entity);
|
||||||
}
|
}
|
||||||
$this->fpdo->deleteFrom($this->tableName)->disableSmartJoin()->where($columnName, $value)->execute();
|
$this->pdo->deleteFrom($this->tableName)->where($columnName, $value)->execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function afterLoad(Entity $entity)
|
protected function afterLoad(Entity $entity)
|
||||||
|
@ -197,7 +197,7 @@ abstract class AbstractDao implements ICrudDao, IBatchDao
|
||||||
if ($value instanceof RequirementCompositeValue)
|
if ($value instanceof RequirementCompositeValue)
|
||||||
{
|
{
|
||||||
$sql = $sqlColumn;
|
$sql = $sqlColumn;
|
||||||
$bindings = [$value->getValues()];
|
$bindings = $value->getValues();
|
||||||
|
|
||||||
if ($requirement->isNegated())
|
if ($requirement->isNegated())
|
||||||
$sql = 'NOT ' . $sql;
|
$sql = 'NOT ' . $sql;
|
||||||
|
@ -239,7 +239,7 @@ abstract class AbstractDao implements ICrudDao, IBatchDao
|
||||||
else
|
else
|
||||||
throw new \Exception('Bad value: ' . get_class($value));
|
throw new \Exception('Bad value: ' . get_class($value));
|
||||||
|
|
||||||
$query->where($sql, ...$bindings);
|
$query->where($sql, $bindings);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function arrayToEntities(array $arrayEntities, $entityConverter = null)
|
protected function arrayToEntities(array $arrayEntities, $entityConverter = null)
|
||||||
|
@ -259,7 +259,6 @@ abstract class AbstractDao implements ICrudDao, IBatchDao
|
||||||
private function setDatabaseConnection(DatabaseConnection $databaseConnection)
|
private function setDatabaseConnection(DatabaseConnection $databaseConnection)
|
||||||
{
|
{
|
||||||
$this->pdo = $databaseConnection->getPDO();
|
$this->pdo = $databaseConnection->getPDO();
|
||||||
$this->fpdo = new \FluentPDO($this->pdo);
|
|
||||||
$this->driver = $databaseConnection->getDriver();
|
$this->driver = $databaseConnection->getDriver();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -60,7 +60,7 @@ class FavoritesDao extends AbstractDao implements ICrudDao
|
||||||
|
|
||||||
private function get(User $user, Entity $entity)
|
private function get(User $user, Entity $entity)
|
||||||
{
|
{
|
||||||
$query = $this->fpdo->from($this->tableName)->where('userId', $user->getId());
|
$query = $this->pdo->from($this->tableName)->where('userId', $user->getId());
|
||||||
|
|
||||||
if ($entity instanceof Post)
|
if ($entity instanceof Post)
|
||||||
$query->where('postId', $entity->getId());
|
$query->where('postId', $entity->getId());
|
||||||
|
|
|
@ -38,12 +38,12 @@ class PostDao extends AbstractDao implements ICrudDao
|
||||||
|
|
||||||
public function getCount()
|
public function getCount()
|
||||||
{
|
{
|
||||||
return count($this->fpdo->from($this->tableName));
|
return count($this->pdo->from($this->tableName));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getTotalFileSize()
|
public function getTotalFileSize()
|
||||||
{
|
{
|
||||||
$query = $this->fpdo->from($this->tableName)->select('SUM(originalFileSize) AS __sum');
|
$query = $this->pdo->from($this->tableName)->select('SUM(originalFileSize) AS __sum');
|
||||||
return intval(iterator_to_array($query)[0]['__sum']);
|
return intval(iterator_to_array($query)[0]['__sum']);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,10 +54,9 @@ class PostDao extends AbstractDao implements ICrudDao
|
||||||
|
|
||||||
public function findByTagName($tagName)
|
public function findByTagName($tagName)
|
||||||
{
|
{
|
||||||
$query = $this->fpdo->from('posts')
|
$query = $this->pdo->from('posts')
|
||||||
->disableSmartJoin()
|
->innerJoin('postTags', 'postTags.postId = posts.id')
|
||||||
->innerJoin('postTags ON postTags.postId = posts.id')
|
->innerJoin('tags', 'postTags.tagId = tags.id')
|
||||||
->innerJoin('tags ON postTags.tagId = tags.id')
|
|
||||||
->where('tags.name', $tagName);
|
->where('tags.name', $tagName);
|
||||||
$arrayEntities = iterator_to_array($query);
|
$arrayEntities = iterator_to_array($query);
|
||||||
return $this->arrayToEntities($arrayEntities);
|
return $this->arrayToEntities($arrayEntities);
|
||||||
|
@ -184,21 +183,20 @@ class PostDao extends AbstractDao implements ICrudDao
|
||||||
|
|
||||||
private function getRelatedPosts(Post $post)
|
private function getRelatedPosts(Post $post)
|
||||||
{
|
{
|
||||||
$query = $this->fpdo
|
|
||||||
->from('postRelations')
|
|
||||||
->where('post1id = :post1id OR post2id = :post2id', [
|
|
||||||
':post1id' => $post->getId(),
|
|
||||||
':post2id' => $post->getId()]);
|
|
||||||
|
|
||||||
$relatedPostIds = [];
|
$relatedPostIds = [];
|
||||||
foreach ($query as $arrayEntity)
|
|
||||||
|
foreach ($this->pdo->from('postRelations')->where('post1id', $post->getId()) as $arrayEntity)
|
||||||
{
|
{
|
||||||
$post1id = intval($arrayEntity['post1id']);
|
$postId = intval($arrayEntity['post2id']);
|
||||||
$post2id = intval($arrayEntity['post2id']);
|
if ($postId !== $post->getId())
|
||||||
if ($post1id !== $post->getId())
|
$relatedPostIds[] = $postId;
|
||||||
$relatedPostIds[] = $post1id;
|
}
|
||||||
if ($post2id !== $post->getId())
|
|
||||||
$relatedPostIds[] = $post2id;
|
foreach ($this->pdo->from('postRelations')->where('post2id', $post->getId()) as $arrayEntity)
|
||||||
|
{
|
||||||
|
$postId = intval($arrayEntity['post1id']);
|
||||||
|
if ($postId !== $post->getId())
|
||||||
|
$relatedPostIds[] = $postId;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->findByIds($relatedPostIds);
|
return $this->findByIds($relatedPostIds);
|
||||||
|
@ -242,25 +240,25 @@ class PostDao extends AbstractDao implements ICrudDao
|
||||||
{
|
{
|
||||||
return $arrayEntity['tagId'];
|
return $arrayEntity['tagId'];
|
||||||
},
|
},
|
||||||
iterator_to_array($this->fpdo->from('postTags')->where('postId', $post->getId())));
|
iterator_to_array($this->pdo->from('postTags')->where('postId', $post->getId())));
|
||||||
|
|
||||||
$tagRelationsToInsert = array_diff($tagIds, $existingTagRelationIds);
|
$tagRelationsToInsert = array_diff($tagIds, $existingTagRelationIds);
|
||||||
$tagRelationsToDelete = array_diff($existingTagRelationIds, $tagIds);
|
$tagRelationsToDelete = array_diff($existingTagRelationIds, $tagIds);
|
||||||
|
|
||||||
foreach ($tagRelationsToInsert as $tagId)
|
foreach ($tagRelationsToInsert as $tagId)
|
||||||
{
|
{
|
||||||
$this->fpdo->insertInto('postTags')->values(['postId' => $post->getId(), 'tagId' => $tagId])->execute();
|
$this->pdo->insertInto('postTags')->values(['postId' => $post->getId(), 'tagId' => $tagId])->execute();
|
||||||
}
|
}
|
||||||
foreach ($tagRelationsToDelete as $tagId)
|
foreach ($tagRelationsToDelete as $tagId)
|
||||||
{
|
{
|
||||||
$this->fpdo->deleteFrom('postTags')->where('postId', $post->getId())->where('tagId', $tagId)->execute();
|
$this->pdo->deleteFrom('postTags')->where('postId', $post->getId())->where('tagId', $tagId)->execute();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private function syncPostRelations(Post $post)
|
private function syncPostRelations(Post $post)
|
||||||
{
|
{
|
||||||
$this->fpdo->deleteFrom('postRelations')->where('post1id', $post->getId())->execute();
|
$this->pdo->deleteFrom('postRelations')->where('post1id', $post->getId())->execute();
|
||||||
$this->fpdo->deleteFrom('postRelations')->where('post2id', $post->getId())->execute();
|
$this->pdo->deleteFrom('postRelations')->where('post2id', $post->getId())->execute();
|
||||||
|
|
||||||
$relatedPostIds = array_filter(array_unique(array_map(
|
$relatedPostIds = array_filter(array_unique(array_map(
|
||||||
function ($post)
|
function ($post)
|
||||||
|
@ -273,7 +271,7 @@ class PostDao extends AbstractDao implements ICrudDao
|
||||||
|
|
||||||
foreach ($relatedPostIds as $postId)
|
foreach ($relatedPostIds as $postId)
|
||||||
{
|
{
|
||||||
$this->fpdo
|
$this->pdo
|
||||||
->insertInto('postRelations')
|
->insertInto('postRelations')
|
||||||
->values([
|
->values([
|
||||||
'post1id' => $post->getId(),
|
'post1id' => $post->getId(),
|
||||||
|
|
|
@ -27,7 +27,7 @@ class ScoreDao extends AbstractDao implements ICrudDao
|
||||||
|
|
||||||
public function getScore(User $user, Entity $entity)
|
public function getScore(User $user, Entity $entity)
|
||||||
{
|
{
|
||||||
$query = $this->fpdo->from($this->tableName)->where('userId', $user->getId());
|
$query = $this->pdo->from($this->tableName)->where('userId', $user->getId());
|
||||||
|
|
||||||
if ($entity instanceof Post)
|
if ($entity instanceof Post)
|
||||||
$query->where('postId', $entity->getId());
|
$query->where('postId', $entity->getId());
|
||||||
|
|
|
@ -24,7 +24,7 @@ class SnapshotDao extends AbstractDao
|
||||||
|
|
||||||
public function findByTypeAndKey($type, $primaryKey)
|
public function findByTypeAndKey($type, $primaryKey)
|
||||||
{
|
{
|
||||||
$query = $this->fpdo
|
$query = $this->pdo
|
||||||
->from($this->tableName)
|
->from($this->tableName)
|
||||||
->where('type', $type)
|
->where('type', $type)
|
||||||
->where('primaryKey', $primaryKey)
|
->where('primaryKey', $primaryKey)
|
||||||
|
|
|
@ -38,9 +38,8 @@ class TagDao extends AbstractDao implements ICrudDao
|
||||||
|
|
||||||
public function findByPostIds($postIds)
|
public function findByPostIds($postIds)
|
||||||
{
|
{
|
||||||
$query = $this->fpdo->from($this->tableName)
|
$query = $this->pdo->from($this->tableName)
|
||||||
->disableSmartJoin()
|
->innerJoin('postTags', 'postTags.tagId = tags.id')
|
||||||
->innerJoin('postTags ON postTags.tagId = tags.id')
|
|
||||||
->where('postTags.postId', $postIds);
|
->where('postTags.postId', $postIds);
|
||||||
$arrayEntities = iterator_to_array($query);
|
$arrayEntities = iterator_to_array($query);
|
||||||
return $this->arrayToEntities($arrayEntities);
|
return $this->arrayToEntities($arrayEntities);
|
||||||
|
@ -52,11 +51,10 @@ class TagDao extends AbstractDao implements ICrudDao
|
||||||
if (!$tag)
|
if (!$tag)
|
||||||
return [];
|
return [];
|
||||||
$tagId = $tag->getId();
|
$tagId = $tag->getId();
|
||||||
$query = $this->fpdo->from($this->tableName)
|
$query = $this->pdo->from($this->tableName)
|
||||||
->select('COUNT(pt2.postId) AS postCount')
|
->select('COUNT(pt2.postId) AS postCount')
|
||||||
->disableSmartJoin()
|
->innerJoin('postTags pt1', 'pt1.tagId = tags.id')
|
||||||
->innerJoin('postTags pt1 ON pt1.tagId = tags.id')
|
->innerJoin('postTags pt2', 'pt2.postId = pt1.postId')
|
||||||
->innerJoin('postTags pt2 ON pt2.postId = pt1.postId')
|
|
||||||
->where('pt2.tagId', $tagId)
|
->where('pt2.tagId', $tagId)
|
||||||
->groupBy('tags.id')
|
->groupBy('tags.id')
|
||||||
->orderBy('postCount DESC, name ASC');
|
->orderBy('postCount DESC, name ASC');
|
||||||
|
@ -79,7 +77,7 @@ class TagDao extends AbstractDao implements ICrudDao
|
||||||
public function export()
|
public function export()
|
||||||
{
|
{
|
||||||
$exported = [];
|
$exported = [];
|
||||||
foreach ($this->fpdo->from('tags') as $arrayEntity)
|
foreach ($this->pdo->from($this->tableName) as $arrayEntity)
|
||||||
{
|
{
|
||||||
$exported[$arrayEntity['id']] = [
|
$exported[$arrayEntity['id']] = [
|
||||||
'name' => $arrayEntity['name'],
|
'name' => $arrayEntity['name'],
|
||||||
|
@ -91,7 +89,7 @@ class TagDao extends AbstractDao implements ICrudDao
|
||||||
//upgrades on old databases
|
//upgrades on old databases
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
$relations = iterator_to_array($this->fpdo->from('tagRelations'));
|
$relations = iterator_to_array($this->pdo->from('tagRelations'));
|
||||||
}
|
}
|
||||||
catch (\Exception $e)
|
catch (\Exception $e)
|
||||||
{
|
{
|
||||||
|
@ -160,7 +158,7 @@ class TagDao extends AbstractDao implements ICrudDao
|
||||||
|
|
||||||
elseif ($requirement->getType() === TagFilter::REQUIREMENT_CATEGORY)
|
elseif ($requirement->getType() === TagFilter::REQUIREMENT_CATEGORY)
|
||||||
{
|
{
|
||||||
$sql = 'IFNULL(category, \'default\') = ?';
|
$sql = 'IFNULL(category, \'default\')';
|
||||||
$requirement->setType($sql);
|
$requirement->setType($sql);
|
||||||
return parent::decorateQueryFromRequirement($query, $requirement);
|
return parent::decorateQueryFromRequirement($query, $requirement);
|
||||||
}
|
}
|
||||||
|
@ -190,7 +188,7 @@ class TagDao extends AbstractDao implements ICrudDao
|
||||||
|
|
||||||
private function syncRelatedTagsByType(Tag $tag, array $relatedTags, $type)
|
private function syncRelatedTagsByType(Tag $tag, array $relatedTags, $type)
|
||||||
{
|
{
|
||||||
$this->fpdo->deleteFrom('tagRelations')
|
$this->pdo->deleteFrom('tagRelations')
|
||||||
->where('tag1id', $tag->getId())
|
->where('tag1id', $tag->getId())
|
||||||
->where('type', $type)
|
->where('type', $type)
|
||||||
->execute();
|
->execute();
|
||||||
|
@ -206,7 +204,7 @@ class TagDao extends AbstractDao implements ICrudDao
|
||||||
|
|
||||||
foreach ($relatedTagIds as $tagId)
|
foreach ($relatedTagIds as $tagId)
|
||||||
{
|
{
|
||||||
$this->fpdo
|
$this->pdo
|
||||||
->insertInto('tagRelations')
|
->insertInto('tagRelations')
|
||||||
->values([
|
->values([
|
||||||
'tag1id' => $tag->getId(),
|
'tag1id' => $tag->getId(),
|
||||||
|
@ -219,9 +217,8 @@ class TagDao extends AbstractDao implements ICrudDao
|
||||||
private function findRelatedTagsByType(Tag $tag, $type)
|
private function findRelatedTagsByType(Tag $tag, $type)
|
||||||
{
|
{
|
||||||
$tagId = $tag->getId();
|
$tagId = $tag->getId();
|
||||||
$query = $this->fpdo->from($this->tableName)
|
$query = $this->pdo->from($this->tableName)
|
||||||
->disableSmartJoin()
|
->innerJoin('tagRelations tr', 'tags.id = tr.tag2id')
|
||||||
->innerJoin('tagRelations tr ON tags.id = tr.tag2id')
|
|
||||||
->where('tr.type', $type)
|
->where('tr.type', $type)
|
||||||
->where('tr.tag1id', $tagId);
|
->where('tr.tag1id', $tagId);
|
||||||
$arrayEntities = iterator_to_array($query);
|
$arrayEntities = iterator_to_array($query);
|
||||||
|
|
|
@ -20,7 +20,7 @@ class TokenDao extends AbstractDao
|
||||||
|
|
||||||
public function findByAdditionalDataAndPurpose($additionalData, $purpose)
|
public function findByAdditionalDataAndPurpose($additionalData, $purpose)
|
||||||
{
|
{
|
||||||
$query = $this->fpdo->from($this->tableName)
|
$query = $this->pdo->from($this->tableName)
|
||||||
->where('additionalData', $additionalData)
|
->where('additionalData', $additionalData)
|
||||||
->where('purpose', $purpose);
|
->where('purpose', $purpose);
|
||||||
$arrayEntities = iterator_to_array($query);
|
$arrayEntities = iterator_to_array($query);
|
||||||
|
|
|
@ -52,7 +52,7 @@ class UserDao extends AbstractDao implements ICrudDao
|
||||||
public function deleteByName($userName)
|
public function deleteByName($userName)
|
||||||
{
|
{
|
||||||
$this->deleteBy('name', $userName);
|
$this->deleteBy('name', $userName);
|
||||||
$this->fpdo->deleteFrom('tokens')->where('additionalData', $userName);
|
$this->pdo->deleteFrom('tokens')->where('additionalData', $userName);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function afterLoad(Entity $user)
|
protected function afterLoad(Entity $user)
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
<?php
|
<?php
|
||||||
namespace Szurubooru;
|
namespace Szurubooru;
|
||||||
use Szurubooru\Config;
|
use Szurubooru\Config;
|
||||||
|
use Szurubooru\PDOEx\PDOEx;
|
||||||
|
|
||||||
class DatabaseConnection
|
class DatabaseConnection
|
||||||
{
|
{
|
||||||
|
|
174
src/PDOEx/BaseQuery.php
Normal file
174
src/PDOEx/BaseQuery.php
Normal file
|
@ -0,0 +1,174 @@
|
||||||
|
<?php
|
||||||
|
namespace Szurubooru\PDOEx;
|
||||||
|
|
||||||
|
abstract class BaseQuery implements \IteratorAggregate
|
||||||
|
{
|
||||||
|
const CLAUSE_BASE = 'base';
|
||||||
|
const CLAUSE_WHERE = 'where';
|
||||||
|
const CLAUSE_JOIN = 'join';
|
||||||
|
const CLAUSE_ORDER = 'order';
|
||||||
|
const CLAUSE_GROUP = 'group';
|
||||||
|
const CLAUSE_LIMIT = 'limit';
|
||||||
|
|
||||||
|
protected $table;
|
||||||
|
protected $pdoex;
|
||||||
|
|
||||||
|
protected $clauses;
|
||||||
|
protected $parameters;
|
||||||
|
|
||||||
|
public function __construct(PDOEx $pdoex, $table)
|
||||||
|
{
|
||||||
|
$this->pdoex = $pdoex;
|
||||||
|
$this->table = $table;
|
||||||
|
$this->clauses = [];
|
||||||
|
$this->parameters = [];
|
||||||
|
$this->init();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getIterator()
|
||||||
|
{
|
||||||
|
return $this->execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getQuery()
|
||||||
|
{
|
||||||
|
return $this->buildQuery();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function execute()
|
||||||
|
{
|
||||||
|
$query = $this->buildQuery();
|
||||||
|
$parameters = $this->getParameters();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
$result = $this->pdoex->prepare($query);
|
||||||
|
if (!$result || !$result->execute($parameters))
|
||||||
|
$this->throwQueryException($query, $parameters, 'unknown reason');
|
||||||
|
}
|
||||||
|
catch (\PDOException $e)
|
||||||
|
{
|
||||||
|
$this->throwQueryException($query, $parameters, $e->getMessage());
|
||||||
|
}
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function innerJoin($table, $condition)
|
||||||
|
{
|
||||||
|
if (!isset($this->clauses[self::CLAUSE_JOIN]))
|
||||||
|
$this->clauses[self::CLAUSE_JOIN] = [];
|
||||||
|
|
||||||
|
$this->clauses[self::CLAUSE_JOIN][] = 'INNER JOIN ' . $table . ' ON ' . $condition;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function where($key, $value = null)
|
||||||
|
{
|
||||||
|
if ($key === null)
|
||||||
|
{
|
||||||
|
$this->clauses[self::CLAUSE_WHERE] = [];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isset($this->clauses[self::CLAUSE_WHERE]))
|
||||||
|
$this->clauses[self::CLAUSE_WHERE] = [];
|
||||||
|
|
||||||
|
$sql = empty($this->clauses[self::CLAUSE_WHERE]) ? 'WHERE' : 'AND';
|
||||||
|
|
||||||
|
if (strpos($key, '?') !== false)
|
||||||
|
{
|
||||||
|
if (!is_array($value))
|
||||||
|
$value = [$value];
|
||||||
|
assert(substr_count($key, '?') === count($value), 'Binding ' . print_r($value, true) . ' to ' . $key);
|
||||||
|
$index = 0;
|
||||||
|
$sql .= ' ' . preg_replace_callback(
|
||||||
|
'/\?/',
|
||||||
|
function($match) use (&$index, $value)
|
||||||
|
{
|
||||||
|
$ret = $this->bind($value[$index]);
|
||||||
|
$index ++;
|
||||||
|
return $ret;
|
||||||
|
},
|
||||||
|
$key);
|
||||||
|
$this->clauses[self::CLAUSE_WHERE][] = $sql;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!is_array($value))
|
||||||
|
{
|
||||||
|
if ($value === null)
|
||||||
|
$sql .= ' ' . $key . ' IS NULL';
|
||||||
|
else
|
||||||
|
$sql .= ' ' . $key . ' = ' . $this->bind($value);
|
||||||
|
$this->clauses[self::CLAUSE_WHERE][] = $sql;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty($value))
|
||||||
|
{
|
||||||
|
$sql .= ' 0';
|
||||||
|
$this->clauses[self::CLAUSE_WHERE][] = $sql;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
$sql .= ' ' . $key . ' IN (';
|
||||||
|
foreach ($value as $id => $val)
|
||||||
|
{
|
||||||
|
$sql .= $this->bind($val) . ', ';
|
||||||
|
}
|
||||||
|
$sql = substr($sql, 0, -2);
|
||||||
|
$sql .= ')';
|
||||||
|
$this->clauses[self::CLAUSE_WHERE][] = $sql;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getParameters()
|
||||||
|
{
|
||||||
|
return $this->parameters;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function buildQuery()
|
||||||
|
{
|
||||||
|
$priorities = array_flip([
|
||||||
|
self::CLAUSE_BASE,
|
||||||
|
self::CLAUSE_JOIN,
|
||||||
|
self::CLAUSE_WHERE,
|
||||||
|
self::CLAUSE_GROUP,
|
||||||
|
self::CLAUSE_ORDER,
|
||||||
|
self::CLAUSE_LIMIT]);
|
||||||
|
uksort(
|
||||||
|
$this->clauses,
|
||||||
|
function($clauseNameA, $clauseNameB) use ($priorities)
|
||||||
|
{
|
||||||
|
return $priorities[$clauseNameA] - $priorities[$clauseNameB];
|
||||||
|
});
|
||||||
|
|
||||||
|
$query = '';
|
||||||
|
foreach ($this->clauses as $statements)
|
||||||
|
{
|
||||||
|
if (!is_array($statements))
|
||||||
|
$statements = [$statements];
|
||||||
|
foreach ($statements as $statement)
|
||||||
|
$query .= ' ' . $statement;
|
||||||
|
}
|
||||||
|
return trim($query);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract function init();
|
||||||
|
|
||||||
|
protected function bind($value)
|
||||||
|
{
|
||||||
|
$id = ':' . uniqid();
|
||||||
|
$this->parameters[$id] = $value;
|
||||||
|
return $id;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function throwQueryException($query, $parameters, $message)
|
||||||
|
{
|
||||||
|
throw new \Exception(sprintf(
|
||||||
|
'Problem executing query "%s" with parameters %s: %s',
|
||||||
|
$query,
|
||||||
|
print_r($parameters, true),
|
||||||
|
$message));
|
||||||
|
}
|
||||||
|
}
|
10
src/PDOEx/DeleteQuery.php
Normal file
10
src/PDOEx/DeleteQuery.php
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
<?php
|
||||||
|
namespace Szurubooru\PDOEx;
|
||||||
|
|
||||||
|
class DeleteQuery extends BaseQuery
|
||||||
|
{
|
||||||
|
protected function init()
|
||||||
|
{
|
||||||
|
$this->clauses[self::CLAUSE_BASE] = 'DELETE FROM ' . $this->table;
|
||||||
|
}
|
||||||
|
}
|
41
src/PDOEx/InsertQuery.php
Normal file
41
src/PDOEx/InsertQuery.php
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
<?php
|
||||||
|
namespace Szurubooru\PDOEx;
|
||||||
|
|
||||||
|
class InsertQuery extends BaseQuery
|
||||||
|
{
|
||||||
|
private $values = [];
|
||||||
|
|
||||||
|
public function values(array $values)
|
||||||
|
{
|
||||||
|
$this->values = $values;
|
||||||
|
$this->refreshBaseQuery();
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function where($key, $value = null)
|
||||||
|
{
|
||||||
|
throw new \BadMethodCallException('This makes no sense!');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function innerJoin($table, $condition)
|
||||||
|
{
|
||||||
|
throw new \BadMethodCallException('This makes no sense!');
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function init()
|
||||||
|
{
|
||||||
|
$this->refreshBaseQuery();
|
||||||
|
}
|
||||||
|
|
||||||
|
private function refreshBaseQuery()
|
||||||
|
{
|
||||||
|
$sql = 'INSERT INTO ' . $this->table;
|
||||||
|
$sql .= ' (' . implode(', ', array_keys($this->values)) . ')';
|
||||||
|
$sql .= ' VALUES (';
|
||||||
|
foreach ($this->values as $value)
|
||||||
|
$sql .= $this->bind($value) . ', ';
|
||||||
|
$sql = substr($sql, 0, -2);
|
||||||
|
$sql .= ')';
|
||||||
|
$this->clauses[self::CLAUSE_BASE] = $sql;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
<?php
|
<?php
|
||||||
namespace Szurubooru;
|
namespace Szurubooru\PDOEx;
|
||||||
|
|
||||||
class PDOEx extends \PDO
|
class PDOEx extends \PDO
|
||||||
{
|
{
|
||||||
|
@ -22,4 +22,24 @@ class PDOEx extends \PDO
|
||||||
{
|
{
|
||||||
return $this->statements;
|
return $this->statements;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function from($table)
|
||||||
|
{
|
||||||
|
return new SelectQuery($this, $table);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function insertInto($table)
|
||||||
|
{
|
||||||
|
return new InsertQuery($this, $table);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function update($table)
|
||||||
|
{
|
||||||
|
return new UpdateQuery($this, $table);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function deleteFrom($table)
|
||||||
|
{
|
||||||
|
return new DeleteQuery($this, $table);
|
||||||
|
}
|
||||||
}
|
}
|
95
src/PDOEx/SelectQuery.php
Normal file
95
src/PDOEx/SelectQuery.php
Normal file
|
@ -0,0 +1,95 @@
|
||||||
|
<?php
|
||||||
|
namespace Szurubooru\PDOEx;
|
||||||
|
|
||||||
|
class SelectQuery extends BaseQuery implements \Countable
|
||||||
|
{
|
||||||
|
private $selectTarget = '';
|
||||||
|
private $orderTarget = '';
|
||||||
|
private $offset = 0;
|
||||||
|
private $limit = null;
|
||||||
|
|
||||||
|
public function limit($limit)
|
||||||
|
{
|
||||||
|
if ($limit === null or $limit === false)
|
||||||
|
$this->limit = null;
|
||||||
|
else
|
||||||
|
$this->limit = intval($limit);
|
||||||
|
$this->refreshLimitClause();
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function offset($offset)
|
||||||
|
{
|
||||||
|
$this->offset = intval($offset);
|
||||||
|
$this->refreshLimitClause();
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function select($key)
|
||||||
|
{
|
||||||
|
if ($key === null)
|
||||||
|
$this->selectTarget = '';
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ($this->selectTarget)
|
||||||
|
$this->selectTarget .= ', ';
|
||||||
|
$this->selectTarget .= $key;
|
||||||
|
}
|
||||||
|
$this->refreshBaseClause();
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function orderBy($key, $dir = null)
|
||||||
|
{
|
||||||
|
if ($key === null)
|
||||||
|
$this->orderTarget = '';
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ($this->orderTarget)
|
||||||
|
$this->orderTarget .= ', ';
|
||||||
|
$this->orderTarget .= rtrim($key . ' ' . $dir);
|
||||||
|
}
|
||||||
|
$this->refreshOrderClause();
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function groupBy($key)
|
||||||
|
{
|
||||||
|
$this->clauses[self::CLAUSE_GROUP] = 'GROUP BY ' . $key;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function count()
|
||||||
|
{
|
||||||
|
$query = clone($this);
|
||||||
|
return iterator_to_array($query->select(null)->select('COUNT(1) AS c'))[0]['c'];
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function init()
|
||||||
|
{
|
||||||
|
$this->selectTarget = $this->table . '.*';
|
||||||
|
$this->refreshBaseClause();
|
||||||
|
}
|
||||||
|
|
||||||
|
private function refreshBaseClause()
|
||||||
|
{
|
||||||
|
$this->clauses[self::CLAUSE_BASE] = 'SELECT ' . $this->selectTarget . ' FROM ' . $this->table;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function refreshOrderClause()
|
||||||
|
{
|
||||||
|
$this->clauses[self::CLAUSE_ORDER] = 'ORDER BY ' . $this->orderTarget;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function refreshLimitClause()
|
||||||
|
{
|
||||||
|
$sql = '';
|
||||||
|
if ($this->limit !== null)
|
||||||
|
{
|
||||||
|
$sql .= 'LIMIT ' . $this->limit;
|
||||||
|
if ($this->offset !== null and $this->offset !== 0)
|
||||||
|
$sql .= ' OFFSET ' . intval($this->offset);
|
||||||
|
}
|
||||||
|
$this->clauses[self::CLAUSE_LIMIT] = $sql;
|
||||||
|
}
|
||||||
|
}
|
34
src/PDOEx/UpdateQuery.php
Normal file
34
src/PDOEx/UpdateQuery.php
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
<?php
|
||||||
|
namespace Szurubooru\PDOEx;
|
||||||
|
|
||||||
|
class UpdateQuery extends BaseQuery
|
||||||
|
{
|
||||||
|
private $values = [];
|
||||||
|
|
||||||
|
public function set(array $values)
|
||||||
|
{
|
||||||
|
$this->values = $values;
|
||||||
|
$this->refreshBaseQuery();
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function innerJoin($table, $condition)
|
||||||
|
{
|
||||||
|
throw new \BadMethodCallException('This makes no sense!');
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function init()
|
||||||
|
{
|
||||||
|
$this->refreshBaseQuery();
|
||||||
|
}
|
||||||
|
|
||||||
|
private function refreshBaseQuery()
|
||||||
|
{
|
||||||
|
$sql = 'UPDATE ' . $this->table;
|
||||||
|
$sql .= ' SET ';
|
||||||
|
foreach ($this->values as $key => $value)
|
||||||
|
$sql .= $key . ' = ' . $this->bind($value) . ', ';
|
||||||
|
$sql = substr($sql, 0, -2);
|
||||||
|
$this->clauses[self::CLAUSE_BASE] = $sql;
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,6 +4,12 @@ namespace Szurubooru\SearchServices\Requirements;
|
||||||
class RequirementCompositeValue implements IRequirementValue
|
class RequirementCompositeValue implements IRequirementValue
|
||||||
{
|
{
|
||||||
private $values = [];
|
private $values = [];
|
||||||
|
|
||||||
|
public function __construct(array $values = [])
|
||||||
|
{
|
||||||
|
$this->setValues($values);
|
||||||
|
}
|
||||||
|
|
||||||
public function getValues()
|
public function getValues()
|
||||||
{
|
{
|
||||||
return $this->values;
|
return $this->values;
|
||||||
|
|
|
@ -145,6 +145,29 @@ final class PostDaoTest extends AbstractDatabaseTestCase
|
||||||
$this->assertEquals(1, count($postDao->findAll()));
|
$this->assertEquals(1, count($postDao->findAll()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testFindingByTagName()
|
||||||
|
{
|
||||||
|
$tag1 = new Tag();
|
||||||
|
$tag1->setName('tag1');
|
||||||
|
$tag1->setCreationTime(date('c'));
|
||||||
|
$tag2 = new Tag();
|
||||||
|
$tag2->setName('tag2');
|
||||||
|
$tag2->setCreationTime(date('c'));
|
||||||
|
$this->tagDao->save($tag1);
|
||||||
|
$this->tagDao->save($tag2);
|
||||||
|
|
||||||
|
$postDao = $this->getPostDao();
|
||||||
|
$post1 = self::getTestPost();
|
||||||
|
$post1->setTags([$tag1]);
|
||||||
|
$postDao->save($post1);
|
||||||
|
$post2 = self::getTestPost();
|
||||||
|
$post2->setTags([$tag2]);
|
||||||
|
$postDao->save($post2);
|
||||||
|
|
||||||
|
$this->assertEntitiesEqual([$post1], array_values($postDao->findByTagName('tag1')));
|
||||||
|
$this->assertEntitiesEqual([$post2], array_values($postDao->findByTagName('tag2')));
|
||||||
|
}
|
||||||
|
|
||||||
public function testSavingTags()
|
public function testSavingTags()
|
||||||
{
|
{
|
||||||
$tag1 = new Tag();
|
$tag1 = new Tag();
|
||||||
|
|
|
@ -5,6 +5,7 @@ use Szurubooru\Entities\Tag;
|
||||||
use Szurubooru\SearchServices\Filters\TagFilter;
|
use Szurubooru\SearchServices\Filters\TagFilter;
|
||||||
use Szurubooru\SearchServices\Requirements\Requirement;
|
use Szurubooru\SearchServices\Requirements\Requirement;
|
||||||
use Szurubooru\SearchServices\Requirements\RequirementSingleValue;
|
use Szurubooru\SearchServices\Requirements\RequirementSingleValue;
|
||||||
|
use Szurubooru\SearchServices\Requirements\RequirementCompositeValue;
|
||||||
use Szurubooru\SearchServices\Result;
|
use Szurubooru\SearchServices\Result;
|
||||||
use Szurubooru\Tests\AbstractDatabaseTestCase;
|
use Szurubooru\Tests\AbstractDatabaseTestCase;
|
||||||
|
|
||||||
|
@ -34,6 +35,30 @@ final class TagDaoFilterTest extends AbstractDatabaseTestCase
|
||||||
$this->assertEntitiesEqual([$tag3, $tag1], array_values($result->getEntities()));
|
$this->assertEntitiesEqual([$tag3, $tag1], array_values($result->getEntities()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testCompositeCategories()
|
||||||
|
{
|
||||||
|
$tag1 = $this->getTestTag('test 1');
|
||||||
|
$tag2 = $this->getTestTag('test 2');
|
||||||
|
$tag3 = $this->getTestTag('test 3');
|
||||||
|
$tag1->setCategory(null);
|
||||||
|
$tag2->setCategory('misc');
|
||||||
|
$tag3->setCategory('other');
|
||||||
|
$tagDao = $this->getTagDao();
|
||||||
|
$tagDao->save($tag1);
|
||||||
|
$tagDao->save($tag2);
|
||||||
|
$tagDao->save($tag3);
|
||||||
|
|
||||||
|
$searchFilter = new TagFilter();
|
||||||
|
$requirement = new Requirement();
|
||||||
|
$requirement->setType(TagFilter::REQUIREMENT_CATEGORY);
|
||||||
|
$requirement->setValue(new RequirementCompositeValue(['misc', 'other']));
|
||||||
|
$requirement->setNegated(true);
|
||||||
|
$searchFilter->addRequirement($requirement);
|
||||||
|
$result = $tagDao->findFiltered($searchFilter);
|
||||||
|
$this->assertEquals(1, $result->getTotalRecords());
|
||||||
|
$this->assertEntitiesEqual([$tag1], array_values($result->getEntities()));
|
||||||
|
}
|
||||||
|
|
||||||
private function getTagDao()
|
private function getTagDao()
|
||||||
{
|
{
|
||||||
return new TagDao($this->databaseConnection);
|
return new TagDao($this->databaseConnection);
|
||||||
|
|
27
tests/PDOEx/DeleteQueryTest.php
Normal file
27
tests/PDOEx/DeleteQueryTest.php
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
<?php
|
||||||
|
namespace Szurubooru\Tests\PDOEx;
|
||||||
|
use Szurubooru\PDOEx\DeleteQuery;
|
||||||
|
use Szurubooru\PDOEx\PDOEx;
|
||||||
|
use Szurubooru\Tests\AbstractTestCase;
|
||||||
|
|
||||||
|
final class DeleteQueryTest extends AbstractTestCase
|
||||||
|
{
|
||||||
|
public function testDefault()
|
||||||
|
{
|
||||||
|
$query = $this->getDeleteQuery();
|
||||||
|
$this->assertEquals('DELETE FROM test', $query->getQuery());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testBasicWhere()
|
||||||
|
{
|
||||||
|
$query = $this->getDeleteQuery();
|
||||||
|
$query->where('column', 'value');
|
||||||
|
$this->assertRegExp('/^DELETE FROM test WHERE column = :[\w]*$/', $query->getQuery());
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getDeleteQuery()
|
||||||
|
{
|
||||||
|
$pdoMock = $this->mock(PDOEx::class);
|
||||||
|
return new DeleteQuery($pdoMock, 'test');
|
||||||
|
}
|
||||||
|
}
|
21
tests/PDOEx/InsertQueryTest.php
Normal file
21
tests/PDOEx/InsertQueryTest.php
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
<?php
|
||||||
|
namespace Szurubooru\Tests\PDOEx;
|
||||||
|
use Szurubooru\PDOEx\InsertQuery;
|
||||||
|
use Szurubooru\PDOEx\PDOEx;
|
||||||
|
use Szurubooru\Tests\AbstractTestCase;
|
||||||
|
|
||||||
|
final class InsertQueryTest extends AbstractTestCase
|
||||||
|
{
|
||||||
|
public function testDefault()
|
||||||
|
{
|
||||||
|
$query = $this->getInsertQuery();
|
||||||
|
$query->values(['key1' => 'value', 'key2' => 'value2']);
|
||||||
|
$this->assertRegExp('/^INSERT INTO test \(key1, key2\) VALUES \(:\w*, :\w*\)$/', $query->getQuery());
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getInsertQuery()
|
||||||
|
{
|
||||||
|
$pdoMock = $this->mock(PDOEx::class);
|
||||||
|
return new InsertQuery($pdoMock, 'test');
|
||||||
|
}
|
||||||
|
}
|
188
tests/PDOEx/SelectQueryTest.php
Normal file
188
tests/PDOEx/SelectQueryTest.php
Normal file
|
@ -0,0 +1,188 @@
|
||||||
|
<?php
|
||||||
|
namespace Szurubooru\Tests\PDOEx;
|
||||||
|
use Szurubooru\PDOEx\PDOEx;
|
||||||
|
use Szurubooru\PDOEx\SelectQuery;
|
||||||
|
use Szurubooru\Tests\AbstractTestCase;
|
||||||
|
|
||||||
|
final class SelectQueryTest extends AbstractTestCase
|
||||||
|
{
|
||||||
|
public function testDefault()
|
||||||
|
{
|
||||||
|
$query = $this->getSelectQuery();
|
||||||
|
$this->assertEquals('SELECT test.* FROM test', $query->getQuery());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testAdditionalColumns()
|
||||||
|
{
|
||||||
|
$query = $this->getSelectQuery();
|
||||||
|
$query->select('SUM(1) AS sum');
|
||||||
|
$query->select('something else');
|
||||||
|
$this->assertEquals('SELECT test.*, SUM(1) AS sum, something else FROM test', $query->getQuery());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testResettingAdditionalColumns()
|
||||||
|
{
|
||||||
|
$query = $this->getSelectQuery();
|
||||||
|
$query->select(null);
|
||||||
|
$query->select('SUM(1) AS sum');
|
||||||
|
$this->assertEquals('SELECT SUM(1) AS sum FROM test', $query->getQuery());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testInnerJoin()
|
||||||
|
{
|
||||||
|
$query = $this->getSelectQuery();
|
||||||
|
$query->innerJoin('test2', 'test2.id = test.foreignId');
|
||||||
|
$this->assertEquals('SELECT test.* FROM test INNER JOIN test2 ON test2.id = test.foreignId', $query->getQuery());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testMultipleInnerJoins()
|
||||||
|
{
|
||||||
|
$query = $this->getSelectQuery();
|
||||||
|
$query->innerJoin('test2', 'test2.id = test.foreignId');
|
||||||
|
$query->innerJoin('test3', 'test3.id = test2.foreignId');
|
||||||
|
$this->assertEquals('SELECT test.* FROM test INNER JOIN test2 ON test2.id = test.foreignId INNER JOIN test3 ON test3.id = test2.foreignId', $query->getQuery());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testSelectAfterInnerJoin()
|
||||||
|
{
|
||||||
|
$query = $this->getSelectQuery();
|
||||||
|
$query->innerJoin('test2', 'test2.id = test.foreignId');
|
||||||
|
$query->select('whatever');
|
||||||
|
$this->assertEquals('SELECT test.*, whatever FROM test INNER JOIN test2 ON test2.id = test.foreignId', $query->getQuery());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testBasicWhere()
|
||||||
|
{
|
||||||
|
$query = $this->getSelectQuery();
|
||||||
|
$query->where('column', 'value');
|
||||||
|
$this->assertRegExp('/^SELECT test\.\* FROM test WHERE column = :[\w]*$/', $query->getQuery());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testMultipleWhere()
|
||||||
|
{
|
||||||
|
$query = $this->getSelectQuery();
|
||||||
|
$query->where('column1', 'value1');
|
||||||
|
$query->where('column2', 'value2');
|
||||||
|
$this->assertRegExp('/^SELECT test\.\* FROM test WHERE column1 = :\w* AND column2 = :\w*$/', $query->getQuery());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testManualWhere()
|
||||||
|
{
|
||||||
|
$query = $this->getSelectQuery();
|
||||||
|
$query->where('column1 >= ? AND column2 <= ?', ['value1', 'value2']);
|
||||||
|
$this->assertRegExp('/^SELECT test\.\* FROM test WHERE column1 >= :\w* AND column2 <= :\w*$/', $query->getQuery());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testWhereNull()
|
||||||
|
{
|
||||||
|
$query = $this->getSelectQuery();
|
||||||
|
$query->where('column', null);
|
||||||
|
$this->assertRegExp('/^SELECT test\.\* FROM test WHERE column IS NULL$/', $query->getQuery());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testResettingWhere()
|
||||||
|
{
|
||||||
|
$query = $this->getSelectQuery();
|
||||||
|
$query->where('column1', 'value1');
|
||||||
|
$query->where(null);
|
||||||
|
$query->where('column2', 'value2');
|
||||||
|
$this->assertRegExp('/^SELECT test\.\* FROM test WHERE column2 = :\w*$/', $query->getQuery());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testEmptyIn()
|
||||||
|
{
|
||||||
|
$query = $this->getSelectQuery();
|
||||||
|
$query->where('column', []);
|
||||||
|
$this->assertRegExp('/^SELECT test\.\* FROM test WHERE 0$/', $query->getQuery());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testIn()
|
||||||
|
{
|
||||||
|
$query = $this->getSelectQuery();
|
||||||
|
$query->where('column', ['val1', 'val2']);
|
||||||
|
$this->assertRegExp('/^SELECT test\.\* FROM test WHERE column IN \(:\w*, :\w*\)$/', $query->getQuery());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testMixedInAndWhere()
|
||||||
|
{
|
||||||
|
$query = $this->getSelectQuery();
|
||||||
|
$query->where('column1', ['val1', 'val2']);
|
||||||
|
$query->where('column2', 'val3');
|
||||||
|
$this->assertRegExp('/^SELECT test\.\* FROM test WHERE column1 IN \(:\w*, :\w*\) AND column2 = :\w*$/', $query->getQuery());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testGroupBy()
|
||||||
|
{
|
||||||
|
$query = $this->getSelectQuery();
|
||||||
|
$query->groupBy('test.id');
|
||||||
|
$this->assertEquals('SELECT test.* FROM test GROUP BY test.id', $query->getQuery());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testGroupByAndOrderBy()
|
||||||
|
{
|
||||||
|
$query = $this->getSelectQuery();
|
||||||
|
$query->groupBy('test.id');
|
||||||
|
$query->orderBy('test.whatever');
|
||||||
|
$this->assertEquals('SELECT test.* FROM test GROUP BY test.id ORDER BY test.whatever', $query->getQuery());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testOrderBy()
|
||||||
|
{
|
||||||
|
$query = $this->getSelectQuery();
|
||||||
|
$query->orderBy('id DESC');
|
||||||
|
$this->assertEquals('SELECT test.* FROM test ORDER BY id DESC', $query->getQuery());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testOrderByFlavor2()
|
||||||
|
{
|
||||||
|
$query = $this->getSelectQuery();
|
||||||
|
$query->orderBy('id', 'DESC');
|
||||||
|
$this->assertEquals('SELECT test.* FROM test ORDER BY id DESC', $query->getQuery());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testOrderByMultiple()
|
||||||
|
{
|
||||||
|
$query = $this->getSelectQuery();
|
||||||
|
$query->orderBy('id', 'DESC');
|
||||||
|
$query->orderBy('id2', 'ASC');
|
||||||
|
$this->assertEquals('SELECT test.* FROM test ORDER BY id DESC, id2 ASC', $query->getQuery());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testResettingOrderBy()
|
||||||
|
{
|
||||||
|
$query = $this->getSelectQuery();
|
||||||
|
$query->orderBy('id', 'DESC');
|
||||||
|
$query->orderBy(null);
|
||||||
|
$query->orderBy('id2', 'ASC');
|
||||||
|
$this->assertEquals('SELECT test.* FROM test ORDER BY id2 ASC', $query->getQuery());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testLimit()
|
||||||
|
{
|
||||||
|
$query = $this->getSelectQuery();
|
||||||
|
$query->limit(5);
|
||||||
|
$this->assertEquals('SELECT test.* FROM test LIMIT 5', $query->getQuery());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testLimitWithOffset()
|
||||||
|
{
|
||||||
|
$query = $this->getSelectQuery();
|
||||||
|
$query->offset(2);
|
||||||
|
$query->limit(5);
|
||||||
|
$this->assertEquals('SELECT test.* FROM test LIMIT 5 OFFSET 2', $query->getQuery());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testOffsetWithoutLimit()
|
||||||
|
{
|
||||||
|
$query = $this->getSelectQuery();
|
||||||
|
$query->offset(2);
|
||||||
|
$query->limit(null);
|
||||||
|
$this->assertEquals('SELECT test.* FROM test', $query->getQuery());
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getSelectQuery()
|
||||||
|
{
|
||||||
|
$pdoMock = $this->mock(PDOEx::class);
|
||||||
|
return new SelectQuery($pdoMock, 'test');
|
||||||
|
}
|
||||||
|
}
|
21
tests/PDOEx/UpdateQueryTest.php
Normal file
21
tests/PDOEx/UpdateQueryTest.php
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
<?php
|
||||||
|
namespace Szurubooru\Tests\PDOEx;
|
||||||
|
use Szurubooru\PDOEx\PDOEx;
|
||||||
|
use Szurubooru\PDOEx\UpdateQuery;
|
||||||
|
use Szurubooru\Tests\AbstractTestCase;
|
||||||
|
|
||||||
|
final class UpdateQueryTest extends AbstractTestCase
|
||||||
|
{
|
||||||
|
public function testDefault()
|
||||||
|
{
|
||||||
|
$query = $this->getUpdateQuery();
|
||||||
|
$query->set(['key1' => 'value', 'key2' => 'value2']);
|
||||||
|
$this->assertRegExp('/^UPDATE test SET key1 = :\w*, key2 = :\w*$/', $query->getQuery());
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getUpdateQuery()
|
||||||
|
{
|
||||||
|
$pdoMock = $this->mock(PDOEx::class);
|
||||||
|
return new UpdateQuery($pdoMock, 'test');
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue