Increased API readability

- Removed Abstract*Job hierarchy
- Introduced EntityRetrievers
- Introduced JobPager
- Moved files around
This commit is contained in:
Marcin Kurczewski 2014-05-12 16:46:14 +02:00
parent 484adbbf49
commit 098f11bd09
68 changed files with 857 additions and 472 deletions

View file

@ -33,12 +33,12 @@ final class Api
return $statuses; return $statuses;
} }
public static function checkArguments(AbstractJob $job) public static function checkArguments(IJob $job)
{ {
self::runArgumentCheck($job, $job->getRequiredArguments()); self::runArgumentCheck($job, $job->getRequiredArguments());
} }
public static function checkPrivileges(AbstractJob $job) public static function checkPrivileges(IJob $job)
{ {
if ($job->isAuthenticationRequired()) if ($job->isAuthenticationRequired())
Access::assertAuthentication(); Access::assertAuthentication();
@ -57,7 +57,7 @@ final class Api
} }
} }
private static function runArgumentCheck($job, $item) private static function runArgumentCheck(IJob $job, $item)
{ {
if (is_array($item)) if (is_array($item))
throw new Exception('Argument definition cannot be an array.'); throw new Exception('Argument definition cannot be an array.');

View file

@ -1,7 +1,7 @@
<?php <?php
class ApiJobUnsatisfiedException extends SimpleException class ApiJobUnsatisfiedException extends SimpleException
{ {
public function __construct(AbstractJob $job, $arg = null) public function __construct(IJob $job, $arg = null)
{ {
parent::__construct('%s cannot be run due to unsatisfied execution conditions (%s).', parent::__construct('%s cannot be run due to unsatisfied execution conditions (%s).',
get_class($job), get_class($job),

View file

@ -0,0 +1,36 @@
<?php
class CommentRetriever implements IEntityRetriever
{
private $job;
public function __construct(IJob $job)
{
$this->job = $job;
}
public function tryRetrieve()
{
if ($this->job->hasArgument(JobArgs::ARG_COMMENT_ENTITY))
return $this->job->getArgument(JobArgs::ARG_COMMENT_ENTITY);
if ($this->job->hasArgument(JobArgs::ARG_COMMENT_ID))
return CommentModel::getById($this->job->getArgument(JobArgs::ARG_COMMENT_ID));
return null;
}
public function retrieve()
{
$comment = $this->tryRetrieve();
if ($comment)
return $comment;
throw new ApiJobUnsatisfiedException($this->job);
}
public function getRequiredArguments()
{
return JobArgs::Alternative(
JobArgs::ARG_COMMENT_ID,
JobArgs::ARG_COMMENT_ENTITY);
}
}

View file

@ -0,0 +1,8 @@
<?php
interface IEntityRetriever
{
public function __construct(IJob $job);
public function tryRetrieve();
public function retrieve();
public function getRequiredArguments();
}

View file

@ -0,0 +1,40 @@
<?php
class PostRetriever implements IEntityRetriever
{
private $job;
public function __construct(IJob $job)
{
$this->job = $job;
}
public function tryRetrieve()
{
if ($this->job->hasArgument(JobArgs::ARG_POST_ENTITY))
return $this->job->getArgument(JobArgs::ARG_POST_ENTITY);
if ($this->job->hasArgument(JobArgs::ARG_POST_ID))
return PostModel::getById($this->job->getArgument(JobArgs::ARG_POST_ID));
if ($this->job->hasArgument(JobArgs::ARG_POST_NAME))
return PostModel::getByName($job->getArgument(JobArgs::ARG_POST_NAME));
return null;
}
public function retrieve()
{
$post = $this->tryRetrieve();
if ($post)
return $post;
throw new ApiJobUnsatisfiedException($this->job);
}
public function getRequiredArguments()
{
return JobArgs::Alternative(
JobArgs::ARG_POST_ID,
JobArgs::ARG_POST_NAME,
JobArgs::ARG_POST_ENTITY);
}
}

View file

@ -0,0 +1,36 @@
<?php
class SafePostRetriever implements IEntityRetriever
{
private $job;
public function __construct(IJob $job)
{
$this->job = $job;
}
public function tryRetrieve()
{
if ($this->job->hasArgument(JobArgs::ARG_POST_ENTITY))
return $this->job->getArgument(JobArgs::ARG_POST_ENTITY);
if ($this->job->hasArgument(JobArgs::ARG_POST_NAME))
return PostModel::getByName($this->job->getArgument(JobArgs::ARG_POST_NAME));
return null;
}
public function retrieve()
{
$post = $this->tryRetrieve();
if ($post)
return $post;
throw new ApiJobUnsatisfiedException($this->job);
}
public function getRequiredArguments()
{
return JobArgs::Alternative(
JobArgs::ARG_POST_NAME,
JobArgs::ARG_POST_ENTITY);
}
}

View file

@ -0,0 +1,37 @@
<?php
class UserRetriever implements IEntityRetriever
{
private $job;
public function __construct(IJob $job)
{
$this->job = $job;
}
public function tryRetrieve()
{
if ($this->job->hasArgument(JobArgs::ARG_USER_ENTITY))
return $this->job->getArgument(JobArgs::ARG_USER_ENTITY);
if ($this->job->hasArgument(JobArgs::ARG_USER_NAME))
return UserModel::getByNameOrEmail($this->job->getArgument(JobArgs::ARG_USER_NAME));
return null;
}
public function retrieve()
{
$user = $this->tryRetrieve();
if ($user)
return $user;
throw new ApiJobUnsatisfiedException($this->job);
}
public function getRequiredArguments()
{
return JobArgs::Alternative(
JobArgs::ARG_USER_NAME,
JobArgs::ARG_USER_EMAIL,
JobArgs::ARG_USER_ENTITY);
}
}

View file

@ -0,0 +1,50 @@
<?php
class JobPager
{
private $job;
public function __construct(IJob $job)
{
$this->pageSize = 20;
$this->job = $job;
}
public function setPageSize($newPageSize)
{
$this->pageSize = $newPageSize;
}
public function getPageSize()
{
return $this->pageSize;
}
public function getPageNumber()
{
if ($this->job->hasArgument(JobArgs::ARG_PAGE_NUMBER))
return (int) $this->job->getArgument(JobArgs::ARG_PAGE_NUMBER);
return 1;
}
public function getRequiredArguments()
{
return JobArgs::Optional(JobArgs::ARG_PAGE_NUMBER);
}
public function serialize($entities, $totalEntityCount)
{
$pageSize = $this->getPageSize();
$pageNumber = $this->getPageNumber();
$pageCount = ceil($totalEntityCount / $pageSize);
$pageNumber = $this->getPageNumber();
$pageNumber = min($pageCount, $pageNumber);
$ret = new StdClass;
$ret->entities = $entities;
$ret->entityCount = $totalEntityCount;
$ret->page = $pageNumber;
$ret->pageCount = $pageCount;
return $ret;
}
}

View file

@ -1,5 +1,5 @@
<?php <?php
abstract class AbstractJob abstract class AbstractJob implements IJob
{ {
const CONTEXT_NORMAL = 1; const CONTEXT_NORMAL = 1;
const CONTEXT_BATCH_EDIT = 2; const CONTEXT_BATCH_EDIT = 2;
@ -14,10 +14,7 @@ abstract class AbstractJob
public abstract function execute(); public abstract function execute();
public function getRequiredArguments() public abstract function getRequiredArguments();
{
return null;
}
public function getRequiredPrivileges() public function getRequiredPrivileges()
{ {

View file

@ -1,29 +0,0 @@
<?php
abstract class AbstractCommentJob extends AbstractJob
{
protected $comment;
public function prepare()
{
if ($this->hasArgument(JobArgs::ARG_COMMENT_ENTITY))
{
$this->comment = $this->getArgument(JobArgs::ARG_COMMENT_ENTITY);
}
else
{
$commentId = $this->getArgument(JobArgs::ARG_COMMENT_ID);
$this->comment = CommentModel::getById($commentId);
}
}
public function getRequiredArguments()
{
return JobArgs::Conjunction(
JobArgs::Alternative(
JobArgs::ARG_COMMENT_ID,
JobArgs::ARG_COMMENT_ENTITY),
$this->getRequiredSubArguments());
}
public abstract function getRequiredSubArguments();
}

View file

@ -1,9 +1,16 @@
<?php <?php
class AddCommentJob extends AbstractPostJob class AddCommentJob extends AbstractJob
{ {
protected $postRetriever;
public function __construct()
{
$this->postRetriever = new PostRetriever($this);
}
public function execute() public function execute()
{ {
$post = $this->post; $post = $this->postRetriever->retrieve();
$user = Auth::getCurrentUser(); $user = Auth::getCurrentUser();
$text = $this->getArgument(JobArgs::ARG_NEW_TEXT); $text = $this->getArgument(JobArgs::ARG_NEW_TEXT);
@ -21,9 +28,11 @@ class AddCommentJob extends AbstractPostJob
return $comment; return $comment;
} }
public function getRequiredSubArguments() public function getRequiredArguments()
{ {
return JobArgs::ARG_NEW_TEXT; return JobArgs::Conjunction(
$this->postRetriever->getRequiredArguments(),
JobArgs::ARG_NEW_TEXT);
} }
public function getRequiredPrivileges() public function getRequiredPrivileges()

View file

@ -1,27 +1,35 @@
<?php <?php
class DeleteCommentJob extends AbstractCommentJob class DeleteCommentJob extends AbstractJob
{ {
protected $commentRetriever;
public function __construct()
{
$this->commentRetriever = new CommentRetriever($this);
}
public function execute() public function execute()
{ {
$post = $this->comment->getPost(); $comment = $this->commentRetriever->retrieve();
$post = $comment->getPost();
CommentModel::remove($this->comment); CommentModel::remove($comment);
Logger::log('{user} removed comment from {post}', [ Logger::log('{user} removed comment from {post}', [
'user' => TextHelper::reprUser(Auth::getCurrentUser()), 'user' => TextHelper::reprUser(Auth::getCurrentUser()),
'post' => TextHelper::reprPost($post)]); 'post' => TextHelper::reprPost($post)]);
} }
public function getRequiredSubArguments() public function getRequiredArguments()
{ {
return null; return $this->commentRetriever->getRequiredArguments();
} }
public function getRequiredPrivileges() public function getRequiredPrivileges()
{ {
return new Privilege( return new Privilege(
Privilege::DeleteComment, Privilege::DeleteComment,
Access::getIdentity($this->comment->getCommenter())); Access::getIdentity($this->commentRetriever->retrieve()->getCommenter()));
} }
public function isAuthenticationRequired() public function isAuthenticationRequired()

View file

@ -1,9 +1,16 @@
<?php <?php
class EditCommentJob extends AbstractCommentJob class EditCommentJob extends AbstractJob
{ {
protected $commentRetriever;
public function __construct()
{
$this->commentRetriever = new CommentRetriever($this);
}
public function execute() public function execute()
{ {
$comment = $this->comment; $comment = $this->commentRetriever->retrieve();
$comment->setCreationTime(time()); $comment->setCreationTime(time());
$comment->setText($this->getArgument(JobArgs::ARG_NEW_TEXT)); $comment->setText($this->getArgument(JobArgs::ARG_NEW_TEXT));
@ -16,16 +23,18 @@ class EditCommentJob extends AbstractCommentJob
return $comment; return $comment;
} }
public function getRequiredSubArguments() public function getRequiredArguments()
{ {
return JobArgs::ARG_NEW_TEXT; return JobArgs::Conjunction(
$this->commentRetriever->getRequiredArguments(),
JobArgs::ARG_NEW_TEXT);
} }
public function getRequiredPrivileges() public function getRequiredPrivileges()
{ {
return new Privilege( return new Privilege(
Privilege::EditComment, Privilege::EditComment,
Access::getIdentity($this->comment->getCommenter())); Access::getIdentity($this->commentRetriever->retrieve()->getCommenter()));
} }
public function isAuthenticationRequired() public function isAuthenticationRequired()

View file

@ -1,10 +1,23 @@
<?php <?php
class ListCommentsJob extends AbstractPageJob class ListCommentsJob extends AbstractJob implements IPagedJob
{ {
protected $pager;
public function __construct()
{
$this->pager = new JobPager($this);
$this->pager->setPageSize(getConfig()->comments->commentsPerPage);
}
public function getPager()
{
return $this->pager;
}
public function execute() public function execute()
{ {
$pageSize = $this->getPageSize(); $pageSize = $this->pager->getPageSize();
$page = $this->getArgument(JobArgs::ARG_PAGE_NUMBER); $page = $this->pager->getPageNumber();
$query = 'comment_min:1 order:comment_date,desc'; $query = 'comment_min:1 order:comment_date,desc';
$posts = PostSearchService::getEntities($query, $pageSize, $page); $posts = PostSearchService::getEntities($query, $pageSize, $page);
@ -17,17 +30,12 @@ class ListCommentsJob extends AbstractPageJob
$comments = array_merge($comments, $post->getComments()); $comments = array_merge($comments, $post->getComments());
CommentModel::preloadCommenters($comments); CommentModel::preloadCommenters($comments);
return $this->getPager($posts, $postCount, $page, $pageSize); return $this->pager->serialize($posts, $postCount);
} }
public function getDefaultPageSize() public function getRequiredArguments()
{ {
return intval(getConfig()->comments->commentsPerPage); return $this->pager->getRequiredArguments();
}
public function getRequiredSubArguments()
{
return null;
} }
public function getRequiredPrivileges() public function getRequiredPrivileges()

View file

@ -1,21 +1,27 @@
<?php <?php
class PreviewCommentJob extends AbstractJob class PreviewCommentJob extends AbstractJob
{ {
protected $commentRetriever;
protected $postRetriever;
public function __construct()
{
$this->commentRetriever = new CommentRetriever($this);
$this->postRetriever = new PostRetriever($this);
}
public function execute() public function execute()
{ {
$user = Auth::getCurrentUser(); $user = Auth::getCurrentUser();
$text = $this->getArgument(JobArgs::ARG_NEW_TEXT); $text = $this->getArgument(JobArgs::ARG_NEW_TEXT);
if ($this->hasArgument(JobArgs::ARG_POST_ID)) $comment = $this->commentRetriever->tryRetrieve();
if (!$comment)
{ {
$post = PostModel::getById($this->getArgument(JobArgs::ARG_POST_ID)); $post = $this->postRetriever->retrieve();
$comment = CommentModel::spawn(); $comment = CommentModel::spawn();
$comment->setPost($post); $comment->setPost($post);
} }
else
{
$comment = CommentModel::getById($this->getArgument(JobArgs::ARG_COMMENT_ID));
}
$comment->setCommenter($user); $comment->setCommenter($user);
$comment->setCreationTime(time()); $comment->setCreationTime(time());
@ -31,8 +37,8 @@ class PreviewCommentJob extends AbstractJob
return JobArgs::Conjunction( return JobArgs::Conjunction(
JobArgs::ARG_NEW_TEXT, JobArgs::ARG_NEW_TEXT,
JobArgs::Alternative( JobArgs::Alternative(
JobArgs::ARG_COMMENT_ID, $this->commentRetriever->getRequiredArguments(),
JobArgs::ARG_POST_ID)); $this->postRetriever->getRequiredArguments()));
} }
public function getRequiredPrivileges() public function getRequiredPrivileges()

17
src/Api/Jobs/IJob.php Normal file
View file

@ -0,0 +1,17 @@
<?php
interface IJob
{
public function prepare();
public function execute();
public function getRequiredArguments();
public function getRequiredPrivileges();
public function isAuthenticationRequired();
public function isConfirmedEmailRequired();
public function getArgument($key);
public function getArguments();
public function hasArgument($key);
public function setArgument($key, $value);
public function setArguments(array $arguments);
}

View file

@ -0,0 +1,5 @@
<?php
interface IPagedJob
{
public function getPager();
}

View file

@ -1,10 +1,23 @@
<?php <?php
class GetLogJob extends AbstractPageJob class GetLogJob extends AbstractJob implements IPagedJob
{ {
protected $pager;
public function __construct()
{
$this->pager = new JobPager($this);
$this->pager->setPageSize(getConfig()->browsing->logsPerPage);
}
public function getPager()
{
return $this->pager;
}
public function execute() public function execute()
{ {
$pageSize = $this->getPageSize(); $pageSize = $this->pager->getPageSize();
$page = $this->getArgument(JobArgs::ARG_PAGE_NUMBER); $page = $this->pager->getPageNumber();
$name = $this->getArgument(JobArgs::ARG_LOG_ID); $name = $this->getArgument(JobArgs::ARG_LOG_ID);
$query = $this->getArgument(JobArgs::ARG_QUERY); $query = $this->getArgument(JobArgs::ARG_QUERY);
@ -31,17 +44,13 @@ class GetLogJob extends AbstractPageJob
$lineCount = count($lines); $lineCount = count($lines);
$lines = array_slice($lines, ($page - 1) * $pageSize, $pageSize); $lines = array_slice($lines, ($page - 1) * $pageSize, $pageSize);
return $this->getPager($lines, $lineCount, $page, $pageSize); return $this->pager->serialize($lines, $lineCount);
} }
public function getDefaultPageSize() public function getRequiredArguments()
{
return intval(getConfig()->browsing->logsPerPage);
}
public function getRequiredSubArguments()
{ {
return JobArgs::Conjunction( return JobArgs::Conjunction(
$this->pager->getRequiredArguments(),
JobArgs::ARG_LOG_ID, JobArgs::ARG_LOG_ID,
JobArgs::ARG_QUERY); JobArgs::ARG_QUERY);
} }

View file

@ -1,42 +0,0 @@
<?php
abstract class AbstractPageJob extends AbstractJob
{
protected $pageSize = null;
public abstract function getDefaultPageSize();
public function getPageSize()
{
return $this->pageSize === null
? $this->getDefaultPageSize()
: $this->pageSize;
}
public function setPageSize($pageSize)
{
$this->pageSize = $pageSize;
return $this;
}
public function getPager($entities, $entityCount, $page, $pageSize)
{
$pageCount = ceil($entityCount / $pageSize);
$page = min($pageCount, $page);
$ret = new StdClass;
$ret->entities = $entities;
$ret->entityCount = $entityCount;
$ret->page = $page;
$ret->pageCount = $pageCount;
return $ret;
}
public function getRequiredArguments()
{
return JobArgs::Conjunction(
JobArgs::ARG_PAGE_NUMBER,
$this->getRequiredSubArguments());
}
public abstract function getRequiredSubArguments();
}

View file

@ -1,32 +0,0 @@
<?php
class ListPostsJob extends AbstractPageJob
{
public function execute()
{
$pageSize = $this->getPageSize();
$page = $this->getArgument(JobArgs::ARG_PAGE_NUMBER);
$query = $this->getArgument(JobArgs::ARG_QUERY);
$posts = PostSearchService::getEntities($query, $pageSize, $page);
$postCount = PostSearchService::getEntityCount($query);
PostModel::preloadTags($posts);
return $this->getPager($posts, $postCount, $page, $pageSize);
}
public function getDefaultPageSize()
{
return intval(getConfig()->browsing->postsPerPage);
}
public function getRequiredSubArguments()
{
return JobArgs::ARG_QUERY;
}
public function getRequiredPrivileges()
{
return new Privilege(Privilege::ListPosts);
}
}

View file

@ -1,30 +0,0 @@
<?php
class ListTagsJob extends AbstractPageJob
{
public function execute()
{
$pageSize = $this->getPageSize();
$page = $this->getArgument(JobArgs::ARG_PAGE_NUMBER);
$query = $this->getArgument(JobArgs::ARG_QUERY);
$tags = TagSearchService::getEntities($query, $pageSize, $page);
$tagCount = TagSearchService::getEntityCount($query);
return $this->getPager($tags, $tagCount, $page, $pageSize);
}
public function getDefaultPageSize()
{
return intval(getConfig()->browsing->tagsPerPage);
}
public function getRequiredSubArguments()
{
return JobArgs::ARG_QUERY;
}
public function getRequiredPrivileges()
{
return new Privilege(Privilege::ListTags);
}
}

View file

@ -1,30 +0,0 @@
<?php
class ListUsersJob extends AbstractPageJob
{
public function execute()
{
$pageSize = $this->getPageSize();
$page = $this->getArgument(JobArgs::ARG_PAGE_NUMBER);
$filter = $this->getArgument(JobArgs::ARG_QUERY);
$users = UserSearchService::getEntities($filter, $pageSize, $page);
$userCount = UserSearchService::getEntityCount($filter);
return $this->getPager($users, $userCount, $page, $pageSize);
}
public function getDefaultPageSize()
{
return intval(getConfig()->browsing->usersPerPage);
}
public function getRequiredSubArguments()
{
return JobArgs::ARG_QUERY;
}
public function getRequiredPrivileges()
{
return new Privilege(Privilege::ListUsers);
}
}

View file

@ -1,35 +0,0 @@
<?php
abstract class AbstractPostJob extends AbstractJob
{
protected $post;
public function prepare()
{
if ($this->hasArgument(JobArgs::ARG_POST_ENTITY))
{
$this->post = $this->getArgument(JobArgs::ARG_POST_ENTITY);
}
elseif ($this->hasArgument(JobArgs::ARG_POST_ID))
{
$postId = $this->getArgument(JobArgs::ARG_POST_ID);
$this->post = PostModel::getById($postId);
}
else
{
$postName = $this->getArgument(JobArgs::ARG_POST_NAME);
$this->post = PostModel::getByName($postName);
}
}
public function getRequiredArguments()
{
return JobArgs::Conjunction(
JobArgs::Alternative(
JobArgs::ARG_POST_ID,
JobArgs::ARG_POST_NAME,
JobArgs::ARG_POST_ENTITY),
$this->getRequiredSubArguments());
}
public abstract function getRequiredSubArguments();
}

View file

@ -1,9 +1,16 @@
<?php <?php
class DeletePostJob extends AbstractPostJob class DeletePostJob extends AbstractJob
{ {
protected $postRetriever;
public function __construct()
{
$this->postRetriever = new PostRetriever($this);
}
public function execute() public function execute()
{ {
$post = $this->post; $post = $this->postRetriever->retrieve();
PostModel::remove($post); PostModel::remove($post);
@ -12,16 +19,16 @@ class DeletePostJob extends AbstractPostJob
'post' => TextHelper::reprPost($post)]); 'post' => TextHelper::reprPost($post)]);
} }
public function getRequiredSubArguments() public function getRequiredArguments()
{ {
return null; return $this->postRetriever->getRequiredArguments();
} }
public function getRequiredPrivileges() public function getRequiredPrivileges()
{ {
return new Privilege( return new Privilege(
Privilege::DeletePost, Privilege::DeletePost,
Access::getIdentity($this->post->getUploader())); Access::getIdentity($this->postRetriever->retrieve()->getUploader()));
} }
public function isAuthenticationRequired() public function isAuthenticationRequired()

View file

@ -1,9 +1,16 @@
<?php <?php
class EditPostContentJob extends AbstractPostJob class EditPostContentJob extends AbstractJob
{ {
protected $postRetriever;
public function __construct()
{
$this->postRetriever = new PostRetriever($this);
}
public function execute() public function execute()
{ {
$post = $this->post; $post = $this->postRetriever->retrieve();
if ($this->hasArgument(JobArgs::ARG_NEW_POST_CONTENT_URL)) if ($this->hasArgument(JobArgs::ARG_NEW_POST_CONTENT_URL))
{ {
@ -26,11 +33,13 @@ class EditPostContentJob extends AbstractPostJob
return $post; return $post;
} }
public function getRequiredSubArguments() public function getRequiredArguments()
{ {
return JobArgs::Alternative( return JobArgs::Conjunction(
JobArgs::ARG_NEW_POST_CONTENT, $this->postRetriever->getRequiredArguments(),
JobArgs::ARG_NEW_POST_CONTENT_URL); JobArgs::Alternative(
JobArgs::ARG_NEW_POST_CONTENT,
JobArgs::ARG_NEW_POST_CONTENT_URL));
} }
public function getRequiredPrivileges() public function getRequiredPrivileges()
@ -39,6 +48,6 @@ class EditPostContentJob extends AbstractPostJob
$this->getContext() == self::CONTEXT_BATCH_ADD $this->getContext() == self::CONTEXT_BATCH_ADD
? Privilege::AddPostContent ? Privilege::AddPostContent
: Privilege::EditPostContent, : Privilege::EditPostContent,
Access::getIdentity($this->post->getUploader())); Access::getIdentity($this->postRetriever->retrieve()->getUploader()));
} }
} }

View file

@ -1,9 +1,16 @@
<?php <?php
class EditPostJob extends AbstractPostJob class EditPostJob extends AbstractJob
{ {
protected $postRetriever;
public function __construct()
{
$this->postRetriever = new PostRetriever($this);
}
public function execute() public function execute()
{ {
$post = $this->post; $post = $this->postRetriever->retrieve();
Logger::bufferChanges(); Logger::bufferChanges();
@ -43,9 +50,9 @@ class EditPostJob extends AbstractPostJob
return $post; return $post;
} }
public function getRequiredSubArguments() public function getRequiredArguments()
{ {
return null; return $this->postRetriever->getRequiredArguments();
} }
public function getRequiredPrivileges() public function getRequiredPrivileges()
@ -54,6 +61,6 @@ class EditPostJob extends AbstractPostJob
$this->getContext() == self::CONTEXT_BATCH_ADD $this->getContext() == self::CONTEXT_BATCH_ADD
? Privilege::AddPost ? Privilege::AddPost
: Privilege::EditPost, : Privilege::EditPost,
Access::getIdentity($this->post->getUploader())); Access::getIdentity($this->postRetriever->retrieve()->getUploader()));
} }
} }

View file

@ -1,9 +1,16 @@
<?php <?php
class EditPostRelationsJob extends AbstractPostJob class EditPostRelationsJob extends AbstractJob
{ {
protected $postRetriever;
public function __construct()
{
$this->postRetriever = new PostRetriever($this);
}
public function execute() public function execute()
{ {
$post = $this->post; $post = $this->postRetriever->retrieve();
$relations = $this->getArgument(JobArgs::ARG_NEW_RELATED_POST_IDS); $relations = $this->getArgument(JobArgs::ARG_NEW_RELATED_POST_IDS);
$oldRelatedIds = array_map(function($post) { return $post->getId(); }, $post->getRelations()); $oldRelatedIds = array_map(function($post) { return $post->getId(); }, $post->getRelations());
@ -32,9 +39,11 @@ class EditPostRelationsJob extends AbstractPostJob
return $post; return $post;
} }
public function getRequiredSubArguments() public function getRequiredArguments()
{ {
return JobArgs::ARG_NEW_RELATED_POST_IDS; return JobArgs::Conjunction(
$this->postRetriever->getRequiredArguments(),
JobArgs::ARG_NEW_RELATED_POST_IDS);
} }
public function getRequiredPrivileges() public function getRequiredPrivileges()
@ -43,6 +52,6 @@ class EditPostRelationsJob extends AbstractPostJob
$this->getContext() == self::CONTEXT_BATCH_ADD $this->getContext() == self::CONTEXT_BATCH_ADD
? Privilege::AddPostRelations ? Privilege::AddPostRelations
: Privilege::EditPostRelations, : Privilege::EditPostRelations,
Access::getIdentity($this->post->getUploader())); Access::getIdentity($this->postRetriever->retrieve()->getUploader()));
} }
} }

View file

@ -1,9 +1,16 @@
<?php <?php
class EditPostSafetyJob extends AbstractPostJob class EditPostSafetyJob extends AbstractJob
{ {
protected $postRetriever;
public function __construct()
{
$this->postRetriever = new PostRetriever($this);
}
public function execute() public function execute()
{ {
$post = $this->post; $post = $this->postRetriever->retrieve();
$newSafety = new PostSafety($this->getArgument(JobArgs::ARG_NEW_SAFETY)); $newSafety = new PostSafety($this->getArgument(JobArgs::ARG_NEW_SAFETY));
$oldSafety = $post->getSafety(); $oldSafety = $post->getSafety();
@ -23,9 +30,11 @@ class EditPostSafetyJob extends AbstractPostJob
return $post; return $post;
} }
public function getRequiredSubArguments() public function getRequiredArguments()
{ {
return JobArgs::ARG_NEW_SAFETY; return JobArgs::Conjunction(
$this->postRetriever->getRequiredArguments(),
JobArgs::ARG_NEW_SAFETY);
} }
public function getRequiredPrivileges() public function getRequiredPrivileges()
@ -34,6 +43,6 @@ class EditPostSafetyJob extends AbstractPostJob
$this->getContext() == self::CONTEXT_BATCH_ADD $this->getContext() == self::CONTEXT_BATCH_ADD
? Privilege::AddPostSafety ? Privilege::AddPostSafety
: Privilege::EditPostSafety, : Privilege::EditPostSafety,
Access::getIdentity($this->post->getUploader())); Access::getIdentity($this->postRetriever->retrieve()->getUploader()));
} }
} }

View file

@ -1,9 +1,16 @@
<?php <?php
class EditPostSourceJob extends AbstractPostJob class EditPostSourceJob extends AbstractJob
{ {
protected $postRetriever;
public function __construct()
{
$this->postRetriever = new PostRetriever($this);
}
public function execute() public function execute()
{ {
$post = $this->post; $post = $this->postRetriever->retrieve();
$newSource = $this->getArgument(JobArgs::ARG_NEW_SOURCE); $newSource = $this->getArgument(JobArgs::ARG_NEW_SOURCE);
$oldSource = $post->getSource(); $oldSource = $post->getSource();
@ -23,9 +30,11 @@ class EditPostSourceJob extends AbstractPostJob
return $post; return $post;
} }
public function getRequiredSubArguments() public function getRequiredArguments()
{ {
return JobArgs::ARG_NEW_SOURCE; return JobArgs::Conjunction(
$this->postRetriever->getRequiredArguments(),
JobArgs::ARG_NEW_SOURCE);
} }
public function getRequiredPrivileges() public function getRequiredPrivileges()
@ -34,6 +43,6 @@ class EditPostSourceJob extends AbstractPostJob
$this->getContext() == self::CONTEXT_BATCH_ADD $this->getContext() == self::CONTEXT_BATCH_ADD
? Privilege::AddPostSource ? Privilege::AddPostSource
: Privilege::EditPostSource, : Privilege::EditPostSource,
Access::getIdentity($this->post->getUploader())); Access::getIdentity($this->postRetriever->retrieve()->getUploader()));
} }
} }

View file

@ -1,9 +1,16 @@
<?php <?php
class EditPostTagsJob extends AbstractPostJob class EditPostTagsJob extends AbstractJob
{ {
protected $postRetriever;
public function __construct()
{
$this->postRetriever = new PostRetriever($this);
}
public function execute() public function execute()
{ {
$post = $this->post; $post = $this->postRetriever->retrieve();
$tagNames = $this->getArgument(JobArgs::ARG_NEW_TAG_NAMES); $tagNames = $this->getArgument(JobArgs::ARG_NEW_TAG_NAMES);
if (!is_array($tagNames)) if (!is_array($tagNames))
@ -40,9 +47,11 @@ class EditPostTagsJob extends AbstractPostJob
return $post; return $post;
} }
public function getRequiredSubArguments() public function getRequiredArguments()
{ {
return JobArgs::ARG_NEW_TAG_NAMES; return JobArgs::Conjunction(
$this->postRetriever->getRequiredArguments(),
JobArgs::ARG_NEW_TAG_NAMES);
} }
public function getRequiredPrivileges() public function getRequiredPrivileges()
@ -51,6 +60,6 @@ class EditPostTagsJob extends AbstractPostJob
$this->getContext() == self::CONTEXT_BATCH_ADD $this->getContext() == self::CONTEXT_BATCH_ADD
? Privilege::AddPostTags ? Privilege::AddPostTags
: Privilege::EditPostTags, : Privilege::EditPostTags,
Access::getIdentity($this->post->getUploader())); Access::getIdentity($this->postRetriever->retrieve()->getUploader()));
} }
} }

