diff --git a/lib/chibi-core b/lib/chibi-core
index 19bb5ee3..78597486 160000
--- a/lib/chibi-core
+++ b/lib/chibi-core
@@ -1 +1 @@
-Subproject commit 19bb5ee3901cf6402d7507c30b8fc183c3fc0bcc
+Subproject commit 78597486abb1bd6344a64a70c87d9deca14b7ff7
diff --git a/public_html/dispatch.php b/public_html/dispatch.php
index 9487a97d..7a8f9dd1 100644
--- a/public_html/dispatch.php
+++ b/public_html/dispatch.php
@@ -1,95 +1,5 @@
query = $query;
-
-function renderView()
-{
- $context = Core::getContext();
- \Chibi\View::render($context->layoutName, $context);
-}
-
-$context->simpleControllerName = null;
-$context->simpleActionName = null;
-
-\Chibi\Router::setObserver(function($route, $args)
-{
- $context = Core::getContext();
- $context->route = $route;
- list ($className, $methodName) = $route->destination;
-
- $context->simpleControllerName = TextCaseConverter::convert(
- str_replace('Controller', '', $className),
- TextCaseConverter::CAMEL_CASE,
- TextCaseConverter::SPINAL_CASE);
-
- $context->simpleActionName = TextCaseConverter::convert(
- preg_replace('/Action|View/', '', $methodName),
- TextCaseConverter::CAMEL_CASE,
- TextCaseConverter::SPINAL_CASE);
-
- $context->viewName = sprintf(
- '%s-%s',
- $context->simpleControllerName,
- $context->simpleActionName);
-});
-
-Assets::setTitle(Core::getConfig()->main->title);
-
-$context->handleExceptions = false;
-$context->layoutName
- = isset($_SERVER['HTTP_X_AJAX'])
- ? 'layout-json'
- : 'layout-normal';
-$context->viewName = '';
-$context->transport = new StdClass;
-
-SessionHelper::init();
-if (!Auth::isLoggedIn())
- Auth::tryAutoLogin();
-
-register_shutdown_function(function()
-{
- $error = error_get_last();
- if ($error !== null)
- \Chibi\Util\Headers::setCode(400);
-});
-
-try
-{
- try
- {
- \Chibi\Router::run($query);
- renderView();
- AuthController::observeWorkFinish();
- }
- catch (\Chibi\UnhandledRouteException $e)
- {
- throw new SimpleNotFoundException($query . ' not found.');
- }
-}
-catch (SimpleException $e)
-{
- if ($e instanceof SimpleNotFoundException)
- \Chibi\Util\Headers::setCode(404);
- else
- \Chibi\Util\Headers::setCode(400);
- Messenger::message($e->getMessage(), false);
- if (!$context->handleExceptions)
- $context->viewName = 'message';
- renderView();
-}
-catch (Exception $e)
-{
- \Chibi\Util\Headers::setCode(400);
- Messenger::message($e->getMessage(), false);
- $context->transport->exception = $e;
- $context->transport->queries = \Chibi\Database::getLogs();
- $context->viewName = 'error-exception';
- renderView();
-}
+$dispatcher = new Dispatcher();
+$dispatcher->run();
diff --git a/src/Controllers/AbstractController.php b/src/Controllers/AbstractController.php
new file mode 100644
index 00000000..8bfed787
--- /dev/null
+++ b/src/Controllers/AbstractController.php
@@ -0,0 +1,82 @@
+switchLayout('layout-normal');
+
+ $this->assets = new Assets();
+ $this->assets->setTitle(Core::getConfig()->main->title);
+ }
+
+ public function __destruct()
+ {
+ if ($this->isAjax())
+ $this->renderAjax();
+ }
+
+ public function renderAjax()
+ {
+ $this->switchLayout('layout-json');
+ $this->renderView(null);
+ }
+
+ public function renderFile()
+ {
+ $this->switchLayout('layout-file');
+ $this->renderView(null);
+ }
+
+ public function renderView($viewName)
+ {
+ //no matter which controller runs it (including ErrorController), render only once
+ if (self::isRendered())
+ return;
+
+ self::markAsRendered();
+ $context = Core::getContext();
+ if ($viewName !== null)
+ $context->viewName = $viewName;
+ View::renderTopLevel($this->layoutName, $this->assets);
+ }
+
+
+ protected function redirectToLastVisitedUrl($filter = null)
+ {
+ $targetUrl = SessionHelper::getLastVisitedUrl($filter);
+ if (!$targetUrl)
+ $targetUrl = \Chibi\Router::linkTo(['StaticPagesController', 'mainPageView']);
+ $this->redirect($targetUrl);
+ }
+
+ protected function redirect($url)
+ {
+ if (!$this->isAjax())
+ \Chibi\Util\Url::forward($url);
+ }
+
+
+ private static function isRendered()
+ {
+ return self::$isRendered;
+ }
+
+ private static function markAsRendered()
+ {
+ self::$isRendered = true;
+ }
+
+ private function switchLayout($layoutName)
+ {
+ $this->layoutName = $layoutName;
+ }
+}
diff --git a/src/Controllers/AuthController.php b/src/Controllers/AuthController.php
index 35385003..9f215d12 100644
--- a/src/Controllers/AuthController.php
+++ b/src/Controllers/AuthController.php
@@ -1,53 +1,35 @@
redirectToLastVisitedUrl('auth');
+ else
+ $this->renderView('auth-login');
}
public function loginAction()
{
- $context = Core::getContext();
- $context->viewName = 'auth-login';
- $context->handleExceptions = true;
+ try
+ {
+ $suppliedName = InputHelper::get('name');
+ $suppliedPassword = InputHelper::get('password');
+ $remember = boolval(InputHelper::get('remember'));
+ Auth::login($suppliedName, $suppliedPassword, $remember);
+ }
+ catch (SimpleException $e)
+ {
+ Messenger::fail($e->getMessage());
+ $this->renderView('auth-login');
+ }
- $suppliedName = InputHelper::get('name');
- $suppliedPassword = InputHelper::get('password');
- $remember = boolval(InputHelper::get('remember'));
- Auth::login($suppliedName, $suppliedPassword, $remember);
- self::redirect();
+ $this->redirectToLastVisitedUrl('auth');
}
public function logoutAction()
{
Auth::logout();
- self::redirect();
- }
-
- public static function observeWorkFinish()
- {
- if (strpos(\Chibi\Util\Headers::get('Content-Type'), 'text/html') === false)
- return;
- if (\Chibi\Util\Headers::getCode() != 200)
- return;
- $context = Core::getContext();
- if ($context->simpleControllerName == 'auth')
- return;
- $_SESSION['login-redirect-url'] = $context->query;
- }
-
- private static function redirect()
- {
- if (isset($_SESSION['login-redirect-url']))
- {
- \Chibi\Util\Url::forward(\Chibi\Util\Url::makeAbsolute($_SESSION['login-redirect-url']));
- unset($_SESSION['login-redirect-url']);
- exit;
- }
- \Chibi\Util\Url::forward(\Chibi\Router::linkTo(['StaticPagesController', 'mainPageView']));
- exit;
+ $this->redirectToLastVisitedUrl('auth');
}
}
diff --git a/src/Controllers/CommentController.php b/src/Controllers/CommentController.php
index 829cb8e6..32f88f1f 100644
--- a/src/Controllers/CommentController.php
+++ b/src/Controllers/CommentController.php
@@ -1,5 +1,5 @@
transport->posts = $ret->entities;
$context->transport->paginator = $ret;
+ $this->renderView('comment-list');
}
public function addAction()
@@ -26,6 +27,7 @@ class CommentController
]);
Core::getContext()->transport->textPreview = $comment->getTextMarkdown();
+ $this->renderAjax();
}
else
{
@@ -35,13 +37,18 @@ class CommentController
JobArgs::ARG_POST_ID => InputHelper::get('post-id'),
JobArgs::ARG_NEW_TEXT => InputHelper::get('text')
]);
+
+ if ($this->isAjax())
+ $this->renderAjax();
+ else
+ $this->redirectToLastVisitedUrl();
}
- $this->redirectToLastVisitedUrl();
}
public function editView($id)
{
Core::getContext()->transport->comment = CommentModel::getById($id);
+ $this->renderView('comment-edit');
}
public function editAction($id)
@@ -56,6 +63,7 @@ class CommentController
]);
Core::getContext()->transport->textPreview = $comment->getTextMarkdown();
+ $this->renderAjax();
}
else
{
@@ -65,8 +73,12 @@ class CommentController
JobArgs::ARG_COMMENT_ID => $id,
JobArgs::ARG_NEW_TEXT => InputHelper::get('text')
]);
+
+ if ($this->isAjax())
+ $this->renderAjax();
+ else
+ $this->redirectToLastVisitedUrl('comment/');
}
- $this->redirectToLastVisitedUrl();
}
public function deleteAction($id)
@@ -76,14 +88,10 @@ class CommentController
[
JobArgs::ARG_COMMENT_ID => $id,
]);
- $this->redirectToLastVisitedUrl();
- }
- private function redirectToLastVisitedUrl()
- {
- $lastUrl = SessionHelper::getLastVisitedUrl();
- if ($lastUrl)
- \Chibi\Util\Url::forward($lastUrl);
- exit;
+ if ($this->isAjax())
+ $this->renderAjax();
+ else
+ $this->redirectToLastVisitedUrl('comment/');
}
}
diff --git a/src/Controllers/ErrorController.php b/src/Controllers/ErrorController.php
new file mode 100644
index 00000000..144f9331
--- /dev/null
+++ b/src/Controllers/ErrorController.php
@@ -0,0 +1,30 @@
+getMessage());
+
+ if ($this->isAjax())
+ $this->renderAjax();
+ else
+ $this->renderView('message');
+ }
+
+ public function seriousExceptionView(Exception $exception)
+ {
+ \Chibi\Util\Headers::setCode(400);
+ Messenger::fail($exception->getMessage());
+ $context->transport->exception = $exception;
+ $context->transport->queries = \Chibi\Database::getLogs();
+
+ if ($this->isAjax())
+ $this->renderAjax();
+ else
+ $this->renderView('error-exception');
+ }
+}
diff --git a/src/Controllers/LogController.php b/src/Controllers/LogController.php
index df93ca20..d12b2ce9 100644
--- a/src/Controllers/LogController.php
+++ b/src/Controllers/LogController.php
@@ -1,30 +1,27 @@
transport->logs = $ret;
+ $this->renderView('log-list');
}
public function logView($name, $page = 1, $filter = '')
{
- $context = Core::getContext();
- $context->viewName = 'log-view';
-
//redirect requests in form of ?query=... to canonical address
$formQuery = InputHelper::get('query');
if ($formQuery !== null)
{
- \Chibi\Util\Url::forward(
- \Chibi\Router::linkTo(
- ['LogController', 'logView'],
- [
- 'name' => $name,
- 'filter' => $formQuery,
- 'page' => 1
- ]));
- exit;
+ $this->redirect(\Chibi\Router::linkTo(
+ ['LogController', 'logView'],
+ [
+ 'name' => $name,
+ 'filter' => $formQuery,
+ 'page' => 1
+ ]));
+ return;
}
$ret = Api::run(
@@ -46,9 +43,11 @@ class LogController
$lines = TextHelper::parseMarkdown($lines, true);
$lines = trim($lines);
+ $context = Core::getContext();
$context->transport->paginator = $ret;
$context->transport->lines = $lines;
$context->transport->filter = $filter;
$context->transport->name = $name;
+ $this->renderView('log-view');
}
}
diff --git a/src/Controllers/PostController.php b/src/Controllers/PostController.php
index 99dbf96f..70db4d14 100644
--- a/src/Controllers/PostController.php
+++ b/src/Controllers/PostController.php
@@ -1,68 +1,75 @@
viewName = 'post-list-wrapper';
$context->source = $source;
$context->additionalInfo = $additionalInfo;
- $context->handleExceptions = true;
- //redirect requests in form of /posts/?query=... to canonical address
- $formQuery = InputHelper::get('query');
- if ($formQuery !== null)
+ try
{
- $context->transport->searchQuery = $formQuery;
- $context->transport->lastSearchQuery = $formQuery;
- if (strpos($formQuery, '/') !== false)
- throw new SimpleException('Search query contains invalid characters');
+ //redirect requests in form of /posts/?query=... to canonical address
+ $formQuery = InputHelper::get('query');
+ if ($formQuery !== null)
+ {
+ $context->transport->searchQuery = $formQuery;
+ $context->transport->lastSearchQuery = $formQuery;
+ if (strpos($formQuery, '/') !== false)
+ throw new SimpleException('Search query contains invalid characters');
- $url = \Chibi\Router::linkTo(['PostController', 'listView'], [
- 'source' => $source,
- 'additionalInfo' => $additionalInfo,
- 'query' => $formQuery]);
- \Chibi\Util\Url::forward($url);
- exit;
+ $url = \Chibi\Router::linkTo(['PostController', 'listView'], [
+ 'source' => $source,
+ 'additionalInfo' => $additionalInfo,
+ 'query' => $formQuery]);
+ $this->redirect($url);
+ return;
+ }
+
+ $query = trim($query);
+ $context->transport->searchQuery = $query;
+ $context->transport->lastSearchQuery = $query;
+ if ($source == 'mass-tag')
+ {
+ Access::assert(new Privilege(Privilege::MassTag));
+ $context->massTagTag = $additionalInfo;
+ $context->massTagQuery = $query;
+
+ if (!Access::check(new Privilege(Privilege::MassTag, 'all')))
+ $query = trim($query . ' submit:' . Auth::getCurrentUser()->getName());
+ }
+
+ $ret = Api::run(
+ new ListPostsJob(),
+ [
+ JobArgs::ARG_PAGE_NUMBER => $page,
+ JobArgs::ARG_QUERY => $query
+ ]);
+
+ $context->transport->posts = $ret->entities;
+ $context->transport->paginator = $ret;
+ }
+ catch (SimpleException $e)
+ {
+ Messenger::fail($e->getMessage());
}
- $query = trim($query);
- $context->transport->searchQuery = $query;
- $context->transport->lastSearchQuery = $query;
- if ($source == 'mass-tag')
- {
- Access::assert(new Privilege(Privilege::MassTag));
- $context->massTagTag = $additionalInfo;
- $context->massTagQuery = $query;
-
- if (!Access::check(new Privilege(Privilege::MassTag, 'all')))
- $query = trim($query . ' submit:' . Auth::getCurrentUser()->getName());
- }
-
- $ret = Api::run(
- new ListPostsJob(),
- [
- JobArgs::ARG_PAGE_NUMBER => $page,
- JobArgs::ARG_QUERY => $query
- ]);
-
- $context->transport->posts = $ret->entities;
- $context->transport->paginator = $ret;
+ $this->renderView('post-list-wrapper');
}
public function favoritesView($page = 1)
{
- $this->listView('favmin:1', $page);
+ $this->listView('favmin:1', $page, 'favorites');
}
public function upvotedView($page = 1)
{
- $this->listView('scoremin:1', $page);
+ $this->listView('scoremin:1', $page, 'upvoted');
}
public function randomView($page = 1)
{
- $this->listView('order:random', $page);
+ $this->listView('order:random', $page, 'random');
}
public function toggleTagAction($id, $tag, $enable)
@@ -79,11 +86,15 @@ class PostController
JobArgs::ARG_NEW_STATE => $enable,
]);
- $this->redirectToLastVisitedUrl();
+ if ($this->isAjax())
+ $this->renderAjax();
+ else
+ $this->redirectToLastVisitedUrl();
}
public function uploadView()
{
+ $this->renderView('post-upload');
}
public function uploadAction()
@@ -111,6 +122,11 @@ class PostController
}
Api::run(new AddPostJob(), $jobArgs);
+
+ if ($this->isAjax())
+ $this->renderAjax();
+ else
+ $this->redirectToPostList();
}
public function editView($id)
@@ -119,6 +135,7 @@ class PostController
JobArgs::ARG_POST_ID => $id]);
$context = Core::getContext()->transport->post = $post;
+ $this->renderView('post-edit');
}
public function editAction($id)
@@ -163,13 +180,21 @@ class PostController
}
Api::run(new EditPostJob(), $jobArgs);
- $this->redirectToGenericView($id);
+
+ if ($this->isAjax())
+ $this->renderAjax();
+ else
+ $this->redirectToGenericView($id);
}
public function flagAction($id)
{
Api::run(new FlagPostJob(), [JobArgs::ARG_POST_ID => $id]);
- $this->redirectToGenericView($id);
+
+ if ($this->isAjax())
+ $this->renderAjax();
+ else
+ $this->redirectToGenericView($id);
}
public function hideAction($id)
@@ -192,7 +217,7 @@ class PostController
{
Api::run(new DeletePostJob(), [
JobArgs::ARG_POST_ID => $id]);
- $this->redirectToGenericView($id);
+ $this->redirectToPostList();
}
public function addFavoriteAction($id)
@@ -229,7 +254,6 @@ class PostController
public function genericView($id)
{
$context = Core::getContext();
- $context->viewName = 'post-view';
$post = Api::run(new GetPostJob(), [
JobArgs::ARG_POST_ID => $id]);
@@ -262,6 +286,8 @@ class PostController
$context->transport->post = $post;
$context->transport->prevPostId = $prevPostId ? $prevPostId : null;
$context->transport->nextPostId = $nextPostId ? $nextPostId : null;
+
+ $this->renderView('post-view');
}
public function fileView($name)
@@ -275,7 +301,7 @@ class PostController
$context->transport->fileHash = 'post' . md5(substr($ret->fileContent, 0, 4096));
$context->transport->fileContent = $ret->fileContent;
$context->transport->lastModified = $ret->lastModified;
- $context->layoutName = 'layout-file';
+ $this->renderFile();
}
public function thumbView($name)
@@ -289,9 +315,10 @@ class PostController
$context->transport->fileHash = 'thumb' . md5(substr($ret->fileContent, 0, 4096));
$context->transport->fileContent = $ret->fileContent;
$context->transport->lastModified = $ret->lastModified;
- $context->layoutName = 'layout-file';
+ $this->renderFile();
}
+
private function splitPostIds($string)
{
$ids = preg_split('/\D/', trim($string));
@@ -309,19 +336,15 @@ class PostController
return $tags;
}
- private function redirectToLastVisitedUrl()
+ private function redirectToPostList()
{
- $lastUrl = SessionHelper::getLastVisitedUrl();
- if ($lastUrl)
- \Chibi\Util\Url::forward($lastUrl);
- exit;
+ $this->redirect(\Chibi\Router::linkTo(['PostController', 'listView']));
}
private function redirectToGenericView($id)
{
- \Chibi\Util\Url::forward(\Chibi\Router::linkTo(
+ $this->redirect(\Chibi\Router::linkTo(
['PostController', 'genericView'],
['id' => $id]));
- exit;
}
}
diff --git a/src/Controllers/StaticPagesController.php b/src/Controllers/StaticPagesController.php
index 990704e0..c50e6f92 100644
--- a/src/Controllers/StaticPagesController.php
+++ b/src/Controllers/StaticPagesController.php
@@ -1,11 +1,10 @@
transport->postCount = PostModel::getCount();
- $context->viewName = 'static-main';
$context->transport->postSpaceUsage = PostModel::getSpaceUsage();
PostModel::featureRandomPostIfNecessary();
@@ -17,6 +16,8 @@ class StaticPagesController
$context->featuredPostUser = UserModel::tryGetByName(
PropertyModel::get(PropertyModel::FeaturedPostUserName));
}
+
+ $this->renderView('static-main');
}
public function helpView($tab = null)
@@ -31,9 +32,10 @@ class StaticPagesController
if (!isset($config->help->paths[$tab]))
throw new SimpleException('Invalid tab');
- $context->viewName = 'static-help';
$context->path = TextHelper::absolutePath($config->help->paths[$tab]);
$context->tab = $tab;
+
+ $this->renderView('static-help');
}
public function fatalErrorView($code = null)
diff --git a/src/Controllers/TagController.php b/src/Controllers/TagController.php
index 531f3acf..4e278fec 100644
--- a/src/Controllers/TagController.php
+++ b/src/Controllers/TagController.php
@@ -1,5 +1,5 @@
viewName = 'tag-list-wrapper';
$context->highestUsage = TagSearchService::getMostUsedTag()->getPostCount();
$context->filter = $filter;
$context->transport->tags = $ret->entities;
$context->transport->paginator = $ret;
+ $this->renderViewWithSource('tag-list-wrapper', 'list');
}
public function autoCompleteView()
@@ -42,6 +42,8 @@ class TagController
'count' => $tag->getPostCount(),
];
}, $ret->entities));
+
+ $this->renderAjax();
}
public function relatedView()
@@ -67,76 +69,94 @@ class TagController
'count' => $tag->getPostCount(),
];
}, $ret->entities));
+
+ $this->renderAjax();
}
public function mergeView()
{
- $context = Core::getContext();
- $context->viewName = 'tag-list-wrapper';
+ $this->renderViewWithSource('tag-list-wrapper', 'merge');
}
public function mergeAction()
{
- $context = Core::getContext();
- $context->viewName = 'tag-list-wrapper';
- $context->handleExceptions = true;
+ try
+ {
+ Api::run(
+ new MergeTagsJob(),
+ [
+ JobArgs::ARG_SOURCE_TAG_NAME => InputHelper::get('source-tag'),
+ JobArgs::ARG_TARGET_TAG_NAME => InputHelper::get('target-tag'),
+ ]);
- Api::run(
- new MergeTagsJob(),
- [
- JobArgs::ARG_SOURCE_TAG_NAME => InputHelper::get('source-tag'),
- JobArgs::ARG_TARGET_TAG_NAME => InputHelper::get('target-tag'),
- ]);
+ Messenger::success('Tags merged successfully.');
+ }
+ catch (SimpleException $e)
+ {
+ Messenger::fail($e->getMessage());
+ }
- Messenger::message('Tags merged successfully.');
+ $this->renderViewWithSource('tag-list-wrapper', 'merge');
}
public function renameView()
{
- $context = Core::getContext();
- $context->viewName = 'tag-list-wrapper';
+ $this->renderViewWithSource('tag-list-wrapper', 'rename');
}
public function renameAction()
{
- $context = Core::getContext();
- $context->viewName = 'tag-list-wrapper';
- $context->handleExceptions = true;
+ try
+ {
+ Api::run(
+ new RenameTagsJob(),
+ [
+ JobArgs::ARG_SOURCE_TAG_NAME => InputHelper::get('source-tag'),
+ JobArgs::ARG_TARGET_TAG_NAME => InputHelper::get('target-tag'),
+ ]);
- Api::run(
- new RenameTagsJob(),
- [
- JobArgs::ARG_SOURCE_TAG_NAME => InputHelper::get('source-tag'),
- JobArgs::ARG_TARGET_TAG_NAME => InputHelper::get('target-tag'),
- ]);
+ Messenger::success('Tag renamed successfully.');
+ }
+ catch (Exception $e)
+ {
+ Messenger::fail($e->getMessage());
+ }
- Messenger::message('Tag renamed successfully.');
+ $this->renderViewWithSource('tag-list-wrapper', 'rename');
}
public function massTagRedirectView()
{
- $context = Core::getContext();
- $context->viewName = 'tag-list-wrapper';
-
Access::assert(new Privilege(Privilege::MassTag));
+ $this->renderViewWithSource('tag-list-wrapper', 'mass-tag');
}
public function massTagRedirectAction()
{
- $this->massTagRedirectView();
+ Access::assert(new Privilege(Privilege::MassTag));
$suppliedOldPage = intval(InputHelper::get('old-page'));
$suppliedOldQuery = InputHelper::get('old-query');
$suppliedQuery = InputHelper::get('query');
$suppliedTag = InputHelper::get('tag');
- $params = [
+ $params =
+ [
'source' => 'mass-tag',
'query' => $suppliedQuery ?: ' ',
'additionalInfo' => $suppliedTag ? $suppliedTag : '',
];
+
if ($suppliedOldPage != 0 and $suppliedOldQuery == $suppliedQuery)
$params['page'] = $suppliedOldPage;
- \Chibi\Util\Url::forward(\Chibi\Router::linkTo(['PostController', 'listView'], $params));
- exit;
+
+ $this->redirect(\Chibi\Router::linkTo(['PostController', 'listView'], $params));
+ }
+
+
+ private function renderViewWithSource($viewName, $source)
+ {
+ $context = Core::getContext();
+ $context->source = $source;
+ $this->renderView($viewName);
}
}
diff --git a/src/Controllers/UserController.php b/src/Controllers/UserController.php
index 7c43adcc..943eb4bd 100644
--- a/src/Controllers/UserController.php
+++ b/src/Controllers/UserController.php
@@ -1,5 +1,5 @@
filter = $filter;
$context->transport->users = $ret->entities;
$context->transport->paginator = $ret;
+ $this->renderView('user-list');
}
public function genericView($identifier, $tab = 'favs', $page = 1)
{
- $user = Api::run(
- new GetUserJob(),
- $this->appendUserIdentifierArgument([], $identifier));
-
- $flagged = in_array(TextHelper::reprUser($user), SessionHelper::get('flagged', []));
-
- if ($tab == 'uploads')
- $query = 'submit:' . $user->getName();
- elseif ($tab == 'favs')
- $query = 'fav:' . $user->getName();
-
- elseif ($tab == 'delete')
- {
- Access::assert(new Privilege(
- Privilege::DeleteUser,
- Access::getIdentity($user)));
- }
- elseif ($tab == 'settings')
- {
- Access::assert(new Privilege(
- Privilege::ChangeUserSettings,
- Access::getIdentity($user)));
- }
- elseif ($tab == 'edit' and !(new EditUserJob)->canEditAnything(Auth::getCurrentUser()))
- Access::fail();
-
- $context = Core::getContext();
- $context->flagged = $flagged;
- $context->transport->tab = $tab;
- $context->transport->user = $user;
- $context->handleExceptions = true;
- $context->viewName = 'user-view';
-
- if (isset($query))
- {
- $ret = Api::run(
- new ListPostsJob(),
- [
- JobArgs::ARG_PAGE_NUMBER => $page,
- JobArgs::ARG_QUERY => $query
- ]);
-
- $context->transport->posts = $ret->entities;
- $context->transport->paginator = $ret;
- $context->transport->lastSearchQuery = $query;
- }
+ $this->prepareGenericView($identifier, $tab, $page);
+ $this->renderView('user-view');
}
public function settingsAction($identifier)
{
- $this->genericView($identifier, 'settings');
+ $this->prepareGenericView($identifier, 'settings');
- $suppliedSafety = InputHelper::get('safety');
- $desiredSafety = PostSafety::makeFlags($suppliedSafety);
+ try
+ {
+ $suppliedSafety = InputHelper::get('safety');
+ $desiredSafety = PostSafety::makeFlags($suppliedSafety);
- $user = Api::run(
- new EditUserSettingsJob(),
- $this->appendUserIdentifierArgument(
- [
- JobArgs::ARG_NEW_SETTINGS =>
+ $user = Api::run(
+ new EditUserSettingsJob(),
+ $this->appendUserIdentifierArgument(
[
- UserSettings::SETTING_SAFETY => $desiredSafety,
- UserSettings::SETTING_ENDLESS_SCROLLING => InputHelper::get('endless-scrolling'),
- UserSettings::SETTING_POST_TAG_TITLES => InputHelper::get('post-tag-titles'),
- UserSettings::SETTING_HIDE_DISLIKED_POSTS => InputHelper::get('hide-disliked-posts'),
- ]
- ], $identifier));
+ JobArgs::ARG_NEW_SETTINGS =>
+ [
+ UserSettings::SETTING_SAFETY => $desiredSafety,
+ UserSettings::SETTING_ENDLESS_SCROLLING => InputHelper::get('endless-scrolling'),
+ UserSettings::SETTING_POST_TAG_TITLES => InputHelper::get('post-tag-titles'),
+ UserSettings::SETTING_HIDE_DISLIKED_POSTS => InputHelper::get('hide-disliked-posts'),
+ ]
+ ], $identifier));
- Core::getContext()->transport->user = $user;
- if ($user->getId() == Auth::getCurrentUser()->getId())
- Auth::setCurrentUser($user);
+ Core::getContext()->transport->user = $user;
+ if ($user->getId() == Auth::getCurrentUser()->getId())
+ Auth::setCurrentUser($user);
- Messenger::message('Browsing settings updated!');
+ Messenger::success('Browsing settings updated!');
+ }
+ catch (SimpleException $e)
+ {
+ Messenger::fail($e->getMessage());
+ }
+
+ $this->renderView('user-view');
}
public function editAction($identifier)
{
- $this->genericView($identifier, 'edit');
- $this->requirePasswordConfirmation();
+ $this->prepareGenericView($identifier, 'edit');
- if (InputHelper::get('password1') != InputHelper::get('password2'))
- throw new SimpleException('Specified passwords must be the same');
+ try
+ {
+ $this->requirePasswordConfirmation();
- $args =
- [
- JobArgs::ARG_NEW_USER_NAME => InputHelper::get('name'),
- JobArgs::ARG_NEW_PASSWORD => InputHelper::get('password1'),
- JobArgs::ARG_NEW_EMAIL => InputHelper::get('email'),
- JobArgs::ARG_NEW_ACCESS_RANK => InputHelper::get('access-rank'),
- ];
- $args = $this->appendUserIdentifierArgument($args, $identifier);
+ if (InputHelper::get('password1') != InputHelper::get('password2'))
+ throw new SimpleException('Specified passwords must be the same');
- $args = array_filter($args);
- $user = Api::run(new EditUserJob(), $args);
+ $args =
+ [
+ JobArgs::ARG_NEW_USER_NAME => InputHelper::get('name'),
+ JobArgs::ARG_NEW_PASSWORD => InputHelper::get('password1'),
+ JobArgs::ARG_NEW_EMAIL => InputHelper::get('email'),
+ JobArgs::ARG_NEW_ACCESS_RANK => InputHelper::get('access-rank'),
+ ];
+ $args = $this->appendUserIdentifierArgument($args, $identifier);
- if (Auth::getCurrentUser()->getId() == $user->getId())
- Auth::setCurrentUser($user);
+ $args = array_filter($args);
+ $user = Api::run(new EditUserJob(), $args);
- $message = 'Account settings updated!';
- if (Mailer::getMailCounter() > 0)
- $message .= ' You will be sent an e-mail address confirmation message soon.';
+ if (Auth::getCurrentUser()->getId() == $user->getId())
+ Auth::setCurrentUser($user);
- Messenger::message($message);
+ $message = 'Account settings updated!';
+ if (Mailer::getMailCounter() > 0)
+ $message .= ' You will be sent an e-mail address confirmation message soon.';
+
+ Messenger::success($message);
+ }
+ catch (SimpleException $e)
+ {
+ Messenger::fail($e->getMessage());
+ }
+
+ $this->renderView('user-view');
+ }
+
+ public function deleteAction($identifier)
+ {
+ $this->prepareGenericView($identifier, 'delete');
+
+ try
+ {
+ $this->requirePasswordConfirmation();
+
+ Api::run(
+ new DeleteUserJob(),
+ $this->appendUserIdentifierArgument([], $identifier));
+
+ $user = UserModel::tryGetById(Auth::getCurrentUser()->getId());
+ if (!$user)
+ Auth::logOut();
+
+ $this->redirectToMainPage();
+ }
+ catch (SimpleException $e)
+ {
+ Messenger::fail($e->getMessage());
+ $this->renderView('user-view');
+ }
}
public function toggleSafetyAction($safety)
@@ -144,23 +144,6 @@ class UserController
$this->redirectToLastVisitedUrl();
}
- public function deleteAction($identifier)
- {
- $this->genericView($identifier, 'delete');
- $this->requirePasswordConfirmation();
-
- Api::run(
- new DeleteUserJob(),
- $this->appendUserIdentifierArgument([], $identifier));
-
- $user = UserModel::tryGetById(Auth::getCurrentUser()->getId());
- if (!$user)
- Auth::logOut();
-
- \Chibi\Util\Url::forward(\Chibi\Router::linkTo(['StaticPagesController', 'mainPageView']));
- exit;
- }
-
public function flagAction($identifier)
{
Api::run(
@@ -199,70 +182,70 @@ class UserController
public function registrationView()
{
- $context = Core::getContext();
- $context->handleExceptions = true;
-
- //check if already logged in
if (Auth::isLoggedIn())
- {
- \Chibi\Util\Url::forward(\Chibi\Router::linkTo(['StaticPagesController', 'mainPageView']));
- exit;
- }
+ $this->redirectToMainPage();
+ $this->renderView('user-registration');
}
public function registrationAction()
{
- $this->registrationView();
-
- if (InputHelper::get('password1') != InputHelper::get('password2'))
- throw new SimpleException('Specified passwords must be the same');
-
- $user = Api::run(new AddUserJob(),
- [
- JobArgs::ARG_NEW_USER_NAME => InputHelper::get('name'),
- JobArgs::ARG_NEW_PASSWORD => InputHelper::get('password1'),
- JobArgs::ARG_NEW_EMAIL => InputHelper::get('email'),
- ]);
-
- if (!Core::getConfig()->registration->needEmailForRegistering and !Core::getConfig()->registration->staffActivation)
+ try
{
- Auth::setCurrentUser($user);
+ if (InputHelper::get('password1') != InputHelper::get('password2'))
+ throw new SimpleException('Specified passwords must be the same');
+
+ $user = Api::run(new AddUserJob(),
+ [
+ JobArgs::ARG_NEW_USER_NAME => InputHelper::get('name'),
+ JobArgs::ARG_NEW_PASSWORD => InputHelper::get('password1'),
+ JobArgs::ARG_NEW_EMAIL => InputHelper::get('email'),
+ ]);
+
+ if (!$this->isAnyAccountActivationNeeded())
+ {
+ Auth::setCurrentUser($user);
+ }
+
+ $message = 'Congratulations, your account was created.';
+ if (Mailer::getMailCounter() > 0)
+ {
+ $message .= ' Please wait for activation e-mail.';
+ if (Core::getConfig()->registration->staffActivation)
+ $message .= ' After this, your registration must be confirmed by staff.';
+ }
+ elseif (Core::getConfig()->registration->staffActivation)
+ $message .= ' Your registration must be now confirmed by staff.';
+
+ Messenger::success($message);
+ }
+ catch (SimpleException $e)
+ {
+ Messenger::fail($e->getMessage());
}
- $message = 'Congratulations, your account was created.';
- if (Mailer::getMailCounter() > 0)
- {
- $message .= ' Please wait for activation e-mail.';
- if (Core::getConfig()->registration->staffActivation)
- $message .= ' After this, your registration must be confirmed by staff.';
- }
- elseif (Core::getConfig()->registration->staffActivation)
- $message .= ' Your registration must be now confirmed by staff.';
-
- Messenger::message($message);
+ $this->renderView('user-registration');
}
public function activationView()
{
- $context = Core::getContext();
- $context->viewName = 'user-select';
- Assets::setSubTitle('account activation');
+ $this->assets->setSubTitle('account activation');
+ $this->renderView('user-select');
}
public function activationAction($tokenText)
{
- $context = Core::getContext();
- $context->viewName = 'message';
- Assets::setSubTitle('account activation');
+ $this->assets->setSubTitle('account activation');
$identifier = InputHelper::get('identifier');
+ try
+ {
if (empty($tokenText))
{
Api::run(
new ActivateUserEmailJob(),
$this->appendUserIdentifierArgument([], $identifier));
- Messenger::message('Activation e-mail resent.');
+ Messenger::success('Activation e-mail resent.');
}
else
{
@@ -272,45 +255,115 @@ class UserController
$message = 'Activation completed successfully.';
if (Core::getConfig()->registration->staffActivation)
$message .= ' However, your account still must be confirmed by staff.';
- Messenger::message($message);
+ Messenger::success($message);
if (!Core::getConfig()->registration->staffActivation)
Auth::setCurrentUser($user);
}
+ }
+ catch (SimpleException $e)
+ {
+ Messenger::fail($e->getMessage());
+ }
+
+ $this->renderView('message');
}
public function passwordResetView()
{
- $context = Core::getContext();
- $context->viewName = 'user-select';
- Assets::setSubTitle('password reset');
+ $this->assets->setSubTitle('password reset');
+ $this->renderView('user-select');
}
public function passwordResetAction($tokenText)
{
- $context = Core::getContext();
- $context->viewName = 'message';
- Assets::setSubTitle('password reset');
+ $this->assets->setSubTitle('password reset');
$identifier = InputHelper::get('identifier');
- if (empty($tokenText))
+ try
{
- Api::run(
- new PasswordResetJob(),
- $this->appendUserIdentifierArgument([], $identifier));
+ if (empty($tokenText))
+ {
+ Api::run(
+ new PasswordResetJob(),
+ $this->appendUserIdentifierArgument([], $identifier));
- Messenger::message('E-mail sent. Follow instructions to reset password.');
+ Messenger::success('E-mail sent. Follow instructions to reset password.');
+ }
+ else
+ {
+ $ret = Api::run(new PasswordResetJob(), [ JobArgs::ARG_TOKEN => $tokenText ]);
+
+ Messenger::success(sprintf(
+ 'Password reset successful. Your new password is **%s**.',
+ $ret->newPassword));
+
+ Auth::setCurrentUser($ret->user);
+ }
}
- else
+ catch (SimpleException $e)
{
- $ret = Api::run(new PasswordResetJob(), [ JobArgs::ARG_TOKEN => $tokenText ]);
-
- Messenger::message(sprintf(
- 'Password reset successful. Your new password is **%s**.',
- $ret->newPassword));
-
- Auth::setCurrentUser($ret->user);
+ Messenger::fail($e->getMessage());
}
+
+ $this->renderView('message');
+ }
+
+
+ private function prepareGenericView($identifier, $tab, $page = 1)
+ {
+ $user = Api::run(
+ new GetUserJob(),
+ $this->appendUserIdentifierArgument([], $identifier));
+
+ $flagged = in_array(TextHelper::reprUser($user), SessionHelper::get('flagged', []));
+
+ if ($tab == 'uploads')
+ $query = 'submit:' . $user->getName();
+ elseif ($tab == 'favs')
+ $query = 'fav:' . $user->getName();
+
+ elseif ($tab == 'delete')
+ {
+ Access::assert(new Privilege(
+ Privilege::DeleteUser,
+ Access::getIdentity($user)));
+ }
+ elseif ($tab == 'settings')
+ {
+ Access::assert(new Privilege(
+ Privilege::ChangeUserSettings,
+ Access::getIdentity($user)));
+ }
+ elseif ($tab == 'edit' and !(new EditUserJob)->canEditAnything(Auth::getCurrentUser()))
+ Access::fail();
+
+ $context = Core::getContext();
+ $context->flagged = $flagged;
+ $context->transport->tab = $tab;
+ $context->transport->user = $user;
+
+ if (isset($query))
+ {
+ $ret = Api::run(
+ new ListPostsJob(),
+ [
+ JobArgs::ARG_PAGE_NUMBER => $page,
+ JobArgs::ARG_QUERY => $query
+ ]);
+
+ $context->transport->posts = $ret->entities;
+ $context->transport->paginator = $ret;
+ $context->transport->lastSearchQuery = $query;
+ }
+ }
+
+
+ private function isAnyAccountActivationNeeded()
+ {
+ $config = Core::getConfig();
+ return ($config->registration->needEmailForRegistering
+ or $config->registration->staffActivation);
}
private function requirePasswordConfirmation()
@@ -334,19 +387,16 @@ class UserController
return $arguments;
}
- private function redirectToLastVisitedUrl()
+ private function redirectToMainPage()
{
- $lastUrl = SessionHelper::getLastVisitedUrl();
- if ($lastUrl)
- \Chibi\Util\Url::forward($lastUrl);
+ $this->redirect(\Chibi\Router::linkTo(['StaticPagesController', 'mainPageView']));
exit;
}
private function redirectToGenericView($identifier)
{
- \Chibi\Util\Url::forward(\Chibi\Router::linkTo(
+ $this->redirect(\Chibi\Router::linkTo(
['UserController', 'genericView'],
['identifier' => $identifier]));
- exit;
}
}
diff --git a/src/Dispatcher.php b/src/Dispatcher.php
new file mode 100644
index 00000000..f557a2d9
--- /dev/null
+++ b/src/Dispatcher.php
@@ -0,0 +1,77 @@
+retrieveQuery();
+
+ $context = Core::getContext();
+ $context->query = $query;
+ $context->transport = new StdClass;
+
+ $this->setRouterObserver();
+ $this->ensureResponseCodeUponFail();
+
+ SessionHelper::init();
+ if (!Auth::isLoggedIn())
+ Auth::tryAutoLogin();
+
+ $this->routeAndHandleErrors($query);
+ }
+
+ private function routeAndHandleErrors($query)
+ {
+ try
+ {
+ \Chibi\Router::run($query);
+ }
+ catch (\Chibi\UnhandledRouteException $e)
+ {
+ $errorController = new ErrorController;
+ $errorController->simpleExceptionView(new SimpleNotFoundException($query . ' not found.'));
+ }
+ catch (SimpleException $e)
+ {
+ $errorController = new ErrorController;
+ $errorController->simpleExceptionView($e);
+ }
+ catch (SimpleException $e)
+ {
+ $errorController = new ErrorController;
+ $errorController->seriousExceptionView($e);
+ }
+ }
+
+ private function ensureResponseCodeUponFail()
+ {
+ register_shutdown_function(function()
+ {
+ $error = error_get_last();
+ if ($error !== null)
+ \Chibi\Util\Headers::setCode(400);
+ });
+ }
+
+ private function retrieveQuery()
+ {
+ if (isset($_SERVER['REDIRECT_URL']))
+ return $this->parseRawHttpQuery($_SERVER['REDIRECT_URL']);
+ else
+ return $this->parseRawHttpQuery($_SERVER['REQUEST_URI']);
+ }
+
+ private function parseRawHttpQuery($rawHttpQuery)
+ {
+ return rtrim($rawHttpQuery, '/');
+ }
+
+ private function setRouterObserver()
+ {
+ \Chibi\Router::setObserver(function($route, $args)
+ {
+ $context = Core::getContext();
+ $context->route = $route;
+ });
+ }
+}
+
diff --git a/src/Helpers/Assets.php b/src/Helpers/Assets.php
index 50d555ce..678de702 100644
--- a/src/Helpers/Assets.php
+++ b/src/Helpers/Assets.php
@@ -1,47 +1,41 @@
subTitle = $text;
}
- public static function setSubTitle($text)
+ public function setPageThumb($path)
{
- self::$subTitle = $text;
+ $this->pageThumb = $path;
}
- public static function setPageThumb($path)
- {
- self::$pageThumb = $path;
- }
-
- public static function addStylesheet($path)
+ public function addStylesheet($path)
{
return parent::addStylesheet('/media/css/' . $path);
}
- public static function addScript($path)
+ public function addScript($path)
{
return parent::addScript('/media/js/' . $path);
}
- public static function transformHtml($html)
+ public function transformHtml($html)
{
- self::$title = isset(self::$subTitle)
- ? sprintf('%s – %s', self::$title, self::$subTitle)
- : self::$title;
+ $this->title = isset($this->subTitle)
+ ? sprintf('%s – %s', $this->title, $this->subTitle)
+ : $this->title;
$html = parent::transformHtml($html);
- $headSnippet = '';
+ $headSnippet = '';
$headSnippet .= '';
- if (!empty(self::$pageThumb))
- $headSnippet .= '';
+ if (!empty($this->pageThumb))
+ $headSnippet .= '';
$bodySnippet = '