This repository has been archived on 2025-02-26. You can view files and clone it, but cannot push or open issues or pull requests.
szurubooru/src/Models/Model_Post_QueryBuilder.php

414 lines
9.5 KiB
PHP
Raw Normal View History

2013-10-28 11:19:15 +01:00
<?php
class Model_Post_QueryBuilder implements AbstractQueryBuilder
{
protected static function attachTableCount($dbQuery, $tableName, $shortName)
{
$dbQuery
->addSql(', ')
->open()
->select('COUNT(1)')
->from($tableName)
->where($tableName . '.post_id = post.id')
->close()
->as($shortName . '_count');
}
protected static function attachCommentCount($dbQuery)
{
self::attachTableCount($dbQuery, 'comment', 'comment');
}
protected static function attachFavCount($dbQuery)
{
self::attachTableCount($dbQuery, 'favoritee', 'fav');
}
protected static function attachTagCount($dbQuery)
{
self::attachTableCount($dbQuery, 'post_tag', 'tag');
}
protected static function filterUserSafety($dbQuery)
{
2013-10-30 16:22:46 +01:00
$allowedSafety = PrivilegesHelper::getAllowedSafety();
2013-10-28 11:19:15 +01:00
$dbQuery->addSql('safety')->in('(' . R::genSlots($allowedSafety) . ')');
foreach ($allowedSafety as $s)
$dbQuery->put($s);
}
protected static function filterUserHidden($dbQuery)
{
if (!PrivilegesHelper::confirm(Privilege::ListPosts, 'hidden'))
$dbQuery->not()->addSql('hidden');
else
$dbQuery->addSql('1');
}
protected static function filterChain($dbQuery)
{
if (isset($dbQuery->__chained))
$dbQuery->and();
else
$dbQuery->where();
$dbQuery->__chained = true;
}
protected static function filterNegate($dbQuery)
{
$dbQuery->not();
}
protected static function filterTag($dbQuery, $val)
{
$dbQuery
->exists()
->open()
->select('1')
->from('post_tag')
->innerJoin('tag')
->on('post_tag.tag_id = tag.id')
->where('post_id = post.id')
->and('LOWER(tag.name) = LOWER(?)')->put($val)
->close();
}
protected static function filterTokenId($dbQuery, $val)
{
$ids = preg_split('/[;,]/', $val);
$ids = array_map('intval', $ids);
$dbQuery->addSql('id')->in('(' . R::genSlots($ids) . ')');
foreach ($ids as $id)
$dbQuery->put($id);
}
protected static function filterTokenIdMin($dbQuery, $val)
{
$dbQuery->addSql('id >= ?')->put(intval($val));
}
protected static function filterTokenIdMax($dbQuery, $val)
{
$dbQuery->addSql('id <= ?')->put(intval($val));
}
2013-11-10 12:23:59 +01:00
protected static function filterTokenScoreMin($dbQuery, $val)
{
$dbQuery->addSql('score >= ?')->put(intval($val));
}
protected static function filterTokenScoreMax($dbQuery, $val)
{
$dbQuery->addSql('score <= ?')->put(intval($val));
}
2013-10-28 11:19:15 +01:00
protected static function filterTokenTagMin($dbQuery, $val)
{
$dbQuery->addSql('tag_count >= ?')->put(intval($val));
}
protected static function filterTokenTagMax($dbQuery, $val)
{
$dbQuery->addSql('tag_count <= ?')->put(intval($val));
}
protected static function filterTokenFavMin($dbQuery, $val)
{
$dbQuery->addSql('fav_count >= ?')->put(intval($val));
}
protected static function filterTokenFavMax($dbQuery, $val)
{
$dbQuery->addSql('fav_count <= ?')->put(intval($val));
}
protected static function filterTokenCommentMin($dbQuery, $val)
{
$dbQuery->addSql('comment_count >= ?')->put(intval($val));
}
protected static function filterTokenCommentMax($dbQuery, $val)
{
$dbQuery->addSql('comment_count <= ?')->put(intval($val));
}
protected static function filterTokenType($dbQuery, $val)
{
switch (strtolower($val))
2013-10-28 11:19:15 +01:00
{
case 'swf':
$type = PostType::Flash;
break;
case 'img':
$type = PostType::Image;
break;
case 'yt':
case 'youtube':
$type = PostType::Youtube;
break;
default:
throw new SimpleException('Unknown type "' . $val . '"');
}
$dbQuery->addSql('type = ?')->put($type);
}
protected static function __filterTokenDateParser($val)
{
list ($year, $month, $day) = explode('-', $val . '-0-0');
$yearMin = $yearMax = intval($year);
$monthMin = $monthMax = intval($month);
$monthMin = $monthMin ?: 1;
$monthMax = $monthMax ?: 12;
$dayMin = $dayMax = intval($day);
$dayMin = $dayMin ?: 1;
$dayMax = $dayMax ?: intval(date('t', mktime(0, 0, 0, $monthMax, 1, $year)));
$timeMin = mktime(0, 0, 0, $monthMin, $dayMin, $yearMin);
$timeMax = mktime(0, 0, -1, $monthMax, $dayMax+1, $yearMax);
return [$timeMin, $timeMax];
}
protected static function filterTokenDate($dbQuery, $val)
{
list ($timeMin, $timeMax) = self::__filterTokenDateParser($val);
$dbQuery
->addSql('upload_date >= ?')->and('upload_date <= ?')
->put($timeMin)
->put($timeMax);
}
protected static function filterTokenDateMin($dbQuery, $val)
{
list ($timeMin, $timeMax) = self::__filterTokenDateParser($val);
$dbQuery->addSql('upload_date >= ?')->put($timeMin);
}
protected static function filterTokenDateMax($dbQuery, $val)
{
list ($timeMin, $timeMax) = self::__filterTokenDateParser($val);
$dbQuery->addSql('upload_date <= ?')->put($timeMax);
}
protected static function filterTokenFav($dbQuery, $val)
{
$dbQuery
->exists()
->open()
->select('1')
->from('favoritee')
->innerJoin('user')
->on('favoritee.user_id = user.id')
->where('post_id = post.id')
2013-11-21 22:29:38 +01:00
->and('LOWER(user.name) = LOWER(?)')->put($val)
2013-10-28 11:19:15 +01:00
->close();
}
protected static function filterTokenFavs($dbQuery, $val)
{
return self::filterTokenFav($dbQuery, $val);
}
protected static function filterTokenFavitee($dbQuery, $val)
{
return self::filterTokenFav($dbQuery, $val);
}
protected static function filterTokenFaviter($dbQuery, $val)
{
return self::filterTokenFav($dbQuery, $val);
}
protected static function filterTokenComment($dbQuery, $val)
{
$dbQuery
->exists()
->open()
->select('1')
->from('comment')
->innerJoin('user')
->on('commenter_id = user.id')
->where('post_id = post.id')
2013-11-21 22:29:38 +01:00
->and('LOWER(user.name) = LOWER(?)')->put($val)
->close();
}
protected static function filterTokenCommenter($dbQuery, $val)
{
return self::filterTokenComment($dbQuery, $val);
}
2013-10-28 11:19:15 +01:00
protected static function filterTokenSubmit($dbQuery, $val)
{
$dbQuery
->addSql('uploader_id = ')
->open()
->select('user.id')
->from('user')
2013-11-21 22:29:38 +01:00
->where('LOWER(name) = LOWER(?)')->put($val)
2013-10-28 11:19:15 +01:00
->close();
}
protected static function filterTokenUploader($dbQuery, $val)
{
return self::filterTokenSubmit($dbQuery, $val);
}
protected static function filterTokenUpload($dbQuery, $val)
{
return self::filterTokenSubmit($dbQuery, $val);
}
protected static function filterTokenUploaded($dbQuery, $val)
{
return self::filterTokenSubmit($dbQuery, $val);
}
protected static function order($dbQuery, $val)
{
$randomReset = true;
$orderDir = 1;
if (substr($val, -4) == 'desc')
{
$orderDir = 1;
$val = rtrim(substr($val, 0, -4), ',');
}
elseif (substr($val, -3) == 'asc')
{
$orderDir = -1;
$val = rtrim(substr($val, 0, -3), ',');
}
if ($val{0} == '-')
{
$orderDir *= -1;
$val = substr($val, 1);
}
switch ($val)
{
case 'id':
$orderColumn = 'post.id';
break;
case 'date':
$orderColumn = 'post.upload_date';
break;
case 'comment':
case 'comments':
case 'commentcount':
$orderColumn = 'comment_count';
break;
case 'fav':
case 'favs':
case 'favcount':
$orderColumn = 'fav_count';
break;
2013-11-10 12:23:59 +01:00
case 'score':
$orderDir *= -1;
$orderColumn = 'score';
break;
2013-10-28 11:19:15 +01:00
case 'tag':
case 'tags':
case 'tagcount':
$orderColumn = 'tag_count';
break;
case 'random':
//seeding works like this: if you visit anything
//that triggers order other than random, the seed
//is going to reset. however, it stays the same as
//long as you keep visiting pages with order:random
//specified.
$randomReset = false;
if (!isset($_SESSION['browsing-seed']))
$_SESSION['browsing-seed'] = mt_rand();
$seed = $_SESSION['browsing-seed'];
$orderColumn = 'SUBSTR(id * ' . $seed .', LENGTH(id) + 2)';
break;
default:
throw new SimpleException('Unknown key "' . $val . '"');
}
if ($randomReset and isset($_SESSION['browsing-seed']))
2013-10-28 11:19:15 +01:00
unset($_SESSION['browsing-seed']);
$dbQuery->orderBy($orderColumn);
if ($orderDir == 1)
$dbQuery->desc();
else
$dbQuery->asc();
}
public static function build($dbQuery, $query)
{
$config = \Chibi\Registry::getConfig();
self::attachCommentCount($dbQuery);
self::attachFavCount($dbQuery);
self::attachTagCount($dbQuery);
$dbQuery->from('post');
self::filterChain($dbQuery);
self::filterUserSafety($dbQuery);
self::filterChain($dbQuery);
self::filterUserHidden($dbQuery);
/* query tokens */
$tokens = array_filter(array_unique(explode(' ', $query)), function($x) { return $x != ''; });
if (count($tokens) > $config->browsing->maxSearchTokens)
throw new SimpleException('Too many search tokens (maximum: ' . $config->browsing->maxSearchTokens . ')');
$orderToken = 'id';
foreach ($tokens as $token)
{
if ($token{0} == '-')
{
$token = substr($token, 1);
$neg = true;
}
else
{
$neg = false;
}
$pos = strpos($token, ':');
if ($pos === false)
{
self::filterChain($dbQuery);
if ($neg)
self::filterNegate($dbQuery);
self::filterTag($dbQuery, $token);
continue;
}
$key = strtolower(substr($token, 0, $pos));
2013-10-28 11:19:15 +01:00
$val = substr($token, $pos + 1);
$methodName = 'filterToken' . TextHelper::kebabCaseToCamelCase($key);
if (method_exists(__CLASS__, $methodName))
{
self::filterChain($dbQuery);
if ($neg)
self::filterNegate($dbQuery);
self::$methodName($dbQuery, $val);
}
elseif ($key == 'order')
{
if ($neg)
$orderToken = $val;
else
$orderToken = '-' . $val;
}
else
{
throw new SimpleException('Unknown key "' . $key . '"');
}
}
self::order($dbQuery, strtolower($orderToken));
2013-10-28 11:19:15 +01:00
}
}