2 namespace wcf\data\moderation\queue
;
3 use wcf\data\
object\type\ObjectTypeCache
;
4 use wcf\data\user\User
;
5 use wcf\data\AbstractDatabaseObjectAction
;
6 use wcf\system\database\util\PreparedStatementConditionBuilder
;
7 use wcf\system\exception\PermissionDeniedException
;
8 use wcf\system\exception\UserInputException
;
9 use wcf\system\moderation\queue\ModerationQueueManager
;
10 use wcf\system\request\LinkHandler
;
11 use wcf\system\user\storage\UserStorageHandler
;
12 use wcf\system\visitTracker\VisitTracker
;
16 * Executes moderation queue-related actions.
18 * @author Alexander Ebert
19 * @copyright 2001-2019 WoltLab GmbH
20 * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
21 * @package WoltLabSuite\Core\Data\Moderation\Queue
23 * @method ModerationQueueEditor[] getObjects()
24 * @method ModerationQueueEditor getSingleObject()
26 class ModerationQueueAction
extends AbstractDatabaseObjectAction
{
30 protected $className = ModerationQueueEditor
::class;
33 * moderation queue editor object
34 * @var ModerationQueueEditor
36 public $moderationQueueEditor = null;
46 * @return ModerationQueue
48 public function create() {
49 if (!isset($this->parameters
['data']['lastChangeTime'])) {
50 $this->parameters
['data']['lastChangeTime'] = TIME_NOW
;
53 /** @noinspection PhpIncompatibleReturnTypeInspection */
54 return parent
::create();
60 public function update() {
61 if (!isset($this->parameters
['data']['lastChangeTime'])) {
62 $this->parameters
['data']['lastChangeTime'] = TIME_NOW
;
69 * Marks a list of objects as done.
71 public function markAsDone() {
72 if (empty($this->objects
)) {
77 foreach ($this->getObjects() as $queue) {
78 $queueIDs[] = $queue->queueID
;
81 $conditions = new PreparedStatementConditionBuilder();
82 $conditions->add("queueID IN (?)", [$queueIDs]);
84 $sql = "UPDATE wcf".WCF_N
."_moderation_queue
85 SET status = ".ModerationQueue
::STATUS_DONE
."
87 $statement = WCF
::getDB()->prepareStatement($sql);
88 $statement->execute($conditions->getParameters());
90 // reset number of active moderation queue items
91 ModerationQueueManager
::getInstance()->resetModerationCount();
95 * Validates parameters to fetch a list of outstanding queues.
97 public function validateGetOutstandingQueues() {
98 WCF
::getSession()->checkPermissions(['mod.general.canUseModeration']);
102 * Returns a list of outstanding queues.
106 public function getOutstandingQueues() {
107 // Maximum cardinality of the returned array
108 static $MAX_ITEMS = 10;
110 $conditions = new PreparedStatementConditionBuilder();
111 $conditions->add("moderation_queue_to_user.userID = ?", [WCF
::getUser()->userID
]);
112 $conditions->add("moderation_queue_to_user.isAffected = ?", [1]);
113 $conditions->add("moderation_queue.status IN (?)", [[ModerationQueue
::STATUS_OUTSTANDING
, ModerationQueue
::STATUS_PROCESSING
]]);
114 $conditions->add("moderation_queue.time > ?", [VisitTracker
::getInstance()->getVisitTime('com.woltlab.wcf.moderation.queue')]);
115 $conditions->add("(moderation_queue.time > tracked_visit.visitTime OR tracked_visit.visitTime IS NULL)");
117 $sql = "SELECT moderation_queue.queueID
118 FROM wcf".WCF_N
."_moderation_queue_to_user moderation_queue_to_user
119 LEFT JOIN wcf".WCF_N
."_moderation_queue moderation_queue
120 ON (moderation_queue.queueID = moderation_queue_to_user.queueID)
121 LEFT JOIN wcf".WCF_N
."_tracked_visit tracked_visit
122 ON (tracked_visit.objectTypeID = ".VisitTracker
::getInstance()->getObjectTypeID('com.woltlab.wcf.moderation.queue')." AND tracked_visit.objectID = moderation_queue.queueID AND tracked_visit.userID = ".WCF
::getUser()->userID
.")
124 ORDER BY moderation_queue.lastChangeTime DESC";
125 $statement = WCF
::getDB()->prepareStatement($sql, $MAX_ITEMS);
126 $statement->execute($conditions->getParameters());
127 $queueIDs = $statement->fetchAll(\PDO
::FETCH_COLUMN
);
130 if (!empty($queueIDs)) {
131 $queueList = new ViewableModerationQueueList();
132 $queueList->getConditionBuilder()->add("moderation_queue.queueID IN (?)", [$queueIDs]);
133 $queueList->sqlOrderBy
= "moderation_queue.lastChangeTime DESC";
134 $queueList->readObjects();
135 foreach ($queueList as $queue) {
140 // check if user storage is outdated
141 $totalCount = ModerationQueueManager
::getInstance()->getUnreadModerationCount();
142 $count = count($queues);
143 if ($count < $MAX_ITEMS) {
144 // load more entries to fill up list
145 $queueList = new ViewableModerationQueueList();
146 $queueList->getConditionBuilder()->add("moderation_queue.status IN (?)", [[ModerationQueue
::STATUS_OUTSTANDING
, ModerationQueue
::STATUS_PROCESSING
]]);
147 if (!empty($queueIDs)) $queueList->getConditionBuilder()->add("moderation_queue.queueID NOT IN (?)", [$queueIDs]);
148 $queueList->sqlOrderBy
= "moderation_queue.lastChangeTime DESC";
149 $queueList->sqlLimit
= $MAX_ITEMS - $count;
150 $queueList->readObjects();
151 foreach ($queueList as $queue) {
155 // check if stored count is out of sync
156 if ($count < $totalCount) {
157 UserStorageHandler
::getInstance()->reset([WCF
::getUser()->userID
], 'outstandingModerationCount');
159 // check for orphaned queues
160 $queueCount = ModerationQueueManager
::getInstance()->getUnreadModerationCount();
161 if (count($queues) < $queueCount) {
162 ModerationQueueManager
::getInstance()->identifyOrphans();
167 WCF
::getTPL()->assign([
172 'template' => WCF
::getTPL()->fetch('moderationQueueList'),
173 'totalCount' => $totalCount
178 * Validates parameters to show the user assign form.
180 public function validateGetAssignUserForm() {
181 $this->moderationQueueEditor
= $this->getSingleObject();
183 // check if queue is accessible for current user
184 if (!$this->moderationQueueEditor
->canEdit()) {
185 throw new PermissionDeniedException();
190 * Returns the user assign form.
194 public function getAssignUserForm() {
195 $assignedUser = $this->moderationQueueEditor
->assignedUserID ?
new User($this->moderationQueueEditor
->assignedUserID
) : null;
197 WCF
::getTPL()->assign([
198 'assignedUser' => $assignedUser,
199 'queue' => $this->moderationQueueEditor
203 'template' => WCF
::getTPL()->fetch('moderationQueueAssignUser')
208 * Validates parameters to assign a user.
210 public function validateAssignUser() {
211 // To assign a user we need to be able to fetch the assignment form.
212 $this->validateGetAssignUserForm();
214 $this->readInteger('assignedUserID', true);
216 if ($this->parameters
['assignedUserID'] && $this->parameters
['assignedUserID'] != -1) {
217 if ($this->parameters
['assignedUserID'] != WCF
::getUser()->userID
&& $this->parameters
['assignedUserID'] != $this->moderationQueueEditor
->assignedUserID
) {
218 // user id is either faked or changed during viewing, use database value instead
219 $this->parameters
['assignedUserID'] = $this->moderationQueueEditor
->assignedUserID
;
223 if ($this->parameters
['assignedUserID'] == -1) {
224 $this->readString('assignedUsername');
226 $this->user
= User
::getUserByUsername($this->parameters
['assignedUsername']);
227 if (!$this->user
->userID
) {
228 throw new UserInputException('assignedUsername', 'notFound');
232 $objectType = ObjectTypeCache
::getInstance()->getObjectType($this->moderationQueueEditor
->objectTypeID
);
233 if (!$objectType->getProcessor()->isAffectedUser($this->moderationQueueEditor
->getDecoratedObject(), $this->user
->userID
)) {
234 throw new UserInputException('assignedUsername', 'notAffected');
237 $this->parameters
['assignedUserID'] = $this->user
->userID
;
238 $this->parameters
['assignedUsername'] = '';
241 $this->user
= new User($this->parameters
['assignedUserID']);
246 * Returns the data for the newly assigned user.
250 public function assignUser() {
251 $data = ['assignedUserID' => $this->parameters
['assignedUserID'] ?
: null];
252 if ($this->user
->userID
) {
253 if ($this->moderationQueueEditor
->status
== ModerationQueue
::STATUS_OUTSTANDING
) {
254 $data['status'] = ModerationQueue
::STATUS_PROCESSING
;
258 if ($this->moderationQueueEditor
->status
== ModerationQueue
::STATUS_PROCESSING
) {
259 $data['status'] = ModerationQueue
::STATUS_OUTSTANDING
;
263 $this->moderationQueueEditor
->update($data);
265 $username = $this->user
->userID ?
$this->user
->username
: WCF
::getLanguage()->get('wcf.moderation.assignedUser.nobody');
267 if ($this->user
->userID
) {
268 $link = LinkHandler
::getInstance()->getLink('User', ['object' => $this->user
]);
272 if (isset($data['status'])) {
273 $newStatus = ($data['status'] == ModerationQueue
::STATUS_OUTSTANDING
) ?
'outstanding' : 'processing';
278 'newStatus' => $newStatus,
279 'userID' => $this->user
->userID
,
280 'username' => $username
285 * Marks queue entries as read.
287 public function markAsRead() {
288 if (empty($this->parameters
['visitTime'])) {
289 $this->parameters
['visitTime'] = TIME_NOW
;
292 if (empty($this->objects
)) {
293 $this->readObjects();
296 foreach ($this->getObjects() as $queue) {
297 VisitTracker
::getInstance()->trackObjectVisit('com.woltlab.wcf.moderation.queue', $queue->queueID
, $this->parameters
['visitTime']);
301 UserStorageHandler
::getInstance()->reset([WCF
::getUser()->userID
], 'unreadModerationCount');
303 if (count($this->objects
) == 1) {
304 $queue = reset($this->objects
);
307 'markAsRead' => $queue->queueID
,
308 'totalCount' => ModerationQueueManager
::getInstance()->getUnreadModerationCount(true)
316 public function validateMarkAsRead() {
317 if (empty($this->objects
)) {
318 $this->readObjects();
321 foreach ($this->getObjects() as $queue) {
322 if (!$queue->canEdit()) {
323 throw new PermissionDeniedException();
329 * Marks all queue entries as read.
331 public function markAllAsRead() {
332 VisitTracker
::getInstance()->trackTypeVisit('com.woltlab.wcf.moderation.queue');
335 UserStorageHandler
::getInstance()->reset([WCF
::getUser()->userID
], 'unreadModerationCount');
338 'markAllAsRead' => true
343 * Validates the mark all as read action.
345 public function validateMarkAllAsRead() {