Upgraded to newest chibi

- Separate non-static router class
- Moved some setup code to new method, Core::init
- Persistent database connection between tests
This commit is contained in:
Marcin Kurczewski 2014-05-23 23:34:50 +02:00
parent 2a8493fa69
commit 50e4b40721
66 changed files with 714 additions and 659 deletions

@ -1 +1 @@
Subproject commit a6c610e5c68220cf672debe765752662807c0d39
Subproject commit 9f48e7007a9c35caa991522d730d4f3778a1df3e

@ -1 +1 @@
Subproject commit 6bb18c1c6ed7ea952ae7a8dab792d5364a334201
Subproject commit b88f3a056d3f34b15f5e7e58f892cedaf9009395

View file

@ -3,14 +3,14 @@ final class Api
{
public static function getUrl()
{
return \Chibi\Router::linkTo(['ApiController', 'runAction']);
return Core::getRouter()->linkTo(['ApiController', 'runAction']);
}
public static function run(IJob $job, $jobArgs)
{
$user = Auth::getCurrentUser();
return \Chibi\Database::transaction(function() use ($job, $jobArgs)
return Core::getDatabase()->transaction(function() use ($job, $jobArgs)
{
$job->setArguments($jobArgs);
@ -27,7 +27,7 @@ final class Api
public static function runMultiple($jobs)
{
$statuses = [];
\Chibi\Database::transaction(function() use ($jobs, &$statuses)
Core::getDatabase()->transaction(function() use ($jobs, &$statuses)
{
foreach ($jobs as $jobItem)
{

View file

@ -2,7 +2,7 @@
class JobArgsAlternative extends JobArgsNestedStruct
{
/**
* simplifies the structure as much as possible
* Simplifies the structure as much as possible
* and returns new class or existing args.
*/
public static function factory(array $args)

View file

@ -57,7 +57,7 @@ class AbstractController
{
$targetUrl = SessionHelper::getLastVisitedUrl($filter);
if (!$targetUrl)
$targetUrl = \Chibi\Router::linkTo(['StaticPagesController', 'mainPageView']);
$targetUrl = Core::getRouter()->linkTo(['StaticPagesController', 'mainPageView']);
$this->redirect($targetUrl);
}

View file

@ -21,7 +21,7 @@ class ErrorController extends AbstractController
Messenger::fail($exception->getMessage());
$context = Core::getContext();
$context->transport->exception = $exception;
$context->transport->queries = \Chibi\Database::getLogs();
$context->transport->queries = Core::getDatabase()->getLogs();
if ($this->isAjax())
$this->renderAjax();

View file

@ -14,7 +14,7 @@ class LogController extends AbstractController
$formQuery = InputHelper::get('query');
if ($formQuery !== null)
{
$this->redirect(\Chibi\Router::linkTo(
$this->redirect(Core::getRouter()->linkTo(
['LogController', 'logView'],
[
'name' => $name,

View file

@ -66,7 +66,7 @@ class PostController extends AbstractController
$params['page'] = 1;
$url = \Chibi\Router::linkTo(['PostController', 'listView'], $params);
$url = Core::getRouter()->linkTo(['PostController', 'listView'], $params);
$this->redirect($url);
}
@ -364,12 +364,12 @@ class PostController extends AbstractController
private function redirectToPostList()
{
$this->redirect(\Chibi\Router::linkTo(['PostController', 'listView']));
$this->redirect(Core::getRouter()->linkTo(['PostController', 'listView']));
}
private function redirectToGenericView($identifier)
{
$this->redirect(\Chibi\Router::linkTo(
$this->redirect(Core::getRouter()->linkTo(
['PostController', 'genericView'],
['identifier' => $identifier]));
}

View file

@ -388,13 +388,13 @@ class UserController extends AbstractController
private function redirectToMainPage()
{
$this->redirect(\Chibi\Router::linkTo(['StaticPagesController', 'mainPageView']));
$this->redirect(Core::getRouter()->linkTo(['StaticPagesController', 'mainPageView']));
exit;
}
private function redirectToGenericView($identifier)
{
$this->redirect(\Chibi\Router::linkTo(
$this->redirect(Core::getRouter()->linkTo(
['UserController', 'genericView'],
['identifier' => $identifier]));
}

View file

@ -127,7 +127,7 @@ class CustomMarkdown extends \Michelf\MarkdownExtra
protected function doPosts($text)
{
$link = \Chibi\Router::linkTo(['PostController', 'genericView'], ['identifier' => '_post_']);
$link = Core::getRouter()->linkTo(['PostController', 'genericView'], ['identifier' => '_post_']);
return preg_replace_callback('/(?:(?<![^\s\(\)\[\]]))@(\d+)/', function($x) use ($link)
{
return $this->hashPart('<a href="' . str_replace('_post_', $x[1], $link) . '"><code>' . $x[0] . '</code></a>');
@ -136,7 +136,7 @@ class CustomMarkdown extends \Michelf\MarkdownExtra
protected function doTags($text)
{
$link = \Chibi\Router::linkTo(['PostController', 'listView'], ['query' => '_query_']);
$link = Core::getRouter()->linkTo(['PostController', 'listView'], ['query' => '_query_']);
return preg_replace_callback('/(?:(?<![^\s\(\)\[\]]))#([()\[\]a-zA-Z0-9_.-]+)/', function($x) use ($link)
{
return $this->hashPart('<a href="' . str_replace('_query_', $x[1], $link) . '">' . $x[0] . '</a>');
@ -145,7 +145,7 @@ class CustomMarkdown extends \Michelf\MarkdownExtra
protected function doUsers($text)
{
$link = \Chibi\Router::linkTo(['UserController', 'genericView'], ['identifier' => '_name_']);
$link = Core::getRouter()->linkTo(['UserController', 'genericView'], ['identifier' => '_name_']);
return preg_replace_callback('/(?:(?<![^\s\(\)\[\]]))\+([a-zA-Z0-9_-]+)/', function($x) use ($link)
{
return $this->hashPart('<a href="' . str_replace('_name_', $x[1], $link) . '">' . $x[0] . '</a>');
@ -154,7 +154,7 @@ class CustomMarkdown extends \Michelf\MarkdownExtra
protected function doSearchPermalinks($text)
{
$link = \Chibi\Router::linkTo(['PostController', 'listView'], ['query' => '_query_']);
$link = Core::getRouter()->linkTo(['PostController', 'listView'], ['query' => '_query_']);
return preg_replace_callback('{\[search\]((?:[^\[]|\[(?!\/?search\]))+)\[\/search\]}is', function($x) use ($link)
{
return $this->hashPart('<a href="' . str_replace('_query_', urlencode($x[1]), $link) . '">' . $x[1] . '</a>');

View file

@ -23,9 +23,9 @@ class Dispatcher
{
try
{
\Chibi\Router::run($query);
Core::getRouter()->run($query);
}
catch (\Chibi\UnhandledRouteException $e)
catch (\Chibi\Routing\UnhandledRouteException $e)
{
$errorController = new ErrorController;
$errorController->simpleExceptionView(new SimpleNotFoundException($query . ' not found.'));
@ -67,7 +67,7 @@ class Dispatcher
private function setRouterObserver()
{
\Chibi\Router::setObserver(function($route, $args)
Core::getRouter()->setObserver(function($route, $args)
{
$context = Core::getContext();
$context->route = $route;

View file

@ -92,7 +92,7 @@ class Mailer
$token->setExpirationTime(null);
TokenModel::save($token);
$tokens['link'] = \Chibi\Router::linkTo($linkDestination, ['tokenText' => $token->getText()]);
$tokens['link'] = Core::getRouter()->linkTo($linkDestination, ['tokenText' => $token->getText()]);
$tokens['token'] = $token->getText(); //yeah
return self::sendMail($mail, $tokens);

View file

@ -1,6 +1,5 @@
<?php
use \Chibi\Sql as Sql;
use \Chibi\Database as Database;
abstract class AbstractCrudModel implements IModel
{
@ -38,7 +37,7 @@ abstract class AbstractCrudModel implements IModel
protected static function removeMultiple($entities)
{
$cb = [get_called_class(), 'removeSingle'];
Database::transaction(function() use ($entities, $cb)
Core::getDatabase()->transaction(function() use ($entities, $cb)
{
foreach ($entities as $entity)
{
@ -63,7 +62,7 @@ abstract class AbstractCrudModel implements IModel
protected static function saveMultiple($entities)
{
$cb = [get_called_class(), 'saveSingle'];
return Database::transaction(function() use ($entities, $cb)
return Core::getDatabase()->transaction(function() use ($entities, $cb)
{
$ret = [];
foreach ($entities as $entity)
@ -90,12 +89,12 @@ abstract class AbstractCrudModel implements IModel
public static function tryGetById($key)
{
$stmt = new Sql\SelectStatement();
$stmt = Sql\Statements::select();
$stmt->setColumn('*');
$stmt->setTable(static::getTableName());
$stmt->setCriterion(new Sql\EqualsFunctor('id', new Sql\Binding($key)));
$stmt->setCriterion(Sql\Functors::equals('id', new Sql\Binding($key)));
$row = Database::fetchOne($stmt);
$row = Core::getDatabase()->fetchOne($stmt);
return $row
? static::spawnFromDatabaseRow($row)
: null;
@ -103,12 +102,12 @@ abstract class AbstractCrudModel implements IModel
public static function getAllByIds(array $ids)
{
$stmt = new Sql\SelectStatement();
$stmt = Sql\Statements::select();
$stmt->setColumn('*');
$stmt->setTable(static::getTableName());
$stmt->setCriterion(Sql\InFunctor::fromArray('id', Sql\Binding::fromArray(array_unique($ids))));
$stmt->setCriterion(Sql\Functors::in('id', Sql\Binding::fromArray(array_unique($ids))));
$rows = Database::fetchAll($stmt);
$rows = Core::getDatabase()->fetchAll($stmt);
if ($rows)
return static::spawnFromDatabaseRows($rows);
@ -117,10 +116,10 @@ abstract class AbstractCrudModel implements IModel
public static function getCount()
{
$stmt = new Sql\SelectStatement();
$stmt->setColumn(new Sql\AliasFunctor(new Sql\CountFunctor('1'), 'count'));
$stmt = Sql\Statements::select();
$stmt->setColumn(Sql\Functors::alias(Sql\Functors::count('1'), 'count'));
$stmt->setTable(static::getTableName());
return (int) Database::fetchOne($stmt)['count'];
return (int) Core::getDatabase()->fetchOne($stmt)['count'];
}
@ -136,11 +135,11 @@ abstract class AbstractCrudModel implements IModel
public static function forgeId($entity)
{
$table = static::getTableName();
if (!Database::inTransaction())
if (!Core::getDatabase()->inTransaction())
throw new Exception('Can be run only within transaction');
if (!$entity->getId())
{
$stmt = new Sql\InsertStatement();
$stmt = Sql\Statements::insert();
$stmt->setTable($table);
foreach ($entity as $key => $val)
{
@ -150,8 +149,8 @@ abstract class AbstractCrudModel implements IModel
$stmt->setColumn($key, new Sql\Binding($val));
}
Database::exec($stmt);
$entity->setId((int) Database::lastInsertId());
Core::getDatabase()->execute($stmt);
$entity->setId((int) Core::getDatabase()->lastInsertId());
}
}

View file

@ -1,6 +1,5 @@
<?php
use \Chibi\Sql as Sql;
use \Chibi\Database as Database;
final class CommentModel extends AbstractCrudModel
{
@ -14,7 +13,7 @@ final class CommentModel extends AbstractCrudModel
$comment->validate();
$comment->getPost()->removeCache('comment_count');
Database::transaction(function() use ($comment)
Core::getDatabase()->transaction(function() use ($comment)
{
self::forgeId($comment);
@ -24,14 +23,14 @@ final class CommentModel extends AbstractCrudModel
'comment_date' => $comment->getCreationTime(),
'commenter_id' => $comment->getCommenterId()];
$stmt = new Sql\UpdateStatement();
$stmt = Sql\Statements::update();
$stmt->setTable('comment');
$stmt->setCriterion(new Sql\EqualsFunctor('id', new Sql\Binding($comment->getId())));
$stmt->setCriterion(Sql\Functors::equals('id', new Sql\Binding($comment->getId())));
foreach ($bindings as $key => $val)
$stmt->setColumn($key, new Sql\Binding($val));
Database::exec($stmt);
Core::getDatabase()->execute($stmt);
});
return $comment;
@ -39,13 +38,13 @@ final class CommentModel extends AbstractCrudModel
protected static function removeSingle($comment)
{
Database::transaction(function() use ($comment)
Core::getDatabase()->transaction(function() use ($comment)
{
$comment->getPost()->removeCache('comment_count');
$stmt = new Sql\DeleteStatement();
$stmt = Sql\Statements::delete();
$stmt->setTable('comment');
$stmt->setCriterion(new Sql\EqualsFunctor('id', new Sql\Binding($comment->getId())));
Database::exec($stmt);
$stmt->setCriterion(Sql\Functors::equals('id', new Sql\Binding($comment->getId())));
Core::getDatabase()->execute($stmt);
});
}
@ -53,12 +52,12 @@ final class CommentModel extends AbstractCrudModel
public static function getAllByPostId($key)
{
$stmt = new Sql\SelectStatement();
$stmt = Sql\Statements::select();
$stmt->setColumn('comment.*');
$stmt->setTable('comment');
$stmt->setCriterion(new Sql\EqualsFunctor('post_id', new Sql\Binding($key)));
$stmt->setCriterion(Sql\Functors::equals('post_id', new Sql\Binding($key)));
$rows = Database::fetchAll($stmt);
$rows = Core::getDatabase()->fetchAll($stmt);
if ($rows)
return self::spawnFromDatabaseRows($rows);
return [];

View file

@ -55,11 +55,11 @@ abstract class AbstractEntity implements IValidatable
if ($this->hasCache($columnName))
return $this->getCache($columnName);
$stmt = new \Chibi\Sql\SelectStatement();
$stmt = \Chibi\Sql\Statements::select();
$stmt->setTable($this->model->getTableName());
$stmt->setColumn($columnName);
$stmt->setCriterion(new \Chibi\Sql\EqualsFunctor('id', new \Chibi\Sql\Binding($this->getId())));
$value = \Chibi\Database::fetchOne($stmt)[$columnName];
$stmt->setCriterion(\Chibi\Sql\Functors::equals('id', new \Chibi\Sql\Binding($this->getId())));
$value = Core::getDatabase()->fetchOne($stmt)[$columnName];
$this->setCache($columnName, $value);
return $value;
}

View file

@ -1,6 +1,5 @@
<?php
use \Chibi\Sql as Sql;
use \Chibi\Database as Database;
final class PostEntity extends AbstractEntity implements IValidatable, ISerializable
{
@ -129,12 +128,12 @@ final class PostEntity extends AbstractEntity implements IValidatable, ISerializ
{
if ($this->hasCache('favoritee'))
return $this->getCache('favoritee');
$stmt = new Sql\SelectStatement();
$stmt = \Chibi\Sql\Statements::select();
$stmt->setColumn('user.*');
$stmt->setTable('user');
$stmt->addInnerJoin('favoritee', new Sql\EqualsFunctor('favoritee.user_id', 'user.id'));
$stmt->setCriterion(new Sql\EqualsFunctor('favoritee.post_id', new Sql\Binding($this->getId())));
$rows = Database::fetchAll($stmt);
$stmt->addInnerJoin('favoritee', Sql\Functors::equals('favoritee.user_id', 'user.id'));
$stmt->setCriterion(Sql\Functors::equals('favoritee.post_id', new Sql\Binding($this->getId())));
$rows = Core::getDatabase()->fetchAll($stmt);
$favorites = UserModel::spawnFromDatabaseRows($rows);
$this->setCache('favoritee', $favorites);
return $favorites;
@ -160,21 +159,21 @@ final class PostEntity extends AbstractEntity implements IValidatable, ISerializ
if ($this->hasCache('relations'))
return $this->getCache('relations');
$stmt = new Sql\SelectStatement();
$stmt = \Chibi\Sql\Statements::select();
$stmt->setColumn('post.*');
$stmt->setTable('post');
$binding = new Sql\Binding($this->getId());
$stmt->addInnerJoin('crossref', (new Sql\DisjunctionFunctor)
$stmt->addInnerJoin('crossref', Sql\Functors::disjunction()
->add(
(new Sql\ConjunctionFunctor)
->add(new Sql\EqualsFunctor('post.id', 'crossref.post2_id'))
->add(new Sql\EqualsFunctor('crossref.post_id', $binding)))
Sql\Functors::conjunction()
->add(Sql\Functors::equals('post.id', 'crossref.post2_id'))
->add(Sql\Functors::equals('crossref.post_id', $binding)))
->add(
(new Sql\ConjunctionFunctor)
->add(new Sql\EqualsFunctor('post.id', 'crossref.post_id'))
->add(new Sql\EqualsFunctor('crossref.post2_id', $binding))));
$rows = Database::fetchAll($stmt);
$posts = PostModel::spawnFromDatabaseRows($rows);
Sql\Functors::conjunction()
->add(Sql\Functors::equals('post.id', 'crossref.post_id'))
->add(Sql\Functors::equals('crossref.post2_id', $binding))));
$rows = Core::getDatabase()->fetchAll($stmt);
$posts = $this->model->spawnFromDatabaseRows($rows);
$this->setCache('relations', $posts);
return $posts;
}
@ -343,27 +342,27 @@ final class PostEntity extends AbstractEntity implements IValidatable, ISerializ
public function tryGetWorkingFullPath()
{
return PostModel::tryGetWorkingFullPath($this->getName());
return $this->model->tryGetWorkingFullPath($this->getName());
}
public function getFullPath()
{
return PostModel::getFullPath($this->getName());
return $this->model->getFullPath($this->getName());
}
public function tryGetWorkingThumbnailPath()
{
return PostModel::tryGetWorkingThumbnailPath($this->getName());
return $this->model->tryGetWorkingThumbnailPath($this->getName());
}
public function getCustomThumbnailSourcePath()
{
return PostModel::getCustomThumbnailSourcePath($this->getName());
return $this->model->getCustomThumbnailSourcePath($this->getName());
}
public function getThumbnailPath()
{
return PostModel::getThumbnailPath($this->getName());
return $this->model->getThumbnailPath($this->getName());
}
public function hasCustomThumbnail()
@ -463,7 +462,7 @@ final class PostEntity extends AbstractEntity implements IValidatable, ISerializ
throw new SimpleException('Invalid file type "%s"', $this->getMimeType());
}
$duplicatedPost = PostModel::tryGetByHash($this->getFileHash());
$duplicatedPost = $this->model->tryGetByHash($this->getFileHash());
if ($duplicatedPost !== null and (!$this->getId() or $this->getId() != $duplicatedPost->getId()))
{
throw new SimpleException(
@ -501,7 +500,7 @@ final class PostEntity extends AbstractEntity implements IValidatable, ISerializ
if (file_exists($thumbnailPath))
unlink($thumbnailPath);
$duplicatedPost = PostModel::tryGetByHash($youtubeId);
$duplicatedPost = $this->model->tryGetByHash($youtubeId);
if ($duplicatedPost !== null and (!$this->getId() or $this->getId() != $duplicatedPost->getId()))
{
throw new SimpleException(

View file

@ -1,6 +1,5 @@
<?php
use \Chibi\Sql as Sql;
use \Chibi\Database as Database;
final class TagEntity extends AbstractEntity implements IValidatable, ISerializable
{
@ -63,11 +62,11 @@ final class TagEntity extends AbstractEntity implements IValidatable, ISerializa
if ($this->hasCache('post_count'))
return $this->getCache('post_count');
$stmt = new Sql\SelectStatement();
$stmt->setColumn(new Sql\AliasFunctor(new Sql\CountFunctor('1'), 'post_count'));
$stmt = \Chibi\Sql\Statements::select();
$stmt->setColumn(Sql\Functors::alias(Sql\Functors::count('1'), 'post_count'));
$stmt->setTable('post_tag');
$stmt->setCriterion(new Sql\EqualsFunctor('tag_id', new Sql\Binding($this->getId())));
$row = Database::fetchOne($stmt);
$stmt->setCriterion(Sql\Functors::equals('tag_id', new Sql\Binding($this->getId())));
$row = Core::getDatabase()->fetchOne($stmt);
$this->setCache('post_count', (int) $row['post_count']);
return $this->getCache('post_count');
}

View file

@ -1,6 +1,5 @@
<?php
use \Chibi\Sql as Sql;
use \Chibi\Database as Database;
final class UserEntity extends AbstractEntity implements IValidatable, ISerializable
{
@ -336,24 +335,24 @@ final class UserEntity extends AbstractEntity implements IValidatable, ISerializ
public function hasFavorited($post)
{
$stmt = new Sql\SelectStatement();
$stmt->setColumn(new Sql\AliasFunctor(new Sql\CountFunctor('1'), 'count'));
$stmt = \Chibi\Sql\Statements::select();
$stmt->setColumn(Sql\Functors::alias(Sql\Functors::count('1'), 'count'));
$stmt->setTable('favoritee');
$stmt->setCriterion((new Sql\ConjunctionFunctor)
->add(new Sql\EqualsFunctor('user_id', new Sql\Binding($this->getId())))
->add(new Sql\EqualsFunctor('post_id', new Sql\Binding($post->getId()))));
return Database::fetchOne($stmt)['count'] == 1;
$stmt->setCriterion(Sql\Functors::conjunction()
->add(Sql\Functors::equals('user_id', new Sql\Binding($this->getId())))
->add(Sql\Functors::equals('post_id', new Sql\Binding($post->getId()))));
return Core::getDatabase()->fetchOne($stmt)['count'] == 1;
}
public function getScore($post)
{
$stmt = new Sql\SelectStatement();
$stmt = \Chibi\Sql\Statements::select();
$stmt->setColumn('score');
$stmt->setTable('post_score');
$stmt->setCriterion((new Sql\ConjunctionFunctor)
->add(new Sql\EqualsFunctor('user_id', new Sql\Binding($this->getId())))
->add(new Sql\EqualsFunctor('post_id', new Sql\Binding($post->getId()))));
$row = Database::fetchOne($stmt);
$stmt->setCriterion(Sql\Functors::conjunction()
->add(Sql\Functors::equals('user_id', new Sql\Binding($this->getId())))
->add(Sql\Functors::equals('post_id', new Sql\Binding($post->getId()))));
$row = Core::getDatabase()->fetchOne($stmt);
if ($row)
return intval($row['score']);
return null;
@ -361,29 +360,29 @@ final class UserEntity extends AbstractEntity implements IValidatable, ISerializ
public function getFavoriteCount()
{
$stmt = new Sql\SelectStatement();
$stmt->setColumn(new Sql\AliasFunctor(new Sql\CountFunctor('1'), 'count'));
$stmt = \Chibi\Sql\Statements::select();
$stmt->setColumn(Sql\Functors::alias(Sql\Functors::count('1'), 'count'));
$stmt->setTable('favoritee');
$stmt->setCriterion(new Sql\EqualsFunctor('user_id', new Sql\Binding($this->getId())));
return (int) Database::fetchOne($stmt)['count'];
$stmt->setCriterion(Sql\Functors::equals('user_id', new Sql\Binding($this->getId())));
return (int) Core::getDatabase()->fetchOne($stmt)['count'];
}
public function getCommentCount()
{
$stmt = new Sql\SelectStatement();
$stmt->setColumn(new Sql\AliasFunctor(new Sql\CountFunctor('1'), 'count'));
$stmt = \Chibi\Sql\Statements::select();
$stmt->setColumn(Sql\Functors::alias(Sql\Functors::count('1'), 'count'));
$stmt->setTable('comment');
$stmt->setCriterion(new Sql\EqualsFunctor('commenter_id', new Sql\Binding($this->getId())));
return (int) Database::fetchOne($stmt)['count'];
$stmt->setCriterion(Sql\Functors::equals('commenter_id', new Sql\Binding($this->getId())));
return (int) Core::getDatabase()->fetchOne($stmt)['count'];
}
public function getPostCount()
{
$stmt = new Sql\SelectStatement();
$stmt->setColumn(new Sql\AliasFunctor(new Sql\CountFunctor('1'), 'count'));
$stmt = \Chibi\Sql\Statements::select();
$stmt->setColumn(Sql\Functors::alias(Sql\Functors::count('1'), 'count'));
$stmt->setTable('post');
$stmt->setCriterion(new Sql\EqualsFunctor('uploader_id', new Sql\Binding($this->getId())));
return (int) Database::fetchOne($stmt)['count'];
$stmt->setCriterion(Sql\Functors::equals('uploader_id', new Sql\Binding($this->getId())));
return (int) Core::getDatabase()->fetchOne($stmt)['count'];
}

View file

@ -1,6 +1,5 @@
<?php
use \Chibi\Sql as Sql;
use \Chibi\Database as Database;
final class PostModel extends AbstractCrudModel
{
@ -13,7 +12,7 @@ final class PostModel extends AbstractCrudModel
{
$post->validate();
Database::transaction(function() use ($post)
Core::getDatabase()->transaction(function() use ($post)
{
self::forgeId($post);
@ -33,50 +32,50 @@ final class PostModel extends AbstractCrudModel
'source' => $post->getSource(),
];
$stmt = new Sql\UpdateStatement();
$stmt = Sql\Statements::update();
$stmt->setTable('post');
foreach ($bindings as $key => $value)
$stmt->setColumn($key, new Sql\Binding($value));
$stmt->setCriterion(new Sql\EqualsFunctor('id', new Sql\Binding($post->getId())));
Database::exec($stmt);
$stmt->setCriterion(Sql\Functors::equals('id', new Sql\Binding($post->getId())));
Core::getDatabase()->execute($stmt);
//tags
$tags = $post->getTags();
$stmt = new Sql\DeleteStatement();
$stmt = Sql\Statements::delete();
$stmt->setTable('post_tag');
$stmt->setCriterion(new Sql\EqualsFunctor('post_id', new Sql\Binding($post->getId())));
Database::exec($stmt);
$stmt->setCriterion(Sql\Functors::equals('post_id', new Sql\Binding($post->getId())));
Core::getDatabase()->execute($stmt);
foreach ($tags as $postTag)
{
$stmt = new Sql\InsertStatement();
$stmt = Sql\Statements::insert();
$stmt->setTable('post_tag');
$stmt->setColumn('post_id', new Sql\Binding($post->getId()));
$stmt->setColumn('tag_id', new Sql\Binding($postTag->getId()));
Database::exec($stmt);
Core::getDatabase()->execute($stmt);
}
//relations
$relations = $post->getRelations();
$stmt = new Sql\DeleteStatement();
$stmt = Sql\Statements::delete();
$stmt->setTable('crossref');
$binding = new Sql\Binding($post->getId());
$stmt->setCriterion((new Sql\DisjunctionFunctor)
->add(new Sql\EqualsFunctor('post_id', $binding))
->add(new Sql\EqualsFunctor('post2_id', $binding)));
Database::exec($stmt);
$stmt->setCriterion(Sql\Functors::disjunction()
->add(Sql\Functors::equals('post_id', $binding))
->add(Sql\Functors::equals('post2_id', $binding)));
Core::getDatabase()->execute($stmt);
foreach ($relations as $relatedPost)
{
$stmt = new Sql\InsertStatement();
$stmt = Sql\Statements::insert();
$stmt->setTable('crossref');
$stmt->setColumn('post_id', new Sql\Binding($post->getId()));
$stmt->setColumn('post2_id', new Sql\Binding($relatedPost->getId()));
Database::exec($stmt);
Core::getDatabase()->execute($stmt);
}
});
@ -85,33 +84,33 @@ final class PostModel extends AbstractCrudModel
protected static function removeSingle($post)
{
Database::transaction(function() use ($post)
Core::getDatabase()->transaction(function() use ($post)
{
$binding = new Sql\Binding($post->getId());
$stmt = new Sql\DeleteStatement();
$stmt = Sql\Statements::delete();
$stmt->setTable('post_score');
$stmt->setCriterion(new Sql\EqualsFunctor('post_id', $binding));
Database::exec($stmt);
$stmt->setCriterion(Sql\Functors::equals('post_id', $binding));
Core::getDatabase()->execute($stmt);
$stmt->setTable('post_tag');
Database::exec($stmt);
Core::getDatabase()->execute($stmt);
$stmt->setTable('favoritee');
Database::exec($stmt);
Core::getDatabase()->execute($stmt);
$stmt->setTable('comment');
Database::exec($stmt);
Core::getDatabase()->execute($stmt);
$stmt->setTable('crossref');
$stmt->setCriterion((new Sql\DisjunctionFunctor)
->add(new Sql\EqualsFunctor('post_id', $binding))
->add(new Sql\EqualsFunctor('post_id', $binding)));
Database::exec($stmt);
$stmt->setCriterion(Sql\Functors::disjunction()
->add(Sql\Functors::equals('post_id', $binding))
->add(Sql\Functors::equals('post_id', $binding)));
Core::getDatabase()->execute($stmt);
$stmt->setTable('post');
$stmt->setCriterion(new Sql\EqualsFunctor('id', $binding));
Database::exec($stmt);
$stmt->setCriterion(Sql\Functors::equals('id', $binding));
Core::getDatabase()->execute($stmt);
});
}
@ -128,12 +127,12 @@ final class PostModel extends AbstractCrudModel
public static function tryGetByName($key, $throw = true)
{
$stmt = new Sql\SelectStatement();
$stmt = Sql\Statements::select();
$stmt->setColumn('*');
$stmt->setTable('post');
$stmt->setCriterion(new Sql\EqualsFunctor('name', new Sql\Binding($key)));
$stmt->setCriterion(Sql\Functors::equals('name', new Sql\Binding($key)));
$row = Database::fetchOne($stmt);
$row = Core::getDatabase()->fetchOne($stmt);
return $row
? self::spawnFromDatabaseRow($row)
: null;
@ -158,12 +157,12 @@ final class PostModel extends AbstractCrudModel
public static function tryGetByHash($key)
{
$stmt = new Sql\SelectStatement();
$stmt = Sql\Statements::select();
$stmt->setColumn('*');
$stmt->setTable('post');
$stmt->setCriterion(new Sql\EqualsFunctor('file_hash', new Sql\Binding($key)));
$stmt->setCriterion(Sql\Functors::equals('file_hash', new Sql\Binding($key)));
$row = Database::fetchOne($stmt);
$row = Core::getDatabase()->fetchOne($stmt);
return $row
? self::spawnFromDatabaseRow($row)
: null;
@ -186,12 +185,12 @@ final class PostModel extends AbstractCrudModel
}
$postIds = array_unique(array_keys($postMap));
$stmt = new Sql\SelectStatement();
$stmt = Sql\Statements::select();
$stmt->setTable('comment');
$stmt->addColumn('comment.*');
$stmt->addColumn('post_id');
$stmt->setCriterion(Sql\InFunctor::fromArray('post_id', Sql\Binding::fromArray($postIds)));
$rows = Database::fetchAll($stmt);
$stmt->setCriterion(Sql\Functors::in('post_id', Sql\Binding::fromArray($postIds)));
$rows = Core::getDatabase()->fetchAll($stmt);
foreach ($rows as $row)
{
@ -226,13 +225,13 @@ final class PostModel extends AbstractCrudModel
}
$postIds = array_unique(array_keys($postMap));
$stmt = new Sql\SelectStatement();
$stmt = Sql\Statements::select();
$stmt->setTable('tag');
$stmt->addColumn('tag.*');
$stmt->addColumn('post_id');
$stmt->addInnerJoin('post_tag', new Sql\EqualsFunctor('post_tag.tag_id', 'tag.id'));
$stmt->setCriterion(Sql\InFunctor::fromArray('post_id', Sql\Binding::fromArray($postIds)));
$rows = Database::fetchAll($stmt);
$stmt->addInnerJoin('post_tag', Sql\Functors::equals('post_tag.tag_id', 'tag.id'));
$stmt->setCriterion(Sql\Functors::in('post_id', Sql\Binding::fromArray($postIds)));
$rows = Core::getDatabase()->fetchAll($stmt);
foreach ($rows as $row)
{
@ -352,15 +351,15 @@ final class PostModel extends AbstractCrudModel
public static function featureRandomPost()
{
$stmt = (new Sql\SelectStatement)
$stmt = Sql\Statements::select()
->setColumn('id')
->setTable('post')
->setCriterion((new Sql\ConjunctionFunctor)
->add(new Sql\NegationFunctor(new Sql\StringExpression('hidden')))
->add(new Sql\EqualsFunctor('type', new Sql\Binding(PostType::Image)))
->add(new Sql\EqualsFunctor('safety', new Sql\Binding(PostSafety::Safe))))
->setOrderBy(new Sql\RandomFunctor(), Sql\SelectStatement::ORDER_DESC);
$featuredPostId = Database::fetchOne($stmt)['id'];
->setCriterion(Sql\Functors::conjunction()
->add(Sql\Functors::negation(new Sql\StringExpression('hidden')))
->add(Sql\Functors::equals('type', new Sql\Binding(PostType::Image)))
->add(Sql\Functors::equals('safety', new Sql\Binding(PostSafety::Safe))))
->setOrderBy(Sql\Functors::random(), Sql\Statements\SelectStatement::ORDER_DESC);
$featuredPostId = Core::getDatabase()->fetchOne($stmt)['id'];
if (!$featuredPostId)
return null;

View file

@ -1,6 +1,5 @@
<?php
use \Chibi\Sql as Sql;
use \Chibi\Database as Database;
final class PropertyModel implements IModel
{
@ -14,9 +13,11 @@ final class PropertyModel implements IModel
static $allProperties;
static $loaded;
static $database;
public static function init()
{
self::$database = Core::getDatabase();
self::$allProperties = null;
self::$loaded = false;
}
@ -33,10 +34,10 @@ final class PropertyModel implements IModel
self::$loaded = true;
self::$allProperties = [];
$stmt = new Sql\SelectStatement();
$stmt = Sql\Statements::select();
$stmt ->setColumn('*');
$stmt ->setTable('property');
foreach (Database::fetchAll($stmt) as $row)
foreach (self::$database->fetchAll($stmt) as $row)
self::$allProperties[$row['prop_id']] = $row['value'];
}
@ -51,28 +52,28 @@ final class PropertyModel implements IModel
public static function set($propertyId, $value)
{
self::loadIfNecessary();
Database::transaction(function() use ($propertyId, $value)
self::$database->transaction(function() use ($propertyId, $value)
{
$stmt = new Sql\SelectStatement();
$stmt = Sql\Statements::select();
$stmt->setColumn('id');
$stmt->setTable('property');
$stmt->setCriterion(new Sql\EqualsFunctor('prop_id', new Sql\Binding($propertyId)));
$row = Database::fetchOne($stmt);
$stmt->setCriterion(Sql\Functors::equals('prop_id', new Sql\Binding($propertyId)));
$row = self::$database->fetchOne($stmt);
if ($row)
{
$stmt = new Sql\UpdateStatement();
$stmt->setCriterion(new Sql\EqualsFunctor('prop_id', new Sql\Binding($propertyId)));
$stmt = Sql\Statements::update();
$stmt->setCriterion(Sql\Functors::equals('prop_id', new Sql\Binding($propertyId)));
}
else
{
$stmt = new Sql\InsertStatement();
$stmt = Sql\Statements::insert();
$stmt->setColumn('prop_id', new Sql\Binding($propertyId));
}
$stmt->setTable('property');
$stmt->setColumn('value', new Sql\Binding($value));
Database::exec($stmt);
self::$database->execute($stmt);
self::$allProperties[$propertyId] = $value;
});

View file

@ -5,7 +5,7 @@ abstract class AbstractSearchParser
{
protected $statement;
public function decorate(Sql\SelectStatement $statement, $filterString)
public function decorate($statement, $filterString)
{
$this->statement = $statement;
@ -67,17 +67,17 @@ abstract class AbstractSearchParser
$orderByString = strtolower(array_shift($arr));
$orderDirString = strtolower(array_shift($arr));
if ($orderDirString == 'asc')
$orderDir = Sql\SelectStatement::ORDER_ASC;
$orderDir = Sql\Statements\SelectStatement::ORDER_ASC;
elseif ($orderDirString == 'desc')
$orderDir = Sql\SelectStatement::ORDER_DESC;
$orderDir = Sql\Statements\SelectStatement::ORDER_DESC;
else
throw new SimpleException('Invalid search order direction "%s"', $searchOrderDir);
if ($neg)
{
$orderDir = $orderDir == Sql\SelectStatement::ORDER_ASC
? Sql\SelectStatement::ORDER_DESC
: Sql\SelectStatement::ORDER_ASC;
$orderDir = $orderDir == Sql\Statements\SelectStatement::ORDER_ASC
? Sql\Statements\SelectStatement::ORDER_DESC
: Sql\Statements\SelectStatement::ORDER_ASC;
}
if (!$this->processOrderToken($orderByString, $orderDir))

View file

@ -13,7 +13,7 @@ class PostSearchParser extends AbstractSearchParser
$config = Core::getConfig();
$this->tags = [];
$crit = new Sql\ConjunctionFunctor();
$crit = Sql\Functors::conjunction();
$allowedSafety = array_map(
function($safety)
@ -21,7 +21,7 @@ class PostSearchParser extends AbstractSearchParser
return $safety->toInteger();
},
Access::getAllowedSafety());
$crit->add(Sql\InFunctor::fromArray('post.safety', Sql\Binding::fromArray($allowedSafety)));
$crit->add(Sql\Functors::in('post.safety', Sql\Binding::fromArray($allowedSafety)));
$this->statement->setCriterion($crit);
if (count($tokens) > $config->browsing->maxSearchTokens)
@ -43,20 +43,20 @@ class PostSearchParser extends AbstractSearchParser
{
list ($tagName, $neg) = $item;
$tag = TagModel::getByName($tagName);
$innerStmt = new Sql\SelectStatement();
$innerStmt = Sql\Statements::select();
$innerStmt->setTable('post_tag');
$innerStmt->setCriterion((new Sql\ConjunctionFunctor)
->add(new Sql\EqualsFunctor('post_tag.post_id', 'post.id'))
->add(new Sql\EqualsFunctor('post_tag.tag_id', new Sql\Binding($tag->getId()))));
$operator = new Sql\ExistsFunctor($innerStmt);
$innerStmt->setCriterion(Sql\Functors::conjunction()
->add(Sql\Functors::equals('post_tag.post_id', 'post.id'))
->add(Sql\Functors::equals('post_tag.tag_id', new Sql\Binding($tag->getId()))));
$operator = Sql\Functors::exists($innerStmt);
if ($neg)
$operator = new Sql\NegationFunctor($operator);
$operator = Sql\Functors::negation($operator);
$this->statement->getCriterion()->add($operator);
}
$this->statement->addOrderBy('post.id',
empty($this->statement->getOrderBy())
? Sql\SelectStatement::ORDER_DESC
? Sql\Statements\SelectStatement::ORDER_DESC
: $this->statement->getOrderBy()[0][1]);
}
@ -72,91 +72,91 @@ class PostSearchParser extends AbstractSearchParser
{
$ids = preg_split('/[;,]/', $value);
$ids = array_map('intval', $ids);
return Sql\InFunctor::fromArray('post.id', Sql\Binding::fromArray($ids));
return Sql\Functors::in('post.id', Sql\Binding::fromArray($ids));
}
if (in_array($key, ['name', 'names', 'hash', 'hashes']))
{
$ids = preg_split('/[;,]/', $value);
return Sql\InFunctor::fromArray('post.name', Sql\Binding::fromArray($ids));
return Sql\Functors::in('post.name', Sql\Binding::fromArray($ids));
}
elseif (in_array($key, ['fav', 'favs', 'favd']))
{
$user = UserModel::getByName($value);
$innerStmt = (new Sql\SelectStatement)
$innerStmt = Sql\Statements::select()
->setTable('favoritee')
->setCriterion((new Sql\ConjunctionFunctor)
->add(new Sql\EqualsFunctor('favoritee.post_id', 'post.id'))
->add(new Sql\EqualsFunctor('favoritee.user_id', new Sql\Binding($user->getId()))));
return new Sql\ExistsFunctor($innerStmt);
->setCriterion(Sql\Functors::conjunction()
->add(Sql\Functors::equals('favoritee.post_id', 'post.id'))
->add(Sql\Functors::equals('favoritee.user_id', new Sql\Binding($user->getId()))));
return Sql\Functors::exists($innerStmt);
}
elseif (in_array($key, ['comment', 'comments', 'commenter', 'commented']))
{
$user = UserModel::getByName($value);
$innerStmt = (new Sql\SelectStatement)
$innerStmt = Sql\Statements::select()
->setTable('comment')
->setCriterion((new Sql\ConjunctionFunctor)
->add(new Sql\EqualsFunctor('comment.post_id', 'post.id'))
->add(new Sql\EqualsFunctor('comment.commenter_id', new Sql\Binding($user->getId()))));
return new Sql\ExistsFunctor($innerStmt);
->setCriterion(Sql\Functors::conjunction()
->add(Sql\Functors::equals('comment.post_id', 'post.id'))
->add(Sql\Functors::equals('comment.commenter_id', new Sql\Binding($user->getId()))));
return Sql\Functors::exists($innerStmt);
}
elseif (in_array($key, ['submit', 'upload', 'uploads', 'uploader', 'uploaded']))
{
$user = UserModel::getByName($value);
return new Sql\EqualsFunctor('post.uploader_id', new Sql\Binding($user->getId()));
return Sql\Functors::equals('post.uploader_id', new Sql\Binding($user->getId()));
}
elseif (in_array($key, ['idmin', 'id_min']))
return new Sql\EqualsOrGreaterFunctor('post.id', new Sql\Binding(intval($value)));
return Sql\Functors::equalsOrGreater('post.id', new Sql\Binding(intval($value)));
elseif (in_array($key, ['idmax', 'id_max']))
return new Sql\EqualsOrLesserFunctor('post.id', new Sql\Binding(intval($value)));
return Sql\Functors::equalsOrLesser('post.id', new Sql\Binding(intval($value)));
elseif (in_array($key, ['scoremin', 'score_min']))
return new Sql\EqualsOrGreaterFunctor('post.score', new Sql\Binding(intval($value)));
return Sql\Functors::equalsOrGreater('post.score', new Sql\Binding(intval($value)));
elseif (in_array($key, ['scoremax', 'score_max']))
return new Sql\EqualsOrLesserFunctor('post.score', new Sql\Binding(intval($value)));
return Sql\Functors::equalsOrLesser('post.score', new Sql\Binding(intval($value)));
elseif (in_array($key, ['tagmin', 'tag_min']))
return new Sql\EqualsOrGreaterFunctor('post.tag_count', new Sql\Binding(intval($value)));
return Sql\Functors::equalsOrGreater('post.tag_count', new Sql\Binding(intval($value)));
elseif (in_array($key, ['tagmax', 'tag_max']))
return new Sql\EqualsOrLesserFunctor('post.tag_count', new Sql\Binding(intval($value)));
return Sql\Functors::equalsOrLesser('post.tag_count', new Sql\Binding(intval($value)));
elseif (in_array($key, ['favmin', 'fav_min']))
return new Sql\EqualsOrGreaterFunctor('post.fav_count', new Sql\Binding(intval($value)));
return Sql\Functors::equalsOrGreater('post.fav_count', new Sql\Binding(intval($value)));
elseif (in_array($key, ['favmax', 'fav_max']))
return new Sql\EqualsOrLesserFunctor('post.fav_count', new Sql\Binding(intval($value)));
return Sql\Functors::equalsOrLesser('post.fav_count', new Sql\Binding(intval($value)));
elseif (in_array($key, ['commentmin', 'comment_min']))
return new Sql\EqualsOrGreaterFunctor('post.comment_count', new Sql\Binding(intval($value)));
return Sql\Functors::equalsOrGreater('post.comment_count', new Sql\Binding(intval($value)));
elseif (in_array($key, ['commentmax', 'comment_max']))
return new Sql\EqualsOrLesserFunctor('post.comment_count', new Sql\Binding(intval($value)));
return Sql\Functors::equalsOrLesser('post.comment_count', new Sql\Binding(intval($value)));
elseif (in_array($key, ['date']))
{
list ($dateMin, $dateMax) = self::parseDate($value);
return (new Sql\ConjunctionFunctor)
->add(new Sql\EqualsOrLesserFunctor('post.upload_date', new Sql\Binding($dateMax)))
->add(new Sql\EqualsOrGreaterFunctor('post.upload_date', new Sql\Binding($dateMin)));
return Sql\Functors::conjunction()
->add(Sql\Functors::equalsOrLesser('post.upload_date', new Sql\Binding($dateMax)))
->add(Sql\Functors::equalsOrGreater('post.upload_date', new Sql\Binding($dateMin)));
}
elseif (in_array($key, ['datemin', 'date_min']))
{
list ($dateMin, $dateMax) = self::parseDate($value);
return new Sql\EqualsOrGreaterFunctor('post.upload_date', new Sql\Binding($dateMin));
return Sql\Functors::equalsOrGreater('post.upload_date', new Sql\Binding($dateMin));
}
elseif (in_array($key, ['datemax', 'date_max']))
{
list ($dateMin, $dateMax) = self::parseDate($value);
return new Sql\EqualsOrLesserFunctor('post.upload_date', new Sql\Binding($dateMax));
return Sql\Functors::equalsOrLesser('post.upload_date', new Sql\Binding($dateMax));
}
elseif ($key == 'special')
@ -173,11 +173,11 @@ class PostSearchParser extends AbstractSearchParser
{
if (!$this->statement->isTableJoined('post_score'))
{
$this->statement->addLeftOuterJoin('post_score', (new Sql\ConjunctionFunctor)
->add(new Sql\EqualsFunctor('post_score.post_id', 'post.id'))
->add(new Sql\EqualsFunctor('post_score.user_id', new Sql\Binding($activeUser->getId()))));
$this->statement->addLeftOuterJoin('post_score', Sql\Functors::conjunction()
->add(Sql\Functors::equals('post_score.post_id', 'post.id'))
->add(Sql\Functors::equals('post_score.user_id', new Sql\Binding($activeUser->getId()))));
}
return new Sql\EqualsFunctor(new Sql\IfNullFunctor('post_score.score', '0'), '1');
return Sql\Functors::equals(Sql\Functors::ifNull('post_score.score', '0'), '1');
}
elseif (in_array($value, ['dislike', 'disliked', 'dislikes']))
@ -185,11 +185,11 @@ class PostSearchParser extends AbstractSearchParser
$this->showDisliked = true;
if (!$this->statement->isTableJoined('post_score'))
{
$this->statement->addLeftOuterJoin('post_score', (new Sql\ConjunctionFunctor)
->add(new Sql\EqualsFunctor('post_score.post_id', 'post.id'))
->add(new Sql\EqualsFunctor('post_score.user_id', new Sql\Binding($activeUser->getId()))));
$this->statement->addLeftOuterJoin('post_score', Sql\Functors::conjunction()
->add(Sql\Functors::equals('post_score.post_id', 'post.id'))
->add(Sql\Functors::equals('post_score.user_id', new Sql\Binding($activeUser->getId()))));
}
return new Sql\EqualsFunctor(new Sql\IfNullFunctor('post_score.score', '0'), '-1');
return Sql\Functors::equals(Sql\Functors::ifNull('post_score.score', '0'), '-1');
}
elseif ($value == 'hidden')
@ -216,7 +216,7 @@ class PostSearchParser extends AbstractSearchParser
else
throw new SimpleException('Invalid post type "%s"', $value);
return new Sql\EqualsFunctor('type', new Sql\Binding($type));
return Sql\Functors::equals('type', new Sql\Binding($type));
}
return null;
@ -229,7 +229,7 @@ class PostSearchParser extends AbstractSearchParser
return false;
if ($neg)
$criterion = new Sql\NegationFunctor($criterion);
$criterion = Sql\Functors::negation($criterion);
$this->statement->getCriterion()->add($criterion);
return true;
@ -275,9 +275,9 @@ class PostSearchParser extends AbstractSearchParser
if (!isset($_SESSION['browsing-seed']))
$_SESSION['browsing-seed'] = mt_rand();
$seed = $_SESSION['browsing-seed'];
$orderColumn = new Sql\SubstrFunctor(
new Sql\MultiplicationFunctor('post.id', $seed),
new Sql\AdditionFunctor(new Sql\LengthFunctor('post.id'), '2'));
$orderColumn = Sql\Functors::substr(
Sql\Functors::multiplication('post.id', $seed),
Sql\Functors::addition(Sql\Functors::length('post.id'), '2'));
}
else

View file

@ -12,10 +12,10 @@ class TagSearchParser extends AbstractSearchParser
},
Access::getAllowedSafety());
$this->statement
->addInnerJoin('post_tag', new Sql\EqualsFunctor('tag.id', 'post_tag.tag_id'))
->addInnerJoin('post', new Sql\EqualsFunctor('post.id', 'post_tag.post_id'))
->setCriterion((new Sql\ConjunctionFunctor)
->add(Sql\InFunctor::fromArray('safety', Sql\Binding::fromArray($allowedSafety))))
->addInnerJoin('post_tag', Sql\Functors::equals('tag.id', 'post_tag.tag_id'))
->addInnerJoin('post', Sql\Functors::equals('post.id', 'post_tag.post_id'))
->setCriterion(Sql\Functors::conjunction()
->add(Sql\Functors::in('safety', Sql\Binding::fromArray($allowedSafety))))
->setGroupBy('tag.id');
}
@ -29,7 +29,7 @@ class TagSearchParser extends AbstractSearchParser
$value .= '%';
$this->statement->getCriterion()
->add(new Sql\NoCaseFunctor(new Sql\LikeFunctor('tag.name', new Sql\Binding($value))));
->add(Sql\Functors::noCase(Sql\Functors::like('tag.name', new Sql\Binding($value))));
return true;
}
@ -39,7 +39,7 @@ class TagSearchParser extends AbstractSearchParser
if ($orderByString == 'popularity')
$this->statement->setOrderBy('post_count', $orderDir);
elseif ($orderByString == 'alpha')
$this->statement->setOrderBy(new Sql\CaseFunctor('tag.name'), $orderDir);
$this->statement->setOrderBy(Sql\Functors::{'case'}('tag.name'), $orderDir);
else
return false;
return true;

View file

@ -10,9 +10,9 @@ class UserSearchParser extends AbstractSearchParser
if ($value == 'pending')
{
$this->statement->setCriterion((new Sql\DisjunctionFunctor)
->add(new Sql\IsFunctor('staff_confirmed', new Sql\NullFunctor()))
->add(new Sql\EqualsFunctor('staff_confirmed', '0')));
$this->statement->setCriterion(Sql\Functors::disjunction()
->add(Sql\Functors::is('staff_confirmed', Sql\Functors::null()))
->add(Sql\Functors::equals('staff_confirmed', '0')));
return true;
}
return false;
@ -21,7 +21,7 @@ class UserSearchParser extends AbstractSearchParser
protected function processOrderToken($orderByString, $orderDir)
{
if ($orderByString == 'alpha')
$this->statement->setOrderBy(new Sql\NoCaseFunctor('name'), $orderDir);
$this->statement->setOrderBy(Sql\Functors::noCase('name'), $orderDir);
elseif ($orderByString == 'date')
$this->statement->setOrderBy('join_date', $orderDir);
else

View file

@ -1,6 +1,5 @@
<?php
use \Chibi\Sql as Sql;
use \Chibi\Database as Database;
abstract class AbstractSearchService
{
@ -18,17 +17,17 @@ abstract class AbstractSearchService
return $parserClassName;
}
protected static function decorateParser(Sql\SelectStatement $stmt, $searchQuery)
protected static function decorateParser($stmt, $searchQuery)
{
$parserClassName = self::getParserClassName();
(new $parserClassName)->decorate($stmt, $searchQuery);
}
protected static function decorateCustom(Sql\SelectStatement $stmt)
protected static function decorateCustom($stmt)
{
}
protected static function decoratePager(Sql\SelectStatement $stmt, $perPage, $page)
protected static function decoratePager($stmt, $perPage, $page)
{
if ($perPage === null)
return;
@ -42,14 +41,14 @@ abstract class AbstractSearchService
$modelClassName = self::getModelClassName();
$table = $modelClassName::getTableName();
$stmt = new Sql\SelectStatement();
$stmt = Sql\Statements::select();
$stmt->setColumn($table . '.*');
$stmt->setTable($table);
static::decorateParser($stmt, $searchQuery);
static::decorateCustom($stmt);
static::decoratePager($stmt, $perPage, $page);
return Database::fetchAll($stmt);
return Core::getDatabase()->fetchAll($stmt);
}
public static function getEntities($searchQuery, $perPage = null, $page = 1)
@ -64,16 +63,16 @@ abstract class AbstractSearchService
$modelClassName = self::getModelClassName();
$table = $modelClassName::getTableName();
$innerStmt = new Sql\SelectStatement();
$innerStmt = Sql\Statements::select();
$innerStmt->setTable($table);
static::decorateParser($innerStmt, $searchQuery);
static::decorateCustom($innerStmt);
$innerStmt->resetOrderBy();
$stmt = new Sql\SelectStatement();
$stmt->setColumn(new Sql\AliasFunctor(new Sql\CountFunctor('1'), 'count'));
$stmt = Sql\Statements::select();
$stmt->setColumn(Sql\Functors::alias(Sql\Functors::count('1'), 'count'));
$stmt->setSource($innerStmt, 'inner_stmt');
return Database::fetchOne($stmt)['count'];
return Core::getDatabase()->fetchOne($stmt)['count'];
}
}

View file

@ -1,37 +1,36 @@
<?php
use \Chibi\Sql as Sql;
use \Chibi\Database as Database;
class PostSearchService extends AbstractSearchService
{
public static function getPostIdsAround($searchQuery, $postId)
{
return Database::transaction(function() use ($searchQuery, $postId)
return Core::getDatabase()->transaction(function() use ($searchQuery, $postId)
{
if (Database::getDriver() == 'sqlite')
$stmt = new Sql\RawStatement('CREATE TEMPORARY TABLE IF NOT EXISTS post_search(id INTEGER PRIMARY KEY AUTOINCREMENT, post_id INTEGER)');
if (Core::getDatabase()->getDriver() == 'sqlite')
$stmt = Sql\Statements::raw('CREATE TEMPORARY TABLE IF NOT EXISTS post_search(id INTEGER PRIMARY KEY AUTOINCREMENT, post_id INTEGER)');
else
$stmt = new Sql\RawStatement('CREATE TEMPORARY TABLE IF NOT EXISTS post_search(id INTEGER PRIMARY KEY AUTO_INCREMENT, post_id INTEGER)');
Database::exec($stmt);
$stmt = Sql\Statements::raw('CREATE TEMPORARY TABLE IF NOT EXISTS post_search(id INTEGER PRIMARY KEY AUTO_INCREMENT, post_id INTEGER)');
Core::getDatabase()->execute($stmt);
$stmt = new Sql\DeleteStatement();
$stmt = Sql\Statements::delete();
$stmt->setTable('post_search');
Database::exec($stmt);
Core::getDatabase()->execute($stmt);
$innerStmt = new Sql\SelectStatement($searchQuery);
$innerStmt = Sql\Statements::select($searchQuery);
$innerStmt->setColumn('post.id');
$innerStmt->setTable('post');
self::decorateParser($innerStmt, $searchQuery);
$stmt = new Sql\InsertStatement();
$stmt = Sql\Statements::insert();
$stmt->setTable('post_search');
$stmt->setSource(['post_id'], $innerStmt);
Database::exec($stmt);
Core::getDatabase()->execute($stmt);
$stmt = new Sql\SelectStatement();
$stmt = Sql\Statements::select();
$stmt->setTable('post_search');
$stmt->setColumn('id');
$stmt->setCriterion(new Sql\EqualsFunctor('post_id', new Sql\Binding($postId)));
$rowId = Database::fetchOne($stmt)['id'];
$stmt->setCriterion(Sql\Functors::equals('post_id', new Sql\Binding($postId)));
$rowId = Core::getDatabase()->fetchOne($stmt)['id'];
//it's possible that given post won't show in search results:
//it can be hidden, it can have prohibited safety etc.
@ -41,11 +40,11 @@ class PostSearchService extends AbstractSearchService
$rowId = intval($rowId);
$stmt->setColumn('post_id');
$stmt->setCriterion(new Sql\EqualsFunctor('id', new Sql\Binding($rowId - 1)));
$nextPostId = Database::fetchOne($stmt)['post_id'];
$stmt->setCriterion(Sql\Functors::equals('id', new Sql\Binding($rowId - 1)));
$nextPostId = Core::getDatabase()->fetchOne($stmt)['post_id'];
$stmt->setCriterion(new Sql\EqualsFunctor('id', new Sql\Binding($rowId + 1)));
$prevPostId = Database::fetchOne($stmt)['post_id'];
$stmt->setCriterion(Sql\Functors::equals('id', new Sql\Binding($rowId + 1)));
$prevPostId = Core::getDatabase()->fetchOne($stmt)['post_id'];
return [$prevPostId, $nextPostId];
});

View file

@ -1,12 +1,11 @@
<?php
use \Chibi\Sql as Sql;
use \Chibi\Database as Database;
class TagSearchService extends AbstractSearchService
{
public static function decorateCustom(Sql\SelectStatement $stmt)
public static function decorateCustom($stmt)
{
$stmt->addColumn(new Sql\AliasFunctor(new Sql\CountFunctor('post_tag.post_id'), 'post_count'));
$stmt->addColumn(Sql\Functors::alias(Sql\Functors::count('post_tag.post_id'), 'post_count'));
}
public static function getRelatedTags($parentTagName)
@ -51,52 +50,52 @@ class TagSearchService extends AbstractSearchService
public static function getMostUsedTag()
{
$stmt = (new Sql\SelectStatement)
$stmt = Sql\Statements::select()
->setTable('post_tag')
->addInnerJoin('tag', new Sql\EqualsFunctor('post_tag.tag_id', 'tag.id'))
->addInnerJoin('tag', Sql\Functors::equals('post_tag.tag_id', 'tag.id'))
->addColumn('tag.*')
->addColumn(new Sql\AliasFunctor(new Sql\CountFunctor('post_tag.post_id'), 'post_count'))
->addColumn(Sql\Functors::alias(Sql\Functors::count('post_tag.post_id'), 'post_count'))
->setGroupBy('post_tag.tag_id')
->setOrderBy('post_count', Sql\SelectStatement::ORDER_DESC)
->setOrderBy('post_count', Sql\Statements\SelectStatement::ORDER_DESC)
->setLimit(1, 0);
return TagModel::spawnFromDatabaseRow(Database::fetchOne($stmt));
return TagModel::spawnFromDatabaseRow(Core::getDatabase()->fetchOne($stmt));
}
private static function getSiblingTagsWithOccurences($parentTagId)
{
$stmt = (new Sql\SelectStatement)
$stmt = Sql\Statements::select()
->setTable('tag')
->addColumn('tag.*')
->addColumn(new Sql\AliasFunctor(new Sql\CountFunctor('post_tag.post_id'), 'post_count'))
->addInnerJoin('post_tag', new Sql\EqualsFunctor('post_tag.tag_id', 'tag.id'))
->addColumn(Sql\Functors::alias(Sql\Functors::count('post_tag.post_id'), 'post_count'))
->addInnerJoin('post_tag', Sql\Functors::equals('post_tag.tag_id', 'tag.id'))
->setGroupBy('tag.id')
->setOrderBy('post_count', Sql\SelectStatement::ORDER_DESC)
->setCriterion(new Sql\ExistsFunctor((new Sql\SelectStatement)
->setOrderBy('post_count', Sql\Statements\SelectStatement::ORDER_DESC)
->setCriterion(Sql\Functors::exists(Sql\Statements::select()
->setTable('post_tag pt2')
->setCriterion((new Sql\ConjunctionFunctor)
->add(new Sql\EqualsFunctor('pt2.post_id', 'post_tag.post_id'))
->add(new Sql\EqualsFunctor('pt2.tag_id', new Sql\Binding($parentTagId)))
->setCriterion(Sql\Functors::conjunction()
->add(Sql\Functors::equals('pt2.post_id', 'post_tag.post_id'))
->add(Sql\Functors::equals('pt2.tag_id', new Sql\Binding($parentTagId)))
)));
$rows = [];
foreach (Database::fetchAll($stmt) as $row)
foreach (Core::getDatabase()->fetchAll($stmt) as $row)
$rows[$row['id']] = $row;
return $rows;
}
private static function getGlobalOccurencesForTags($tagIds)
{
$stmt = (new Sql\SelectStatement)
$stmt = Sql\Statements::select()
->setTable('tag')
->addColumn('tag.*')
->addColumn(new Sql\AliasFunctor(new Sql\CountFunctor('post_tag.post_id'), 'post_count'))
->addInnerJoin('post_tag', new Sql\EqualsFunctor('post_tag.tag_id', 'tag.id'))
->addColumn(Sql\Functors::alias(Sql\Functors::count('post_tag.post_id'), 'post_count'))
->addInnerJoin('post_tag', Sql\Functors::equals('post_tag.tag_id', 'tag.id'))
->setCriterion(Sql\InFunctor::fromArray('tag.id', Sql\Binding::fromArray($tagIds)))
->setGroupBy('tag.id');
$rows = [];
foreach (Database::fetchAll($stmt) as $row)
foreach (Core::getDatabase()->fetchAll($stmt) as $row)
$rows[$row['id']] = $row;
return $rows;
}

View file

@ -1,6 +1,5 @@
<?php
use \Chibi\Sql as Sql;
use \Chibi\Database as Database;
final class TagModel extends AbstractCrudModel
{
@ -13,16 +12,16 @@ final class TagModel extends AbstractCrudModel
{
$tag->validate();
Database::transaction(function() use ($tag)
Core::getDatabase()->transaction(function() use ($tag)
{
self::forgeId($tag, 'tag');
$stmt = new Sql\UpdateStatement();
$stmt = Sql\Statements::update();
$stmt->setTable('tag');
$stmt->setColumn('name', new Sql\Binding($tag->getName()));
$stmt->setCriterion(new Sql\EqualsFunctor('id', new Sql\Binding($tag->getId())));
$stmt->setCriterion(Sql\Functors::equals('id', new Sql\Binding($tag->getId())));
Database::exec($stmt);
Core::getDatabase()->execute($stmt);
});
return $tag;
@ -32,20 +31,20 @@ final class TagModel extends AbstractCrudModel
{
$binding = new Sql\Binding($tag->getId());
$stmt = new Sql\DeleteStatement();
$stmt = Sql\Statements::delete();
$stmt->setTable('post_tag');
$stmt->setCriterion(new Sql\EqualsFunctor('tag_id', $binding));
Database::exec($stmt);
$stmt->setCriterion(Sql\Functors::equals('tag_id', $binding));
Core::getDatabase()->execute($stmt);
$stmt = new Sql\DeleteStatement();
$stmt = Sql\Statements::delete();
$stmt->setTable('tag');
$stmt->setCriterion(new Sql\EqualsFunctor('id', $binding));
Database::exec($stmt);
$stmt->setCriterion(Sql\Functors::equals('id', $binding));
Core::getDatabase()->execute($stmt);
}
public static function rename($sourceName, $targetName)
{
Database::transaction(function() use ($sourceName, $targetName)
Core::getDatabase()->transaction(function() use ($sourceName, $targetName)
{
$sourceTag = self::getByName($sourceName);
$targetTag = self::tryGetByName($targetName);
@ -65,7 +64,7 @@ final class TagModel extends AbstractCrudModel
public static function merge($sourceName, $targetName)
{
Database::transaction(function() use ($sourceName, $targetName)
Core::getDatabase()->transaction(function() use ($sourceName, $targetName)
{
$sourceTag = self::getByName($sourceName);
$targetTag = self::getByName($targetName);
@ -73,40 +72,40 @@ final class TagModel extends AbstractCrudModel
if ($sourceTag->getId() == $targetTag->getId())
throw new SimpleException('Source and target tag are the same');
$stmt = new Sql\SelectStatement();
$stmt = Sql\Statements::select();
$stmt->setColumn('post.id');
$stmt->setTable('post');
$stmt->setCriterion(
(new Sql\ConjunctionFunctor)
Sql\Functors::conjunction()
->add(
new Sql\ExistsFunctor(
(new Sql\SelectStatement)
Sql\Functors::exists(
Sql\Statements::select()
->setTable('post_tag')
->setCriterion(
(new Sql\ConjunctionFunctor)
->add(new Sql\EqualsFunctor('post_tag.post_id', 'post.id'))
->add(new Sql\EqualsFunctor('post_tag.tag_id', new Sql\Binding($sourceTag->getId()))))))
Sql\Functors::conjunction()
->add(Sql\Functors::equals('post_tag.post_id', 'post.id'))
->add(Sql\Functors::equals('post_tag.tag_id', new Sql\Binding($sourceTag->getId()))))))
->add(
new Sql\NegationFunctor(
new Sql\ExistsFunctor(
(new Sql\SelectStatement)
Sql\Functors::negation(
Sql\Functors::exists(
Sql\Statements::select()
->setTable('post_tag')
->setCriterion(
(new Sql\ConjunctionFunctor)
->add(new Sql\EqualsFunctor('post_tag.post_id', 'post.id'))
->add(new Sql\EqualsFunctor('post_tag.tag_id', new Sql\Binding($targetTag->getId()))))))));
$rows = Database::fetchAll($stmt);
Sql\Functors::conjunction()
->add(Sql\Functors::equals('post_tag.post_id', 'post.id'))
->add(Sql\Functors::equals('post_tag.tag_id', new Sql\Binding($targetTag->getId()))))))));
$rows = Core::getDatabase()->fetchAll($stmt);
$postIds = array_map(function($row) { return $row['id']; }, $rows);
self::remove($sourceTag);
foreach ($postIds as $postId)
{
$stmt = new Sql\InsertStatement();
$stmt = Sql\Statements::insert();
$stmt->setTable('post_tag');
$stmt->setColumn('post_id', new Sql\Binding($postId));
$stmt->setColumn('tag_id', new Sql\Binding($targetTag->getId()));
Database::exec($stmt);
Core::getDatabase()->execute($stmt);
}
});
}
@ -114,13 +113,13 @@ final class TagModel extends AbstractCrudModel
public static function getAllByPostId($key)
{
$stmt = new Sql\SelectStatement();
$stmt = Sql\Statements::select();
$stmt->setColumn('tag.*');
$stmt->setTable('tag');
$stmt->addInnerJoin('post_tag', new Sql\EqualsFunctor('post_tag.tag_id', 'tag.id'));
$stmt->setCriterion(new Sql\EqualsFunctor('post_tag.post_id', new Sql\Binding($key)));
$stmt->addInnerJoin('post_tag', Sql\Functors::equals('post_tag.tag_id', 'tag.id'));
$stmt->setCriterion(Sql\Functors::equals('post_tag.post_id', new Sql\Binding($key)));
$rows = Database::fetchAll($stmt);
$rows = Core::getDatabase()->fetchAll($stmt);
if ($rows)
return self::spawnFromDatabaseRows($rows);
return [];
@ -136,12 +135,12 @@ final class TagModel extends AbstractCrudModel
public static function tryGetByName($key)
{
$stmt = new Sql\SelectStatement();
$stmt = Sql\Statements::select();
$stmt->setColumn('tag.*');
$stmt->setTable('tag');
$stmt->setCriterion(new Sql\NoCaseFunctor(new Sql\EqualsFunctor('name', new Sql\Binding($key))));
$stmt->setCriterion(Sql\Functors::noCase(Sql\Functors::equals('name', new Sql\Binding($key))));
$row = Database::fetchOne($stmt);
$row = Core::getDatabase()->fetchOne($stmt);
return $row
? self::spawnFromDatabaseRow($row)
: null;
@ -151,15 +150,15 @@ final class TagModel extends AbstractCrudModel
public static function removeUnused()
{
$stmt = (new Sql\DeleteStatement)
$stmt = Sql\Statements::delete()
->setTable('tag')
->setCriterion(
new Sql\NegationFunctor(
new Sql\ExistsFunctor(
(new Sql\SelectStatement)
Sql\Functors::negation(
Sql\Functors::exists(
Sql\Statements::select()
->setTable('post_tag')
->setCriterion(new Sql\EqualsFunctor('post_tag.tag_id', 'tag.id')))));
Database::exec($stmt);
->setCriterion(Sql\Functors::equals('post_tag.tag_id', 'tag.id')))));
Core::getDatabase()->execute($stmt);
}
public static function spawnFromNames(array $tagNames)

View file

@ -1,6 +1,5 @@
<?php
use \Chibi\Sql as Sql;
use \Chibi\Database as Database;
final class TokenModel extends AbstractCrudModel
{
@ -13,7 +12,7 @@ final class TokenModel extends AbstractCrudModel
{
$token->validate();
Database::transaction(function() use ($token)
Core::getDatabase()->transaction(function() use ($token)
{
self::forgeId($token);
@ -24,14 +23,14 @@ final class TokenModel extends AbstractCrudModel
'expires' => $token->getExpirationTime(),
];
$stmt = new Sql\UpdateStatement();
$stmt = Sql\Statements::update();
$stmt->setTable('user_token');
$stmt->setCriterion(new Sql\EqualsFunctor('id', new Sql\Binding($token->getId())));
$stmt->setCriterion(Sql\Functors::equals('id', new Sql\Binding($token->getId())));
foreach ($bindings as $key => $val)
$stmt->setColumn($key, new Sql\Binding($val));
Database::exec($stmt);
Core::getDatabase()->execute($stmt);
});
return $token;
@ -50,12 +49,12 @@ final class TokenModel extends AbstractCrudModel
if (empty($key))
throw new SimpleNotFoundException('Invalid security token');
$stmt = new Sql\SelectStatement();
$stmt = Sql\Statements::select();
$stmt->setTable('user_token');
$stmt->setColumn('*');
$stmt->setCriterion(new Sql\EqualsFunctor('token', new Sql\Binding($key)));
$stmt->setCriterion(Sql\Functors::equals('token', new Sql\Binding($key)));
$row = Database::fetchOne($stmt);
$row = Core::getDatabase()->fetchOne($stmt);
return $row
? self::spawnFromDatabaseRow($row)
: null;

View file

@ -1,6 +1,5 @@
<?php
use \Chibi\Sql as Sql;
use \Chibi\Database as Database;
final class UserModel extends AbstractCrudModel
{
@ -13,7 +12,7 @@ final class UserModel extends AbstractCrudModel
{
$user->validate();
Database::transaction(function() use ($user)
Core::getDatabase()->transaction(function() use ($user)
{
self::forgeId($user);
@ -32,14 +31,14 @@ final class UserModel extends AbstractCrudModel
'avatar_style' => $user->getAvatarStyle()->toInteger(),
];
$stmt = (new Sql\UpdateStatement)
$stmt = Sql\Statements::update()
->setTable('user')
->setCriterion(new Sql\EqualsFunctor('id', new Sql\Binding($user->getId())));
->setCriterion(Sql\Functors::equals('id', new Sql\Binding($user->getId())));
foreach ($bindings as $key => $val)
$stmt->setColumn($key, new Sql\Binding($val));
Database::exec($stmt);
Core::getDatabase()->execute($stmt);
});
return $user;
@ -47,33 +46,33 @@ final class UserModel extends AbstractCrudModel
protected static function removeSingle($user)
{
Database::transaction(function() use ($user)
Core::getDatabase()->transaction(function() use ($user)
{
$binding = new Sql\Binding($user->getId());
$stmt = new Sql\DeleteStatement();
$stmt = Sql\Statements::delete();
$stmt->setTable('post_score');
$stmt->setCriterion(new Sql\EqualsFunctor('user_id', $binding));
Database::exec($stmt);
$stmt->setCriterion(Sql\Functors::equals('user_id', $binding));
Core::getDatabase()->execute($stmt);
$stmt->setTable('favoritee');
Database::exec($stmt);
Core::getDatabase()->execute($stmt);
$stmt->setTable('user');
$stmt->setCriterion(new Sql\EqualsFunctor('id', $binding));
Database::exec($stmt);
$stmt->setCriterion(Sql\Functors::equals('id', $binding));
Core::getDatabase()->execute($stmt);
$stmt = new Sql\UpdateStatement();
$stmt = Sql\Statements::update();
$stmt->setTable('comment');
$stmt->setCriterion(new Sql\EqualsFunctor('commenter_id', $binding));
$stmt->setColumn('commenter_id', new Sql\NullFunctor());
Database::exec($stmt);
$stmt->setCriterion(Sql\Functors::equals('commenter_id', $binding));
$stmt->setColumn('commenter_id', Sql\Functors::null());
Core::getDatabase()->execute($stmt);
$stmt = new Sql\UpdateStatement();
$stmt = Sql\Statements::update();
$stmt->setTable('post');
$stmt->setCriterion(new Sql\EqualsFunctor('uploader_id', $binding));
$stmt->setColumn('uploader_id', new Sql\NullFunctor());
Database::exec($stmt);
$stmt->setCriterion(Sql\Functors::equals('uploader_id', $binding));
$stmt->setColumn('uploader_id', Sql\Functors::null());
Core::getDatabase()->execute($stmt);
});
}
@ -89,12 +88,12 @@ final class UserModel extends AbstractCrudModel
public static function tryGetByName($key)
{
$stmt = new Sql\SelectStatement();
$stmt = Sql\Statements::select();
$stmt->setColumn('*');
$stmt->setTable('user');
$stmt->setCriterion(new Sql\NoCaseFunctor(new Sql\EqualsFunctor('name', new Sql\Binding(trim($key)))));
$stmt->setCriterion(Sql\Functors::noCase(Sql\Functors::equals('name', new Sql\Binding(trim($key)))));
$row = Database::fetchOne($stmt);
$row = Core::getDatabase()->fetchOne($stmt);
return $row
? self::spawnFromDatabaseRow($row)
: null;
@ -112,14 +111,14 @@ final class UserModel extends AbstractCrudModel
{
$key = trim($key);
$stmt = new Sql\SelectStatement();
$stmt = Sql\Statements::select();
$stmt->setColumn('*');
$stmt->setTable('user');
$stmt->setCriterion((new Sql\DisjunctionFunctor)
->add(new Sql\NoCaseFunctor(new Sql\EqualsFunctor('email_unconfirmed', new Sql\Binding($key))))
->add(new Sql\NoCaseFunctor(new Sql\EqualsFunctor('email_confirmed', new Sql\Binding($key)))));
$stmt->setCriterion(Sql\Functors::disjunction()
->add(Sql\Functors::noCase(Sql\Functors::equals('email_unconfirmed', new Sql\Binding($key))))
->add(Sql\Functors::noCase(Sql\Functors::equals('email_confirmed', new Sql\Binding($key)))));
$row = Database::fetchOne($stmt);
$row = Core::getDatabase()->fetchOne($stmt);
return $row
? self::spawnFromDatabaseRow($row)
: null;
@ -129,56 +128,56 @@ final class UserModel extends AbstractCrudModel
public static function updateUserScore($user, $post, $score)
{
Database::transaction(function() use ($user, $post, $score)
Core::getDatabase()->transaction(function() use ($user, $post, $score)
{
$post->removeCache('score');
$stmt = new Sql\DeleteStatement();
$stmt = Sql\Statements::delete();
$stmt->setTable('post_score');
$stmt->setCriterion((new Sql\ConjunctionFunctor)
->add(new Sql\EqualsFunctor('post_id', new Sql\Binding($post->getId())))
->add(new Sql\EqualsFunctor('user_id', new Sql\Binding($user->getId()))));
Database::exec($stmt);
$stmt->setCriterion(Sql\Functors::conjunction()
->add(Sql\Functors::equals('post_id', new Sql\Binding($post->getId())))
->add(Sql\Functors::equals('user_id', new Sql\Binding($user->getId()))));
Core::getDatabase()->execute($stmt);
$score = intval($score);
if (abs($score) > 1)
throw new SimpleException('Invalid score');
if ($score != 0)
{
$stmt = new Sql\InsertStatement();
$stmt = Sql\Statements::insert();
$stmt->setTable('post_score');
$stmt->setColumn('post_id', new Sql\Binding($post->getId()));
$stmt->setColumn('user_id', new Sql\Binding($user->getId()));
$stmt->setColumn('score', new Sql\Binding($score));
Database::exec($stmt);
Core::getDatabase()->execute($stmt);
}
});
}
public static function addToUserFavorites($user, $post)
{
Database::transaction(function() use ($user, $post)
Core::getDatabase()->transaction(function() use ($user, $post)
{
$post->removeCache('fav_count');
self::removeFromUserFavorites($user, $post);
$stmt = new Sql\InsertStatement();
$stmt = Sql\Statements::insert();
$stmt->setTable('favoritee');
$stmt->setColumn('post_id', new Sql\Binding($post->getId()));
$stmt->setColumn('user_id', new Sql\Binding($user->getId()));
$stmt->setColumn('fav_date', time());
Database::exec($stmt);
Core::getDatabase()->execute($stmt);
});
}
public static function removeFromUserFavorites($user, $post)
{
Database::transaction(function() use ($user, $post)
Core::getDatabase()->transaction(function() use ($user, $post)
{
$post->removeCache('fav_count');
$stmt = new Sql\DeleteStatement();
$stmt = Sql\Statements::delete();
$stmt->setTable('favoritee');
$stmt->setCriterion((new Sql\ConjunctionFunctor)
->add(new Sql\EqualsFunctor('post_id', new Sql\Binding($post->getId())))
->add(new Sql\EqualsFunctor('user_id', new Sql\Binding($user->getId()))));
Database::exec($stmt);
$stmt->setCriterion(Sql\Functors::conjunction()
->add(Sql\Functors::equals('post_id', new Sql\Binding($post->getId())))
->add(Sql\Functors::equals('user_id', new Sql\Binding($user->getId()))));
Core::getDatabase()->execute($stmt);
});
}

166
src/Router.php Normal file
View file

@ -0,0 +1,166 @@
<?php
class Router extends \Chibi\Routing\Router
{
public function __construct()
{
$this->registerMisc();
$this->registerStaticPages();
$this->registerAuth();
$this->registerPostController();
$this->registerUserController();
$this->registerLogController();
$this->registerTagController();
$this->registerCommentController();
}
private function registerMisc()
{
$this->register(['ApiController', 'runAction'], null, '/api');
}
private function registerStaticPages()
{
$this->register(['StaticPagesController', 'mainPageView'], 'GET', '');
$this->register(['StaticPagesController', 'mainPageView'], 'GET', '/index');
$this->register(['StaticPagesController', 'apiDocsView'], 'GET', '/api-docs');
$this->register(['StaticPagesController', 'helpView'], 'GET', '/help');
$this->register(['StaticPagesController', 'helpView'], 'GET', '/help/{tab}');
$this->register(['StaticPagesController', 'fatalErrorView'], 'POST', '/fatal-error/{code}');
$this->register(['StaticPagesController', 'fatalErrorView'], 'GET', '/fatal-error/{code}');
}
private function registerAuth()
{
$this->register(['AuthController', 'loginView'], 'GET', '/auth/login');
$this->register(['AuthController', 'loginAction'], 'POST', '/auth/login');
$this->register(['AuthController', 'logoutAction'], 'POST', '/auth/logout');
$this->register(['AuthController', 'logoutAction'], 'GET', '/auth/logout');
}
private function registerPostController()
{
$postValidation =
[
'tag' => '[^\/]*',
'enable' => '0|1',
'source' => 'posts|mass-tag',
'query' => '[^\/]*',
'additionalInfo' => '[^\/]*',
'score' => '-1|0|1',
'page' => '\d*',
];
$this->register(['PostController', 'uploadView'], 'GET', '/posts/upload', $postValidation);
$this->register(['PostController', 'uploadAction'], 'POST', '/posts/upload', $postValidation);
$this->register(['PostController', 'editView'], 'GET', '/post/{identifier}/edit', $postValidation);
$this->register(['PostController', 'editAction'], 'POST', '/post/{identifier}/edit', $postValidation);
$this->register(['PostController', 'deleteAction'], null, '/post/{identifier}/delete', $postValidation);
$this->register(['PostController', 'listView'], 'GET', '/{source}', $postValidation);
$this->register(['PostController', 'listView'], 'GET', '/{source}/{page}', $postValidation);
$this->register(['PostController', 'listView'], 'GET', '/{source}/{query}/{page}', $postValidation);
$this->register(['PostController', 'listView'], 'GET', '/{source}/{query}/{additionalInfo}/{page}', $postValidation);
$this->register(['PostController', 'listRedirectAction'], 'POST', '/{source}-redirect', $postValidation);
$this->register(['PostController', 'randomView'], 'GET', '/random', $postValidation);
$this->register(['PostController', 'randomView'], 'GET', '/random/{page}', $postValidation);
$this->register(['PostController', 'favoritesView'], 'GET', '/favorites', $postValidation);
$this->register(['PostController', 'favoritesView'], 'GET', '/favorites/{page}', $postValidation);
$this->register(['PostController', 'upvotedView'], 'GET', '/upvoted', $postValidation);
$this->register(['PostController', 'upvotedView'], 'GET', '/upvoted/{page}', $postValidation);
$this->register(['PostController', 'genericView'], 'GET', '/post/{identifier}', $postValidation);
$this->register(['PostController', 'fileView'], 'GET', '/post/{name}/retrieve', $postValidation);
$this->register(['PostController', 'thumbnailView'], 'GET', '/post/{name}/thumb', $postValidation);
$this->register(['PostController', 'toggleTagAction'], null, '/post/{identifier}/toggle-tag/{tag}/{enable}', $postValidation);
$this->register(['PostController', 'flagAction'], null, '/post/{identifier}/flag', $postValidation);
$this->register(['PostController', 'hideAction'], null, '/post/{identifier}/hide', $postValidation);
$this->register(['PostController', 'unhideAction'], null, '/post/{identifier}/unhide', $postValidation);
$this->register(['PostController', 'removeFavoriteAction'], null, '/post/{identifier}/rem-fav', $postValidation);
$this->register(['PostController', 'addFavoriteAction'], null, '/post/{identifier}/add-fav', $postValidation);
$this->register(['PostController', 'scoreAction'], null, '/post/{identifier}/score/{score}', $postValidation);
$this->register(['PostController', 'featureAction'], null, '/post/{identifier}/feature', $postValidation);
}
private function registerUserController()
{
$userValidation =
[
'identifier' => '[^\/]+',
'page' => '\d*',
'tab' => 'favs|uploads|settings|edit|delete',
'filter' => '[^\/]+',
];
$this->register(['UserController', 'listView'], 'GET', '/users', $userValidation);
$this->register(['UserController', 'listView'], 'GET', '/users/{page}', $userValidation);
$this->register(['UserController', 'listView'], 'GET', '/users/{filter}/{page}', $userValidation);
$this->register(['UserController', 'genericView'], 'GET', '/user/{identifier}/{tab}', $userValidation);
$this->register(['UserController', 'genericView'], 'GET', '/user/{identifier}/{tab}/{page}', $userValidation);
$this->register(['UserController', 'editAction'], 'POST', '/user/{identifier}/edit', $userValidation);
$this->register(['UserController', 'registrationView'], 'GET', '/register', $userValidation);
$this->register(['UserController', 'registrationAction'], 'POST', '/register', $userValidation);
$this->register(['UserController', 'activationView'], 'GET', '/activation', $userValidation);
$this->register(['UserController', 'activationAction'], 'POST', '/activation', $userValidation);
$this->register(['UserController', 'activationAction'], 'GET', '/activation/{tokenText}', $userValidation);
$this->register(['UserController', 'passwordResetView'], 'GET', '/password-reset', $userValidation);
$this->register(['UserController', 'passwordResetAction'], 'POST', '/password-reset', $userValidation);
$this->register(['UserController', 'passwordResetAction'], 'GET', '/password-reset/{tokenText}', $userValidation);
$this->register(['UserController', 'flagAction'], null, '/user/{identifier}/flag', $userValidation);
$this->register(['UserController', 'banAction'], null, '/user/{identifier}/ban', $userValidation);
$this->register(['UserController', 'unbanAction'], null, '/user/{identifier}/unban', $userValidation);
$this->register(['UserController', 'acceptRegistrationAction'], null, '/user/{identifier}/accept-registration', $userValidation);
$this->register(['UserController', 'deleteAction'], null, '/user/{identifier}/delete', $userValidation);
$this->register(['UserController', 'settingsAction'], null, '/user/{identifier}/settings', $userValidation);
$this->register(['UserController', 'toggleSafetyAction'], null, '/user/toggle-safety/{safety}', $userValidation);
}
private function registerLogController()
{
$this->register(['LogController', 'listView'], 'GET', '/logs');
$this->register(['LogController', 'logView'], 'GET', '/log/{name}', ['name' => '[0-9a-zA-Z._-]+']);
$this->register(['LogController', 'logView'], 'GET', '/log/{name}/{page}', ['name' => '[0-9a-zA-Z._-]+', 'page' => '\d*']);
$this->register(['LogController', 'logView'], 'GET', '/log/{name}/{page}/{filter}', ['name' => '[0-9a-zA-Z._-]+', 'page' => '\d*', 'filter' => '.*']);
}
private function registerTagController()
{
$tagValidation =
[
'page' => '\d*',
'filter' => '[^\/]+',
];
$this->register(['TagController', 'listView'], 'GET', '/tags', $tagValidation);
$this->register(['TagController', 'listView'], 'GET', '/tags/{page}', $tagValidation);
$this->register(['TagController', 'listView'], 'GET', '/tags/{filter}/{page}', $tagValidation);
$this->register(['TagController', 'autoCompleteView'], 'GET', '/tags-autocomplete', $tagValidation);
$this->register(['TagController', 'relatedView'], 'GET', '/tags-related', $tagValidation);
$this->register(['TagController', 'renameView'], 'GET', '/tags-rename', $tagValidation);
$this->register(['TagController', 'renameAction'], 'POST', '/tags-rename', $tagValidation);
$this->register(['TagController', 'mergeView'], 'GET', '/tags-merge', $tagValidation);
$this->register(['TagController', 'mergeAction'], 'POST', '/tags-merge', $tagValidation);
$this->register(['TagController', 'massTagRedirectView'], 'GET', '/mass-tag-redirect', $tagValidation);
}
private function registerCommentController()
{
$commentValidation =
[
'id' => '\d+',
'page' => '\d+',
];
$this->register(['CommentController', 'listView'], 'GET', '/comments', $commentValidation);
$this->register(['CommentController', 'listView'], 'GET', '/comments/{page}', $commentValidation);
$this->register(['CommentController', 'addAction'], 'POST', '/comment/add', $commentValidation);
$this->register(['CommentController', 'deleteAction'], null, '/comment/{id}/delete', $commentValidation);
$this->register(['CommentController', 'editView'], 'GET', '/comment/{id}/edit', $commentValidation);
$this->register(['CommentController', 'editAction'], 'POST', '/comment/{id}/edit', $commentValidation);
}
}

View file

@ -1,5 +1,5 @@
<?php
class View extends \Chibi\View
class View extends \Chibi\Views\View
{
public static function renderTopLevel($viewName, $assets)
{

View file

@ -5,13 +5,13 @@ $this->assets->addStylesheet('auth.css');
<form
method="post"
action="<?= \Chibi\Router::linkTo(
action="<?= Core::getRouter()->linkTo(
['AuthController', 'loginAction']) ?>"
class="auth">
<p>
If you don't have an account yet,<br/>
<a href="<?= \Chibi\Router::linkTo(['UserController', 'registrationView']); ?>">click here</a> to create a new one.
<a href="<?= Core::getRouter()->linkTo(['UserController', 'registrationView']); ?>">click here</a> to create a new one.
</p>
<?php
@ -43,9 +43,9 @@ $this->assets->addStylesheet('auth.css');
<div>
<p>Problems logging in?</p>
<ul>
<li><a href="<?= \Chibi\Router::linkTo(['UserController', 'passwordResetView']) ?>">I don't remember my password</a></li>
<li><a href="<?= \Chibi\Router::linkTo(['UserController', 'activationView']) ?>">I haven't received activation e-mail</a></li>
<li><a href="<?= \Chibi\Router::linkTo(['UserController', 'registrationView']) ?>">I don't have an account</a></li>
<li><a href="<?= Core::getRouter()->linkTo(['UserController', 'passwordResetView']) ?>">I don't remember my password</a></li>
<li><a href="<?= Core::getRouter()->linkTo(['UserController', 'activationView']) ?>">I haven't received activation e-mail</a></li>
<li><a href="<?= Core::getRouter()->linkTo(['UserController', 'registrationView']) ?>">I don't have an account</a></li>
</ul>
</div>
</div>

View file

@ -5,7 +5,7 @@ $this->assets->addScript('comment-edit.js');
<form
method="post"
action="<?= \Chibi\Router::linkTo(['CommentController', 'addAction']) ?>"
action="<?= Core::getRouter()->linkTo(['CommentController', 'addAction']) ?>"
class="add-comment">
<h1>add comment</h1>

View file

@ -5,7 +5,7 @@ $this->assets->addScript('comment-edit.js');
<form
method="post"
action="<?= \Chibi\Router::linkTo(
action="<?= Core::getRouter()->linkTo(
['CommentController', 'editAction'],
['id' => $this->context->transport->comment->getId()]) ?>"
class="edit-comment">

View file

@ -31,7 +31,7 @@ $this->assets->setSubTitle('comments');
<?php endforeach ?>
<?php if (count($comments) > count($commentsToDisplay)): ?>
<a href="<?= \Chibi\Router::linkTo(
<a href="<?= Core::getRouter()->linkTo(
['PostController', 'genericView'],
['id' => $this->context->post->getId()]) ?>">
<span class="hellip">(more&hellip;)</span>

View file

@ -8,7 +8,7 @@
<div class="avatar">
<?php $commenter = $this->context->comment->getCommenter() ?>
<?php if ($commenter): ?>
<a href="<?= \Chibi\Router::linkTo(
<a href="<?= Core::getRouter()->linkTo(
['UserController', 'genericView'],
['identifier' => $commenter->getName()]) ?>">
<img src="<?= htmlspecialchars($commenter->getAvatarUrl(40)) ?>" alt="<?= $commenter->getName() ?>"/>
@ -24,7 +24,7 @@
<div class="header">
<span class="nickname">
<?php if ($commenter): ?>
<a href="<?= \Chibi\Router::linkTo(
<a href="<?= Core::getRouter()->linkTo(
['UserController', 'genericView'],
['identifier' => $commenter->getName()]) ?>">
<?= $commenter->getName() ?>
@ -42,7 +42,7 @@
Privilege::EditComment,
Access::getIdentity($commenter)))): ?>
<span class="edit">
<a href="<?= \Chibi\Router::linkTo(
<a href="<?= Core::getRouter()->linkTo(
['CommentController', 'editView'],
['id' => $this->context->comment->getId()]) ?>">
edit
@ -56,7 +56,7 @@
<span class="delete">
<a class="simple-action confirmable"
data-confirm-text="Are you sure you want to delete this comment?"
href="<?= \Chibi\Router::linkTo(
href="<?= Core::getRouter()->linkTo(
['CommentController', 'deleteAction'],
['id' => $this->context->comment->getId()]) ?>">
delete

View file

@ -3,10 +3,10 @@ $this->assets->addStylesheet('debug.css');
?>
<div class="main-wrapper">
<?php foreach (\Chibi\Database::getLogs() as $log): ?>
<?php foreach (Core::getDatabase()->getLogs() as $log): ?>
<div class="debug">
<?php
$query = $log->getStatement()->getAsString();
$query = $log->getStatement();
$query = str_replace('(', '<span>(', $query);
$query = str_replace(')', ')</span>', $query);
?>
@ -14,9 +14,9 @@ $this->assets->addStylesheet('debug.css');
<pre class="bindings"><?= join(', ', array_map(function($key) use ($log)
{
return $key . '=<span class="value">' . $log->getStatement()->getBindings()[$key] . '</span>';
return $key . '=<span class="value">' . $log->getBindings()[$key] . '</span>';
},
array_keys($log->getStatement()->getBindings()))) ?></pre>
array_keys($log->getBindings()))) ?></pre>
<table>
<tr><td>Execution:</td><td><?= sprintf('%.05fs', $log->getExecutionTime()) ?></td></tr>

View file

@ -45,15 +45,15 @@ $this->assets->addScript('core.js');
<?= PropertyModel::get(PropertyModel::EngineVersion) ?>
</a>
</span>
<span><a href="<?= \Chibi\Router::linkTo(['StaticPagesController', 'apiDocsView']) ?>">API</a></span>
<span><a href="<?= Core::getRouter()->linkTo(['StaticPagesController', 'apiDocsView']) ?>">API</a></span>
<?php if (Access::check(new Privilege(Privilege::ListLogs))): ?>
<span><a href="<?= \Chibi\Router::linkTo(['LogController', 'listView']) ?>">Logs</a></span>
<span><a href="<?= Core::getRouter()->linkTo(['LogController', 'listView']) ?>">Logs</a></span>
<?php endif ?>
</div>
<div class="right">
<span><?= TextHelper::useBytesUnits(memory_get_usage()) ?></span>
<span><?= sprintf('%.04f', microtime(true) - $this->context->startTime) ?>s</span>
<span><?= $x = count(\Chibi\Database::getLogs()) ?> <?= $x != 1 ? 'queries' : 'query' ?></span>
<span><?= $x = count(Core::getDatabase()->getLogs()) ?> <?= $x != 1 ? 'queries' : 'query' ?></span>
</div>
<div class="clear"></div>
<hr/>

View file

@ -8,7 +8,7 @@ $this->context->subTitle = 'latest logs';
<ul>
<?php foreach ($this->context->transport->logs as $log): ?>
<li>
<a href="<?= \Chibi\Router::linkTo(['LogController', 'logView'], ['name' => $log]) ?>">
<a href="<?= Core::getRouter()->linkTo(['LogController', 'logView'], ['name' => $log]) ?>">
<?= $log ?>
</a>
</li>

View file

@ -5,7 +5,7 @@ $this->assets->addStylesheet('logs.css');
<?php if (empty($this->context->transport->lines)): ?>
<p class="alert alert-warning">
This log is empty. <a href="<?= \Chibi\Router::linkTo(['LogController', 'listView']) ?>">Go back</a>
This log is empty. <a href="<?= Core::getRouter()->linkTo(['LogController', 'listView']) ?>">Go back</a>
</p>
<?php else: ?>
<?php
@ -14,7 +14,7 @@ $this->assets->addStylesheet('logs.css');
?>
<form method="get"
action="<?= \Chibi\Router::linkTo(
action="<?= Core::getRouter()->linkTo(
['LogController', 'logView'],
['name' => $this->context->transport->name]) ?>">

View file

@ -34,7 +34,7 @@ if (!function_exists('pageUrl'))
$page = max(1, min($context->transport->paginator->pageCount, $page));
$params = $context->route->arguments;
$params['page'] = $page;
return \Chibi\Router::linkTo($destination, $params);
return Core::getRouter()->linkTo($destination, $params);
}
}
?>

View file

@ -1,5 +1,5 @@
<form method="post"
action="<?= \Chibi\Router::linkTo(
action="<?= Core::getRouter()->linkTo(
['PostController', 'editAction'],
['identifier' => $this->context->transport->post->getId()]) ?>"
enctype="multipart/form-data"

View file

@ -1,5 +1,5 @@
<?php
$this->assets->setPageThumbnail(\Chibi\Router::linkTo(
$this->assets->setPageThumbnail(Core::getRouter()->linkTo(
['PostController', 'thumbnailView'],
['name' => $this->context->transport->post->getName()]));
$post = $this->context->transport->post;
@ -12,7 +12,7 @@ $post = $this->context->transport->post;
<?php endif ?>
<img alt="<?= $post->getName() ?>"
src="<?= \Chibi\Router::linkTo(
src="<?= Core::getRouter()->linkTo(
['PostController', 'fileView'],
['name' => $post->getName()]) ?>"/>
@ -26,12 +26,12 @@ $post = $this->context->transport->post;
type="<?= $post->getMimeType() ?>"
width="<?= $post->getImageWidth() ?>"
height="<?= $post->getImageHeight() ?>"
data="<?= \Chibi\Router::linkTo(
data="<?= Core::getRouter()->linkTo(
['PostController', 'fileView'],
['name' => $post->getName()]) ?>">
<param name="wmode" value="opaque"/>
<param name="movie" value="<?= \Chibi\Router::linkTo(
<param name="movie" value="<?= Core::getRouter()->linkTo(
['PostController', 'fileView'],
['name' => $post->getName()]) ?>"/>
@ -51,7 +51,7 @@ $post = $this->context->transport->post;
<video style="max-width: 100%" controls>
<source
type="<?= $post->getMimeType() ?>"
src="<?= \Chibi\Router::linkTo(
src="<?= Core::getRouter()->linkTo(
['PostController', 'fileView'],
['name' => $post->getName()]) ?>">

View file

@ -4,26 +4,26 @@ $this->assets->setSubTitle('posts');
$tabs = [];
$activeTab = 0;
if (Access::check(new Privilege(Privilege::ListPosts)))
$tabs []= ['All posts', \Chibi\Router::linkTo(['PostController', 'listView'])];
$tabs []= ['All posts', Core::getRouter()->linkTo(['PostController', 'listView'])];
if (Access::check(new Privilege(Privilege::ListPosts)))
{
$tabs []= ['Random', \Chibi\Router::linkTo(['PostController', 'randomView'])];
$tabs []= ['Random', Core::getRouter()->linkTo(['PostController', 'randomView'])];
if ($this->context->source == 'random')
$activeTab = count($tabs) - 1;
$tabs []= ['Favorites', \Chibi\Router::linkTo(['PostController', 'favoritesView'])];
$tabs []= ['Favorites', Core::getRouter()->linkTo(['PostController', 'favoritesView'])];
if ($this->context->source == 'favorites')
$activeTab = count($tabs) - 1;
$tabs []= ['Upvoted', \Chibi\Router::linkTo(['PostController', 'upvotedView'])];
$tabs []= ['Upvoted', Core::getRouter()->linkTo(['PostController', 'upvotedView'])];
if ($this->context->source == 'upvoted')
$activeTab = count($tabs) - 1;
}
if (Access::check(new Privilege(Privilege::MassTag)))
{
$tabs []= ['Mass tag', \Chibi\Router::linkTo(['PostController', 'listView'], [
$tabs []= ['Mass tag', Core::getRouter()->linkTo(['PostController', 'listView'], [
'source' => 'mass-tag',
'query' => isset($this->context->transport->searchQuery)
? htmlspecialchars($this->context->transport->searchQuery)

View file

@ -29,7 +29,7 @@ if ($masstag)
<?php if ($masstag): ?>
<a class="toggle-tag"
href="<?= \Chibi\Router::linkTo(['PostController', 'toggleTagAction'], [
href="<?= Core::getRouter()->linkTo(['PostController', 'toggleTagAction'], [
'identifier' => $this->context->post->getId(),
'tag' => $this->context->additionalInfo,
'enable' => in_array('tagged', $classNames) ? '0' : '1']) ?>"
@ -45,11 +45,11 @@ if ($masstag)
<?php if (Auth::getCurrentUser()->getSettings()->hasEnabledPostTagTitles()): ?>
title="<?= TextHelper::reprTags($this->context->post->getTags()) ?>"
<?php endif ?>
href="<?= \Chibi\Router::linkTo(['PostController', 'genericView'], ['identifier' => $this->context->post->getId()]) ?>">
href="<?= Core::getRouter()->linkTo(['PostController', 'genericView'], ['identifier' => $this->context->post->getId()]) ?>">
<img
class="thumb"
src="<?= \Chibi\Router::linkTo(['PostController', 'thumbnailView'], ['name' => $this->context->post->getName()]) ?>"
src="<?= Core::getRouter()->linkTo(['PostController', 'thumbnailView'], ['name' => $this->context->post->getName()]) ?>"
alt="<?= TextHelper::reprPost($this->context->post) ?>"/>
<?php

View file

@ -37,7 +37,7 @@ $this->assets->addScript('../lib/tagit/jquery.tagit.js');
<div class="clear"></div>
</div>
<div id="upload-step2" data-redirect-url="<?= \Chibi\Router::linkTo(['PostController', 'listView']) ?>">
<div id="upload-step2" data-redirect-url="<?= Core::getRouter()->linkTo(['PostController', 'listView']) ?>">
<hr>
<div class="posts">
@ -68,7 +68,7 @@ $this->assets->addScript('../lib/tagit/jquery.tagit.js');
</a>
</div>
<form action="<?= \Chibi\Router::linkTo(['PostController', 'uploadAction']) ?>" method="post">
<form action="<?= Core::getRouter()->linkTo(['PostController', 'uploadAction']) ?>" method="post">
<div class="form-row file-name">
<label>File:</label>
<div class="input-wrapper">

View file

@ -30,7 +30,7 @@ $canEditAnything = count(array_filter($editPostPrivileges)) > 0;
<nav id="around">
<div class="left">
<?php if ($this->context->transport->nextPostId): ?>
<a href="<?= \Chibi\Router::linkTo(
<a href="<?= Core::getRouter()->linkTo(
['PostController', 'genericView'],
['identifier' => $this->context->transport->nextPostId]) ?>">
<?php else: ?>
@ -43,7 +43,7 @@ $canEditAnything = count(array_filter($editPostPrivileges)) > 0;
<div class="right">
<?php if ($this->context->transport->prevPostId): ?>
<a href="<?= \Chibi\Router::linkTo(
<a href="<?= Core::getRouter()->linkTo(
['PostController', 'genericView'],
['identifier' => $this->context->transport->prevPostId]) ?>">
<?php else: ?>
@ -59,7 +59,7 @@ $canEditAnything = count(array_filter($editPostPrivileges)) > 0;
<?php if (!empty($this->context->transport->lastSearchQuery)): ?>
<div class="text">
Current&nbsp;search:<br/>
<a href="<?= \Chibi\Router::linkTo(
<a href="<?= Core::getRouter()->linkTo(
['PostController', 'listView'],
['query' => $this->context->transport->lastSearchQuery]) ?>">
<?= $this->context->transport->lastSearchQuery ?>
@ -75,7 +75,7 @@ $canEditAnything = count(array_filter($editPostPrivileges)) > 0;
<?php uasort($tags, function($a, $b) { return strnatcasecmp($a->getName(), $b->getName()); }) ?>
<?php foreach ($tags as $tag): ?>
<li title="<?= $tag->getName() ?>">
<a href="<?= \Chibi\Router::linkTo(
<a href="<?= Core::getRouter()->linkTo(
['PostController', 'listView'],
['query' => $tag->getName()]) ?>"
><?= $tag->getName() ?>
@ -93,7 +93,7 @@ $canEditAnything = count(array_filter($editPostPrivileges)) > 0;
<?php $uploader = $this->context->transport->post->getUploader() ?>
<?php if ($uploader): ?>
<span class="value" title="<?= $val = $uploader->getName() ?>">
<a href="<?= \Chibi\Router::linkTo(
<a href="<?= Core::getRouter()->linkTo(
['UserController', 'genericView'],
['identifier' => $uploader->getName()]) ?>">
<img src="<?= htmlentities($uploader->getAvatarUrl(25)) ?>" alt="<?= $uploader->getName() ?>"/>
@ -153,7 +153,7 @@ $canEditAnything = count(array_filter($editPostPrivileges)) > 0;
<?php
$scoreLink = function($score)
{
return \Chibi\Router::linkTo(
return Core::getRouter()->linkTo(
['PostController', 'scoreAction'],
['identifier' => $this->context->transport->post->getId(), 'score' => $score]);
}
@ -186,7 +186,7 @@ $canEditAnything = count(array_filter($editPostPrivileges)) > 0;
<div class="unit hl-options">
<?php if ($this->context->transport->post->getType()->toInteger() != PostType::Youtube): ?>
<div class="hl-option">
<a title="Download" href="<?= \Chibi\Router::linkTo(
<a title="Download" href="<?= Core::getRouter()->linkTo(
['PostController', 'fileView'],
['name' => $this->context->transport->post->getName()]) ?>">
<i class="icon-dl"></i>
@ -209,7 +209,7 @@ $canEditAnything = count(array_filter($editPostPrivileges)) > 0;
<div class="hl-option">
<?php if (!$this->context->isUserFavorite): ?>
<a class="add-fav icon simple-action"
href="<?= \Chibi\Router::linkTo(
href="<?= Core::getRouter()->linkTo(
['PostController', 'addFavoriteAction'],
['identifier' => $this->context->transport->post->getId()]) ?>">
<i class="icon-fav"></i>
@ -217,7 +217,7 @@ $canEditAnything = count(array_filter($editPostPrivileges)) > 0;
</a>
<?php else: ?>
<a class="rem-fav icon simple-action"
href="<?= \Chibi\Router::linkTo(
href="<?= Core::getRouter()->linkTo(
['PostController', 'removeFavoriteAction'],
['identifier' => $this->context->transport->post->getId()]) ?>">
<i class="icon-fav"></i>
@ -229,7 +229,7 @@ $canEditAnything = count(array_filter($editPostPrivileges)) > 0;
<?php if ($canEditAnything): ?>
<div class="hl-option">
<a class="edit-post icon" href="<?= \Chibi\Router::linkTo(
<a class="edit-post icon" href="<?= Core::getRouter()->linkTo(
['PostController', 'editView'],
['identifier' => $this->context->transport->post->getId()]) ?>">
<i class="icon-edit"></i>
@ -245,7 +245,7 @@ $canEditAnything = count(array_filter($editPostPrivileges)) > 0;
<ul>
<?php foreach ($this->context->transport->post->getFavorites() as $user): ?>
<li>
<a title="<?= $user->getName() ?>" href="<?= \Chibi\Router::linkTo(
<a title="<?= $user->getName() ?>" href="<?= Core::getRouter()->linkTo(
['UserController', 'genericView'],
['identifier' => $user->getName()]) ?>">
<img src="<?= htmlspecialchars($user->getAvatarUrl()) ?>" alt="<?= $user->getName() ?>">
@ -262,7 +262,7 @@ $canEditAnything = count(array_filter($editPostPrivileges)) > 0;
<ul>
<?php foreach ($this->context->transport->post->getRelations() as $relatedPost): ?>
<li>
<a href="<?= \Chibi\Router::linkTo(
<a href="<?= Core::getRouter()->linkTo(
['PostController', 'genericView'],
['identifier' => $relatedPost->getId()]) ?>">
<?= TextHelper::reprPost($relatedPost) ?>
@ -284,11 +284,11 @@ $canEditAnything = count(array_filter($editPostPrivileges)) > 0;
[
'class' => 'feature',
'text' => 'Feature on main page',
'simple-action' => \Chibi\Router::linkTo(
'simple-action' => Core::getRouter()->linkTo(
['PostController', 'featureAction'],
['identifier' => $this->context->transport->post->getId()]),
'data-confirm-text' => 'Are you sure you want to feature this post on the main page?',
'data-redirect-url' => \Chibi\Router::linkTo(['StaticPagesController', 'mainPageView']),
'data-redirect-url' => Core::getRouter()->linkTo(['StaticPagesController', 'mainPageView']),
];
}
@ -311,7 +311,7 @@ $canEditAnything = count(array_filter($editPostPrivileges)) > 0;
[
'class' => 'flag',
'text' => 'Flag for moderator attention',
'simple-action' => \Chibi\Router::linkTo(
'simple-action' => Core::getRouter()->linkTo(
['PostController', 'flagAction'],
['identifier' => $this->context->transport->post->getId()]),
'data-confirm-text' => 'Are you sure you want to flag this post?',
@ -329,7 +329,7 @@ $canEditAnything = count(array_filter($editPostPrivileges)) > 0;
[
'class' => 'unhide',
'text' => 'Unhide',
'simple-action' => \Chibi\Router::linkTo(
'simple-action' => Core::getRouter()->linkTo(
['PostController', 'unhideAction'],
['identifier' => $this->context->transport->post->getId()]),
];
@ -340,7 +340,7 @@ $canEditAnything = count(array_filter($editPostPrivileges)) > 0;
[
'class' => 'hide',
'text' => 'Hide',
'simple-action' => \Chibi\Router::linkTo(
'simple-action' => Core::getRouter()->linkTo(
['PostController', 'hideAction'],
['identifier' => $this->context->transport->post->getId()]),
];
@ -355,11 +355,11 @@ $canEditAnything = count(array_filter($editPostPrivileges)) > 0;
[
'class' => 'delete',
'text' => 'Delete',
'simple-action' => \Chibi\Router::linkTo(
'simple-action' => Core::getRouter()->linkTo(
['PostController', 'deleteAction'],
['identifier' => $this->context->transport->post->getId()]),
'data-confirm-text' => 'Are you sure you want to delete this post?',
'data-redirect-url' => \Chibi\Router::linkTo(['PostController', 'listView']),
'data-redirect-url' => Core::getRouter()->linkTo(['PostController', 'listView']),
];
}

View file

@ -16,7 +16,7 @@ $showTabs = count($tabs) > 1;
<?php else: ?>
<li class="<?= $tab ?>">
<?php endif ?>
<a href="<?= \Chibi\Router::linkTo(
<a href="<?= Core::getRouter()->linkTo(
['StaticPagesController', 'helpView'],
$tab == $firstTab ? [] : ['tab' => $tab]) ?>">
<?= $text ?>

View file

@ -18,7 +18,7 @@ $this->assets->addStylesheet('static-main.css');
<div class="body">
<?php
$this->context->transport->post = $this->context->featuredPost;
$this->context->imageLink = \Chibi\Router::linkTo(
$this->context->imageLink = Core::getRouter()->linkTo(
['PostController', 'genericView'],
['identifier' => $this->context->featuredPost->getId()]);
?>
@ -34,7 +34,7 @@ $this->assets->addStylesheet('static-main.css');
<?php uasort($tags, function($a, $b) { return strnatcasecmp($a->getName(), $b->getName()); }) ?>
<?php foreach ($tags as $tag): ?>
<li>
<a href="<?= \Chibi\Router::linkTo(['PostController', 'listView'], ['query' => $tag->getName()]) ?>">
<a href="<?= Core::getRouter()->linkTo(['PostController', 'listView'], ['query' => $tag->getName()]) ?>">
<?= $tag->getName() ?>
</a>
</li>
@ -46,7 +46,7 @@ $this->assets->addStylesheet('static-main.css');
Featured
<?php if ($this->context->featuredPostUser): ?>
by
<a href="<?= \Chibi\Router::linkTo(
<a href="<?= Core::getRouter()->linkTo(
['UserController', 'genericView'],
['identifier' => $this->context->featuredPostUser->getName()]) ?>">
<?= $this->context->featuredPostUser->getName() ?>

View file

@ -28,7 +28,7 @@ $showTabs = count($tabs) > 1;
<?php else: ?>
<li class="<?= $source ?>">
<?php endif ?>
<a href="<?= \Chibi\Router::linkTo(['TagController', $action]) ?>">
<a href="<?= Core::getRouter()->linkTo(['TagController', $action]) ?>">
<?= $name ?>
</a>
</li>

View file

@ -16,7 +16,7 @@
<?php else: ?>
<li>
<?php endif ?>
<a href="<?= \Chibi\Router::linkTo(['TagController', 'listView'], ['filter' => $key]) ?>"><?= $text ?></a>
<a href="<?= Core::getRouter()->linkTo(['TagController', 'listView'], ['filter' => $key]) ?>"><?= $text ?></a>
</li>
<?php endforeach ?>
</ul>
@ -28,7 +28,7 @@
<?php $max = $this->context->highestUsage ?>
<?php $add = 0. ?>
<?php $mul = 10. / max(1, log(max(1, $max))) ?>
<?php $url = \Chibi\Router::linkTo(['PostController', 'listView'], ['query' => '_query_']) ?>
<?php $url = Core::getRouter()->linkTo(['PostController', 'listView'], ['query' => '_query_']) ?>
<div class="tags paginator-content">
<ul>
<?php foreach ($this->context->transport->tags as $tag): ?>

View file

@ -1,7 +1,7 @@
<div class="form-wrapper">
<form method="post"
class="simple-action"
action="<?= \Chibi\Router::linkTo(
action="<?= Core::getRouter()->linkTo(
['PostController', 'listRedirectAction'],
['source' => 'mass-tag']) ?>">

View file

@ -1,7 +1,7 @@
<div class="form-wrapper">
<form method="post"
class="simple-action"
action="<?= \Chibi\Router::linkTo(['TagController', 'mergeAction']) ?>">
action="<?= Core::getRouter()->linkTo(['TagController', 'mergeAction']) ?>">
<h1>merge tags</h1>

View file

@ -1,7 +1,7 @@
<div class="form-wrapper">
<form method="post"
class="simple-action"
action="<?= \Chibi\Router::linkTo(['TagController', 'renameAction']) ?>">
action="<?= Core::getRouter()->linkTo(['TagController', 'renameAction']) ?>">
<h1>rename tags</h1>

View file

@ -27,14 +27,14 @@
$registerNavItem(
'Home',
\Chibi\Router::linkTo(['StaticPagesController', 'mainPageView']),
Core::getRouter()->linkTo(['StaticPagesController', 'mainPageView']),
$activeController == 'static-pages' and $activeAction == 'main-page');
if (Access::check(new Privilege(Privilege::ListPosts)))
{
$registerNavItem(
'Browse',
\Chibi\Router::linkTo(['PostController', 'listView']),
Core::getRouter()->linkTo(['PostController', 'listView']),
$activeController == 'post' and $activeAction != 'upload');
}
@ -42,7 +42,7 @@
{
$registerNavItem(
'Upload',
\Chibi\Router::linkTo(['PostController', 'uploadView']),
Core::getRouter()->linkTo(['PostController', 'uploadView']),
$activeController == 'post' and $activeAction == 'upload');
}
@ -50,7 +50,7 @@
{
$registerNavItem(
'Comments',
\Chibi\Router::linkTo(['CommentController', 'listView']),
Core::getRouter()->linkTo(['CommentController', 'listView']),
$activeController == 'comment');
}
@ -58,7 +58,7 @@
{
$registerNavItem(
'Tags',
\Chibi\Router::linkTo(['TagController', 'listView']),
Core::getRouter()->linkTo(['TagController', 'listView']),
$activeController == 'tag');
}
@ -66,7 +66,7 @@
{
$registerNavItem(
'Users',
\Chibi\Router::linkTo(['UserController', 'listView']),
Core::getRouter()->linkTo(['UserController', 'listView']),
$activeController == 'user' and $activeAction != 'registration' and
(!isset($this->context->route->arguments['identifier']) or
$this->context->route->arguments['identifier'] != Auth::getCurrentUser()->getName()));
@ -76,32 +76,32 @@
{
$registerNavItem(
'Log in',
\Chibi\Router::linkTo(['AuthController', 'loginView']),
Core::getRouter()->linkTo(['AuthController', 'loginView']),
$activeController == 'auth' and $activeAction == 'login');
$registerNavItem(
'Register',
\Chibi\Router::linkTo(['UserController', 'registrationView']),
Core::getRouter()->linkTo(['UserController', 'registrationView']),
$activeController == 'user' and $activeAction == 'registration');
}
else
{
$registerNavItem(
'My account',
\Chibi\Router::linkTo(['UserController', 'genericView'], ['identifier' => Auth::getCurrentUser()->getName()]),
Core::getRouter()->linkTo(['UserController', 'genericView'], ['identifier' => Auth::getCurrentUser()->getName()]),
$activeController == 'user' and isset($this->context->route->arguments['identifier']) and
$this->context->route->arguments['identifier'] == Auth::getCurrentUser()->getName());
$registerNavItem(
'Log out',
\Chibi\Router::linkTo(['AuthController', 'logoutAction']));
Core::getRouter()->linkTo(['AuthController', 'logoutAction']));
}
if (!empty(Core::getConfig()->help->title))
{
$registerNavItem(
Core::getConfig()->help->title,
\Chibi\Router::linkTo(['StaticPagesController', 'helpView']),
Core::getRouter()->linkTo(['StaticPagesController', 'helpView']),
$activeController == 'static-pages' and $activeAction == 'help');
}
@ -134,7 +134,7 @@
<a class="simple-action <?= Auth::getCurrentUser()->getSettings()->hasEnabledSafety($safety)
? 'enabled'
: 'disabled' ?>"
href="<?= \Chibi\Router::linkTo(
href="<?= Core::getRouter()->linkTo(
['UserController', 'toggleSafetyAction'],
['safety' => $safety->toInteger()]) ?>"
title="<?= sprintf('Searching %s posts: %s',
@ -156,7 +156,7 @@
<li class="search">
<form method="post"
action="<?= \Chibi\Router::linkTo(['PostController', 'listRedirectAction']) ?>"
action="<?= Core::getRouter()->linkTo(['PostController', 'listRedirectAction']) ?>"
name="search">
<input

View file

@ -1,5 +1,5 @@
<form
action="<?= \Chibi\Router::linkTo(
action="<?= Core::getRouter()->linkTo(
['UserController', 'deleteAction'],
['identifier' => $this->context->transport->user->getName()]) ?>"
method="post"

View file

@ -3,7 +3,7 @@ $this->assets->addScript('user-edit.js');
?>
<form
action="<?= \Chibi\Router::linkTo(
action="<?= Core::getRouter()->linkTo(
['UserController', 'editAction'],
['identifier' => $this->context->transport->user->getName()]) ?>"
enctype="multipart/form-data"

View file

@ -24,7 +24,7 @@ $this->assets->addStylesheet('user-list.css');
<?php else: ?>
<li>
<?php endif ?>
<a href="<?= \Chibi\Router::linkTo(['UserController', 'listView'], ['filter' => $key]) ?>">
<a href="<?= Core::getRouter()->linkTo(['UserController', 'listView'], ['filter' => $key]) ?>">
<?= $text ?>
</a>
</li>
@ -39,14 +39,14 @@ $this->assets->addStylesheet('user-list.css');
<div class="users paginator-content">
<?php foreach ($this->context->transport->users as $user): ?>
<div class="user">
<a class="avatar" href="<?= \Chibi\Router::linkTo(
<a class="avatar" href="<?= Core::getRouter()->linkTo(
['UserController', 'genericView'],
['identifier' => $user->getName()]) ?>">
<img src="<?= htmlspecialchars($user->getAvatarUrl(100)) ?>" alt="<?= $user->getName() ?>"/>
</a>
<div class="details">
<h1>
<a href="<?= \Chibi\Router::linkTo(
<a href="<?= Core::getRouter()->linkTo(
['UserController', 'genericView'],
['identifier' => $user->getName()]) ?>">
<?= $user->getName() ?>

View file

@ -10,7 +10,7 @@ $this->assets->setSubTitle('registration form');
?>
<form
action="<?= \Chibi\Router::linkTo(['UserController', 'registrationAction']) ?>"
action="<?= Core::getRouter()->linkTo(['UserController', 'registrationAction']) ?>"
class="auth register"
method="post">

View file

@ -3,7 +3,7 @@ $settings = $this->context->transport->user->getSettings();
?>
<form
action="<?= \Chibi\Router::linkTo(
action="<?= Core::getRouter()->linkTo(
['UserController', 'settingsAction'],
['identifier' => $this->context->transport->user->getName()]) ?>"
method="post"

View file

@ -5,7 +5,7 @@ $this->assets->addStylesheet('user-view.css');
<div id="sidebar">
<div class="avatar-wrapper">
<a href="<?= \Chibi\Router::linkTo(
<a href="<?= Core::getRouter()->linkTo(
['UserController', 'genericView'],
['identifier' => $this->context->transport->user->getName()]) ?>">
@ -96,7 +96,7 @@ $this->assets->addStylesheet('user-view.css');
[
'class' => 'edit',
'text' => 'Edit account settings',
'link' => \Chibi\Router::linkTo(
'link' => Core::getRouter()->linkTo(
['UserController', 'editAction'],
['identifier' => $this->context->transport->user->getName(), 'tab' => 'edit']),
];
@ -110,7 +110,7 @@ $this->assets->addStylesheet('user-view.css');
[
'class' => 'accept-registration',
'text' => 'Accept registration',
'simple-action' => \Chibi\Router::linkTo(
'simple-action' => Core::getRouter()->linkTo(
['UserController', 'acceptRegistrationAction'],
['identifier' => $this->context->transport->user->getName()]),
];
@ -135,7 +135,7 @@ $this->assets->addStylesheet('user-view.css');
[
'class' => 'flag',
'text' => 'Flag for moderator attention',
'simple-action' => \Chibi\Router::linkTo(
'simple-action' => Core::getRouter()->linkTo(
['UserController', 'flagAction'],
['identifier' => $this->context->transport->user->getName()]),
'data-confirm-text' => 'Are you sure you want to flag this user?',
@ -153,7 +153,7 @@ $this->assets->addStylesheet('user-view.css');
[
'class' => 'ban',
'text' => 'Ban user',
'simple-action' => \Chibi\Router::linkTo(
'simple-action' => Core::getRouter()->linkTo(
['UserController', 'banAction'],
['identifier' => $this->context->transport->user->getName()]),
'data-confirm-text' => 'Are you sure you want to ban this user?',
@ -165,7 +165,7 @@ $this->assets->addStylesheet('user-view.css');
[
'class' => 'unban',
'text' => 'Unban user',
'simple-action' => \Chibi\Router::linkTo(
'simple-action' => Core::getRouter()->linkTo(
['UserController', 'unbanAction'],
['identifier' => $this->context->transport->user->getName()]),
'data-confirm-text' => 'Are you sure you want to unban this user?',
@ -181,7 +181,7 @@ $this->assets->addStylesheet('user-view.css');
[
'class' => 'delete',
'text' => 'Delete account',
'link' => \Chibi\Router::linkTo(
'link' => Core::getRouter()->linkTo(
['UserController', 'deleteAction'],
['identifier' => $this->context->transport->user->getName(), 'tab' => 'delete']),
];
@ -200,7 +200,7 @@ $this->assets->addStylesheet('user-view.css');
<?php else: ?>
<li class="favs">
<?php endif ?>
<a href="<?= \Chibi\Router::linkTo(
<a href="<?= Core::getRouter()->linkTo(
['UserController', 'genericView'],
['identifier' => $this->context->transport->user->getName(),
'tab' => 'favs',
@ -214,7 +214,7 @@ $this->assets->addStylesheet('user-view.css');
<?php else: ?>
<li class="uploads">
<?php endif ?>
<a href="<?= \Chibi\Router::linkTo(
<a href="<?= Core::getRouter()->linkTo(
['UserController', 'genericView'],
['identifier' => $this->context->transport->user->getName(),
'tab' => 'uploads',
@ -232,7 +232,7 @@ $this->assets->addStylesheet('user-view.css');
<?php else: ?>
<li class="settings">
<?php endif ?>
<a href="<?= \Chibi\Router::linkTo(
<a href="<?= Core::getRouter()->linkTo(
['UserController', 'genericView'],
['identifier' => $this->context->transport->user->getName(),
'tab' => 'settings']) ?>">
@ -247,7 +247,7 @@ $this->assets->addStylesheet('user-view.css');
<?php else: ?>
<li class="edit">
<?php endif ?>
<a href="<?= \Chibi\Router::linkTo(
<a href="<?= Core::getRouter()->linkTo(
['UserController', 'genericView'],
['identifier' => $this->context->transport->user->getName(),
'tab' => 'edit']) ?>">
@ -264,7 +264,7 @@ $this->assets->addStylesheet('user-view.css');
<?php else: ?>
<li class="delete">
<?php endif ?>
<a href="<?= \Chibi\Router::linkTo(
<a href="<?= Core::getRouter()->linkTo(
['UserController', 'genericView'],
['identifier' => $this->context->transport->user->getName(),
'tab' => 'delete']) ?>">

View file

@ -1,28 +1,37 @@
<?php
$startTime = microtime(true);
//basic settings and preparation
define('DS', DIRECTORY_SEPARATOR);
$rootDir = __DIR__ . DS . '..' . DS;
chdir($rootDir);
date_default_timezone_set('UTC');
setlocale(LC_CTYPE, 'en_US.UTF-8');
ini_set('memory_limit', '128M');
//basic include calls, autoloader init
require_once $rootDir . 'lib' . DS . 'TextCaseConverter' . DS . 'TextCaseConverter.php';
require_once $rootDir . 'lib' . DS . 'php-markdown' . DS . 'Michelf' . DS . 'Markdown.php';
require_once $rootDir . 'lib' . DS . 'php-markdown' . DS . 'Michelf' . DS . 'MarkdownExtra.php';
require_once $rootDir . 'lib' . DS . 'chibi-core' . DS . 'include.php';
\Chibi\AutoLoader::registerFilesystem($rootDir . 'lib' . DS . 'chibi-sql');
\Chibi\AutoLoader::registerFilesystem(__DIR__);
require_once $rootDir . 'src' . DS . 'routes.php';
final class Core
{
private static $context;
private static $config;
private static $router;
private static $database;
private static $rootDir;
static function init()
{
self::$rootDir = __DIR__ . DS . '..' . DS;
chdir(self::$rootDir);
date_default_timezone_set('UTC');
setlocale(LC_CTYPE, 'en_US.UTF-8');
ini_set('memory_limit', '128M');
require_once self::$rootDir . 'lib' . DS . 'TextCaseConverter' . DS . 'TextCaseConverter.php';
require_once self::$rootDir . 'lib' . DS . 'php-markdown' . DS . 'Michelf' . DS . 'Markdown.php';
require_once self::$rootDir . 'lib' . DS . 'php-markdown' . DS . 'Michelf' . DS . 'MarkdownExtra.php';
require_once self::$rootDir . 'lib' . DS . 'chibi-core' . DS . 'include.php';
require_once self::$rootDir . 'lib' . DS . 'chibi-sql' . DS . 'include.php';
\Chibi\AutoLoader::registerFilesystem(__DIR__);
self::$router = new Router();
}
static function getRouter()
{
return self::$router;
}
static function getConfig()
{
@ -34,35 +43,52 @@ final class Core
return self::$context;
}
static function getDatabase()
{
return self::$database;
}
static function prepareConfig($testEnvironment)
{
//load config manually
global $rootDir;
$configPaths = [];
if (!$testEnvironment)
{
$configPaths []= $rootDir . DS . 'data' . DS . 'config.ini';
$configPaths []= $rootDir . DS . 'data' . DS . 'local.ini';
$configPaths []= self::$rootDir . DS . 'data' . DS . 'config.ini';
$configPaths []= self::$rootDir . DS . 'data' . DS . 'local.ini';
}
else
{
$configPaths []= $rootDir . DS . 'tests' . DS . 'config.ini';
$configPaths []= self::$rootDir . DS . 'tests' . DS . 'config.ini';
}
self::$config = new \Chibi\Config();
foreach ($configPaths as $path)
if (file_exists($path))
self::$config->loadIni($path);
self::$config->rootDir = $rootDir;
self::$config->rootDir = self::$rootDir;
}
static function prepareEnvironment($testEnvironment)
static function prepareContext()
{
//prepare context
global $startTime;
self::$context = new StdClass;
self::$context->startTime = $startTime;
}
static function prepareDatabase()
{
$config = self::getConfig();
self::$database = new \Chibi\Db\Database(
$config->main->dbDriver,
TextHelper::absolutePath($config->main->dbLocation),
isset($config->main->dbUser) ? $config->main->dbUser : null,
isset($config->main->dbPass) ? $config->main->dbPass : null);
\Chibi\Sql\Config::setDriver(self::$database->getDriver());
}
static function prepareEnvironment()
{
self::prepareContext();
$config = self::getConfig();
@ -76,21 +102,10 @@ final class Core
if (!extension_loaded($ext))
die('PHP extension "' . $ext . '" must be enabled to continue.' . PHP_EOL);
if (\Chibi\Database::connected())
\Chibi\Database::disconnect();
if ($testEnvironment)
Auth::setCurrentUser(null);
Access::init();
Logger::init();
Mailer::init();
PropertyModel::init();
\Chibi\Database::connect(
$config->main->dbDriver,
TextHelper::absolutePath($config->main->dbLocation),
isset($config->main->dbUser) ? $config->main->dbUser : null,
isset($config->main->dbPass) ? $config->main->dbPass : null);
}
static function getDbVersion()
@ -154,7 +169,7 @@ final class Core
{
try
{
\Chibi\Database::execUnprepared(new \Chibi\Sql\RawStatement($query));
Core::getDatabase()->executeUnprepared(new \Chibi\Sql\RawStatement($query));
}
catch (Exception $e)
{
@ -178,5 +193,7 @@ final class Core
}
}
Core::init();
Core::prepareConfig(false);
Core::prepareDatabase();
Core::prepareEnvironment(false);

View file

@ -1,127 +0,0 @@
<?php
\Chibi\Router::register(['ApiController', 'runAction'], null, '/api');
\Chibi\Router::register(['StaticPagesController', 'mainPageView'], 'GET', '');
\Chibi\Router::register(['StaticPagesController', 'mainPageView'], 'GET', '/index');
\Chibi\Router::register(['StaticPagesController', 'apiDocsView'], 'GET', '/api-docs');
\Chibi\Router::register(['StaticPagesController', 'helpView'], 'GET', '/help');
\Chibi\Router::register(['StaticPagesController', 'helpView'], 'GET', '/help/{tab}');
\Chibi\Router::register(['StaticPagesController', 'fatalErrorView'], 'POST', '/fatal-error/{code}');
\Chibi\Router::register(['StaticPagesController', 'fatalErrorView'], 'GET', '/fatal-error/{code}');
\Chibi\Router::register(['AuthController', 'loginView'], 'GET', '/auth/login');
\Chibi\Router::register(['AuthController', 'loginAction'], 'POST', '/auth/login');
\Chibi\Router::register(['AuthController', 'logoutAction'], 'POST', '/auth/logout');
\Chibi\Router::register(['AuthController', 'logoutAction'], 'GET', '/auth/logout');
\Chibi\Router::register(['LogController', 'listView'], 'GET', '/logs');
\Chibi\Router::register(['LogController', 'logView'], 'GET', '/log/{name}', ['name' => '[0-9a-zA-Z._-]+']);
\Chibi\Router::register(['LogController', 'logView'], 'GET', '/log/{name}/{page}', ['name' => '[0-9a-zA-Z._-]+', 'page' => '\d*']);
\Chibi\Router::register(['LogController', 'logView'], 'GET', '/log/{name}/{page}/{filter}', ['name' => '[0-9a-zA-Z._-]+', 'page' => '\d*', 'filter' => '.*']);
$postValidation =
[
'tag' => '[^\/]*',
'enable' => '0|1',
'source' => 'posts|mass-tag',
'query' => '[^\/]*',
'additionalInfo' => '[^\/]*',
'score' => '-1|0|1',
'page' => '\d*',
];
\Chibi\Router::register(['PostController', 'uploadView'], 'GET', '/posts/upload', $postValidation);
\Chibi\Router::register(['PostController', 'uploadAction'], 'POST', '/posts/upload', $postValidation);
\Chibi\Router::register(['PostController', 'editView'], 'GET', '/post/{identifier}/edit', $postValidation);
\Chibi\Router::register(['PostController', 'editAction'], 'POST', '/post/{identifier}/edit', $postValidation);
\Chibi\Router::register(['PostController', 'deleteAction'], null, '/post/{identifier}/delete', $postValidation);
\Chibi\Router::register(['PostController', 'listView'], 'GET', '/{source}', $postValidation);
\Chibi\Router::register(['PostController', 'listView'], 'GET', '/{source}/{page}', $postValidation);
\Chibi\Router::register(['PostController', 'listView'], 'GET', '/{source}/{query}/{page}', $postValidation);
\Chibi\Router::register(['PostController', 'listView'], 'GET', '/{source}/{query}/{additionalInfo}/{page}', $postValidation);
\Chibi\Router::register(['PostController', 'listRedirectAction'], 'POST', '/{source}-redirect', $postValidation);
\Chibi\Router::register(['PostController', 'randomView'], 'GET', '/random', $postValidation);
\Chibi\Router::register(['PostController', 'randomView'], 'GET', '/random/{page}', $postValidation);
\Chibi\Router::register(['PostController', 'favoritesView'], 'GET', '/favorites', $postValidation);
\Chibi\Router::register(['PostController', 'favoritesView'], 'GET', '/favorites/{page}', $postValidation);
\Chibi\Router::register(['PostController', 'upvotedView'], 'GET', '/upvoted', $postValidation);
\Chibi\Router::register(['PostController', 'upvotedView'], 'GET', '/upvoted/{page}', $postValidation);
\Chibi\Router::register(['PostController', 'genericView'], 'GET', '/post/{identifier}', $postValidation);
\Chibi\Router::register(['PostController', 'fileView'], 'GET', '/post/{name}/retrieve', $postValidation);
\Chibi\Router::register(['PostController', 'thumbnailView'], 'GET', '/post/{name}/thumb', $postValidation);
\Chibi\Router::register(['PostController', 'toggleTagAction'], null, '/post/{identifier}/toggle-tag/{tag}/{enable}', $postValidation);
\Chibi\Router::register(['PostController', 'flagAction'], null, '/post/{identifier}/flag', $postValidation);
\Chibi\Router::register(['PostController', 'hideAction'], null, '/post/{identifier}/hide', $postValidation);
\Chibi\Router::register(['PostController', 'unhideAction'], null, '/post/{identifier}/unhide', $postValidation);
\Chibi\Router::register(['PostController', 'removeFavoriteAction'], null, '/post/{identifier}/rem-fav', $postValidation);
\Chibi\Router::register(['PostController', 'addFavoriteAction'], null, '/post/{identifier}/add-fav', $postValidation);
\Chibi\Router::register(['PostController', 'scoreAction'], null, '/post/{identifier}/score/{score}', $postValidation);
\Chibi\Router::register(['PostController', 'featureAction'], null, '/post/{identifier}/feature', $postValidation);
$commentValidation =
[
'id' => '\d+',
'page' => '\d+',
];
\Chibi\Router::register(['CommentController', 'listView'], 'GET', '/comments', $commentValidation);
\Chibi\Router::register(['CommentController', 'listView'], 'GET', '/comments/{page}', $commentValidation);
\Chibi\Router::register(['CommentController', 'addAction'], 'POST', '/comment/add', $commentValidation);
\Chibi\Router::register(['CommentController', 'deleteAction'], null, '/comment/{id}/delete', $commentValidation);
\Chibi\Router::register(['CommentController', 'editView'], 'GET', '/comment/{id}/edit', $commentValidation);
\Chibi\Router::register(['CommentController', 'editAction'], 'POST', '/comment/{id}/edit', $commentValidation);
$tagValidation =
[
'page' => '\d*',
'filter' => '[^\/]+',
];
\Chibi\Router::register(['TagController', 'listView'], 'GET', '/tags', $tagValidation);
\Chibi\Router::register(['TagController', 'listView'], 'GET', '/tags/{page}', $tagValidation);
\Chibi\Router::register(['TagController', 'listView'], 'GET', '/tags/{filter}/{page}', $tagValidation);
\Chibi\Router::register(['TagController', 'autoCompleteView'], 'GET', '/tags-autocomplete', $tagValidation);
\Chibi\Router::register(['TagController', 'relatedView'], 'GET', '/tags-related', $tagValidation);
\Chibi\Router::register(['TagController', 'renameView'], 'GET', '/tags-rename', $tagValidation);
\Chibi\Router::register(['TagController', 'renameAction'], 'POST', '/tags-rename', $tagValidation);
\Chibi\Router::register(['TagController', 'mergeView'], 'GET', '/tags-merge', $tagValidation);
\Chibi\Router::register(['TagController', 'mergeAction'], 'POST', '/tags-merge', $tagValidation);
\Chibi\Router::register(['TagController', 'massTagRedirectView'], 'GET', '/mass-tag-redirect', $tagValidation);
$userValidation =
[
'identifier' => '[^\/]+',
'page' => '\d*',
'tab' => 'favs|uploads|settings|edit|delete',
'filter' => '[^\/]+',
];
\Chibi\Router::register(['UserController', 'listView'], 'GET', '/users', $userValidation);
\Chibi\Router::register(['UserController', 'listView'], 'GET', '/users/{page}', $userValidation);
\Chibi\Router::register(['UserController', 'listView'], 'GET', '/users/{filter}/{page}', $userValidation);
\Chibi\Router::register(['UserController', 'genericView'], 'GET', '/user/{identifier}/{tab}', $userValidation);
\Chibi\Router::register(['UserController', 'genericView'], 'GET', '/user/{identifier}/{tab}/{page}', $userValidation);
\Chibi\Router::register(['UserController', 'editAction'], 'POST', '/user/{identifier}/edit', $userValidation);
\Chibi\Router::register(['UserController', 'registrationView'], 'GET', '/register', $userValidation);
\Chibi\Router::register(['UserController', 'registrationAction'], 'POST', '/register', $userValidation);
\Chibi\Router::register(['UserController', 'activationView'], 'GET', '/activation', $userValidation);
\Chibi\Router::register(['UserController', 'activationAction'], 'POST', '/activation', $userValidation);
\Chibi\Router::register(['UserController', 'activationAction'], 'GET', '/activation/{tokenText}', $userValidation);
\Chibi\Router::register(['UserController', 'passwordResetView'], 'GET', '/password-reset', $userValidation);
\Chibi\Router::register(['UserController', 'passwordResetAction'], 'POST', '/password-reset', $userValidation);
\Chibi\Router::register(['UserController', 'passwordResetAction'], 'GET', '/password-reset/{tokenText}', $userValidation);
\Chibi\Router::register(['UserController', 'flagAction'], null, '/user/{identifier}/flag', $userValidation);
\Chibi\Router::register(['UserController', 'banAction'], null, '/user/{identifier}/ban', $userValidation);
\Chibi\Router::register(['UserController', 'unbanAction'], null, '/user/{identifier}/unban', $userValidation);
\Chibi\Router::register(['UserController', 'acceptRegistrationAction'], null, '/user/{identifier}/accept-registration', $userValidation);
\Chibi\Router::register(['UserController', 'deleteAction'], null, '/user/{identifier}/delete', $userValidation);
\Chibi\Router::register(['UserController', 'settingsAction'], null, '/user/{identifier}/settings', $userValidation);
\Chibi\Router::register(['UserController', 'toggleSafetyAction'], null, '/user/toggle-safety/{safety}', $userValidation);

View file

@ -3,7 +3,7 @@ abstract class AbstractMocker implements IMocker
{
public function mockMultiple($number = null)
{
return \Chibi\Database::transaction(function() use ($number)
return Core::getDatabase()->transaction(function() use ($number)
{
$ret = [];
foreach (range(1, $number) as $_)

View file

@ -11,10 +11,10 @@ class SzurubooruTestRunner implements ITestRunner
exit(0);
}
$this->resetEnvironment($options);
$this->connectToDatabase($options);
if ($options->cleanDatabase)
$this->cleanDatabase();
$this->resetEnvironment($options);
$this->connectToDatabase($options);
Core::upgradeDatabase();
@ -33,7 +33,7 @@ class SzurubooruTestRunner implements ITestRunner
$testRunner->setTestWrapperAction(function($callback)
{
\Chibi\Database::rollback(function() use ($callback)
Core::getDatabase()->rollback(function() use ($callback)
{
$callback();
});
@ -101,10 +101,10 @@ class SzurubooruTestRunner implements ITestRunner
private function cleanMysqlDatabase()
{
$stmt = new \Chibi\Sql\RawStatement('DROP DATABASE IF EXISTS ' . $this->getMysqlDatabaseName());
\Chibi\Database::exec($stmt);
$stmt = new \Chibi\Sql\RawStatement('CREATE DATABASE ' . $this->getMysqlDatabaseName());
\Chibi\Database::exec($stmt);
$stmt = \Chibi\Sql\Statements::raw('DROP DATABASE IF EXISTS ' . $this->getMysqlDatabaseName());
Core::getDatabase()->exec($stmt);
$stmt = \Chibi\Sql\Statements::raw('CREATE DATABASE ' . $this->getMysqlDatabaseName());
Core::getDatabase()->exec($stmt);
}
private function removeTestFolders()
@ -142,10 +142,20 @@ class SzurubooruTestRunner implements ITestRunner
rmdir($folder);
}
private function resetEnvironment($options)
private function connectToDatabase($options)
{
$_SESSION = [];
$this->prepareTestConfig($options);
Core::prepareDatabase();
if ($options->dbDriver == 'mysql')
{
$stmt = \Chibi\Sql\Statements::raw('USE ' . $this->getMysqlDatabaseName());
Core::getDatabase()->executeUnprepared($stmt);
}
}
private function prepareTestConfig($options)
{
Core::prepareConfig(true);
Core::getConfig()->main->dbDriver = $options->dbDriver;
@ -159,15 +169,15 @@ class SzurubooruTestRunner implements ITestRunner
Core::getConfig()->main->dbUser = 'test';
Core::getConfig()->main->dbPass = 'test';
}
}
private function resetEnvironment($options)
{
$_SESSION = [];
Auth::setCurrentUser(null);
$this->removeTestFolders();
Core::prepareEnvironment(true);
if ($options->dbDriver == 'mysql')
{
$stmt = new \Chibi\Sql\RawStatement('USE ' . $this->getMysqlDatabaseName());
\Chibi\Database::execUnprepared($stmt);
}
$this->prepareTestConfig($options);
Core::prepareEnvironment();
}
}