View file

@ -1,9 +1,16 @@
<?php <?php
class EditPostThumbJob extends AbstractPostJob class EditPostThumbJob extends AbstractJob
{ {
protected $postRetriever;
public function __construct()
{
$this->postRetriever = new PostRetriever($this);
}
public function execute() public function execute()
{ {
$post = $this->post; $post = $this->postRetriever->retrieve();
$file = $this->getArgument(JobArgs::ARG_NEW_THUMB_CONTENT); $file = $this->getArgument(JobArgs::ARG_NEW_THUMB_CONTENT);
$post->setCustomThumbnailFromPath($file->filePath); $post->setCustomThumbnailFromPath($file->filePath);
@ -18,9 +25,11 @@ class EditPostThumbJob extends AbstractPostJob
return $post; return $post;
} }
public function getRequiredSubArguments() public function getRequiredArguments()
{ {
return JobArgs::ARG_NEW_THUMB_CONTENT; return JobArgs::Conjunction(
$this->postRetriever->getRequiredArguments(),
JobArgs::ARG_NEW_THUMB_CONTENT);
} }
public function getRequiredPrivileges() public function getRequiredPrivileges()
@ -29,6 +38,6 @@ class EditPostThumbJob extends AbstractPostJob
$this->getContext() == self::CONTEXT_BATCH_ADD $this->getContext() == self::CONTEXT_BATCH_ADD
? Privilege::AddPostThumb ? Privilege::AddPostThumb
: Privilege::EditPostThumb, : Privilege::EditPostThumb,
Access::getIdentity($this->post->getUploader())); Access::getIdentity($this->postRetriever->retrieve()->getUploader()));
} }
} }

