From 902aed727882eb4418af094a2935d9b63e96151d Mon Sep 17 00:00:00 2001 From: Marcin Kurczewski Date: Thu, 1 May 2014 16:25:10 +0200 Subject: [PATCH 001/188] Introducing API Right now there's a lot of messy code in controllers. Furthermore, there is no way to interact with szurubooru via vanilla HTTP, since API is next to non-existent. So, basing upon my experiences from another project, I plan to: - Create actual API. It is going to consist of well-defined "jobs" that do things currently done by controllers. Benefits of such approach are as follows: - defining them in their own classes allows to clean up code a lot, - it allows to abstract from input method (POST data, part of URL, whatever), and leave processing of these to controllers, - it allows to make proxy controller, whose purpose would be to let users interact with API (jobs) directly in well-documented and consistent way. - Make controllers responsible only for mediating between views and API. Behavior of these may remain inconsistent, since views they're talking to are also messy to begin with. Such controllers might be removed altogether in the future in favor of making views talk to API directly through previously mentioned ApiController. - Organize all sorts of privilege checking and possibly other stuff into methods within jobs. - Actually distinguish POST from GET requests. - Leave POST-only controller methods as Actions, but rename GET-only methods to Views. Example: editAction for editing comments, but listView for showing comment list. The choice of these suffixes might be subject to changes in future. - Get rid of ?json and $context->transport. They now look like disease to me. This commit introduces job system and converts CommentController to use the new API. --- public_html/dispatch.php | 14 +++-- src/Api.php | 33 +++++++++++ src/Auth.php | 1 + src/Controllers/CommentController.php | 80 +++++++++++---------------- src/Helpers/LogHelper.php | 16 ++++-- src/Jobs/AbstractJob.php | 9 +++ src/Jobs/AddCommentJob.php | 38 +++++++++++++ src/Jobs/EditCommentJob.php | 35 ++++++++++++ src/Jobs/PreviewCommentJob.php | 31 +++++++++++ src/Views/comment-add.phtml | 5 +- src/Views/comment-small.phtml | 6 +- src/Views/top-navigation.phtml | 2 +- 12 files changed, 203 insertions(+), 67 deletions(-) create mode 100644 src/Api.php create mode 100644 src/Jobs/AbstractJob.php create mode 100644 src/Jobs/AddCommentJob.php create mode 100644 src/Jobs/EditCommentJob.php create mode 100644 src/Jobs/PreviewCommentJob.php diff --git a/public_html/dispatch.php b/public_html/dispatch.php index 182d6b54..18b24d3f 100644 --- a/public_html/dispatch.php +++ b/public_html/dispatch.php @@ -35,7 +35,7 @@ $context->simpleActionName = null; TextCaseConverter::SPINAL_CASE); $context->simpleActionName = TextCaseConverter::convert( - str_replace('Action', '', $methodName), + preg_replace('/Action|View/', '', $methodName), TextCaseConverter::CAMEL_CASE, TextCaseConverter::SPINAL_CASE); @@ -45,6 +45,13 @@ $context->simpleActionName = null; $context->simpleActionName); }); +\Chibi\Router::register(['CommentController', 'listView'], 'GET', '/comments'); +\Chibi\Router::register(['CommentController', 'listView'], 'GET', '/comments/{page}', ['page' => '\d+']); +\Chibi\Router::register(['CommentController', 'addAction'], 'POST', '/comment/add'); +\Chibi\Router::register(['CommentController', 'deleteAction'], 'POST', '/comment/{id}/delete', ['id' => '\d+']); +\Chibi\Router::register(['CommentController', 'editView'], 'GET', '/comment/{id}/edit', ['id' => '\d+']); +\Chibi\Router::register(['CommentController', 'editAction'], 'POST', '/comment/{id}/edit', ['id' => '\d+']); + foreach (['GET', 'POST'] as $method) { \Chibi\Router::register(['IndexController', 'indexAction'], $method, ''); @@ -59,11 +66,6 @@ foreach (['GET', 'POST'] as $method) \Chibi\Router::register(['AuthController', 'logoutAction'], $method, '/auth/logout'); \Chibi\Router::register(['AuthController', 'loginAction'], 'POST', '/auth/login'); \Chibi\Router::register(['AuthController', 'logoutAction'], 'POST', '/auth/logout'); - \Chibi\Router::register(['CommentController', 'listAction'], $method, '/comments'); - \Chibi\Router::register(['CommentController', 'listAction'], $method, '/comments/{page}', ['page' => '\d+']); - \Chibi\Router::register(['CommentController', 'addAction'], $method, '/post/{postId}/add-comment', ['postId' => '\d+']); - \Chibi\Router::register(['CommentController', 'deleteAction'], $method, '/comment/{id}/delete', ['id' => '\d+']); - \Chibi\Router::register(['CommentController', 'editAction'], $method, '/comment/{id}/edit', ['id' => '\d+']); $postValidation = [ diff --git a/src/Api.php b/src/Api.php new file mode 100644 index 00000000..64099943 --- /dev/null +++ b/src/Api.php @@ -0,0 +1,33 @@ +requiresAuthentication()) + Access::assertAuthentication(); + + if ($job->requiresConfirmedEmail()) + Access::assertEmailConfirmation(); + + return $job->execute($jobArgs); + }); + } + + public static function runMultiple($jobs) + { + $statuses = []; + \Chibi\Database::transaction(function() use ($jobs, &$statuses) + { + foreach ($jobs as $jobItem) + { + list ($job, $jobArgs) = $jobItem; + $statuses []= self::run($job, $jobArgs); + } + }); + return $statuses; + } +} diff --git a/src/Auth.php b/src/Auth.php index a2c90fd2..e3e91c09 100644 --- a/src/Auth.php +++ b/src/Auth.php @@ -85,6 +85,7 @@ class Auth private static function getAnonymousUser() { $dummy = UserModel::spawn(); + $dummy->id = null; $dummy->name = UserModel::getAnonymousName(); $dummy->accessRank = AccessRank::Anonymous; return $dummy; diff --git a/src/Controllers/CommentController.php b/src/Controllers/CommentController.php index 05cceb5e..5c4a6ea5 100644 --- a/src/Controllers/CommentController.php +++ b/src/Controllers/CommentController.php @@ -1,7 +1,7 @@ transport->paginator->params = func_get_args(); } - public function addAction($postId) + public function previewAction() { - $context = getContext(); - Access::assert(Privilege::AddComment); - if (getConfig()->registration->needEmailForCommenting) - Access::assertEmailConfirmation(); + $comment = Api::run( + new PreviewCommentJob(), + [ + 'text' => InputHelper::get('text') + ]); - $post = PostModel::findById($postId); - $context->transport->post = $post; + getContext()->transport->textPreview = $comment->getText(); + } - if (!InputHelper::get('submit')) - return; + public function addAction() + { + if (InputHelper::get('sender') == 'preview') + return $this->previewAction(); - $text = InputHelper::get('text'); - $text = CommentModel::validateText($text); + $comment = Api::run( + new AddCommentJob(), + [ + 'post-id' => InputHelper::get('post-id'), + 'text' => InputHelper::get('text') + ]); + } - $comment = CommentModel::spawn(); - $comment->setPost($post); - if (Auth::isLoggedIn()) - $comment->setCommenter(Auth::getCurrentUser()); - else - $comment->setCommenter(null); - $comment->commentDate = time(); - $comment->text = $text; - - if (InputHelper::get('sender') != 'preview') - { - CommentModel::save($comment); - LogHelper::log('{user} commented on {post}', ['post' => TextHelper::reprPost($post->id)]); - } - $context->transport->textPreview = $comment->getText(); + public function editView($id) + { + getContext()->transport->comment = CommentModel::findById($id); } public function editAction($id) { - $context = getContext(); - $comment = CommentModel::findById($id); - $context->transport->comment = $comment; + if (InputHelper::get('sender') == 'preview') + return $this->previewAction(); - Access::assert( - Privilege::EditComment, - Access::getIdentity($comment->getCommenter())); - - if (!InputHelper::get('submit')) - return; - - $text = InputHelper::get('text'); - $text = CommentModel::validateText($text); - - $comment->text = $text; - - if (InputHelper::get('sender') != 'preview') - { - CommentModel::save($comment); - LogHelper::log('{user} edited comment in {post}', [ - 'post' => TextHelper::reprPost($comment->getPost())]); - } - $context->transport->textPreview = $comment->getText(); + $comment = Api::run( + new EditCommentJob(), + [ + 'comment-id' => $id, + 'text' => InputHelper::get('text') + ]); } public function deleteAction($id) diff --git a/src/Helpers/LogHelper.php b/src/Helpers/LogHelper.php index 2a1bf35d..f573358d 100644 --- a/src/Helpers/LogHelper.php +++ b/src/Helpers/LogHelper.php @@ -71,11 +71,17 @@ class LogEvent $this->text = $text; $this->ip = isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : '0.0.0.0'; - $tokens['anon'] = UserModel::getAnonymousName(); - if (Auth::isLoggedIn()) - $tokens['user'] = TextHelper::reprUser(Auth::getCurrentUser()->name); - else - $tokens['user'] = $tokens['anon']; + //todo: deprecated + if (!isset($tokens['anon'])) + $tokens['anon'] = UserModel::getAnonymousName(); + if (!isset($tokens['user'])) + { + if (Auth::isLoggedIn()) + $tokens['user'] = TextHelper::reprUser(Auth::getCurrentUser()->name); + else + $tokens['user'] = $tokens['anon']; + } + $this->tokens = $tokens; } diff --git a/src/Jobs/AbstractJob.php b/src/Jobs/AbstractJob.php new file mode 100644 index 00000000..a12400e4 --- /dev/null +++ b/src/Jobs/AbstractJob.php @@ -0,0 +1,9 @@ +setCommenter($user); + $comment->setPost($post); + $comment->commentDate = time(); + $comment->text = $text; + + CommentModel::save($comment); + LogHelper::log('{user} commented on {post}', [ + 'user' => TextHelper::reprUser(Auth::getCurrentUser()), + 'post' => TextHelper::reprPost($comment->getPost()->id)]); + + return $comment; + } + + public function requiresPrivilege() + { + return Privilege::AddComment; + } + + public function requiresAuthentication() + { + return true; + } + + public function requiresConfirmedEmail() + { + return getConfig()->registration->needEmailForCommenting; + } +} diff --git a/src/Jobs/EditCommentJob.php b/src/Jobs/EditCommentJob.php new file mode 100644 index 00000000..1c7d6589 --- /dev/null +++ b/src/Jobs/EditCommentJob.php @@ -0,0 +1,35 @@ +commentDate = time(); + $comment->text = $text; + + CommentModel::save($comment); + LogHelper::log('{user} edited comment in {post}', [ + 'user' => TextHelper::reprUser(Auth::getCurrentUser()), + 'post' => TextHelper::reprPost($comment->getPost())]); + + return $comment; + } + + public function requiresPrivilege() + { + return Privilege::EditComment; + } + + public function requiresAuthentication() + { + return true; + } + + public function requiresConfirmedEmail() + { + return getConfig()->registration->needEmailForCommenting; + } +} diff --git a/src/Jobs/PreviewCommentJob.php b/src/Jobs/PreviewCommentJob.php new file mode 100644 index 00000000..b3f3c35f --- /dev/null +++ b/src/Jobs/PreviewCommentJob.php @@ -0,0 +1,31 @@ +setCommenter($user); + $comment->commentDate = time(); + $comment->text = $text; + + return $comment; + } + + public function requiresPrivilege() + { + return Privilege::AddComment; + } + + public function requiresAuthentication() + { + return true; + } + + public function requiresConfirmedEmail() + { + return getConfig()->registration->needEmailForCommenting; + } +} diff --git a/src/Views/comment-add.phtml b/src/Views/comment-add.phtml index 8733249d..96213d13 100644 --- a/src/Views/comment-add.phtml +++ b/src/Views/comment-add.phtml @@ -5,9 +5,7 @@ Assets::addScript('comment-edit.js');

