Commit | Line | Data |
---|---|---|
00b6f956 MW |
1 | <?php |
2 | namespace wcf\data\like; | |
7067e131 | 3 | use wcf\data\like\object\LikeObjectEditor; |
e53269d6 | 4 | use wcf\data\object\type\ObjectTypeCache; |
7067e131 AE |
5 | use wcf\data\user\User; |
6 | use wcf\data\user\UserEditor; | |
00b6f956 | 7 | use wcf\data\AbstractDatabaseObjectAction; |
32514cd5 | 8 | use wcf\data\IGroupedUserListAction; |
00b6f956 MW |
9 | use wcf\system\exception\PermissionDeniedException; |
10 | use wcf\system\exception\UserInputException; | |
11 | use wcf\system\like\LikeHandler; | |
12 | use wcf\system\user\activity\event\UserActivityEventHandler; | |
7067e131 | 13 | use wcf\system\user\activity\point\UserActivityPointHandler; |
00b6f956 MW |
14 | use wcf\system\user\GroupedUserList; |
15 | use wcf\system\WCF; | |
16 | ||
17 | /** | |
18 | * Executes like-related actions. | |
19 | * | |
20 | * @author Alexander Ebert | |
ca4ba303 | 21 | * @copyright 2001-2014 WoltLab GmbH |
00b6f956 MW |
22 | * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php> |
23 | * @package com.woltlab.wcf | |
24 | * @subpackage data.like | |
25 | * @category Community Framework | |
26 | */ | |
32514cd5 | 27 | class LikeAction extends AbstractDatabaseObjectAction implements IGroupedUserListAction { |
00b6f956 | 28 | /** |
0ad90fc3 | 29 | * @see \wcf\data\AbstractDatabaseObjectAction::$allowGuestAccess |
00b6f956 | 30 | */ |
8700ed2c | 31 | protected $allowGuestAccess = array('getGroupedUserList', 'getLikeDetails', 'load'); |
00b6f956 MW |
32 | |
33 | /** | |
0ad90fc3 | 34 | * @see \wcf\data\AbstractDatabaseObjectAction::$className |
00b6f956 MW |
35 | */ |
36 | protected $className = 'wcf\data\like\LikeEditor'; | |
37 | ||
38 | /** | |
39 | * likeable object | |
0ad90fc3 | 40 | * @var \wcf\data\like\object\ILikeObject |
00b6f956 MW |
41 | */ |
42 | public $likeableObject = null; | |
43 | ||
44 | /** | |
45 | * object type object | |
0ad90fc3 | 46 | * @var \wcf\data\object\type\ObjectType |
00b6f956 MW |
47 | */ |
48 | public $objectType = null; | |
49 | ||
50 | /** | |
51 | * like object type provider object | |
0ad90fc3 | 52 | * @var \wcf\data\like\ILikeObjectTypeProvider |
00b6f956 MW |
53 | */ |
54 | public $objectTypeProvider = null; | |
55 | ||
56 | /** | |
57 | * Validates parameters to fetch like details. | |
58 | */ | |
59 | public function validateGetLikeDetails() { | |
60 | $this->validateObjectParameters(); | |
61 | } | |
62 | ||
63 | /** | |
64 | * Returns like details. | |
65 | * | |
66 | * @return array<string> | |
67 | */ | |
68 | public function getLikeDetails() { | |
cad6116d MW |
69 | $sql = "SELECT userID, likeValue |
70 | FROM wcf".WCF_N."_like | |
71 | WHERE objectID = ? | |
72 | AND objectTypeID = ? | |
73 | ORDER BY time DESC"; | |
00b6f956 MW |
74 | $statement = WCF::getDB()->prepareStatement($sql); |
75 | $statement->execute(array( | |
76 | $this->parameters['data']['objectID'], | |
77 | $this->objectType->objectTypeID | |
78 | )); | |
79 | $data = array( | |
80 | Like::LIKE => array(), | |
81 | Like::DISLIKE => array() | |
82 | ); | |
83 | while ($row = $statement->fetchArray()) { | |
84 | $data[$row['likeValue']][] = $row['userID']; | |
85 | } | |
86 | ||
87 | $values = array(); | |
88 | if (!empty($data[Like::LIKE])) { | |
89 | $values[Like::LIKE] = new GroupedUserList(WCF::getLanguage()->get('wcf.like.details.like')); | |
90 | $values[Like::LIKE]->addUserIDs($data[Like::LIKE]); | |
91 | } | |
92 | if (!empty($data[Like::DISLIKE])) { | |
93 | $values[Like::DISLIKE] = new GroupedUserList(WCF::getLanguage()->get('wcf.like.details.dislike')); | |
94 | $values[Like::DISLIKE]->addUserIDs($data[Like::DISLIKE]); | |
95 | } | |
96 | ||
97 | // load user profiles | |
98 | GroupedUserList::loadUsers(); | |
99 | ||
100 | WCF::getTPL()->assign(array( | |
101 | 'groupedUsers' => $values | |
102 | )); | |
103 | ||
104 | return array( | |
105 | 'containerID' => $this->parameters['data']['containerID'], | |
106 | 'template' => WCF::getTPL()->fetch('groupedUserList') | |
107 | ); | |
108 | } | |
109 | ||
110 | /** | |
111 | * Validates parameters for like-related actions. | |
112 | */ | |
113 | public function validateLike() { | |
114 | $this->validateObjectParameters(); | |
115 | ||
116 | // check permissions | |
117 | if (!WCF::getUser()->userID || !WCF::getSession()->getPermission('user.like.canLike')) { | |
1a6e8c52 | 118 | throw new PermissionDeniedException(); |
00b6f956 MW |
119 | } |
120 | ||
121 | // check if liking own content but forbidden by configuration | |
122 | $this->likeableObject = $this->objectTypeProvider->getObjectByID($this->parameters['data']['objectID']); | |
123 | $this->likeableObject->setObjectType($this->objectType); | |
124 | if (!LIKE_ALLOW_FOR_OWN_CONTENT && ($this->likeableObject->getUserID() == WCF::getUser()->userID)) { | |
125 | throw new PermissionDeniedException(); | |
126 | } | |
127 | } | |
128 | ||
129 | /** | |
0ad90fc3 | 130 | * @see \wcf\data\like\LikeAction::updateLike() |
00b6f956 MW |
131 | */ |
132 | public function like() { | |
133 | return $this->updateLike(Like::LIKE); | |
134 | } | |
135 | ||
136 | /** | |
0ad90fc3 | 137 | * @see \wcf\data\like\LikeAction::validateLike() |
00b6f956 MW |
138 | */ |
139 | public function validateDislike() { | |
d39b7b8f MW |
140 | if (!LIKE_ENABLE_DISLIKE) { |
141 | throw new PermissionDeniedException(); | |
142 | } | |
143 | ||
00b6f956 MW |
144 | $this->validateLike(); |
145 | } | |
146 | ||
147 | /** | |
0ad90fc3 | 148 | * @see \wcf\data\like\LikeAction::updateLike() |
00b6f956 MW |
149 | */ |
150 | public function dislike() { | |
151 | return $this->updateLike(Like::DISLIKE); | |
152 | } | |
153 | ||
154 | /** | |
155 | * Sets like/dislike for an object, executing this method again with the same parameters | |
156 | * will revert the status (removing like/dislike). | |
157 | * | |
158 | * @return array | |
159 | */ | |
160 | protected function updateLike($likeValue) { | |
161 | $likeData = LikeHandler::getInstance()->like($this->likeableObject, WCF::getUser(), $likeValue); | |
162 | ||
163 | // handle activity event | |
164 | if (UserActivityEventHandler::getInstance()->getObjectTypeID($this->objectType->objectType.'.recentActivityEvent')) { | |
165 | if ($likeData['data']['liked'] == 1) { | |
b5f54a71 | 166 | UserActivityEventHandler::getInstance()->fireEvent($this->objectType->objectType.'.recentActivityEvent', $this->parameters['data']['objectID'], $this->likeableObject->getLanguageID()); |
00b6f956 MW |
167 | } |
168 | else { | |
169 | UserActivityEventHandler::getInstance()->removeEvents($this->objectType->objectType.'.recentActivityEvent', array($this->parameters['data']['objectID'])); | |
170 | } | |
171 | } | |
172 | ||
173 | // get stats | |
174 | return array( | |
175 | 'likes' => ($likeData['data']['likes'] === null) ? 0 : $likeData['data']['likes'], | |
176 | 'dislikes' => ($likeData['data']['dislikes'] === null) ? 0 : $likeData['data']['dislikes'], | |
177 | 'cumulativeLikes' => ($likeData['data']['cumulativeLikes'] === null) ? 0 : $likeData['data']['cumulativeLikes'], | |
178 | 'isLiked' => ($likeData['data']['liked'] == 1) ? 1 : 0, | |
179 | 'isDisliked' => ($likeData['data']['liked'] == -1) ? 1 : 0, | |
180 | 'containerID' => $this->parameters['data']['containerID'], | |
181 | 'newValue' => $likeData['newValue'], | |
182 | 'oldValue' => $likeData['oldValue'], | |
183 | 'users' => $likeData['users'] | |
184 | ); | |
185 | } | |
186 | ||
187 | /** | |
188 | * Validates permissions for given object. | |
189 | */ | |
190 | protected function validateObjectParameters() { | |
191 | if (!MODULE_LIKE) { | |
192 | throw new PermissionDeniedException(); | |
193 | } | |
194 | ||
195 | $this->readString('containerID', false, 'data'); | |
196 | $this->readInteger('objectID', false, 'data'); | |
197 | $this->readString('objectType', false, 'data'); | |
198 | ||
199 | $this->objectType = LikeHandler::getInstance()->getObjectType($this->parameters['data']['objectType']); | |
200 | if ($this->objectType === null) { | |
201 | throw new UserInputException('objectType'); | |
202 | } | |
203 | ||
204 | $this->objectTypeProvider = $this->objectType->getProcessor(); | |
205 | $this->likeableObject = $this->objectTypeProvider->getObjectByID($this->parameters['data']['objectID']); | |
206 | $this->likeableObject->setObjectType($this->objectType); | |
207 | if (!$this->objectTypeProvider->checkPermissions($this->likeableObject)) { | |
208 | throw new PermissionDeniedException(); | |
209 | } | |
210 | } | |
32514cd5 MS |
211 | |
212 | /** | |
213 | * @see \wcf\data\IGroupedUserListAction::validateGetGroupedUserList() | |
214 | */ | |
215 | public function validateGetGroupedUserList() { | |
216 | $this->validateObjectParameters(); | |
217 | ||
218 | $this->readInteger('pageNo'); | |
219 | } | |
220 | ||
221 | /** | |
222 | * @see \wcf\data\IGroupedUserListAction::getGroupedUserList() | |
223 | */ | |
224 | public function getGroupedUserList() { | |
225 | // fetch number of pages | |
226 | $sql = "SELECT COUNT(*) | |
227 | FROM wcf".WCF_N."_like | |
228 | WHERE objectID = ? | |
229 | AND objectTypeID = ?"; | |
230 | $statement = WCF::getDB()->prepareStatement($sql); | |
231 | $statement->execute(array( | |
232 | $this->parameters['data']['objectID'], | |
233 | $this->objectType->objectTypeID | |
234 | )); | |
235 | $pageCount = ceil($statement->fetchColumn() / 20); | |
236 | ||
237 | $sql = "SELECT userID, likeValue | |
238 | FROM wcf".WCF_N."_like | |
239 | WHERE objectID = ? | |
240 | AND objectTypeID = ? | |
241 | ORDER BY likeValue DESC, time DESC"; | |
242 | $statement = WCF::getDB()->prepareStatement($sql, 20, ($this->parameters['pageNo'] - 1) * 20); | |
243 | $statement->execute(array( | |
244 | $this->parameters['data']['objectID'], | |
245 | $this->objectType->objectTypeID | |
246 | )); | |
247 | $data = array( | |
248 | Like::LIKE => array(), | |
249 | Like::DISLIKE => array() | |
250 | ); | |
251 | while ($row = $statement->fetchArray()) { | |
252 | $data[$row['likeValue']][] = $row['userID']; | |
253 | } | |
254 | ||
255 | $values = array(); | |
256 | if (!empty($data[Like::LIKE])) { | |
257 | $values[Like::LIKE] = new GroupedUserList(WCF::getLanguage()->get('wcf.like.details.like')); | |
258 | $values[Like::LIKE]->addUserIDs($data[Like::LIKE]); | |
259 | } | |
260 | if (!empty($data[Like::DISLIKE])) { | |
261 | $values[Like::DISLIKE] = new GroupedUserList(WCF::getLanguage()->get('wcf.like.details.dislike')); | |
262 | $values[Like::DISLIKE]->addUserIDs($data[Like::DISLIKE]); | |
263 | } | |
264 | ||
265 | // load user profiles | |
266 | GroupedUserList::loadUsers(); | |
267 | ||
268 | WCF::getTPL()->assign(array( | |
269 | 'groupedUsers' => $values | |
270 | )); | |
271 | ||
272 | return array( | |
273 | 'containerID' => $this->parameters['data']['containerID'], | |
274 | 'pageCount' => $pageCount, | |
275 | 'template' => WCF::getTPL()->fetch('groupedUserList') | |
276 | ); | |
277 | } | |
8700ed2c MW |
278 | |
279 | /** | |
280 | * Validates parameters to load likes. | |
281 | */ | |
282 | public function validateLoad() { | |
283 | $this->readInteger('lastLikeTime', true); | |
284 | $this->readInteger('userID'); | |
285 | $this->readInteger('likeValue'); | |
286 | $this->readString('likeType'); | |
287 | } | |
288 | ||
289 | /** | |
290 | * Loads a list of likes. | |
0f0590c2 | 291 | * |
8700ed2c MW |
292 | * @return array |
293 | */ | |
294 | public function load() { | |
295 | $likeList = new ViewableLikeList(); | |
296 | if ($this->parameters['lastLikeTime']) { | |
297 | $likeList->getConditionBuilder()->add("like_table.time < ?", array($this->parameters['lastLikeTime'])); | |
298 | } | |
299 | if ($this->parameters['likeType'] == 'received') { | |
300 | $likeList->getConditionBuilder()->add("like_table.objectUserID = ?", array($this->parameters['userID'])); | |
301 | } | |
302 | else { | |
303 | $likeList->getConditionBuilder()->add("like_table.userID = ?", array($this->parameters['userID'])); | |
304 | } | |
305 | $likeList->getConditionBuilder()->add("like_table.likeValue = ?", array($this->parameters['likeValue'])); | |
306 | $likeList->readObjects(); | |
7c02c2d4 | 307 | if (!count($likeList)) { |
8700ed2c MW |
308 | return array(); |
309 | } | |
d7f7f6eb | 310 | |
8700ed2c MW |
311 | // parse template |
312 | WCF::getTPL()->assign(array( | |
313 | 'likeList' => $likeList | |
314 | )); | |
d7f7f6eb | 315 | |
8700ed2c | 316 | return array( |
7c02c2d4 | 317 | 'lastLikeTime' => $likeList->getLastLikeTime(), |
8700ed2c MW |
318 | 'template' => WCF::getTPL()->fetch('userProfileLikeItem') |
319 | ); | |
320 | } | |
e53269d6 AE |
321 | |
322 | /** | |
781073ff | 323 | * Copies likes from one object id to another. |
e53269d6 AE |
324 | */ |
325 | public function copy() { | |
326 | $sourceObjectType = ObjectTypeCache::getInstance()->getObjectTypeByName('com.woltlab.wcf.like.likeableObject', $this->parameters['sourceObjectType']); | |
327 | $targetObjectType = ObjectTypeCache::getInstance()->getObjectTypeByName('com.woltlab.wcf.like.likeableObject', $this->parameters['targetObjectType']); | |
328 | ||
329 | // | |
330 | // step 1) get data | |
331 | // | |
332 | ||
333 | // get like object | |
334 | $sql = "SELECT * | |
335 | FROM wcf".WCF_N."_like_object | |
336 | WHERE objectTypeID = ? | |
337 | AND objectID = ?"; | |
338 | $statement = WCF::getDB()->prepareStatement($sql); | |
339 | $statement->execute(array( | |
340 | $sourceObjectType->objectTypeID, | |
341 | $this->parameters['sourceObjectID'] | |
342 | )); | |
343 | $row = $statement->fetchArray(); | |
344 | ||
345 | // no (dis-)likes at all | |
346 | if ($row === false) { | |
347 | return; | |
348 | } | |
349 | ||
350 | unset($row['likeObjectID']); | |
351 | $row['objectTypeID'] = $targetObjectType->objectTypeID; | |
352 | $row['objectID'] = $this->parameters['targetObjectID']; | |
353 | $newLikeObject = LikeObjectEditor::create($row); | |
354 | ||
355 | // | |
356 | // step 2) copy | |
357 | // | |
358 | ||
359 | $sql = "INSERT INTO wcf".WCF_N."_like | |
360 | (objectID, objectTypeID, objectUserID, userID, time, likeValue) | |
361 | SELECT ".$this->parameters['targetObjectID'].", ".$targetObjectType->objectTypeID.", objectUserID, userID, time, likeValue | |
362 | FROM wcf".WCF_N."_like | |
363 | WHERE objectTypeID = ? | |
364 | AND objectID = ?"; | |
365 | $statement = WCF::getDB()->prepareStatement($sql); | |
366 | $statement->execute(array( | |
367 | $sourceObjectType->objectTypeID, | |
368 | $this->parameters['sourceObjectID'] | |
369 | )); | |
370 | ||
371 | // | |
372 | // step 3) update owner | |
373 | // | |
374 | ||
375 | if ($newLikeObject->objectUserID) { | |
376 | $sql = "SELECT COUNT(*) AS count | |
377 | FROM wcf".WCF_N."_like | |
378 | WHERE objectTypeID = ? | |
379 | AND objectID = ? | |
380 | AND likeValue = ?"; | |
381 | $statement = WCF::getDB()->prepareStatement($sql); | |
382 | $statement->execute(array( | |
383 | $targetObjectType->objectTypeID, | |
384 | $this->parameters['targetObjectID'], | |
385 | Like::LIKE | |
386 | )); | |
387 | $row = $statement->fetchArray(); | |
388 | ||
389 | if ($row['count']) { | |
390 | // update received likes | |
391 | $userEditor = new UserEditor(new User($newLikeObject->objectUserID)); | |
392 | $userEditor->updateCounters(array( | |
393 | 'likesReceived' => $row['count'] | |
394 | )); | |
395 | ||
396 | // add activity points | |
397 | UserActivityPointHandler::getInstance()->fireEvents('com.woltlab.wcf.like.activityPointEvent.receivedLikes', array($newLikeObject->objectUserID => $row['count'])); | |
398 | } | |
399 | } | |
400 | } | |
00b6f956 | 401 | } |