Commit | Line | Data |
---|---|---|
fc69b61d | 1 | <?php |
a9229942 | 2 | |
fc69b61d | 3 | namespace wcf\system\moderation\queue; |
a9229942 | 4 | |
71b3faba MS |
5 | use wcf\data\moderation\queue\ModerationQueue; |
6 | use wcf\data\moderation\queue\ModerationQueueAction; | |
fc69b61d | 7 | use wcf\data\moderation\queue\ViewableModerationQueue; |
4493238c C |
8 | use wcf\data\object\type\ObjectTypeCache; |
9 | use wcf\system\cache\builder\UserGroupOptionCacheBuilder; | |
10 | use wcf\system\cache\runtime\UserProfileRuntimeCache; | |
79bbb75a | 11 | use wcf\system\exception\InvalidObjectTypeException; |
fc69b61d | 12 | use wcf\system\request\LinkHandler; |
ae0d522c | 13 | use wcf\system\user\notification\object\ModerationQueueUserNotificationObject; |
4493238c | 14 | use wcf\system\user\notification\object\type\TMultiRecipientModerationQueueCommentUserNotificationObjectType; |
ae0d522c | 15 | use wcf\system\user\notification\UserNotificationHandler; |
fc69b61d MW |
16 | use wcf\system\WCF; |
17 | ||
18 | /** | |
19 | * Moderation queue implementation for reports. | |
a9229942 TD |
20 | * |
21 | * @author Alexander Ebert | |
22 | * @copyright 2001-2019 WoltLab GmbH | |
23 | * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php> | |
fc69b61d | 24 | */ |
a9229942 TD |
25 | class ModerationQueueReportManager extends AbstractModerationQueueManager |
26 | { | |
27 | /** | |
28 | * @inheritDoc | |
29 | */ | |
30 | protected $definitionName = 'com.woltlab.wcf.moderation.report'; | |
31 | ||
32 | /** | |
33 | * Returns true if given item was already reported. | |
34 | * | |
35 | * @param string $objectType | |
36 | * @param int $objectID | |
37 | * @return bool | |
38 | */ | |
39 | public function isAlreadyReported($objectType, $objectID) | |
40 | { | |
41 | $objectTypeID = $this->getObjectTypeID($objectType); | |
42 | ||
43 | $sql = "SELECT COUNT(*) | |
44 | FROM wcf" . WCF_N . "_moderation_queue | |
45 | WHERE objectTypeID = ? | |
46 | AND objectID = ?"; | |
47 | $statement = WCF::getDB()->prepareStatement($sql); | |
48 | $statement->execute([ | |
49 | $objectTypeID, | |
50 | $objectID, | |
51 | ]); | |
52 | ||
53 | return $statement->fetchSingleColumn() > 0; | |
54 | } | |
55 | ||
56 | /** | |
57 | * Returns true if the object with the given data has a pending report. | |
58 | * A pending report has a status other than done. | |
59 | * | |
60 | * @param string $objectType | |
61 | * @param int $objectID | |
62 | * @return bool | |
63 | */ | |
64 | public function hasPendingReport($objectType, $objectID) | |
65 | { | |
66 | $objectTypeID = $this->getObjectTypeID($objectType); | |
67 | ||
68 | $sql = "SELECT COUNT(*) | |
69 | FROM wcf" . WCF_N . "_moderation_queue | |
70 | WHERE objectTypeID = ? | |
71 | AND objectID = ? | |
72 | AND status IN (?, ?)"; | |
73 | $statement = WCF::getDB()->prepareStatement($sql); | |
74 | $statement->execute([ | |
75 | $objectTypeID, | |
76 | $objectID, | |
77 | ModerationQueue::STATUS_OUTSTANDING, | |
78 | ModerationQueue::STATUS_PROCESSING, | |
79 | ]); | |
80 | ||
81 | return $statement->fetchSingleColumn() > 0; | |
82 | } | |
83 | ||
84 | /** | |
85 | * Returns true if current user can report given content. | |
86 | * | |
87 | * @param string $objectType | |
88 | * @param int $objectID | |
89 | * @return bool | |
90 | */ | |
91 | public function canReport($objectType, $objectID) | |
92 | { | |
93 | return $this->getProcessor($objectType)->canReport($objectID); | |
94 | } | |
95 | ||
96 | /** | |
97 | * @inheritDoc | |
98 | */ | |
99 | public function getLink($queueID) | |
100 | { | |
101 | return LinkHandler::getInstance()->getLink('ModerationReport', [ | |
102 | 'id' => $queueID, | |
103 | 'forceFrontend' => true, | |
104 | ]); | |
105 | } | |
106 | ||
107 | /** | |
108 | * Returns rendered template for reported content. | |
109 | * | |
110 | * @param ViewableModerationQueue $queue | |
111 | * @return string | |
112 | */ | |
113 | public function getReportedContent(ViewableModerationQueue $queue) | |
114 | { | |
115 | return $this->getProcessor(null, $queue->objectTypeID)->getReportedContent($queue); | |
116 | } | |
117 | ||
118 | /** | |
119 | * Returns the reported object. | |
120 | * | |
121 | * @param string $objectType | |
122 | * @param int $objectID | |
123 | * @return \wcf\data\IUserContent | |
124 | */ | |
125 | public function getReportedObject($objectType, $objectID) | |
126 | { | |
127 | return $this->getProcessor($objectType)->getReportedObject($objectID); | |
128 | } | |
129 | ||
130 | /** | |
131 | * Adds a report for specified content. | |
132 | * | |
133 | * @param string $objectType | |
134 | * @param int $objectID | |
135 | * @param string $message | |
136 | * @param array $additionalData | |
137 | * @throws InvalidObjectTypeException | |
138 | */ | |
139 | public function addReport($objectType, $objectID, $message, array $additionalData = []) | |
140 | { | |
141 | if (!$this->isValid($objectType)) { | |
142 | throw new InvalidObjectTypeException($objectType, 'com.woltlab.wcf.moderation.report'); | |
143 | } | |
144 | ||
145 | $additionalData['message'] = $message; | |
146 | $this->addEntry( | |
147 | $this->getObjectTypeID($objectType), | |
148 | $objectID, | |
149 | $this->getProcessor($objectType)->getContainerID($objectID), | |
150 | $additionalData | |
151 | ); | |
152 | } | |
153 | ||
154 | /** | |
155 | * @inheritDoc | |
156 | */ | |
157 | protected function addEntry($objectTypeID, $objectID, $containerID = 0, array $additionalData = []) | |
158 | { | |
159 | $sql = "SELECT queueID | |
160 | FROM wcf" . WCF_N . "_moderation_queue | |
161 | WHERE objectTypeID = ? | |
162 | AND objectID = ? | |
163 | AND status <> ?"; | |
164 | $statement = WCF::getDB()->prepareStatement($sql); | |
165 | $statement->execute([ | |
166 | $objectTypeID, | |
167 | $objectID, | |
168 | ModerationQueue::STATUS_DONE, | |
169 | ]); | |
170 | $row = $statement->fetchArray(); | |
171 | ||
172 | if ($row === false) { | |
173 | $objectAction = new ModerationQueueAction([], 'create', [ | |
174 | 'data' => [ | |
175 | 'objectTypeID' => $objectTypeID, | |
176 | 'objectID' => $objectID, | |
177 | 'containerID' => $containerID, | |
178 | 'userID' => WCF::getUser()->userID ?: null, | |
179 | 'time' => TIME_NOW, | |
180 | 'additionalData' => \serialize($additionalData), | |
181 | ], | |
182 | ]); | |
183 | $objectAction->executeAction(); | |
4493238c | 184 | $queue = $objectAction->getReturnValues()['returnValues']; |
a9229942 TD |
185 | } else { |
186 | $objectAction = new ModerationQueueAction([$row['queueID']], 'update', [ | |
187 | 'data' => [ | |
188 | 'status' => ModerationQueue::STATUS_OUTSTANDING, | |
189 | 'containerID' => $containerID, | |
190 | 'userID' => WCF::getUser()->userID ?: null, | |
191 | 'time' => TIME_NOW, | |
192 | 'additionalData' => \serialize($additionalData), | |
193 | ], | |
194 | ]); | |
195 | $objectAction->executeAction(); | |
4493238c | 196 | $queue = new ModerationQueue($row['queueID']); |
a9229942 TD |
197 | } |
198 | ||
199 | ModerationQueueManager::getInstance()->resetModerationCount(); | |
4493238c C |
200 | |
201 | $this->notifyModerators($queue); | |
202 | } | |
203 | ||
204 | private function notifyModerators(ModerationQueue $queue): void | |
205 | { | |
206 | /** @see TMultiRecipientModerationQueueCommentUserNotificationObjectType::loadModerators() */ | |
207 | $userGroupOptionCache = UserGroupOptionCacheBuilder::getInstance()->getData(); | |
208 | $canUseModerationOption = $userGroupOptionCache['options']['mod.general.canUseModeration']; | |
209 | ||
210 | $sql = "SELECT DISTINCT userID | |
211 | FROM ( | |
212 | SELECT userID | |
213 | FROM wcf1_user_to_group | |
214 | WHERE groupID IN ( | |
215 | SELECT groupID | |
216 | FROM wcf1_user_group_option_value | |
217 | WHERE optionID = ? | |
218 | AND optionValue = ? | |
219 | ) | |
220 | ) users_in_groups_with_access | |
221 | WHERE userID NOT IN ( | |
222 | SELECT userID | |
223 | FROM wcf1_user_to_group | |
224 | WHERE groupID IN ( | |
225 | SELECT groupID | |
226 | FROM wcf1_user_group_option_value | |
227 | WHERE optionID = ? | |
228 | AND optionValue = ? | |
229 | ) | |
230 | ) | |
231 | AND userID NOT IN ( | |
232 | SELECT userID | |
233 | FROM wcf1_moderation_queue_to_user | |
234 | WHERE queueID = ? | |
235 | )"; | |
236 | $statement = WCF::getDB()->prepare($sql); | |
237 | $statement->execute([ | |
238 | $canUseModerationOption->optionID, | |
239 | 1, | |
240 | $canUseModerationOption->optionID, | |
241 | -1, | |
242 | $queue->queueID, | |
243 | ]); | |
244 | $userIDs = $statement->fetchAll(\PDO::FETCH_COLUMN); | |
51ce68ad | 245 | if (!$userIDs) { |
4493238c C |
246 | return; |
247 | } | |
248 | UserProfileRuntimeCache::getInstance()->cacheObjectIDs($userIDs); | |
249 | $objectType = ObjectTypeCache::getInstance()->getObjectType($queue->objectTypeID); | |
250 | $processor = $objectType->getProcessor(); | |
51ce68ad | 251 | \assert($processor instanceof IModerationQueueHandler); |
4493238c | 252 | |
4ff55e71 C |
253 | $userIDs = \array_filter($userIDs, function ($userID) use ($processor, $queue) { |
254 | return $processor->isAffectedUser($queue, $userID); | |
255 | }); | |
4493238c C |
256 | if ($userIDs === []) { |
257 | return; | |
258 | } | |
0d710eba C |
259 | foreach ($userIDs as $userID) { |
260 | $user = UserProfileRuntimeCache::getInstance()->getObject($userID); | |
261 | ModerationQueueManager::getInstance()->setAssignment([$queue->queueID => 1], $user->getDecoratedObject()); | |
262 | } | |
263 | ||
ae0d522c C |
264 | UserNotificationHandler::getInstance()->fireEvent( |
265 | 'report', | |
266 | 'com.woltlab.wcf.moderation.queue', | |
267 | new ModerationQueueUserNotificationObject($queue), | |
268 | $userIDs | |
269 | ); | |
a9229942 | 270 | } |
fc69b61d | 271 | } |