View file

@ -1,9 +1,16 @@
<?php <?php
class FeaturePostJob extends AbstractPostJob class FeaturePostJob extends AbstractJob
{ {
protected $postRetriever;
public function __construct()
{
$this->postRetriever = new PostRetriever($this);
}
public function execute() public function execute()
{ {
$post = $this->post; $post = $this->postRetriever->retrieve();
PropertyModel::set(PropertyModel::FeaturedPostId, $post->getId()); PropertyModel::set(PropertyModel::FeaturedPostId, $post->getId());
PropertyModel::set(PropertyModel::FeaturedPostUnixTime, time()); PropertyModel::set(PropertyModel::FeaturedPostUnixTime, time());
@ -20,16 +27,18 @@ class FeaturePostJob extends AbstractPostJob
return $post; return $post;
} }
public function getRequiredSubArguments() public function getRequiredArguments()
{ {
return JobArgs::Optional(JobArgs::ARG_ANONYMOUS); return JobArgs::Conjunction(
$this->postRetriever->getRequiredArguments(),
JobArgs::Optional(JobArgs::ARG_ANONYMOUS));
} }
public function getRequiredPrivileges() public function getRequiredPrivileges()
{ {
return new Privilege( return new Privilege(
Privilege::FeaturePost, Privilege::FeaturePost,
Access::getIdentity($this->post->getUploader())); Access::getIdentity($this->postRetriever->retrieve()->getUploader()));
} }
public function isAuthenticationRequired() public function isAuthenticationRequired()

View file

@ -1,9 +1,16 @@
<?php <?php
class FlagPostJob extends AbstractPostJob class FlagPostJob extends AbstractJob
{ {
protected $postRetriever;
public function __construct()
{
$this->postRetriever = new PostRetriever($this);
}
public function execute() public function execute()
{ {
$post = $this->post; $post = $this->postRetriever->retrieve();
$key = TextHelper::reprPost($post); $key = TextHelper::reprPost($post);
$flagged = SessionHelper::get('flagged', []); $flagged = SessionHelper::get('flagged', []);
@ -19,15 +26,15 @@ class FlagPostJob extends AbstractPostJob
return $post; return $post;
} }
public function getRequiredSubArguments() public function getRequiredArguments()
{ {
return null; return $this->postRetriever->getRequiredArguments();
} }
public function getRequiredPrivileges() public function getRequiredPrivileges()
{ {
return new Privilege( return new Privilege(
Privilege::FlagPost, Privilege::FlagPost,
Access::getIdentity($this->post->getUploader())); Access::getIdentity($this->postRetriever->retrieve()->getUploader()));
} }
} }

View file

@ -1,19 +1,16 @@
<?php <?php
class GetPostContentJob extends AbstractJob class GetPostContentJob extends AbstractJob
{ {
protected $post; protected $postRetriever;
public function prepare() public function __construct()
{ {
if ($this->hasArgument(JobArgs::ARG_POST_ENTITY)) $this->postRetriever = new SafePostRetriever($this);
$this->post = $this->getArgument(JobArgs::ARG_POST_ENTITY);
else
$this->post = PostModel::getByName($this->getArgument(JobArgs::ARG_POST_NAME));
} }
public function execute() public function execute()
{ {
$post = $this->post; $post = $this->postRetriever->retrieve();
$config = getConfig(); $config = getConfig();
$path = $config->main->filesPath . DS . $post->getName(); $path = $config->main->filesPath . DS . $post->getName();
@ -35,14 +32,12 @@ class GetPostContentJob extends AbstractJob
public function getRequiredArguments() public function getRequiredArguments()
{ {
return JobArgs::Alternative( return $this->postRetriever->getRequiredArguments();
JobArgs::ARG_POST_NAME,
JobArgs::ARG_POST_ENTITY);
} }
public function getRequiredPrivileges() public function getRequiredPrivileges()
{ {
$post = $this->post; $post = $this->postRetriever->retrieve();
$privileges = []; $privileges = [];
if ($post->isHidden()) if ($post->isHidden())

View file

@ -1,23 +1,32 @@
<?php <?php
class GetPostJob extends AbstractPostJob class GetPostJob extends AbstractJob
{ {
protected $postRetriever;
public function __construct()
{
$this->postRetriever = new PostRetriever($this);
}
public function execute() public function execute()
{ {
$post = $this->post; $post = $this->postRetriever->retrieve();
CommentModel::preloadCommenters($post->getComments()); CommentModel::preloadCommenters($post->getComments());
return $post; return $post;
} }
public function getRequiredSubArguments() public function getRequiredArguments()
{ {
return null; return JobArgs::Conjunction(
$this->postRetriever->getRequiredArguments(),
null);
} }
public function getRequiredPrivileges() public function getRequiredPrivileges()
{ {
$post = $this->post; $post = $this->postRetriever->retrieve();
$privileges = []; $privileges = [];
if ($post->isHidden()) if ($post->isHidden())

View file

@ -1,13 +1,21 @@
<?php <?php
class GetPostThumbJob extends AbstractJob class GetPostThumbJob extends AbstractJob
{ {
protected $postRetriever;
public function __construct()
{
$this->postRetriever = new SafePostRetriever($this);
}
public function execute() public function execute()
{ {
if ($this->getArgument(JobArgs::ARG_POST_NAME)) //optimize - save extra query to DB
if ($this->hasArgument(JobArgs::ARG_POST_NAME))
$name = $this->getArgument(JobArgs::ARG_POST_NAME); $name = $this->getArgument(JobArgs::ARG_POST_NAME);
else else
{ {
$post = PostModel::getByName($this->getArgument(JobArgs::ARG_POST_ENTITY)); $post = $this->postRetriever->retrieve();
$name = $post->getName(); $name = $post->getName();
} }
@ -21,10 +29,7 @@ class GetPostThumbJob extends AbstractJob
if (!file_exists($path)) if (!file_exists($path))
{ {
$post = PostModel::getByName($name); $post = PostModel::getByName($name);
$post = $this->postRetriever->retrieve();
if ($post->isHidden())
Access::assert(new Privilege(Privilege::ListPosts, 'hidden'));
Access::assert(new Privilege(Privilege::ListPosts, $post->getSafety()->toString()));
$post->generateThumb($width, $height); $post->generateThumb($width, $height);
@ -45,16 +50,14 @@ class GetPostThumbJob extends AbstractJob
public function getRequiredArguments() public function getRequiredArguments()
{ {
return JobArgs::Conjunction( return JobArgs::Conjunction(
JobArgs::Alternative( $this->postRetriever->getRequiredArguments(),
JobArgs::ARG_POST_ENTITY,
JobArgs::ARG_POST_NAME),
JobArgs::Optional(JobArgs::ARG_THUMB_WIDTH), JobArgs::Optional(JobArgs::ARG_THUMB_WIDTH),
JobArgs::Optional(JobArgs::ARG_THUMB_HEIGHT)); JobArgs::Optional(JobArgs::ARG_THUMB_HEIGHT));
} }
public function getRequiredPrivileges() public function getRequiredPrivileges()
{ {
//manually enforced in execute when post is retrieved //privilege check removed to make thumbs faster
return false; return false;
} }
} }

View file

@ -0,0 +1,42 @@
<?php
class ListPostsJob extends AbstractJob implements IPagedJob
{
protected $pager;
public function __construct()
{
$this->pager = new JobPager($this);
$this->pager->setPageSize(getConfig()->browsing->postsPerPage);
}
public function getPager()
{
return $this->pager;
}
public function execute()
{
$pageSize = $this->pager->getPageSize();
$page = $this->pager->getPageNumber();
$query = $this->getArgument(JobArgs::ARG_QUERY);
$posts = PostSearchService::getEntities($query, $pageSize, $page);
$postCount = PostSearchService::getEntityCount($query);
PostModel::preloadTags($posts);
return $this->pager->serialize($posts, $postCount);
}
public function getRequiredArguments()
{
return JobArgs::Conjunction(
$this->pager->getRequiredArguments(),
JobArgs::ARG_QUERY);
}
public function getRequiredPrivileges()
{
return new Privilege(Privilege::ListPosts);
}
}

View file

@ -1,9 +1,16 @@
<?php <?php
class ScorePostJob extends AbstractPostJob class ScorePostJob extends AbstractJob
{ {
protected $postRetriever;
public function __construct()
{
$this->postRetriever = new PostRetriever($this);
}
public function execute() public function execute()
{ {
$post = $this->post; $post = $this->postRetriever->retrieve();
$score = intval($this->getArgument(JobArgs::ARG_NEW_POST_SCORE)); $score = intval($this->getArgument(JobArgs::ARG_NEW_POST_SCORE));
UserModel::updateUserScore(Auth::getCurrentUser(), $post, $score); UserModel::updateUserScore(Auth::getCurrentUser(), $post, $score);
@ -11,16 +18,18 @@ class ScorePostJob extends AbstractPostJob
return $post; return $post;
} }
public function getRequiredSubArguments() public function getRequiredArguments()
{ {
return JobArgs::ARG_NEW_POST_SCORE; return JobArgs::Conjunction(
$this->postRetriever->getRequiredArguments(),
JobArgs::ARG_NEW_POST_SCORE);
} }
public function getRequiredPrivileges() public function getRequiredPrivileges()
{ {
return new Privilege( return new Privilege(
Privilege::ScorePost, Privilege::ScorePost,
Access::getIdentity($this->post->getUploader())); Access::getIdentity($this->postRetriever->retrieve()->getUploader()));
} }
public function isAuthenticationRequired() public function isAuthenticationRequired()

View file

@ -1,9 +1,16 @@
<?php <?php
class TogglePostFavoriteJob extends AbstractPostJob class TogglePostFavoriteJob extends AbstractJob
{ {
protected $postRetriever;
public function __construct()
{
$this->postRetriever = new PostRetriever($this);
}
public function execute() public function execute()
{ {
$post = $this->post; $post = $this->postRetriever->retrieve();
$favorite = boolval($this->getArgument(JobArgs::ARG_NEW_STATE)); $favorite = boolval($this->getArgument(JobArgs::ARG_NEW_STATE));
if ($favorite) if ($favorite)
@ -19,16 +26,18 @@ class TogglePostFavoriteJob extends AbstractPostJob
return $post; return $post;
} }
public function getRequiredSubArguments() public function getRequiredArguments()
{ {
return JobArgs::ARG_NEW_STATE; return JobArgs::Conjunction(
$this->postRetriever->getRequiredArguments(),
JobArgs::ARG_NEW_STATE);
} }
public function getRequiredPrivileges() public function getRequiredPrivileges()
{ {
return new Privilege( return new Privilege(
Privilege::FavoritePost, Privilege::FavoritePost,
Access::getIdentity($this->post->getUploader())); Access::getIdentity($this->postRetriever->retrieve()->getUploader()));
} }
public function isAuthenticationRequired() public function isAuthenticationRequired()

View file

@ -1,11 +1,18 @@
<?php <?php
class TogglePostTagJob extends AbstractPostJob class TogglePostTagJob extends AbstractJob
{ {
protected $postRetriever;
public function __construct()
{
$this->postRetriever = new PostRetriever($this);
}
public function execute() public function execute()
{ {
$tagName = $this->getArgument(JobArgs::ARG_TAG_NAME); $tagName = $this->getArgument(JobArgs::ARG_TAG_NAME);
$enable = boolval($this->getArgument(JobArgs::ARG_NEW_STATE)); $enable = boolval($this->getArgument(JobArgs::ARG_NEW_STATE));
$post = $this->post; $post = $this->postRetriever->retrieve();
$tags = $post->getTags(); $tags = $post->getTags();
@ -50,17 +57,19 @@ class TogglePostTagJob extends AbstractPostJob
return $post; return $post;
} }
public function getRequiredSubArguments() public function getRequiredArguments()
{ {
return JobArgs::Conjunction( return JobArgs::Conjunction(
$this->postRetriever->getRequiredArguments(),
JobArgs::Conjunction(
JobArgs::ARG_TAG_NAME, JobArgs::ARG_TAG_NAME,
Jobargs::ARG_NEW_STATE); Jobargs::ARG_NEW_STATE));
} }
public function getRequiredPrivileges() public function getRequiredPrivileges()
{ {
return new Privilege( return new Privilege(
Privilege::EditPostTags, Privilege::EditPostTags,
Access::getIdentity($this->post->getUploader())); Access::getIdentity($this->postRetriever->retrieve()->getUploader()));
} }
} }

View file

@ -1,9 +1,16 @@
<?php <?php
class TogglePostVisibilityJob extends AbstractPostJob class TogglePostVisibilityJob extends AbstractJob
{ {
protected $postRetriever;
public function __construct()
{
$this->postRetriever = new PostRetriever($this);
}
public function execute() public function execute()
{ {
$post = $this->post; $post = $this->postRetriever->retrieve();
$visible = boolval($this->getArgument(JobArgs::ARG_NEW_STATE)); $visible = boolval($this->getArgument(JobArgs::ARG_NEW_STATE));
$post->setHidden(!$visible); $post->setHidden(!$visible);
@ -19,15 +26,17 @@ class TogglePostVisibilityJob extends AbstractPostJob
return $post; return $post;
} }
public function getRequiredSubArguments() public function getRequiredArguments()
{ {
return JobArgs::ARG_NEW_STATE; return JobArgs::Conjunction(
$this->postRetriever->getRequiredArguments(),
JobArgs::ARG_NEW_STATE);
} }
public function getRequiredPrivileges() public function getRequiredPrivileges()
{ {
return new Privilege( return new Privilege(
Privilege::HidePost, Privilege::HidePost,
Access::getIdentity($this->post->getUploader())); Access::getIdentity($this->postRetriever->retrieve()->getUploader()));
} }
} }

View file

@ -1,10 +1,23 @@
<?php <?php
class ListRelatedTagsJob extends ListTagsJob class ListRelatedTagsJob extends AbstractJob implements IPagedJob
{ {
protected $pager;
public function __construct()
{
$this->pager = new JobPager($this);
$this->pager->setPageSize(getConfig()->browsing->tagsRelated);
}
public function getPager()
{
return $this->pager;
}
public function execute() public function execute()
{ {
$pageSize = $this->getPageSize(); $pageSize = $this->pager->getPageSize();
$page = $this->getArgument(JobArgs::ARG_PAGE_NUMBER); $page = $this->pager->getPageNumber();
$tag = $this->getArgument(JobArgs::ARG_TAG_NAME); $tag = $this->getArgument(JobArgs::ARG_TAG_NAME);
$otherTags = $this->hasArgument(JobArgs::ARG_TAG_NAMES) ? $this->getArgument(JobArgs::ARG_TAG_NAMES) : []; $otherTags = $this->hasArgument(JobArgs::ARG_TAG_NAMES) ? $this->getArgument(JobArgs::ARG_TAG_NAMES) : [];
@ -13,19 +26,19 @@ class ListRelatedTagsJob extends ListTagsJob
$tags = array_filter($tags, function($tag) use ($otherTags) { return !in_array($tag->getName(), $otherTags); }); $tags = array_filter($tags, function($tag) use ($otherTags) { return !in_array($tag->getName(), $otherTags); });
$tags = array_slice($tags, 0, $pageSize); $tags = array_slice($tags, 0, $pageSize);
return $this->getPager($tags, $tagCount, $page, $pageSize); return $this->pager->serialize($tags, $tagCount);
}
public function getDefaultPageSize()
{
return intval(getConfig()->browsing->tagsRelated);
} }
public function getRequiredArguments() public function getRequiredArguments()
{ {
return JobArgs::Conjunction( return JobArgs::Conjunction(
parent::getRequiredArguments(), $this->pager->getRequiredArguments(),
Jobargs::ARG_TAG_NAME, Jobargs::ARG_TAG_NAME,
JobArgs::Optional(JobArgs::ARG_TAG_NAMES)); JobArgs::Optional(JobArgs::ARG_TAG_NAMES));
} }
public function getRequiredPrivileges()
{
return new Privilege(Privilege::ListTags);
}
} }

View file

@ -0,0 +1,40 @@
<?php
class ListTagsJob extends AbstractJob implements IPagedJob
{
protected $pager;
public function __construct()
{
$this->pager = new JobPager($this);
$this->pager->setPageSize(getConfig()->browsing->tagsPerPage);
}
public function getPager()
{
return $this->pager;
}
public function execute()
{
$pageSize = $this->pager->getPageSize();
$page = $this->pager->getPageNumber();
$query = $this->getArgument(JobArgs::ARG_QUERY);
$tags = TagSearchService::getEntities($query, $pageSize, $page);
$tagCount = TagSearchService::getEntityCount($query);
return $this->pager->serialize($tags, $tagCount);
}
public function getRequiredArguments()
{
return JobArgs::Conjunction(
$this->pager->getRequiredArguments(),
JobArgs::ARG_QUERY);
}
public function getRequiredPrivileges()
{
return new Privilege(Privilege::ListTags);
}
}

View file

@ -1,30 +0,0 @@
<?php
abstract class AbstractUserJob extends AbstractJob
{
protected $user;
public function prepare()
{
if ($this->hasArgument(JobArgs::ARG_USER_ENTITY))
{
$this->user = $this->getArgument(JobArgs::ARG_USER_ENTITY);
}
else
{
$userName = $this->getArgument(JobArgs::ARG_USER_NAME);
$this->user = UserModel::getByNameOrEmail($userName);
}
}
public function getRequiredArguments()
{
return JobArgs::Conjunction(
JobArgs::Alternative(
JobArgs::ARG_USER_NAME,
JobArgs::ARG_USER_EMAIL,
JobArgs::ARG_USER_ENTITY),
$this->getRequiredSubArguments());
}
public abstract function getRequiredSubArguments();
}

View file

@ -1,9 +1,16 @@
<?php <?php
class AcceptUserRegistrationJob extends AbstractUserJob class AcceptUserRegistrationJob extends AbstractJob
{ {
protected $userRetriever;
public function __construct()
{
$this->userRetriever = new UserRetriever($this);
}
public function execute() public function execute()
{ {
$user = $this->user; $user = $this->userRetriever->getRequiredArguments();
$user->setStaffConfirmed(true); $user->setStaffConfirmed(true);
UserModel::save($user); UserModel::save($user);
@ -13,9 +20,9 @@ class AcceptUserRegistrationJob extends AbstractUserJob
'subject' => TextHelper::reprUser($user)]); 'subject' => TextHelper::reprUser($user)]);
} }
public function getRequiredSubArguments() public function getRequiredArguments()
{ {
return null; return $this->userRetriever->getRequiredArguments();
} }
public function getRequiredPrivileges() public function getRequiredPrivileges()

View file

@ -1,16 +1,18 @@
<?php <?php
class ActivateUserEmailJob extends AbstractJob class ActivateUserEmailJob extends AbstractJob
{ {
protected $userRetriever;
public function __construct()
{
$this->userRetriever = new UserRetriever($this);
}
public function execute() public function execute()
{ {
if (!$this->hasArgument(JobArgs::ARG_TOKEN)) if (!$this->hasArgument(JobArgs::ARG_TOKEN))
{ {
if ($this->hasArgument(JobArgs::ARG_USER_ENTITY)) $user = $this->userRetriever->retrieve();
$user = $this->getArgument(JobArgs::ARG_USER_ENTITY);
elseif ($this->hasArgument(JobArgs::ARG_USER_NAME))
$user = UserModel::getByName($this->getArgument(JobArgs::ARG_USER_NAME));
else
$user = UserModel::getByEmail($this->getArgument(JobArgs::ARG_USER_EMAIL));
if (empty($user->getUnconfirmedEmail())) if (empty($user->getUnconfirmedEmail()))
{ {
@ -47,10 +49,7 @@ class ActivateUserEmailJob extends AbstractJob
{ {
return JobArgs::Alternative( return JobArgs::Alternative(
JobArgs::ARG_TOKEN, JobArgs::ARG_TOKEN,
JobArgs::Alternative( $this->userRetriever->getRequiredArguments());
JobArgs::ARG_USER_ENTITY,
JobArgs::ARG_USER_EMAIL,
JobArgs::ARG_USER_NAME));
} }
public static function sendEmail($user) public static function sendEmail($user)

View file

@ -1,9 +1,16 @@
<?php <?php
class DeleteUserJob extends AbstractUserJob class DeleteUserJob extends AbstractJob
{ {
protected $userRetriever;
public function __construct()
{
$this->userRetriever = new UserRetriever($this);
}
public function execute() public function execute()
{ {
$user = $this->user; $user = $this->userRetriever->retrieve();
$name = $user->getName(); $name = $user->getName();
UserModel::remove($user); UserModel::remove($user);
@ -13,15 +20,15 @@ class DeleteUserJob extends AbstractUserJob
'subject' => TextHelper::reprUser($name)]); 'subject' => TextHelper::reprUser($name)]);
} }
public function getRequiredSubArguments() public function getRequiredArguments()
{ {
return null; return $this->userRetriever->getRequiredArguments();
} }
public function getRequiredPrivileges() public function getRequiredPrivileges()
{ {
return new Privilege( return new Privilege(
Privilege::DeleteUser, Privilege::DeleteUser,
Access::getIdentity($this->user)); Access::getIdentity($this->userRetriever->retrieve()));
} }
} }

View file

@ -1,9 +1,16 @@
<?php <?php
class EditUserAccessRankJob extends AbstractUserJob class EditUserAccessRankJob extends AbstractJob
{ {
protected $userRetriever;
public function __construct()
{
$this->userRetriever = new UserRetriever($this);
}
public function execute() public function execute()
{ {
$user = $this->user; $user = $this->userRetriever->retrieve();
$newAccessRank = new AccessRank($this->getArgument(JobArgs::ARG_NEW_ACCESS_RANK)); $newAccessRank = new AccessRank($this->getArgument(JobArgs::ARG_NEW_ACCESS_RANK));
$oldAccessRank = $user->getAccessRank(); $oldAccessRank = $user->getAccessRank();
@ -23,15 +30,17 @@ class EditUserAccessRankJob extends AbstractUserJob
return $user; return $user;
} }
public function getRequiredSubArguments() public function getRequiredArguments()
{ {
return JobArgs::ARG_NEW_ACCESS_RANK; return JobArgs::Conjunction(
$this->userRetriever->getRequiredArguments(),
JobArgs::ARG_NEW_ACCESS_RANK);
} }
public function getRequiredPrivileges() public function getRequiredPrivileges()
{ {
return new Privilege( return new Privilege(
Privilege::ChangeUserAccessRank, Privilege::ChangeUserAccessRank,
Access::getIdentity($this->user)); Access::getIdentity($this->userRetriever->retrieve()));
} }
} }

View file

@ -1,13 +1,20 @@
<?php <?php
class EditUserEmailJob extends AbstractUserJob class EditUserEmailJob extends AbstractJob
{ {
protected $userRetriever;
public function __construct()
{
$this->userRetriever = new UserRetriever($this);
}
public function execute() public function execute()
{ {
if (getConfig()->registration->needEmailForRegistering) if (getConfig()->registration->needEmailForRegistering)
if (!$this->hasArgument(JobArgs::ARG_NEW_EMAIL) or empty($this->getArgument(JobArgs::ARG_NEW_EMAIL))) if (!$this->hasArgument(JobArgs::ARG_NEW_EMAIL) or empty($this->getArgument(JobArgs::ARG_NEW_EMAIL)))
throw new SimpleException('E-mail address is required - you will be sent confirmation e-mail.'); throw new SimpleException('E-mail address is required - you will be sent confirmation e-mail.');
$user = $this->user; $user = $this->userRetriever->retrieve();
$newEmail = $this->getArgument(JobArgs::ARG_NEW_EMAIL); $newEmail = $this->getArgument(JobArgs::ARG_NEW_EMAIL);
$oldEmail = $user->getConfirmedEmail(); $oldEmail = $user->getConfirmedEmail();
@ -44,9 +51,11 @@ class EditUserEmailJob extends AbstractUserJob
} }
} }
public function getRequiredSubArguments() public function getRequiredArguments()
{ {
return JobArgs::ARG_NEW_EMAIL; return JobArgs::Conjunction(
$this->userRetriever->getRequiredArguments(),
JobArgs::ARG_NEW_EMAIL);
} }
public function getRequiredPrivileges() public function getRequiredPrivileges()
@ -55,6 +64,6 @@ class EditUserEmailJob extends AbstractUserJob
$this->getContext() == self::CONTEXT_BATCH_ADD $this->getContext() == self::CONTEXT_BATCH_ADD
? Privilege::RegisterAccount ? Privilege::RegisterAccount
: Privilege::ChangeUserEmail, : Privilege::ChangeUserEmail,
Access::getIdentity($this->user)); Access::getIdentity($this->userRetriever->retrieve()));
} }
} }

View file

@ -1,10 +1,12 @@
<?php <?php
class EditUserJob extends AbstractUserJob class EditUserJob extends AbstractJob
{ {
protected $userRetriever;
protected $subJobs; protected $subJobs;
public function __construct() public function __construct()
{ {
$this->userRetriever = new UserRetriever($this);
$this->subJobs = $this->subJobs =
[ [
new EditUserAccessRankJob(), new EditUserAccessRankJob(),
@ -34,7 +36,7 @@ class EditUserJob extends AbstractUserJob
public function execute() public function execute()
{ {
$user = $this->user; $user = $this->userRetriever->retrieve();
Logger::bufferChanges(); Logger::bufferChanges();
@ -65,9 +67,9 @@ class EditUserJob extends AbstractUserJob
return $user; return $user;
} }
public function getRequiredSubArguments() public function getRequiredArguments()
{ {
return null; return $this->userRetriever->getRequiredArguments();
} }
public function getRequiredPrivileges() public function getRequiredPrivileges()

View file

@ -1,9 +1,16 @@
<?php <?php
class EditUserNameJob extends AbstractUserJob class EditUserNameJob extends AbstractJob
{ {
protected $userRetriever;
public function __construct()
{
$this->userRetriever = new UserRetriever($this);
}
public function execute() public function execute()
{ {
$user = $this->user; $user = $this->userRetriever->retrieve();
$newName = $this->getArgument(JobArgs::ARG_NEW_USER_NAME); $newName = $this->getArgument(JobArgs::ARG_NEW_USER_NAME);
$oldName = $user->getName(); $oldName = $user->getName();
@ -23,9 +30,11 @@ class EditUserNameJob extends AbstractUserJob
return $user; return $user;
} }
public function getRequiredSubArguments() public function getRequiredArguments()
{ {
return JobArgs::ARG_NEW_USER_NAME; return JobArgs::Conjunction(
$this->userRetriever->getRequiredArguments(),
JobArgs::ARG_NEW_USER_NAME);
} }
public function getRequiredPrivileges() public function getRequiredPrivileges()
@ -34,6 +43,6 @@ class EditUserNameJob extends AbstractUserJob
$this->getContext() == self::CONTEXT_BATCH_ADD $this->getContext() == self::CONTEXT_BATCH_ADD
? Privilege::RegisterAccount ? Privilege::RegisterAccount
: Privilege::ChangeUserName, : Privilege::ChangeUserName,
Access::getIdentity($this->user)); Access::getIdentity($this->userRetriever->retrieve()));
} }
} }

View file

@ -1,9 +1,16 @@
<?php <?php
class EditUserPasswordJob extends AbstractUserJob class EditUserPasswordJob extends AbstractJob
{ {
protected $userRetriever;
public function __construct()
{
$this->userRetriever = new UserRetriever($this);
}
public function execute() public function execute()
{ {
$user = $this->user; $user = $this->userRetriever->retrieve();
$newPassword = $this->getArgument(JobArgs::ARG_NEW_PASSWORD); $newPassword = $this->getArgument(JobArgs::ARG_NEW_PASSWORD);
$oldPasswordHash = $user->getPasswordHash(); $oldPasswordHash = $user->getPasswordHash();
@ -22,9 +29,11 @@ class EditUserPasswordJob extends AbstractUserJob
return $user; return $user;
} }
public function getRequiredSubArguments() public function getRequiredArguments()
{ {
return JobArgs::ARG_NEW_PASSWORD; return JobArgs::Conjunction(
$this->userRetriever->getRequiredArguments(),
JobArgs::ARG_NEW_PASSWORD);
} }
public function getRequiredPrivileges() public function getRequiredPrivileges()
@ -33,6 +42,6 @@ class EditUserPasswordJob extends AbstractUserJob
$this->getContext() == self::CONTEXT_BATCH_ADD $this->getContext() == self::CONTEXT_BATCH_ADD
? Privilege::RegisterAccount ? Privilege::RegisterAccount
: Privilege::ChangeUserPassword, : Privilege::ChangeUserPassword,
Access::getIdentity($this->user)); Access::getIdentity($this->userRetriever->retrieve()));
} }
} }

View file

@ -1,9 +1,16 @@
<?php <?php
class FlagUserJob extends AbstractUserJob class FlagUserJob extends AbstractJob
{ {
protected $userRetriever;
public function __construct()
{
$this->userRetriever = new UserRetriever($this);
}
public function execute() public function execute()
{ {
$user = $this->user; $user = $this->userRetriever->retrieve();
$key = TextHelper::reprUser($user); $key = TextHelper::reprUser($user);
$flagged = SessionHelper::get('flagged', []); $flagged = SessionHelper::get('flagged', []);
@ -19,15 +26,15 @@ class FlagUserJob extends AbstractUserJob
return $user; return $user;
} }
public function getRequiredSubArguments() public function getRequiredArguments()
{ {
return null; return $this->userRetriever->getRequiredArguments();
} }
public function getRequiredPrivileges() public function getRequiredPrivileges()
{ {
return new Privilege( return new Privilege(
Privilege::FlagUser, Privilege::FlagUser,
Access::getIdentity($this->user)); Access::getIdentity($this->userRetriever->retrieve()));
} }
} }

View file

@ -1,20 +1,27 @@
<?php <?php
class GetUserJob extends AbstractUserJob class GetUserJob extends AbstractJob
{ {
public function execute() protected $userRetriever;
public function __construct()
{ {
return $this->user; $this->userRetriever = new UserRetriever($this);
} }
public function getRequiredSubArguments() public function execute()
{ {
return null; return $this->userRetriever->retrieve();
}
public function getRequiredArguments()
{
return $this->userRetriever->getRequiredArguments();
} }
public function getRequiredPrivileges() public function getRequiredPrivileges()
{ {
return new Privilege( return new Privilege(
Privilege::ViewUser, Privilege::ViewUser,
Access::getIdentity($this->user)); Access::getIdentity($this->userRetriever->retrieve()));
} }
} }

View file

@ -0,0 +1,40 @@
<?php
class ListUsersJob extends AbstractJob implements IPagedJob
{
protected $pager;
public function __construct()
{
$this->pager = new JobPager($this);
$this->pager->setPageSize(getConfig()->browsing->usersPerPage);
}
public function getPager()
{
return $this->pager;
}
public function execute()
{
$pageSize = $this->pager->getPageSize();
$page = $this->pager->getPageNumber();
$filter = $this->getArgument(JobArgs::ARG_QUERY);
$users = UserSearchService::getEntities($filter, $pageSize, $page);
$userCount = UserSearchService::getEntityCount($filter);
return $this->pager->serialize($users, $userCount);
}
public function getRequiredArguments()
{
return JobArgs::Conjunction(
$this->pager->getRequiredArguments(),
JobArgs::ARG_QUERY);
}
public function getRequiredPrivileges()
{
return new Privilege(Privilege::ListUsers);
}
}

View file

@ -1,16 +1,18 @@
<?php <?php
class PasswordResetJob extends AbstractJob class PasswordResetJob extends AbstractJob
{ {
protected $userRetriever;
public function __construct()
{
$this->userRetriever = new UserRetriever($this);
}
public function execute() public function execute()
{ {
if (!$this->hasArgument(JobArgs::ARG_TOKEN)) if (!$this->hasArgument(JobArgs::ARG_TOKEN))
{ {
if ($this->hasArgument(JobArgs::ARG_USER_NAME)) $user = $this->userRetriever->retrieve();
$user = UserModel::getByNameOrEmail($this->getArgument(JobArgs::ARG_USER_NAME));
elseif ($this->hasArgument(JobArgs::ARG_USER_EMAIL))
$user = UserModel::getByNameOrEmail($this->getArgument(JobArgs::ARG_USER_EMAIL));
else
$user = $this->getArgument(JobArgs::ARG_USER_ENTITTY);
if (empty($user->getConfirmedEmail())) if (empty($user->getConfirmedEmail()))
throw new SimpleException('This user has no e-mail confirmed; password reset cannot proceed'); throw new SimpleException('This user has no e-mail confirmed; password reset cannot proceed');
@ -50,9 +52,7 @@ class PasswordResetJob extends AbstractJob
public function getRequiredArguments() public function getRequiredArguments()
{ {
return JobArgs::Alternative( return JobArgs::Alternative(
JobArgs::ARG_USER_NAME, $this->userRetriever->getRequiredArguments(),
JobArgs::ARG_USER_EMAIL,
JobArgs::ARG_USER_ENTITY,
JobArgs::ARG_TOKEN); JobArgs::ARG_TOKEN);
} }

View file

@ -1,9 +1,16 @@
<?php <?php
class ToggleUserBanJob extends AbstractUserJob class ToggleUserBanJob extends AbstractJob
{ {
protected $userRetriever;
public function __construct()
{
$this->userRetriever = new UserRetriever($this);
}
public function execute() public function execute()
{ {
$user = $this->user; $user = $this->userRetriever->retrieve();
$banned = boolval($this->getArgument(JobArgs::ARG_NEW_STATE)); $banned = boolval($this->getArgument(JobArgs::ARG_NEW_STATE));
if ($banned) if ($banned)
@ -22,15 +29,17 @@ class ToggleUserBanJob extends AbstractUserJob
return $user; return $user;
} }
public function getRequiredSubArguments() public function getRequiredArguments()
{ {
return JobArgs::ARG_NEW_STATE; return JobArgs::Conjunction(
$this->userRetriever->getRequiredArguments(),
JobArgs::ARG_NEW_STATE);
} }
public function getRequiredPrivileges() public function getRequiredPrivileges()
{ {
return new Privilege( return new Privilege(
Privilege::BanUser, Privilege::BanUser,
Access::getIdentity($this->user)); Access::getIdentity($this->userRetriever->retrieve()));
} }
} }

View file

@ -44,9 +44,7 @@ class ApiArgumentTest extends AbstractFullApiTest
public function testDeleteCommentJob() public function testDeleteCommentJob()
{ {
$this->testArguments(new DeleteCommentJob(), $this->testArguments(new DeleteCommentJob(),
JobArgs::Alternative( $this->getCommentSelector());
JobArgs::ARG_COMMENT_ENTITY,
JobArgs::ARG_COMMENT_ID));
} }
public function testDeleteUserJob() public function testDeleteUserJob()
@ -60,9 +58,7 @@ class ApiArgumentTest extends AbstractFullApiTest
$this->testArguments(new EditCommentJob(), $this->testArguments(new EditCommentJob(),
JobArgs::Conjunction( JobArgs::Conjunction(
JobArgs::ARG_NEW_TEXT, JobArgs::ARG_NEW_TEXT,
JobArgs::Alternative( $this->getCommentSelector()));
JobArgs::ARG_COMMENT_ENTITY,
JobArgs::ARG_COMMENT_ID)));
} }
public function testEditPostContentJob() public function testEditPostContentJob()
@ -185,7 +181,7 @@ class ApiArgumentTest extends AbstractFullApiTest
JobArgs::Conjunction( JobArgs::Conjunction(
JobArgs::ARG_QUERY, JobArgs::ARG_QUERY,
JobArgs::ARG_LOG_ID, JobArgs::ARG_LOG_ID,
JobArgs::ARG_PAGE_NUMBER)); JobArgs::Optional(JobArgs::ARG_PAGE_NUMBER)));
} }
public function testGetPostContentJob() public function testGetPostContentJob()
@ -218,7 +214,7 @@ class ApiArgumentTest extends AbstractFullApiTest
public function testListCommentsJob() public function testListCommentsJob()
{ {
$this->testArguments(new ListCommentsJob(), $this->testArguments(new ListCommentsJob(),
JobArgs::ARG_PAGE_NUMBER); JobArgs::Optional(JobArgs::ARG_PAGE_NUMBER));
} }
public function testListLogsJob() public function testListLogsJob()
@ -232,7 +228,7 @@ class ApiArgumentTest extends AbstractFullApiTest
$this->testArguments(new ListPostsJob(), $this->testArguments(new ListPostsJob(),
JobArgs::Conjunction( JobArgs::Conjunction(
JobArgs::ARG_QUERY, JobArgs::ARG_QUERY,
JobArgs::ARG_PAGE_NUMBER)); JobArgs::Optional(JobArgs::ARG_PAGE_NUMBER)));
} }
public function testListRelatedTagsJob() public function testListRelatedTagsJob()
@ -241,8 +237,7 @@ class ApiArgumentTest extends AbstractFullApiTest
JobArgs::Conjunction( JobArgs::Conjunction(
JobArgs::Optional(JobArgs::ARG_TAG_NAMES), JobArgs::Optional(JobArgs::ARG_TAG_NAMES),
JobArgs::ARG_TAG_NAME, JobArgs::ARG_TAG_NAME,
JobArgs::ARG_QUERY, JobArgs::Optional(JobArgs::ARG_PAGE_NUMBER)));
JobArgs::ARG_PAGE_NUMBER));
} }
public function testListTagsJob() public function testListTagsJob()
@ -250,7 +245,7 @@ class ApiArgumentTest extends AbstractFullApiTest
$this->testArguments(new ListTagsJob(), $this->testArguments(new ListTagsJob(),
JobArgs::Conjunction( JobArgs::Conjunction(
JobArgs::ARG_QUERY, JobArgs::ARG_QUERY,
JobArgs::ARG_PAGE_NUMBER)); JobArgs::Optional(JobArgs::ARG_PAGE_NUMBER)));
} }
public function testListUsersJob() public function testListUsersJob()
@ -258,7 +253,7 @@ class ApiArgumentTest extends AbstractFullApiTest
$this->testArguments(new ListUsersJob(), $this->testArguments(new ListUsersJob(),
JobArgs::Conjunction( JobArgs::Conjunction(
JobArgs::ARG_QUERY, JobArgs::ARG_QUERY,
JobArgs::ARG_PAGE_NUMBER)); JobArgs::Optional(JobArgs::ARG_PAGE_NUMBER)));
} }
public function testMergeTagsJob() public function testMergeTagsJob()
@ -290,8 +285,8 @@ class ApiArgumentTest extends AbstractFullApiTest
$this->testArguments(new PreviewCommentJob(), $this->testArguments(new PreviewCommentJob(),
JobArgs::Conjunction( JobArgs::Conjunction(
JobArgs::Alternative( JobArgs::Alternative(
JobArgs::ARG_POST_ID, $this->getPostSelector(),
JobArgs::ARG_COMMENT_ID), $this->getCommentSelector()),
JobArgs::ARG_NEW_TEXT)); JobArgs::ARG_NEW_TEXT));
} }
@ -357,6 +352,13 @@ class ApiArgumentTest extends AbstractFullApiTest
JobArgs::ARG_POST_ENTITY); JobArgs::ARG_POST_ENTITY);
} }
protected function getCommentSelector()
{
return JobArgs::Alternative(
JobArgs::ARG_COMMENT_ENTITY,
JobArgs::ARG_COMMENT_ID);
}
protected function getUserSelector() protected function getUserSelector()
{ {
return JobArgs::Alternative( return JobArgs::Alternative(