add comment

@@ -18,6 +16,7 @@ Assets::addScript('comment-edit.js');
+
diff --git a/src/Views/comment-small.phtml b/src/Views/comment-small.phtml index 09d77879..46092298 100644 --- a/src/Views/comment-small.phtml +++ b/src/Views/comment-small.phtml @@ -41,15 +41,15 @@ Assets::addScript('comment-edit.js'); Access::getIdentity($commenter))): ?> edit - Date: Fri, 2 May 2014 08:14:16 +0200 Subject: [PATCH 002/188] Changed default access rank from admin to none --- src/Access.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Access.php b/src/Access.php index 97610391..1086e91c 100644 --- a/src/Access.php +++ b/src/Access.php @@ -38,7 +38,7 @@ class Access return true; $user = Auth::getCurrentUser(); - $minAccessRank = AccessRank::Admin; + $minAccessRank = AccessRank::Nobody; $key = TextCaseConverter::convert(Privilege::toString($privilege), TextCaseConverter::CAMEL_CASE, From 3cdaa85511bdaa79fc4c5b4b4b8c36ea2ebf8747 Mon Sep 17 00:00:00 2001 From: Marcin Kurczewski Date: Fri, 2 May 2014 09:07:22 +0200 Subject: [PATCH 003/188] Added subprivilege authentication --- src/Api.php | 9 +++++++++ src/Jobs/AbstractJob.php | 4 ++++ src/Jobs/AddCommentJob.php | 4 ++-- src/Jobs/EditCommentJob.php | 20 +++++++++++++++----- src/Jobs/PreviewCommentJob.php | 1 - 5 files changed, 30 insertions(+), 8 deletions(-) diff --git a/src/Api.php b/src/Api.php index 64099943..64dc2879 100644 --- a/src/Api.php +++ b/src/Api.php @@ -7,12 +7,21 @@ class Api return \Chibi\Database::transaction(function() use ($job, $jobArgs) { + $job->prepare($jobArgs); + if ($job->requiresAuthentication()) Access::assertAuthentication(); if ($job->requiresConfirmedEmail()) Access::assertEmailConfirmation(); + $p = $job->requiresPrivilege(); + list ($privilege, $subPrivilege) = is_array($p) + ? $p + : [$p, null]; + if ($privilege !== null) + Access::assert($privilege, $subPrivilege); + return $job->execute($jobArgs); }); } diff --git a/src/Jobs/AbstractJob.php b/src/Jobs/AbstractJob.php index a12400e4..d168fcc4 100644 --- a/src/Jobs/AbstractJob.php +++ b/src/Jobs/AbstractJob.php @@ -1,6 +1,10 @@ TextHelper::reprUser(Auth::getCurrentUser()), + 'user' => TextHelper::reprUser($user), 'post' => TextHelper::reprPost($comment->getPost()->id)]); return $comment; diff --git a/src/Jobs/EditCommentJob.php b/src/Jobs/EditCommentJob.php index 1c7d6589..8419b844 100644 --- a/src/Jobs/EditCommentJob.php +++ b/src/Jobs/EditCommentJob.php @@ -1,18 +1,24 @@ comment = CommentModel::findById($arguments['comment-id']); + } + public function execute($arguments) { $user = Auth::getCurrentUser(); - $comment = CommentModel::findById($arguments['comment-id']); - $text = CommentModel::validateText($arguments['text']); + $comment = $this->comment; $comment->commentDate = time(); - $comment->text = $text; + $comment->text = CommentModel::validateText($arguments['text']); CommentModel::save($comment); LogHelper::log('{user} edited comment in {post}', [ - 'user' => TextHelper::reprUser(Auth::getCurrentUser()), + 'user' => TextHelper::reprUser($user), 'post' => TextHelper::reprPost($comment->getPost())]); return $comment; @@ -20,7 +26,11 @@ class EditCommentJob extends AbstractJob public function requiresPrivilege() { - return Privilege::EditComment; + return + [ + Privilege::EditComment, + Access::getIdentity($this->comment->getCommenter()) + ]; } public function requiresAuthentication() diff --git a/src/Jobs/PreviewCommentJob.php b/src/Jobs/PreviewCommentJob.php index b3f3c35f..232258b5 100644 --- a/src/Jobs/PreviewCommentJob.php +++ b/src/Jobs/PreviewCommentJob.php @@ -10,7 +10,6 @@ class PreviewCommentJob extends AbstractJob $comment->setCommenter($user); $comment->commentDate = time(); $comment->text = $text; - return $comment; } From 16c5d6961b549c3bfa797b9cf37d7cb05a6c9902 Mon Sep 17 00:00:00 2001 From: Marcin Kurczewski Date: Fri, 2 May 2014 09:32:47 +0200 Subject: [PATCH 004/188] More robust argument handling --- src/Api.php | 5 +++-- src/Controllers/CommentController.php | 10 +++++----- src/Jobs/AbstractJob.php | 13 ------------- src/Jobs/Abstraction/AbstractJob.php | 28 +++++++++++++++++++++++++++ src/Jobs/Abstraction/JobArgs.php | 7 +++++++ src/Jobs/AddCommentJob.php | 6 +++--- src/Jobs/EditCommentJob.php | 8 ++++---- src/Jobs/PreviewCommentJob.php | 4 ++-- 8 files changed, 52 insertions(+), 29 deletions(-) delete mode 100644 src/Jobs/AbstractJob.php create mode 100644 src/Jobs/Abstraction/AbstractJob.php create mode 100644 src/Jobs/Abstraction/JobArgs.php diff --git a/src/Api.php b/src/Api.php index 64dc2879..2b372a46 100644 --- a/src/Api.php +++ b/src/Api.php @@ -7,7 +7,8 @@ class Api return \Chibi\Database::transaction(function() use ($job, $jobArgs) { - $job->prepare($jobArgs); + $job->setArguments($jobArgs); + $job->prepare(); if ($job->requiresAuthentication()) Access::assertAuthentication(); @@ -22,7 +23,7 @@ class Api if ($privilege !== null) Access::assert($privilege, $subPrivilege); - return $job->execute($jobArgs); + return $job->execute(); }); } diff --git a/src/Controllers/CommentController.php b/src/Controllers/CommentController.php index 5c4a6ea5..2bdcc43f 100644 --- a/src/Controllers/CommentController.php +++ b/src/Controllers/CommentController.php @@ -35,7 +35,7 @@ class CommentController $comment = Api::run( new PreviewCommentJob(), [ - 'text' => InputHelper::get('text') + JobArgs::TEXT => InputHelper::get('text') ]); getContext()->transport->textPreview = $comment->getText(); @@ -49,8 +49,8 @@ class CommentController $comment = Api::run( new AddCommentJob(), [ - 'post-id' => InputHelper::get('post-id'), - 'text' => InputHelper::get('text') + JobArgs::POST_ID => InputHelper::get('post-id'), + JobArgs::TEXT => InputHelper::get('text') ]); } @@ -67,8 +67,8 @@ class CommentController $comment = Api::run( new EditCommentJob(), [ - 'comment-id' => $id, - 'text' => InputHelper::get('text') + JobArgs::COMMENT_ID => $id, + JobArgs::TEXT => InputHelper::get('text') ]); } diff --git a/src/Jobs/AbstractJob.php b/src/Jobs/AbstractJob.php deleted file mode 100644 index d168fcc4..00000000 --- a/src/Jobs/AbstractJob.php +++ /dev/null @@ -1,13 +0,0 @@ -arguments[$key])) + throw new SimpleException('Expected argument "' . $key . '" was not specified'); + + return $this->arguments[$key]; + } + + public function setArguments($arguments) + { + $this->arguments = $arguments; + } +} diff --git a/src/Jobs/Abstraction/JobArgs.php b/src/Jobs/Abstraction/JobArgs.php new file mode 100644 index 00000000..677f11c1 --- /dev/null +++ b/src/Jobs/Abstraction/JobArgs.php @@ -0,0 +1,7 @@ +getArgument(JobArgs::POST_ID)); + $text = CommentModel::validateText($this->getArgument(JobArgs::TEXT)); $comment = CommentModel::spawn(); $comment->setCommenter($user); diff --git a/src/Jobs/EditCommentJob.php b/src/Jobs/EditCommentJob.php index 8419b844..f82abf03 100644 --- a/src/Jobs/EditCommentJob.php +++ b/src/Jobs/EditCommentJob.php @@ -3,18 +3,18 @@ class EditCommentJob extends AbstractJob { protected $comment; - public function prepare($arguments) + public function prepare() { - $this->comment = CommentModel::findById($arguments['comment-id']); + $this->comment = CommentModel::findById($this->getArgument(JobArgs::COMMENT_ID)); } - public function execute($arguments) + public function execute() { $user = Auth::getCurrentUser(); $comment = $this->comment; $comment->commentDate = time(); - $comment->text = CommentModel::validateText($arguments['text']); + $comment->text = CommentModel::validateText($this->getArgument(JobArgs::TEXT)); CommentModel::save($comment); LogHelper::log('{user} edited comment in {post}', [ diff --git a/src/Jobs/PreviewCommentJob.php b/src/Jobs/PreviewCommentJob.php index 232258b5..04f235bd 100644 --- a/src/Jobs/PreviewCommentJob.php +++ b/src/Jobs/PreviewCommentJob.php @@ -1,10 +1,10 @@ getArgument(JobArgs::TEXT)); $comment = CommentModel::spawn(); $comment->setCommenter($user); From 6a28be5e3e3196b027e8696bd6576b8361487b25 Mon Sep 17 00:00:00 2001 From: Marcin Kurczewski Date: Fri, 2 May 2014 09:40:23 +0200 Subject: [PATCH 005/188] Moved comment removal to API --- src/Controllers/CommentController.php | 19 +++++-------- src/Jobs/DeleteCommentJob.php | 40 +++++++++++++++++++++++++++ src/Jobs/EditCommentJob.php | 3 +- 3 files changed, 48 insertions(+), 14 deletions(-) create mode 100644 src/Jobs/DeleteCommentJob.php diff --git a/src/Controllers/CommentController.php b/src/Controllers/CommentController.php index 2bdcc43f..6fce8e3c 100644 --- a/src/Controllers/CommentController.php +++ b/src/Controllers/CommentController.php @@ -46,7 +46,7 @@ class CommentController if (InputHelper::get('sender') == 'preview') return $this->previewAction(); - $comment = Api::run( + Api::run( new AddCommentJob(), [ JobArgs::POST_ID => InputHelper::get('post-id'), @@ -64,7 +64,7 @@ class CommentController if (InputHelper::get('sender') == 'preview') return $this->previewAction(); - $comment = Api::run( + Api::run( new EditCommentJob(), [ JobArgs::COMMENT_ID => $id, @@ -74,15 +74,10 @@ class CommentController public function deleteAction($id) { - $comment = CommentModel::findById($id); - - Access::assert( - Privilege::DeleteComment, - Access::getIdentity($comment->getCommenter())); - - CommentModel::remove($comment); - - LogHelper::log('{user} removed comment from {post}', [ - 'post' => TextHelper::reprPost($comment->getPost())]); + $comment = Api::run( + new DeleteCommentJob(), + [ + JobArgs::COMMENT_ID => $id, + ]); } } diff --git a/src/Jobs/DeleteCommentJob.php b/src/Jobs/DeleteCommentJob.php new file mode 100644 index 00000000..b7f6e7ae --- /dev/null +++ b/src/Jobs/DeleteCommentJob.php @@ -0,0 +1,40 @@ +comment = CommentModel::findById($this->getArgument(JobArgs::COMMENT_ID)); + } + + public function execute() + { + $post = $this->comment->getPost(); + + CommentModel::remove($this->comment); + + LogHelper::log('{user} removed comment from {post}', [ + 'user' => TextHelper::reprUser(Auth::getCurrentUser()), + 'post' => TextHelper::reprPost($post)]); + } + + public function requiresPrivilege() + { + return + [ + Privilege::DeleteComment, + Access::getIdentity($this->comment->getCommenter()) + ]; + } + + public function requiresAuthentication() + { + return true; + } + + public function requiresConfirmedEmail() + { + return getConfig()->registration->needEmailForCommenting; + } +} diff --git a/src/Jobs/EditCommentJob.php b/src/Jobs/EditCommentJob.php index f82abf03..b2c70ff6 100644 --- a/src/Jobs/EditCommentJob.php +++ b/src/Jobs/EditCommentJob.php @@ -10,7 +10,6 @@ class EditCommentJob extends AbstractJob public function execute() { - $user = Auth::getCurrentUser(); $comment = $this->comment; $comment->commentDate = time(); @@ -18,7 +17,7 @@ class EditCommentJob extends AbstractJob CommentModel::save($comment); LogHelper::log('{user} edited comment in {post}', [ - 'user' => TextHelper::reprUser($user), + 'user' => TextHelper::reprUser(Auth::getCurrentUser()), 'post' => TextHelper::reprPost($comment->getPost())]); return $comment; From c0a7fe520986c1135360ffb31d96982e7647fb0a Mon Sep 17 00:00:00 2001 From: Marcin Kurczewski Date: Fri, 2 May 2014 09:50:13 +0200 Subject: [PATCH 006/188] Moved comment listing to API --- src/Controllers/CommentController.php | 34 +++++++-------------- src/Jobs/Abstraction/JobArgs.php | 1 + src/Jobs/ListCommentsJob.php | 44 +++++++++++++++++++++++++++ 3 files changed, 56 insertions(+), 23 deletions(-) create mode 100644 src/Jobs/ListCommentsJob.php diff --git a/src/Controllers/CommentController.php b/src/Controllers/CommentController.php index 6fce8e3c..aeac8357 100644 --- a/src/Controllers/CommentController.php +++ b/src/Controllers/CommentController.php @@ -1,33 +1,21 @@ comments->commentsPerPage); - $searchQuery = 'comment_min:1 order:comment_date,desc'; - - $posts = PostSearchService::getEntities($searchQuery, $commentsPerPage, $page); - $postCount = PostSearchService::getEntityCount($searchQuery); - $pageCount = ceil($postCount / $commentsPerPage); - PostModel::preloadTags($posts); - PostModel::preloadComments($posts); - $comments = []; - foreach ($posts as $post) - $comments = array_merge($comments, $post->getComments()); - CommentModel::preloadCommenters($comments); + $ret = Api::run( + new ListCommentsJob(), + [ + JobArgs::PAGE_NUMBER => $page, + ]); $context = getContext(); - $context->postGroups = true; - $context->transport->posts = $posts; + $context->transport->posts = $ret->posts; $context->transport->paginator = new StdClass; - $context->transport->paginator->page = $page; - $context->transport->paginator->pageCount = $pageCount; - $context->transport->paginator->entityCount = $postCount; - $context->transport->paginator->entities = $posts; - $context->transport->paginator->params = func_get_args(); + $context->transport->paginator->page = $ret->page; + $context->transport->paginator->pageCount = $ret->pageCount; + $context->transport->paginator->entityCount = $ret->postCount; + $context->transport->paginator->entities = $ret->posts; } public function previewAction() diff --git a/src/Jobs/Abstraction/JobArgs.php b/src/Jobs/Abstraction/JobArgs.php index 677f11c1..0c33f3b6 100644 --- a/src/Jobs/Abstraction/JobArgs.php +++ b/src/Jobs/Abstraction/JobArgs.php @@ -4,4 +4,5 @@ class JobArgs const COMMENT_ID = 'comment-id'; const POST_ID = 'post-id'; const TEXT = 'text'; + const PAGE_NUMBER = 'page-number'; } diff --git a/src/Jobs/ListCommentsJob.php b/src/Jobs/ListCommentsJob.php new file mode 100644 index 00000000..4a2e69d8 --- /dev/null +++ b/src/Jobs/ListCommentsJob.php @@ -0,0 +1,44 @@ +getArgument(JobArgs::PAGE_NUMBER); + + $page = max(1, intval($page)); + $commentsPerPage = intval(getConfig()->comments->commentsPerPage); + $searchQuery = 'comment_min:1 order:comment_date,desc'; + + $posts = PostSearchService::getEntities($searchQuery, $commentsPerPage, $page); + $postCount = PostSearchService::getEntityCount($searchQuery); + $pageCount = ceil($postCount / $commentsPerPage); + PostModel::preloadTags($posts); + PostModel::preloadComments($posts); + $comments = []; + foreach ($posts as $post) + $comments = array_merge($comments, $post->getComments()); + CommentModel::preloadCommenters($comments); + + $ret = new StdClass; + $ret->posts = $posts; + $ret->postCount = $postCount; + $ret->page = $page; + $ret->pageCount = $pageCount; + return $ret; + } + + public function requiresPrivilege() + { + return Privilege::ListComments; + } + + public function requiresAuthentication() + { + return false; + } + + public function requiresConfirmedEmail() + { + return false; + } +} From ffeefd06c67d502576de47b169fc6cc0863bee9b Mon Sep 17 00:00:00 2001 From: Marcin Kurczewski Date: Fri, 2 May 2014 13:49:31 +0200 Subject: [PATCH 007/188] Moved post listing to API --- public_html/dispatch.php | 42 +++++++++++----------- src/Controllers/PostController.php | 58 +++++++++++++++--------------- src/Controllers/TagController.php | 2 +- src/CustomMarkdown.php | 4 +-- src/Jobs/Abstraction/JobArgs.php | 1 + src/Jobs/ListCommentsJob.php | 2 ++ src/Jobs/ListPostsJob.php | 41 +++++++++++++++++++++ src/Views/index-index.phtml | 2 +- src/Views/post-list-wrapper.phtml | 10 +++--- src/Views/post-upload.phtml | 2 +- src/Views/post-view.phtml | 6 ++-- src/Views/tag-list.phtml | 2 +- src/Views/top-navigation.phtml | 4 +-- 13 files changed, 110 insertions(+), 66 deletions(-) create mode 100644 src/Jobs/ListPostsJob.php diff --git a/public_html/dispatch.php b/public_html/dispatch.php index 18b24d3f..5702c688 100644 --- a/public_html/dispatch.php +++ b/public_html/dispatch.php @@ -45,6 +45,28 @@ $context->simpleActionName = null; $context->simpleActionName); }); +$postValidation = +[ + 'tag' => '[^\/]*', + 'enable' => '0|1', + 'source' => 'posts|mass-tag', + 'query' => '[^\/]*', + 'additionalInfo' => '[^\/]*', + 'score' => '-1|0|1', +]; + +\Chibi\Router::register(['PostController', 'listView'], 'GET', '/{source}', $postValidation); +\Chibi\Router::register(['PostController', 'listView'], 'GET', '/{source}/{query}', $postValidation); +\Chibi\Router::register(['PostController', 'listView'], 'GET', '/{source}/{query}/{page}', $postValidation); +\Chibi\Router::register(['PostController', 'listView'], 'GET', '/{source}/{additionalInfo}/{query}/{page}', $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(['CommentController', 'listView'], 'GET', '/comments'); \Chibi\Router::register(['CommentController', 'listView'], 'GET', '/comments/{page}', ['page' => '\d+']); \Chibi\Router::register(['CommentController', 'addAction'], 'POST', '/comment/add'); @@ -67,28 +89,8 @@ foreach (['GET', 'POST'] as $method) \Chibi\Router::register(['AuthController', 'loginAction'], 'POST', '/auth/login'); \Chibi\Router::register(['AuthController', 'logoutAction'], 'POST', '/auth/logout'); - $postValidation = - [ - 'tag' => '[^\/]*', - 'enable' => '0|1', - 'source' => 'posts|mass-tag', - 'query' => '[^\/]*', - 'additionalInfo' => '[^\/]*', - 'score' => '-1|0|1', - ]; - \Chibi\Router::register(['PostController', 'uploadAction'], $method, '/posts/upload', $postValidation); - \Chibi\Router::register(['PostController', 'listAction'], $method, '/{source}', $postValidation); - \Chibi\Router::register(['PostController', 'listAction'], $method, '/{source}/{query}', $postValidation); - \Chibi\Router::register(['PostController', 'listAction'], $method, '/{source}/{query}/{page}', $postValidation); - \Chibi\Router::register(['PostController', 'listAction'], $method, '/{source}/{additionalInfo}/{query}/{page}', $postValidation); \Chibi\Router::register(['PostController', 'toggleTagAction'], $method, '/post/{id}/toggle-tag/{tag}/{enable}', $postValidation); - \Chibi\Router::register(['PostController', 'favoritesAction'], $method, '/favorites', $postValidation); - \Chibi\Router::register(['PostController', 'favoritesAction'], $method, '/favorites/{page}', $postValidation); - \Chibi\Router::register(['PostController', 'upvotedAction'], $method, '/upvoted', $postValidation); - \Chibi\Router::register(['PostController', 'upvotedAction'], $method, '/upvoted/{page}', $postValidation); - \Chibi\Router::register(['PostController', 'randomAction'], $method, '/random', $postValidation); - \Chibi\Router::register(['PostController', 'randomAction'], $method, '/random/{page}', $postValidation); \Chibi\Router::register(['PostController', 'viewAction'], $method, '/post/{id}', $postValidation); \Chibi\Router::register(['PostController', 'retrieveAction'], $method, '/post/{name}/retrieve', $postValidation); \Chibi\Router::register(['PostController', 'thumbAction'], $method, '/post/{name}/thumb', $postValidation); diff --git a/src/Controllers/PostController.php b/src/Controllers/PostController.php index 2021e372..661a1d6c 100644 --- a/src/Controllers/PostController.php +++ b/src/Controllers/PostController.php @@ -1,7 +1,7 @@ viewName = 'post-list-wrapper'; @@ -18,7 +18,7 @@ class PostController if (strpos($formQuery, '/') !== false) throw new SimpleException('Search query contains invalid characters'); - $url = \Chibi\Router::linkTo(['PostController', 'listAction'], [ + $url = \Chibi\Router::linkTo(['PostController', 'listView'], [ 'source' => $source, 'additionalInfo' => $additionalInfo, 'query' => $formQuery]); @@ -27,11 +27,8 @@ class PostController } $query = trim($query); - $page = max(1, intval($page)); - $postsPerPage = intval(getConfig()->browsing->postsPerPage); $context->transport->searchQuery = $query; $context->transport->lastSearchQuery = $query; - Access::assert(Privilege::ListPosts); if ($source == 'mass-tag') { Access::assert(Privilege::MassTag); @@ -42,18 +39,34 @@ class PostController $query = trim($query . ' submit:' . Auth::getCurrentUser()->name); } - $posts = PostSearchService::getEntities($query, $postsPerPage, $page); - $postCount = PostSearchService::getEntityCount($query); - $pageCount = ceil($postCount / $postsPerPage); - $page = min($pageCount, $page); - PostModel::preloadTags($posts); + $ret = Api::run( + new ListPostsJob(), + [ + JobArgs::PAGE_NUMBER => $page, + JobArgs::QUERY => $query + ]); + $context->transport->posts = $ret->posts; $context->transport->paginator = new StdClass; - $context->transport->paginator->page = $page; - $context->transport->paginator->pageCount = $pageCount; - $context->transport->paginator->entityCount = $postCount; - $context->transport->paginator->entities = $posts; - $context->transport->posts = $posts; + $context->transport->paginator->page = $ret->page; + $context->transport->paginator->pageCount = $ret->pageCount; + $context->transport->paginator->entityCount = $ret->postCount; + $context->transport->paginator->entities = $ret->posts; + } + + public function favoritesView($page = 1) + { + $this->listView('favmin:1', $page); + } + + public function upvotedView($page = 1) + { + $this->listView('scoremin:1', $page); + } + + public function randomView($page = 1) + { + $this->listView('order:random', $page); } public function toggleTagAction($id, $tag, $enable) @@ -103,21 +116,6 @@ class PostController PostModel::save($post); } - public function favoritesAction($page = 1) - { - $this->listAction('favmin:1', $page); - } - - public function upvotedAction($page = 1) - { - $this->listAction('scoremin:1', $page); - } - - public function randomAction($page = 1) - { - $this->listAction('order:random', $page); - } - public function uploadAction() { $context = getContext(); diff --git a/src/Controllers/TagController.php b/src/Controllers/TagController.php index f8ff5cc2..368a5f3e 100644 --- a/src/Controllers/TagController.php +++ b/src/Controllers/TagController.php @@ -154,6 +154,6 @@ class TagController ]; if ($suppliedOldPage != 0 and $suppliedOldQuery == $suppliedQuery) $params['page'] = $suppliedOldPage; - \Chibi\Util\Url::forward(\Chibi\Router::linkTo(['PostController', 'listAction'], $params)); + \Chibi\Util\Url::forward(\Chibi\Router::linkTo(['PostController', 'listView'], $params)); } } diff --git a/src/CustomMarkdown.php b/src/CustomMarkdown.php index 2cc80f6c..cda304be 100644 --- a/src/CustomMarkdown.php +++ b/src/CustomMarkdown.php @@ -136,7 +136,7 @@ class CustomMarkdown extends \Michelf\MarkdownExtra protected function doTags($text) { - $link = \Chibi\Router::linkTo(['PostController', 'listAction'], ['query' => '_query_']); + $link = \Chibi\Router::linkTo(['PostController', 'listView'], ['query' => '_query_']); return preg_replace_callback('/(?:(?hashPart('' . $x[0] . ''); @@ -154,7 +154,7 @@ class CustomMarkdown extends \Michelf\MarkdownExtra protected function doSearchPermalinks($text) { - $link = \Chibi\Router::linkTo(['PostController', 'listAction'], ['query' => '_query_']); + $link = \Chibi\Router::linkTo(['PostController', 'listView'], ['query' => '_query_']); return preg_replace_callback('{\[search\]((?:[^\[]|\[(?!\/?search\]))+)\[\/search\]}is', function($x) use ($link) { return $this->hashPart('' . $x[1] . ''); diff --git a/src/Jobs/Abstraction/JobArgs.php b/src/Jobs/Abstraction/JobArgs.php index 0c33f3b6..80d849ce 100644 --- a/src/Jobs/Abstraction/JobArgs.php +++ b/src/Jobs/Abstraction/JobArgs.php @@ -5,4 +5,5 @@ class JobArgs const POST_ID = 'post-id'; const TEXT = 'text'; const PAGE_NUMBER = 'page-number'; + const QUERY = 'query'; } diff --git a/src/Jobs/ListCommentsJob.php b/src/Jobs/ListCommentsJob.php index 4a2e69d8..cda2bfb9 100644 --- a/src/Jobs/ListCommentsJob.php +++ b/src/Jobs/ListCommentsJob.php @@ -12,6 +12,8 @@ class ListCommentsJob extends AbstractJob $posts = PostSearchService::getEntities($searchQuery, $commentsPerPage, $page); $postCount = PostSearchService::getEntityCount($searchQuery); $pageCount = ceil($postCount / $commentsPerPage); + $page = min($pageCount, $page); + PostModel::preloadTags($posts); PostModel::preloadComments($posts); $comments = []; diff --git a/src/Jobs/ListPostsJob.php b/src/Jobs/ListPostsJob.php new file mode 100644 index 00000000..34928d39 --- /dev/null +++ b/src/Jobs/ListPostsJob.php @@ -0,0 +1,41 @@ +getArgument(JobArgs::PAGE_NUMBER); + $query = $this->getArgument(JobArgs::QUERY); + + $page = max(1, intval($page)); + $postsPerPage = intval(getConfig()->browsing->postsPerPage); + + $posts = PostSearchService::getEntities($query, $postsPerPage, $page); + $postCount = PostSearchService::getEntityCount($query); + $pageCount = ceil($postCount / $postsPerPage); + $page = min($pageCount, $page); + + PostModel::preloadTags($posts); + + $ret = new StdClass; + $ret->posts = $posts; + $ret->postCount = $postCount; + $ret->page = $page; + $ret->pageCount = $pageCount; + return $ret; + } + + public function requiresPrivilege() + { + return Privilege::ListPosts; + } + + public function requiresAuthentication() + { + return false; + } + + public function requiresConfirmedEmail() + { + return false; + } +} diff --git a/src/Views/index-index.phtml b/src/Views/index-index.phtml index e162bf2a..a1e9a5e1 100644 --- a/src/Views/index-index.phtml +++ b/src/Views/index-index.phtml @@ -29,7 +29,7 @@ Assets::addStylesheet('index-index.css'); name, $b->name); }) ?>
  • - + name ?>
  • diff --git a/src/Views/post-list-wrapper.phtml b/src/Views/post-list-wrapper.phtml index 0b9815a8..ff73c922 100644 --- a/src/Views/post-list-wrapper.phtml +++ b/src/Views/post-list-wrapper.phtml @@ -4,32 +4,32 @@ Assets::setSubTitle('posts'); $tabs = []; $activeTab = 0; if (Access::check(Privilege::ListPosts)) - $tabs []= ['All posts', \Chibi\Router::linkTo(['PostController', 'listAction'])]; + $tabs []= ['All posts', \Chibi\Router::linkTo(['PostController', 'listView'])]; if (Access::check(Privilege::ListPosts)) { - $tabs []= ['Random', \Chibi\Router::linkTo(['PostController', 'randomAction'])]; + $tabs []= ['Random', \Chibi\Router::linkTo(['PostController', 'randomView'])]; if ($this->context->simpleActionName == 'random') $activeTab = count($tabs) - 1; } if (Access::check(Privilege::ListPosts)) { - $tabs []= ['Favorites', \Chibi\Router::linkTo(['PostController', 'favoritesAction'])]; + $tabs []= ['Favorites', \Chibi\Router::linkTo(['PostController', 'favoritesView'])]; if ($this->context->simpleActionName == 'favorites') $activeTab = count($tabs) - 1; } if (Access::check(Privilege::ListPosts)) { - $tabs []= ['Upvoted', \Chibi\Router::linkTo(['PostController', 'upvotedAction'])]; + $tabs []= ['Upvoted', \Chibi\Router::linkTo(['PostController', 'upvotedView'])]; if ($this->context->simpleActionName == 'upvoted') $activeTab = count($tabs) - 1; } if (Access::check(Privilege::MassTag)) { - $tabs []= ['Mass tag', \Chibi\Router::linkTo(['PostController', 'listAction'], [ + $tabs []= ['Mass tag', \Chibi\Router::linkTo(['PostController', 'listView'], [ 'source' => 'mass-tag', 'query' => isset($this->context->transport->searchQuery) ? htmlspecialchars($this->context->transport->searchQuery) diff --git a/src/Views/post-upload.phtml b/src/Views/post-upload.phtml index 0b3b95c2..c33f9685 100644 --- a/src/Views/post-upload.phtml +++ b/src/Views/post-upload.phtml @@ -37,7 +37,7 @@ Assets::addScript('../lib/tagit/jquery.tagit.js');
    -
    +

    diff --git a/src/Views/post-view.phtml b/src/Views/post-view.phtml index d718cec4..910b36f4 100644 --- a/src/Views/post-view.phtml +++ b/src/Views/post-view.phtml @@ -60,7 +60,7 @@ $canEditAnything = count(array_filter($editPostPrivileges)) > 0;
    Current search:
    context->transport->lastSearchQuery ?> @@ -76,7 +76,7 @@ $canEditAnything = count(array_filter($editPostPrivileges)) > 0;
  • name ?> @@ -354,7 +354,7 @@ $canEditAnything = count(array_filter($editPostPrivileges)) > 0; ['PostController', 'deleteAction'], ['id' => $this->context->transport->post->id]), 'data-confirm-text' => 'Are you sure you want to delete this post?', - 'data-redirect-url' => \Chibi\Router::linkTo(['PostController', 'listAction']), + 'data-redirect-url' => \Chibi\Router::linkTo(['PostController', 'listView']), ]; } diff --git a/src/Views/tag-list.phtml b/src/Views/tag-list.phtml index 6dfdea54..a3eba47c 100644 --- a/src/Views/tag-list.phtml +++ b/src/Views/tag-list.phtml @@ -28,7 +28,7 @@ context->highestUsage ?> - '_query_']) ?> + '_query_']) ?>
  • @@ -77,7 +77,7 @@ name="password2" id="password2" placeholder="New password… (repeat)" - value="context->suppliedPassword2) ?>"/> + value=""/>
    @@ -92,8 +92,8 @@ -
    diff --git a/src/Views/comment-add.phtml b/src/Views/comment-add.phtml index 96213d13..cdae4709 100644 --- a/src/Views/comment-add.phtml +++ b/src/Views/comment-add.phtml @@ -17,7 +17,6 @@ Assets::addScript('comment-edit.js');
    -
      diff --git a/src/Views/comment-edit.phtml b/src/Views/comment-edit.phtml index e7f2271a..92a46ce1 100644 --- a/src/Views/comment-edit.phtml +++ b/src/Views/comment-edit.phtml @@ -20,8 +20,6 @@ Assets::addScript('comment-edit.js');
    - -
      diff --git a/src/Views/post-edit.phtml b/src/Views/post-edit.phtml index 4dbed190..6f3c1ee9 100644 --- a/src/Views/post-edit.phtml +++ b/src/Views/post-edit.phtml @@ -119,8 +119,6 @@
    - -
    diff --git a/src/Views/post-upload.phtml b/src/Views/post-upload.phtml index c33f9685..9eead716 100644 --- a/src/Views/post-upload.phtml +++ b/src/Views/post-upload.phtml @@ -114,8 +114,6 @@ Assets::addScript('../lib/tagit/jquery.tagit.js');
    - -
    diff --git a/src/Views/tag-mass-tag.phtml b/src/Views/tag-mass-tag.phtml index ade0dd5a..3f6f959e 100644 --- a/src/Views/tag-mass-tag.phtml +++ b/src/Views/tag-mass-tag.phtml @@ -44,11 +44,6 @@ ? htmlspecialchars($this->context->massTagQuery) : '' ?>"/> - -
    diff --git a/src/Views/tag-merge.phtml b/src/Views/tag-merge.phtml index 980bd822..04eb0b38 100644 --- a/src/Views/tag-merge.phtml +++ b/src/Views/tag-merge.phtml @@ -16,8 +16,6 @@
    - - context) ?>
    diff --git a/src/Views/tag-rename.phtml b/src/Views/tag-rename.phtml index ec7787e9..1d2e6712 100644 --- a/src/Views/tag-rename.phtml +++ b/src/Views/tag-rename.phtml @@ -16,8 +16,6 @@
    - - context) ?>
    diff --git a/src/Views/user-delete.phtml b/src/Views/user-delete.phtml index 01b01ec9..bd755520 100644 --- a/src/Views/user-delete.phtml +++ b/src/Views/user-delete.phtml @@ -16,8 +16,6 @@
    - - context) ?>
    diff --git a/src/Views/user-edit.phtml b/src/Views/user-edit.phtml index e4d6751e..a613e366 100644 --- a/src/Views/user-edit.phtml +++ b/src/Views/user-edit.phtml @@ -106,8 +106,6 @@
    - - context) ?>
    diff --git a/src/Views/user-registration.phtml b/src/Views/user-registration.phtml index 9a6dc542..3a39e802 100644 --- a/src/Views/user-registration.phtml +++ b/src/Views/user-registration.phtml @@ -74,8 +74,6 @@ Assets::setSubTitle('registration form'); context) ?> - -
    diff --git a/src/Views/user-select.phtml b/src/Views/user-select.phtml index f840dc9f..1ad7c546 100644 --- a/src/Views/user-select.phtml +++ b/src/Views/user-select.phtml @@ -17,8 +17,6 @@
    - - context) ?>
    diff --git a/src/Views/user-settings.phtml b/src/Views/user-settings.phtml index 1e4155bd..affc01b0 100644 --- a/src/Views/user-settings.phtml +++ b/src/Views/user-settings.phtml @@ -87,8 +87,6 @@
    - - context) ?>
    From b02c55e52cdbe2376b7ce8d62af5347cd7451fbe Mon Sep 17 00:00:00 2001 From: Marcin Kurczewski Date: Sun, 4 May 2014 17:51:07 +0200 Subject: [PATCH 050/188] Fixed post uploading --- src/Api/Jobs/AddPostJob.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Api/Jobs/AddPostJob.php b/src/Api/Jobs/AddPostJob.php index ed12409e..f0a86fe7 100644 --- a/src/Api/Jobs/AddPostJob.php +++ b/src/Api/Jobs/AddPostJob.php @@ -20,7 +20,7 @@ class AddPostJob extends AbstractJob //warning: it uses the same privileges as post editing internally $arguments = $this->getArguments(); $arguments[EditPostJob::POST_ID] = $post->id; - Api::execute(new EditPostJob(), $arguments); + Api::run(new EditPostJob(), $arguments); //load the post after edits $post = PostModel::findById($post->id); From 977989ffedc52bfa116bef7f8e7bf525a9f56f61 Mon Sep 17 00:00:00 2001 From: Marcin Kurczewski Date: Sun, 4 May 2014 17:53:40 +0200 Subject: [PATCH 051/188] Added one-time save to posts/users adding/editing --- src/Api/AbstractJob.php | 10 ++++++++-- src/Api/AbstractPostJob.php | 11 +++++++++-- src/Api/AbstractUserJob.php | 11 +++++++++-- src/Api/Jobs/AbstractPostEditJob.php | 11 +++++++++++ src/Api/Jobs/AbstractUserEditJob.php | 11 +++++++++++ src/Api/Jobs/AddPostJob.php | 13 ++++++------- src/Api/Jobs/AddUserJob.php | 7 ++----- src/Api/Jobs/EditPostContentJob.php | 6 ++++-- src/Api/Jobs/EditPostJob.php | 10 ++++++++-- src/Api/Jobs/EditPostRelationsJob.php | 5 +++-- src/Api/Jobs/EditPostSafetyJob.php | 5 +++-- src/Api/Jobs/EditPostSourceJob.php | 5 +++-- src/Api/Jobs/EditPostTagsJob.php | 9 ++++++--- src/Api/Jobs/EditPostThumbJob.php | 5 +++-- src/Api/Jobs/EditPostUrlJob.php | 5 +++-- src/Api/Jobs/EditUserAccessRankJob.php | 5 +++-- src/Api/Jobs/EditUserEmailJob.php | 5 +++-- src/Api/Jobs/EditUserJob.php | 12 +++++++++--- src/Api/Jobs/EditUserNameJob.php | 5 +++-- src/Api/Jobs/EditUserPasswordJob.php | 5 +++-- 20 files changed, 110 insertions(+), 46 deletions(-) create mode 100644 src/Api/Jobs/AbstractPostEditJob.php create mode 100644 src/Api/Jobs/AbstractUserEditJob.php diff --git a/src/Api/AbstractJob.php b/src/Api/AbstractJob.php index a71997a9..a4a683f8 100644 --- a/src/Api/AbstractJob.php +++ b/src/Api/AbstractJob.php @@ -2,16 +2,22 @@ abstract class AbstractJob { const COMMENT_ID = 'comment-id'; + const LOG_ID = 'log-id'; + + const POST_ENTITY = 'post'; const POST_ID = 'post-id'; const POST_NAME = 'post-name'; + const TAG_NAME = 'tag-name'; const TAG_NAMES = 'tags'; + + const USER_ENTITY = 'user'; const USER_ID = 'user-id'; const USER_NAME = 'user-name'; - const TEXT = 'text'; + const PAGE_NUMBER = 'page-number'; + const TEXT = 'text'; const QUERY = 'query'; - const LOG_ID = 'log-id'; const STATE = 'state'; protected $arguments; diff --git a/src/Api/AbstractPostJob.php b/src/Api/AbstractPostJob.php index d886a103..470a2187 100644 --- a/src/Api/AbstractPostJob.php +++ b/src/Api/AbstractPostJob.php @@ -5,7 +5,14 @@ abstract class AbstractPostJob extends AbstractJob public function prepare() { - $postId = $this->getArgument(self::POST_ID); - $this->post = PostModel::findByIdOrName($postId); + if ($this->hasArgument(self::POST_ENTITY)) + { + $this->post = $this->getArgument(self::POST_ENTITY); + } + else + { + $postId = $this->getArgument(self::POST_ID); + $this->post = PostModel::findByIdOrName($postId); + } } } diff --git a/src/Api/AbstractUserJob.php b/src/Api/AbstractUserJob.php index 00dab341..1b2acf11 100644 --- a/src/Api/AbstractUserJob.php +++ b/src/Api/AbstractUserJob.php @@ -5,7 +5,14 @@ abstract class AbstractUserJob extends AbstractJob public function prepare() { - $userName = $this->getArgument(self::USER_NAME); - $this->user = UserModel::findByNameOrEmail($userName); + if ($this->hasArgument(self::USER_ENTITY)) + { + $this->user = $this->getArgument(self::USER_ENTITY); + } + else + { + $userName = $this->getArgument(self::USER_NAME); + $this->user = UserModel::findByNameOrEmail($userName); + } } } diff --git a/src/Api/Jobs/AbstractPostEditJob.php b/src/Api/Jobs/AbstractPostEditJob.php new file mode 100644 index 00000000..5d1ce361 --- /dev/null +++ b/src/Api/Jobs/AbstractPostEditJob.php @@ -0,0 +1,11 @@ +skipSaving = true; + return $this; + } +} diff --git a/src/Api/Jobs/AbstractUserEditJob.php b/src/Api/Jobs/AbstractUserEditJob.php new file mode 100644 index 00000000..c72f4639 --- /dev/null +++ b/src/Api/Jobs/AbstractUserEditJob.php @@ -0,0 +1,11 @@ +skipSaving = true; + return $this; + } +} diff --git a/src/Api/Jobs/AddPostJob.php b/src/Api/Jobs/AddPostJob.php index f0a86fe7..05a0cbaa 100644 --- a/src/Api/Jobs/AddPostJob.php +++ b/src/Api/Jobs/AddPostJob.php @@ -17,13 +17,10 @@ class AddPostJob extends AbstractJob PostModel::forgeId($post); //do the edits - //warning: it uses the same privileges as post editing internally + //warning: it uses internally the same privileges as post editing $arguments = $this->getArguments(); - $arguments[EditPostJob::POST_ID] = $post->id; - Api::run(new EditPostJob(), $arguments); - - //load the post after edits - $post = PostModel::findById($post->id); + $arguments[EditPostJob::POST_ENTITY] = $post; + Api::run((new EditPostJob)->skipSaving(), $arguments); // basically means that user didn't specify file nor url //todo: @@ -33,6 +30,9 @@ class AddPostJob extends AbstractJob if (empty($post->type)) throw new SimpleException('No post type detected; upload faled'); + //save to db + PostModel::save($post); + //clean edit log LogHelper::setBuffer([]); @@ -48,7 +48,6 @@ class AddPostJob extends AbstractJob //finish LogHelper::flush(); - PostModel::save($post); return $post; } diff --git a/src/Api/Jobs/AddUserJob.php b/src/Api/Jobs/AddUserJob.php index 46450322..688e56da 100644 --- a/src/Api/Jobs/AddUserJob.php +++ b/src/Api/Jobs/AddUserJob.php @@ -12,7 +12,7 @@ class AddUserJob extends AbstractJob UserModel::forgeId($user); $arguments = $this->getArguments(); - $arguments[EditUserJob::USER_NAME] = $user->name; + $arguments[EditUserJob::USER_ENTITY] = $user; $arguments[EditUserAccessRankJob::NEW_ACCESS_RANK] = $firstUser ? AccessRank::Admin @@ -20,16 +20,13 @@ class AddUserJob extends AbstractJob LogHelper::bufferChanges(); Api::disablePrivilegeChecking(); - Api::run(new EditUserJob(), $arguments); + Api::run((new EditUserJob)->skipSaving(), $arguments); Api::enablePrivilegeChecking(); LogHelper::setBuffer([]); if ($firstUser) $user->confirmEmail(); - //load the user after edits - $user = UserModel::findById($user->id); - //save the user to db if everything went okay UserModel::save($user); diff --git a/src/Api/Jobs/EditPostContentJob.php b/src/Api/Jobs/EditPostContentJob.php index a4d1ff57..46e2c056 100644 --- a/src/Api/Jobs/EditPostContentJob.php +++ b/src/Api/Jobs/EditPostContentJob.php @@ -1,5 +1,5 @@ setContentFromPath($file->filePath, $file->fileName); - PostModel::save($post); + if (!$this->skipSaving) + PostModel::save($post); + LogHelper::log('{user} changed contents of {post}', [ 'user' => TextHelper::reprUser(Auth::getCurrentUser()), 'post' => TextHelper::reprPost($post)]); diff --git a/src/Api/Jobs/EditPostJob.php b/src/Api/Jobs/EditPostJob.php index b08ca696..dc8230de 100644 --- a/src/Api/Jobs/EditPostJob.php +++ b/src/Api/Jobs/EditPostJob.php @@ -1,5 +1,5 @@ skipSaving) + $subJob->skipSaving(); + $args = $this->getArguments(); - $args[self::POST_ID] = $post->id; + $args[self::POST_ENTITY] = $post; try { Api::run($subJob, $args); @@ -31,6 +34,9 @@ class EditPostJob extends AbstractPostJob } } + if (!$this->skipSaving) + PostModel::save($post); + LogHelper::flush(); return $post; } diff --git a/src/Api/Jobs/EditPostRelationsJob.php b/src/Api/Jobs/EditPostRelationsJob.php index 06a999fe..a8134aa9 100644 --- a/src/Api/Jobs/EditPostRelationsJob.php +++ b/src/Api/Jobs/EditPostRelationsJob.php @@ -1,5 +1,5 @@ setRelationsFromText($relations); $newRelatedIds = array_map(function($post) { return $post->id; }, $post->getRelations()); - PostModel::save($post); + if (!$this->skipSaving) + PostModel::save($post); foreach (array_diff($oldRelatedIds, $newRelatedIds) as $post2id) { diff --git a/src/Api/Jobs/EditPostSafetyJob.php b/src/Api/Jobs/EditPostSafetyJob.php index 5fe25803..6ed468ef 100644 --- a/src/Api/Jobs/EditPostSafetyJob.php +++ b/src/Api/Jobs/EditPostSafetyJob.php @@ -1,5 +1,5 @@ safety; $post->setSafety($newSafety); - PostModel::save($post); + if (!$this->skipSaving) + PostModel::save($post); if ($oldSafety != $newSafety) { diff --git a/src/Api/Jobs/EditPostSourceJob.php b/src/Api/Jobs/EditPostSourceJob.php index 7dc6233c..14ca0037 100644 --- a/src/Api/Jobs/EditPostSourceJob.php +++ b/src/Api/Jobs/EditPostSourceJob.php @@ -1,5 +1,5 @@ source; $post->setSource($newSource); - PostModel::save($post); + if (!$this->skipSaving) + PostModel::save($post); if ($oldSource != $newSource) { diff --git a/src/Api/Jobs/EditPostTagsJob.php b/src/Api/Jobs/EditPostTagsJob.php index b82482f2..f9994329 100644 --- a/src/Api/Jobs/EditPostTagsJob.php +++ b/src/Api/Jobs/EditPostTagsJob.php @@ -1,5 +1,5 @@ setTagsFromText($tags); $newTags = array_map(function($tag) { return $tag->name; }, $post->getTags()); - PostModel::save($post); - TagModel::removeUnused(); + if (!$this->skipSaving) + { + PostModel::save($post); + TagModel::removeUnused(); + } foreach (array_diff($oldTags, $newTags) as $tag) { diff --git a/src/Api/Jobs/EditPostThumbJob.php b/src/Api/Jobs/EditPostThumbJob.php index 9f83f4f3..af2cf9a1 100644 --- a/src/Api/Jobs/EditPostThumbJob.php +++ b/src/Api/Jobs/EditPostThumbJob.php @@ -1,5 +1,5 @@ setCustomThumbnailFromPath($file->filePath); - PostModel::save($post); + if (!$this->skipSaving) + PostModel::save($post); LogHelper::log('{user} changed thumb of {post}', [ 'user' => TextHelper::reprUser(Auth::getCurrentUser()), diff --git a/src/Api/Jobs/EditPostUrlJob.php b/src/Api/Jobs/EditPostUrlJob.php index a357cf4f..0817152f 100644 --- a/src/Api/Jobs/EditPostUrlJob.php +++ b/src/Api/Jobs/EditPostUrlJob.php @@ -1,5 +1,5 @@ setContentFromUrl($url); - PostModel::save($post); + if (!$this->skipSaving) + PostModel::save($post); LogHelper::log('{user} changed contents of {post}', [ 'user' => TextHelper::reprUser(Auth::getCurrentUser()), diff --git a/src/Api/Jobs/EditUserAccessRankJob.php b/src/Api/Jobs/EditUserAccessRankJob.php index 5b3de9b1..b62f070c 100644 --- a/src/Api/Jobs/EditUserAccessRankJob.php +++ b/src/Api/Jobs/EditUserAccessRankJob.php @@ -1,5 +1,5 @@ accessRank = $newAccessRank; - UserModel::save($user); + if (!$this->skipSaving) + UserModel::save($user); LogHelper::log('{user} changed {subject}\'s access rank to {rank}', [ 'user' => TextHelper::reprUser(Auth::getCurrentUser()), diff --git a/src/Api/Jobs/EditUserEmailJob.php b/src/Api/Jobs/EditUserEmailJob.php index 5c5f56be..ad49331d 100644 --- a/src/Api/Jobs/EditUserEmailJob.php +++ b/src/Api/Jobs/EditUserEmailJob.php @@ -1,5 +1,5 @@ confirmEmail(); } - UserModel::save($user); + if (!$this->skipSaving) + UserModel::save($user); LogHelper::log('{user} changed {subject}\'s e-mail to {mail}', [ 'user' => TextHelper::reprUser(Auth::getCurrentUser()), diff --git a/src/Api/Jobs/EditUserJob.php b/src/Api/Jobs/EditUserJob.php index 418dece3..b778ba9a 100644 --- a/src/Api/Jobs/EditUserJob.php +++ b/src/Api/Jobs/EditUserJob.php @@ -1,5 +1,5 @@ subJobs as $subJob) { + if ($this->skipSaving) + $subJob->skipSaving(); + $args = $this->getArguments(); - $args[self::USER_NAME] = $user->name; + $args[self::USER_ENTITY] = $user; try { Api::run($subJob, $args); @@ -51,6 +54,9 @@ class EditUserJob extends AbstractUserJob } } + if (!$this->skipSaving) + UserModel::save($user); + LogHelper::flush(); return $user; } diff --git a/src/Api/Jobs/EditUserNameJob.php b/src/Api/Jobs/EditUserNameJob.php index 56342c83..5c23ef7a 100644 --- a/src/Api/Jobs/EditUserNameJob.php +++ b/src/Api/Jobs/EditUserNameJob.php @@ -1,5 +1,5 @@ name = $newName; UserModel::validateUserName($user); - UserModel::save($user); + if (!$this->skipSaving) + UserModel::save($user); LogHelper::log('{user} renamed {old} to {new}', [ 'user' => TextHelper::reprUser(Auth::getCurrentUser()), diff --git a/src/Api/Jobs/EditUserPasswordJob.php b/src/Api/Jobs/EditUserPasswordJob.php index 9e5964be..3958a14a 100644 --- a/src/Api/Jobs/EditUserPasswordJob.php +++ b/src/Api/Jobs/EditUserPasswordJob.php @@ -1,5 +1,5 @@ passHash = $newPasswordHash; - UserModel::save($user); + if (!$this->skipSaving) + UserModel::save($user); LogHelper::log('{user} changed {subject}\'s password', [ 'user' => TextHelper::reprUser(Auth::getCurrentUser()), From d3beb8bc53b6ee285bd00e751afff3e8edefd90b Mon Sep 17 00:00:00 2001 From: Marcin Kurczewski Date: Sun, 4 May 2014 19:06:40 +0200 Subject: [PATCH 052/188] Implemented new enums --- src/Access.php | 28 ++++++------ src/Api/Jobs/AddPostJob.php | 4 +- src/Api/Jobs/EditPostSafetyJob.php | 6 +-- src/Api/Jobs/EditUserAccessRankJob.php | 8 ++-- src/Api/Jobs/GetPostContentJob.php | 2 +- src/Api/Jobs/GetPostJob.php | 2 +- src/Api/Jobs/GetPostThumbJob.php | 2 +- src/Auth.php | 4 +- src/Controllers/UserController.php | 8 ++-- src/Enum.php | 12 +++--- src/IValidatable.php | 5 +++ src/Models/AbstractCrudModel.php | 11 ++++- src/Models/Entities/PostEntity.php | 43 +++++++++++++------ src/Models/Entities/UserEntity.php | 32 +++++++++----- src/Models/Enums/AccessRank.php | 33 +++++++++++++- src/Models/Enums/PostSafety.php | 37 ++++++++++++++-- src/Models/Enums/PostType.php | 25 ++++++++++- src/Models/Enums/Privilege.php | 10 ++++- src/Models/PostModel.php | 42 +++++++++--------- .../SearchParsers/CommentSearchParser.php | 7 ++- src/Models/SearchParsers/PostSearchParser.php | 9 +++- src/Models/SearchParsers/TagSearchParser.php | 7 ++- src/Models/UserModel.php | 27 ++++++++---- src/Views/post-edit.phtml | 6 +-- src/Views/post-file-render.phtml | 8 ++-- src/Views/post-small.phtml | 2 +- src/Views/post-upload.phtml | 4 +- src/Views/post-view.phtml | 6 +-- src/Views/top-navigation.phtml | 10 ++--- src/Views/user-edit.phtml | 13 +++--- src/Views/user-settings.phtml | 6 +-- src/Views/user-view.phtml | 2 +- 32 files changed, 290 insertions(+), 131 deletions(-) create mode 100644 src/IValidatable.php diff --git a/src/Access.php b/src/Access.php index b16bd0e6..9df388d4 100644 --- a/src/Access.php +++ b/src/Access.php @@ -40,24 +40,22 @@ class Access $user = Auth::getCurrentUser(); $minAccessRank = AccessRank::Nobody; - $key = TextCaseConverter::convert(Privilege::toString($privilege->primary), + $key = TextCaseConverter::convert($privilege->toString(), TextCaseConverter::CAMEL_CASE, TextCaseConverter::SPINAL_CASE); - if (isset(self::$privileges[$key])) - { - $minAccessRank = self::$privileges[$key]; - } - if ($privilege->secondary != null) - { - $key2 = $key . '.' . strtolower($privilege->secondary); - if (isset(self::$privileges[$key2])) - { - $minAccessRank = self::$privileges[$key2]; - } - } + $privilege->secondary = null; + $key2 = TextCaseConverter::convert($privilege->toString(), + TextCaseConverter::CAMEL_CASE, + TextCaseConverter::SPINAL_CASE); - return intval($user->accessRank) >= $minAccessRank; + + if (isset(self::$privileges[$key])) + $minAccessRank = self::$privileges[$key]; + elseif (isset(self::$privileges[$key2])) + $minAccessRank = self::$privileges[$key2]; + + return $user->getAccessRank()->toInteger() >= $minAccessRank; } public static function assertAuthentication() @@ -98,7 +96,7 @@ class Access return array_filter(PostSafety::getAll(), function($safety) { - return Access::check(new Privilege(Privilege::ListPosts, PostSafety::toString($safety))) + return Access::check(new Privilege(Privilege::ListPosts, $safety->toString())) and Auth::getCurrentUser()->hasEnabledSafety($safety); }); } diff --git a/src/Api/Jobs/AddPostJob.php b/src/Api/Jobs/AddPostJob.php index 05a0cbaa..7a77b3e1 100644 --- a/src/Api/Jobs/AddPostJob.php +++ b/src/Api/Jobs/AddPostJob.php @@ -27,7 +27,7 @@ class AddPostJob extends AbstractJob //- move this to PostEntity::isValid() //- create IValidatable interface //- enforce entity validity upon calling save() in models - if (empty($post->type)) + if (empty($post->getType())) throw new SimpleException('No post type detected; upload faled'); //save to db @@ -43,7 +43,7 @@ class AddPostJob extends AbstractJob : TextHelper::reprUser(Auth::getCurrentUser()), 'post' => TextHelper::reprPost($post), 'tags' => TextHelper::reprTags($post->getTags()), - 'safety' => PostSafety::toString($post->safety), + 'safety' => $post->getSafety()->toString(), 'source' => $post->source]); //finish diff --git a/src/Api/Jobs/EditPostSafetyJob.php b/src/Api/Jobs/EditPostSafetyJob.php index 6ed468ef..a41c9b6a 100644 --- a/src/Api/Jobs/EditPostSafetyJob.php +++ b/src/Api/Jobs/EditPostSafetyJob.php @@ -6,9 +6,9 @@ class EditPostSafetyJob extends AbstractPostEditJob public function execute() { $post = $this->post; - $newSafety = $this->getArgument(self::SAFETY); + $newSafety = new PostSafety($this->getArgument(self::SAFETY)); - $oldSafety = $post->safety; + $oldSafety = $post->getSafety(); $post->setSafety($newSafety); if (!$this->skipSaving) @@ -19,7 +19,7 @@ class EditPostSafetyJob extends AbstractPostEditJob LogHelper::log('{user} changed safety of {post} to {safety}', [ 'user' => TextHelper::reprUser(Auth::getCurrentUser()), 'post' => TextHelper::reprPost($post), - 'safety' => PostSafety::toString($post->safety)]); + 'safety' => $post->getSafety()->toString()]); } return $post; diff --git a/src/Api/Jobs/EditUserAccessRankJob.php b/src/Api/Jobs/EditUserAccessRankJob.php index b62f070c..357b6805 100644 --- a/src/Api/Jobs/EditUserAccessRankJob.php +++ b/src/Api/Jobs/EditUserAccessRankJob.php @@ -6,13 +6,13 @@ class EditUserAccessRankJob extends AbstractUserEditJob public function execute() { $user = $this->user; - $newAccessRank = UserModel::validateAccessRank($this->getArgument(self::NEW_ACCESS_RANK)); + $newAccessRank = new AccessRank($this->getArgument(self::NEW_ACCESS_RANK)); - $oldAccessRank = $user->accessRank; + $oldAccessRank = $user->getAccessRank(); if ($oldAccessRank == $newAccessRank) return $user; - $user->accessRank = $newAccessRank; + $user->setAccessRank($newAccessRank); if (!$this->skipSaving) UserModel::save($user); @@ -20,7 +20,7 @@ class EditUserAccessRankJob extends AbstractUserEditJob LogHelper::log('{user} changed {subject}\'s access rank to {rank}', [ 'user' => TextHelper::reprUser(Auth::getCurrentUser()), 'subject' => TextHelper::reprUser($user), - 'rank' => AccessRank::toString($newAccessRank)]); + 'rank' => $newAccessRank->toString()]); return $user; } diff --git a/src/Api/Jobs/GetPostContentJob.php b/src/Api/Jobs/GetPostContentJob.php index 96eff85f..ae3d8c9a 100644 --- a/src/Api/Jobs/GetPostContentJob.php +++ b/src/Api/Jobs/GetPostContentJob.php @@ -38,7 +38,7 @@ class GetPostContentJob extends AbstractJob if ($post->hidden) $privileges []= new Privilege(Privilege::ViewPost, 'hidden'); - $privileges []= new Privilege(Privilege::ViewPost, PostSafety::toString($post->safety)); + $privileges []= new Privilege(Privilege::ViewPost, $post->getSafety()->toString()); return $privileges; } diff --git a/src/Api/Jobs/GetPostJob.php b/src/Api/Jobs/GetPostJob.php index 898bda24..f42194ac 100644 --- a/src/Api/Jobs/GetPostJob.php +++ b/src/Api/Jobs/GetPostJob.php @@ -18,7 +18,7 @@ class GetPostJob extends AbstractPostJob if ($post->hidden) $privileges []= new Privilege(Privilege::ViewPost, 'hidden'); - $privileges []= new Privilege(Privilege::ViewPost, PostSafety::toString($post->safety)); + $privileges []= new Privilege(Privilege::ViewPost, $post->getSafety()->toString()); return $privileges; } diff --git a/src/Api/Jobs/GetPostThumbJob.php b/src/Api/Jobs/GetPostThumbJob.php index 514372e1..c87739c3 100644 --- a/src/Api/Jobs/GetPostThumbJob.php +++ b/src/Api/Jobs/GetPostThumbJob.php @@ -20,7 +20,7 @@ class GetPostThumbJob extends AbstractJob if ($post->hidden) Access::assert(new Privilege(Privilege::ListPosts, 'hidden')); - Access::assert(new Privilege(Privilege::ListPosts, PostSafety::toString($post->safety))); + Access::assert(new Privilege(Privilege::ListPosts, $post->getSafety()->toString())); $post->generateThumb($width, $height); diff --git a/src/Auth.php b/src/Auth.php index e3e91c09..f4ba0840 100644 --- a/src/Auth.php +++ b/src/Auth.php @@ -70,7 +70,7 @@ class Auth } else { - $_SESSION['logged-in'] = $user->accessRank != AccessRank::Anonymous; + $_SESSION['logged-in'] = $user->getAccessRank()->toInteger() != AccessRank::Anonymous; $_SESSION['user'] = serialize($user); } } @@ -87,7 +87,7 @@ class Auth $dummy = UserModel::spawn(); $dummy->id = null; $dummy->name = UserModel::getAnonymousName(); - $dummy->accessRank = AccessRank::Anonymous; + $dummy->setAccessRank(new AccessRank(AccessRank::Anonymous)); return $dummy; } } diff --git a/src/Controllers/UserController.php b/src/Controllers/UserController.php index d25b3f90..d6a9a3da 100644 --- a/src/Controllers/UserController.php +++ b/src/Controllers/UserController.php @@ -81,7 +81,7 @@ class UserController $user->enablePostTagTitles(InputHelper::get('post-tag-titles')); $user->enableHidingDislikedPosts(InputHelper::get('hide-disliked-posts')); - if ($user->accessRank != AccessRank::Anonymous) + if ($user->getAccessRank()->toInteger() != AccessRank::Anonymous) UserModel::save($user); if ($user->id == Auth::getCurrentUser()->id) Auth::setCurrentUser($user); @@ -168,12 +168,12 @@ class UserController Privilege::ChangeUserSettings, Access::getIdentity($user))); - if (!in_array($safety, PostSafety::getAll())) - throw new SimpleExcetpion('Invalid safety'); + $safety = new PostSafety($safety); + $safety->validate(); $user->enableSafety($safety, !$user->hasEnabledSafety($safety)); - if ($user->accessRank != AccessRank::Anonymous) + if ($user->getAccessRank()->toInteger() != AccessRank::Anonymous) UserModel::save($user); Auth::setCurrentUser($user); } diff --git a/src/Enum.php b/src/Enum.php index 6987502c..3188f4d7 100644 --- a/src/Enum.php +++ b/src/Enum.php @@ -1,21 +1,23 @@ getConstants(); return array_search($constant, $constants); } - public static function toDisplayString($constant) + public function toDisplayString() { - return TextCaseConverter::convert(static::toString($constant), + return TextCaseConverter::convert($this->toString(), TextCaseConverter::SNAKE_CASE, TextCaseConverter::BLANK_CASE); } - public static function getAll() + public static function getAllConstants() { $cls = new ReflectionClass(get_called_class()); $constants = $cls->getConstants(); diff --git a/src/IValidatable.php b/src/IValidatable.php new file mode 100644 index 00000000..13666bea --- /dev/null +++ b/src/IValidatable.php @@ -0,0 +1,5 @@ +$key = $val; + if (property_exists($entity, $key)) + { + $reflectionProperty = new ReflectionProperty(get_class($entity), $key); + $reflectionProperty->setAccessible(true); + $reflectionProperty->setValue($entity, $val); + } + else + { + $entity->$key = $val; + } } return $entity; } diff --git a/src/Models/Entities/PostEntity.php b/src/Models/Entities/PostEntity.php index 11094c8b..d9c50b99 100644 --- a/src/Models/Entities/PostEntity.php +++ b/src/Models/Entities/PostEntity.php @@ -4,22 +4,22 @@ use \Chibi\Database as Database; class PostEntity extends AbstractEntity { - public $type; + protected $type; public $name; public $origName; public $fileHash; public $fileSize; public $mimeType; - public $safety; + protected $safety; public $hidden; public $uploadDate; public $imageWidth; public $imageHeight; public $uploaderId; public $source; - public $commentCount; - public $favCount; - public $score; + public $commentCount = 0; + public $favCount = 0; + public $score = 0; public function getUploader() { @@ -173,9 +173,26 @@ class PostEntity extends AbstractEntity $this->hidden = boolval($hidden); } - public function setSafety($safety) + public function getType() { - $this->safety = PostModel::validateSafety($safety); + return $this->type; + } + + public function setType(PostType $type) + { + $type->validate(); + $this->type = $type; + } + + public function getSafety() + { + return $this->safety; + } + + public function setSafety(PostSafety $safety) + { + $safety->validate(); + $this->safety = $safety; } public function setSource($source) @@ -233,7 +250,7 @@ class PostEntity extends AbstractEntity $srcPath = $this->getFullPath(); $dstPath = $this->getThumbDefaultPath($width, $height); - if ($this->type == PostType::Youtube) + if ($this->getType()->toInteger() == PostType::Youtube) { return ThumbnailHelper::generateFromUrl( 'http://img.youtube.com/vi/' . $this->fileHash . '/mqdefault.jpg', @@ -263,13 +280,13 @@ class PostEntity extends AbstractEntity case 'image/png': case 'image/jpeg': list ($imageWidth, $imageHeight) = getimagesize($srcPath); - $this->type = PostType::Image; + $this->setType(new PostType(PostType::Image)); $this->imageWidth = $imageWidth; $this->imageHeight = $imageHeight; break; case 'application/x-shockwave-flash': list ($imageWidth, $imageHeight) = getimagesize($srcPath); - $this->type = PostType::Flash; + $this->setType(new PostType(PostType::Flash)); $this->imageWidth = $imageWidth; $this->imageHeight = $imageHeight; break; @@ -280,7 +297,7 @@ class PostEntity extends AbstractEntity case 'video/x-flv': case 'video/3gpp': list ($imageWidth, $imageHeight) = getimagesize($srcPath); - $this->type = PostType::Video; + $this->setType(new PostType(PostType::Video)); $this->imageWidth = $imageWidth; $this->imageHeight = $imageHeight; break; @@ -315,7 +332,7 @@ class PostEntity extends AbstractEntity if (preg_match('/youtube.com\/watch.*?=([a-zA-Z0-9_-]+)/', $srcUrl, $matches)) { $youtubeId = $matches[1]; - $this->type = PostType::Youtube; + $this->setType(new PostType(PostType::Youtube)); $this->mimeType = null; $this->fileSize = null; $this->fileHash = $youtubeId; @@ -360,7 +377,7 @@ class PostEntity extends AbstractEntity $x []= TextHelper::reprTag($tag->name); foreach ($this->getRelations() as $relatedPost) $x []= TextHelper::reprPost($relatedPost); - $x []= $this->safety; + $x []= $this->getSafety()->toInteger(); $x []= $this->source; $x []= $this->fileHash; natcasesort($x); diff --git a/src/Models/Entities/UserEntity.php b/src/Models/Entities/UserEntity.php index 083a8a11..871a08a2 100644 --- a/src/Models/Entities/UserEntity.php +++ b/src/Models/Entities/UserEntity.php @@ -12,10 +12,21 @@ class UserEntity extends AbstractEntity public $emailConfirmed; public $joinDate; public $lastLoginDate; - public $accessRank; + protected $accessRank; public $settings; public $banned; + public function getAccessRank() + { + return $this->accessRank; + } + + public function setAccessRank(AccessRank $accessRank) + { + $accessRank->validate(); + $this->accessRank = $accessRank; + } + public function getAvatarUrl($size = 32) { $subject = !empty($this->emailConfirmed) @@ -44,32 +55,31 @@ class UserEntity extends AbstractEntity $this->settings = $settings; } - public function hasEnabledSafety($safety) + public function hasEnabledSafety(PostSafety $safety) { $all = $this->getSetting(UserModel::SETTING_SAFETY); if (!$all) - return $safety == PostSafety::Safe; - return $all & PostSafety::toFlag($safety); + return $safety->toInteger() == PostSafety::Safe; + return $all & $safety->toFlag(); } - public function enableSafety($safety, $enabled) + public function enableSafety(PostSafety $safety, $enabled) { $all = $this->getSetting(UserModel::SETTING_SAFETY); - if (!$all) - $all = PostSafety::toFlag(PostSafety::Safe); $new = $all; if (!$enabled) { - $new &= ~PostSafety::toFlag($safety); - if (!$new) - $new = PostSafety::toFlag(PostSafety::Safe); + $new &= ~$safety->toFlag(); } else { - $new |= PostSafety::toFlag($safety); + $new |= $safety->toFlag(); } + if (!$new) + $new = (new PostSafety(PostSafety::Safe))->toFlag(); + $this->setSetting(UserModel::SETTING_SAFETY, $new); } diff --git a/src/Models/Enums/AccessRank.php b/src/Models/Enums/AccessRank.php index 8b013917..2216a1cf 100644 --- a/src/Models/Enums/AccessRank.php +++ b/src/Models/Enums/AccessRank.php @@ -1,5 +1,5 @@ accessRank = $accessRank; + } + + public function toInteger() + { + return $this->accessRank; + } + + public function toString() + { + return self::_toString($this->accessRank); + } + + public static function getAll() + { + return array_map(function($constantName) + { + return new self($constantName); + }, self::getAllConstants()); + } + + public function validate() + { + if (!in_array($this->accessRank, self::getAllConstants())) + throw new SimpleException('Invalid access rank "%s"', $this->accessRank); + } } diff --git a/src/Models/Enums/PostSafety.php b/src/Models/Enums/PostSafety.php index 845977b5..99a4342e 100644 --- a/src/Models/Enums/PostSafety.php +++ b/src/Models/Enums/PostSafety.php @@ -1,12 +1,43 @@ safety = $safety; + } + + public function toInteger() + { + return $this->safety; + } + + public function toFlag() + { + return pow(2, $this->safety); + } + + public function toString() + { + return self::_toString($this->safety); + } + + public static function getAll() + { + return array_map(function($constantName) + { + return new self($constantName); + }, self::getAllConstants()); + } + + public function validate() + { + if (!in_array($this->safety, self::getAllConstants())) + throw new SimpleException('Invalid safety type "%s"', $this->safety); } } diff --git a/src/Models/Enums/PostType.php b/src/Models/Enums/PostType.php index 3eb305a1..351cbf4c 100644 --- a/src/Models/Enums/PostType.php +++ b/src/Models/Enums/PostType.php @@ -1,8 +1,31 @@ type = $type; + } + + public function toInteger() + { + return $this->type; + } + + public function toString() + { + return self::_toString($this->type); + } + + public function validate() + { + if (!in_array($this->type, self::getAllConstants())) + throw new SimpleException('Invalid post type "%s"', $this->type); + } } diff --git a/src/Models/Enums/Privilege.php b/src/Models/Enums/Privilege.php index 2c58cff1..4b269d34 100644 --- a/src/Models/Enums/Privilege.php +++ b/src/Models/Enums/Privilege.php @@ -51,6 +51,14 @@ class Privilege extends Enum public function __construct($primary, $secondary = null) { $this->primary = $primary; - $this->secondary = $secondary; + $this->secondary = strtolower($secondary); + } + + public function toString() + { + $string = self::_toString($this->primary); + if ($this->secondary) + $string .= '.' . $this->secondary; + return $string; } } diff --git a/src/Models/PostModel.php b/src/Models/PostModel.php index 80b236df..a2ae0760 100644 --- a/src/Models/PostModel.php +++ b/src/Models/PostModel.php @@ -6,23 +6,33 @@ class PostModel extends AbstractCrudModel { protected static $config; - public static function getTableName() - { - return 'post'; - } - public static function init() { self::$config = getConfig(); } + public static function getTableName() + { + return 'post'; + } + + public static function convertRow($row) + { + $entity = parent::convertRow($row); + + if (isset($row['type'])) + $entity->setType(new PostType($row['type'])); + + if (isset($row['safety'])) + $entity->setSafety(new PostSafety($row['safety'])); + + return $entity; + } + public static function spawn() { $post = new PostEntity; - $post->score = 0; - $post->favCount = 0; - $post->commentCount = 0; - $post->safety = PostSafety::Safe; + $post->setSafety(new PostSafety(PostSafety::Safe)); $post->hidden = false; $post->uploadDate = time(); do @@ -40,13 +50,13 @@ class PostModel extends AbstractCrudModel self::forgeId($post); $bindings = [ - 'type' => $post->type, + 'type' => $post->getType()->toInteger(), 'name' => $post->name, 'orig_name' => $post->origName, 'file_hash' => $post->fileHash, 'file_size' => $post->fileSize, 'mime_type' => $post->mimeType, - 'safety' => $post->safety, + 'safety' => $post->getSafety()->toInteger(), 'hidden' => $post->hidden, 'upload_date' => $post->uploadDate, 'image_width' => $post->imageWidth, @@ -266,16 +276,6 @@ class PostModel extends AbstractCrudModel - public static function validateSafety($safety) - { - $safety = intval($safety); - - if (!in_array($safety, PostSafety::getAll())) - throw new SimpleException('Invalid safety type "%s"', $safety); - - return $safety; - } - public static function validateSource($source) { $source = trim($source); diff --git a/src/Models/SearchParsers/CommentSearchParser.php b/src/Models/SearchParsers/CommentSearchParser.php index 492005ba..5147373a 100644 --- a/src/Models/SearchParsers/CommentSearchParser.php +++ b/src/Models/SearchParsers/CommentSearchParser.php @@ -8,7 +8,12 @@ class CommentSearchParser extends AbstractSearchParser $this->statement->addInnerJoin('post', new Sql\EqualsFunctor('post_id', 'post.id')); $crit = new Sql\ConjunctionFunctor(); - $allowedSafety = Access::getAllowedSafety(); + $allowedSafety = array_map( + function($safety) + { + return $safety->toInteger(); + }, + Access::getAllowedSafety()); $crit->add(Sql\InFunctor::fromArray('post.safety', Sql\Binding::fromArray($allowedSafety))); if (!Access::check(new Privilege(Privilege::ListPosts, 'hidden'))) diff --git a/src/Models/SearchParsers/PostSearchParser.php b/src/Models/SearchParsers/PostSearchParser.php index 5fec6ca4..7958f308 100644 --- a/src/Models/SearchParsers/PostSearchParser.php +++ b/src/Models/SearchParsers/PostSearchParser.php @@ -14,8 +14,13 @@ class PostSearchParser extends AbstractSearchParser $this->tags = []; $crit = new Sql\ConjunctionFunctor(); - $allowedSafety = Access::getAllowedSafety(); - $crit->add(Sql\InFunctor::fromArray('safety', Sql\Binding::fromArray($allowedSafety))); + $allowedSafety = array_map( + function($safety) + { + return $safety->toInteger(); + }, + Access::getAllowedSafety()); + $crit->add(Sql\InFunctor::fromArray('post.safety', Sql\Binding::fromArray($allowedSafety))); $this->statement->setCriterion($crit); if (count($tokens) > $config->browsing->maxSearchTokens) diff --git a/src/Models/SearchParsers/TagSearchParser.php b/src/Models/SearchParsers/TagSearchParser.php index 6b348655..169fa9f8 100644 --- a/src/Models/SearchParsers/TagSearchParser.php +++ b/src/Models/SearchParsers/TagSearchParser.php @@ -5,7 +5,12 @@ class TagSearchParser extends AbstractSearchParser { protected function processSetup(&$tokens) { - $allowedSafety = Access::getAllowedSafety(); + $allowedSafety = array_map( + function($safety) + { + return $safety->toInteger(); + }, + 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')) diff --git a/src/Models/UserModel.php b/src/Models/UserModel.php index c12cd158..3c5dd3e9 100644 --- a/src/Models/UserModel.php +++ b/src/Models/UserModel.php @@ -14,17 +14,29 @@ class UserModel extends AbstractCrudModel return 'user'; } + public static function convertRow($row) + { + $entity = parent::convertRow($row); + + if (isset($row['access_rank'])) + $entity->setAccessRank(new AccessRank($row['access_rank'])); + + return $entity; + } + public static function spawn() { $user = new UserEntity(); + $user->setAccessRank(new AccessRank(AccessRank::Anonymous)); $user->passSalt = md5(mt_rand() . uniqid()); return $user; } public static function save($user) { - if ($user->accessRank == AccessRank::Anonymous) + if ($user->getAccessRank()->toInteger() == AccessRank::Anonymous) throw new Exception('Trying to save anonymous user into database'); + Database::transaction(function() use ($user) { self::forgeId($user); @@ -38,7 +50,7 @@ class UserModel extends AbstractCrudModel 'email_confirmed' => $user->emailConfirmed, 'join_date' => $user->joinDate, 'last_login_date' => $user->lastLoginDate, - 'access_rank' => $user->accessRank, + 'access_rank' => $user->getAccessRank()->toInteger(), 'settings' => $user->settings, 'banned' => $user->banned ]; @@ -234,15 +246,12 @@ class UserModel extends AbstractCrudModel return $email; } - public static function validateAccessRank($accessRank) + public static function validateAccessRank(AccessRank $accessRank) { - $accessRank = intval($accessRank); + $accessRank->validate(); - if (!in_array($accessRank, AccessRank::getAll())) - throw new SimpleException('Invalid access rank type "%s"', $accessRank); - - if ($accessRank == AccessRank::Nobody) - throw new SimpleException('Cannot set special accesss rank "%s"', $accessRank); + if ($accessRank->toInteger() == AccessRank::Nobody) + throw new SimpleException('Cannot set special access rank "%s"', $accessRank->toString()); return $accessRank; } diff --git a/src/Views/post-edit.phtml b/src/Views/post-edit.phtml index 6f3c1ee9..aa8e09bf 100644 --- a/src/Views/post-edit.phtml +++ b/src/Views/post-edit.phtml @@ -23,11 +23,11 @@
    diff --git a/src/Views/post-file-render.phtml b/src/Views/post-file-render.phtml index 17aa4a3c..0bb41679 100644 --- a/src/Views/post-file-render.phtml +++ b/src/Views/post-file-render.phtml @@ -5,7 +5,7 @@ Assets::setPageThumb(\Chibi\Router::linkTo( $post = $this->context->transport->post; ?> -type == PostType::Image): ?> +getType()->toInteger() == PostType::Image): ?> context->imageLink)): ?> @@ -20,7 +20,7 @@ $post = $this->context->transport->post; -type == PostType::Flash): ?> +getType()->toInteger() == PostType::Flash): ?> context->transport->post; -type == PostType::Youtube): ?> +getType()->toInteger() == PostType::Youtube): ?> -type == PostType::Video): ?> +getType()->toInteger() == PostType::Video): ?>