2 namespace wcf\data\like
;
3 use wcf\data\like\
object\LikeObjectEditor
;
4 use wcf\data\
object\type\ObjectTypeCache
;
5 use wcf\data\user\User
;
6 use wcf\data\user\UserEditor
;
7 use wcf\data\AbstractDatabaseObjectAction
;
8 use wcf\data\IGroupedUserListAction
;
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
;
13 use wcf\system\user\activity\point\UserActivityPointHandler
;
14 use wcf\system\user\GroupedUserList
;
18 * Executes like-related actions.
20 * @author Alexander Ebert
21 * @copyright 2001-2014 WoltLab GmbH
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
27 class LikeAction
extends AbstractDatabaseObjectAction
implements IGroupedUserListAction
{
29 * @see \wcf\data\AbstractDatabaseObjectAction::$allowGuestAccess
31 protected $allowGuestAccess = array('getGroupedUserList', 'getLikeDetails', 'load');
34 * @see \wcf\data\AbstractDatabaseObjectAction::$className
36 protected $className = 'wcf\data\like\LikeEditor';
40 * @var \wcf\data\like\object\ILikeObject
42 public $likeableObject = null;
46 * @var \wcf\data\object\type\ObjectType
48 public $objectType = null;
51 * like object type provider object
52 * @var \wcf\data\like\ILikeObjectTypeProvider
54 public $objectTypeProvider = null;
57 * Validates parameters to fetch like details.
59 public function validateGetLikeDetails() {
60 $this->validateObjectParameters();
64 * Returns like details.
66 * @return array<string>
68 public function getLikeDetails() {
69 $sql = "SELECT userID, likeValue
70 FROM wcf".WCF_N
."_like
74 $statement = WCF
::getDB()->prepareStatement($sql);
75 $statement->execute(array(
76 $this->parameters
['data']['objectID'],
77 $this->objectType
->objectTypeID
80 Like
::LIKE
=> array(),
81 Like
::DISLIKE
=> array()
83 while ($row = $statement->fetchArray()) {
84 $data[$row['likeValue']][] = $row['userID'];
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
]);
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
]);
98 GroupedUserList
::loadUsers();
100 WCF
::getTPL()->assign(array(
101 'groupedUsers' => $values
105 'containerID' => $this->parameters
['data']['containerID'],
106 'template' => WCF
::getTPL()->fetch('groupedUserList')
111 * Validates parameters for like-related actions.
113 public function validateLike() {
114 $this->validateObjectParameters();
117 if (!WCF
::getUser()->userID ||
!WCF
::getSession()->getPermission('user.like.canLike')) {
118 throw new PermissionDeniedException();
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();
130 * @see \wcf\data\like\LikeAction::updateLike()
132 public function like() {
133 return $this->updateLike(Like
::LIKE
);
137 * @see \wcf\data\like\LikeAction::validateLike()
139 public function validateDislike() {
140 if (!LIKE_ENABLE_DISLIKE
) {
141 throw new PermissionDeniedException();
144 $this->validateLike();
148 * @see \wcf\data\like\LikeAction::updateLike()
150 public function dislike() {
151 return $this->updateLike(Like
::DISLIKE
);
155 * Sets like/dislike for an object, executing this method again with the same parameters
156 * will revert the status (removing like/dislike).
160 protected function updateLike($likeValue) {
161 $likeData = LikeHandler
::getInstance()->like($this->likeableObject
, WCF
::getUser(), $likeValue);
163 // handle activity event
164 if (UserActivityEventHandler
::getInstance()->getObjectTypeID($this->objectType
->objectType
.'.recentActivityEvent')) {
165 if ($likeData['data']['liked'] == 1) {
166 UserActivityEventHandler
::getInstance()->fireEvent($this->objectType
->objectType
.'.recentActivityEvent', $this->parameters
['data']['objectID'], $this->likeableObject
->getLanguageID());
169 UserActivityEventHandler
::getInstance()->removeEvents($this->objectType
->objectType
.'.recentActivityEvent', array($this->parameters
['data']['objectID']));
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']
188 * Validates permissions for given object.
190 protected function validateObjectParameters() {
192 throw new PermissionDeniedException();
195 $this->readString('containerID', false, 'data');
196 $this->readInteger('objectID', false, 'data');
197 $this->readString('objectType', false, 'data');
199 $this->objectType
= LikeHandler
::getInstance()->getObjectType($this->parameters
['data']['objectType']);
200 if ($this->objectType
=== null) {
201 throw new UserInputException('objectType');
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();
213 * @see \wcf\data\IGroupedUserListAction::validateGetGroupedUserList()
215 public function validateGetGroupedUserList() {
216 $this->validateObjectParameters();
218 $this->readInteger('pageNo');
222 * @see \wcf\data\IGroupedUserListAction::getGroupedUserList()
224 public function getGroupedUserList() {
225 // fetch number of pages
226 $sql = "SELECT COUNT(*)
227 FROM wcf".WCF_N
."_like
229 AND objectTypeID = ?";
230 $statement = WCF
::getDB()->prepareStatement($sql);
231 $statement->execute(array(
232 $this->parameters
['data']['objectID'],
233 $this->objectType
->objectTypeID
235 $pageCount = ceil($statement->fetchColumn() / 20);
237 $sql = "SELECT userID, likeValue
238 FROM wcf".WCF_N
."_like
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
248 Like
::LIKE
=> array(),
249 Like
::DISLIKE
=> array()
251 while ($row = $statement->fetchArray()) {
252 $data[$row['likeValue']][] = $row['userID'];
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
]);
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
]);
265 // load user profiles
266 GroupedUserList
::loadUsers();
268 WCF
::getTPL()->assign(array(
269 'groupedUsers' => $values
273 'containerID' => $this->parameters
['data']['containerID'],
274 'pageCount' => $pageCount,
275 'template' => WCF
::getTPL()->fetch('groupedUserList')
280 * Validates parameters to load likes.
282 public function validateLoad() {
283 $this->readInteger('lastLikeTime', true);
284 $this->readInteger('userID');
285 $this->readInteger('likeValue');
286 $this->readString('likeType');
290 * Loads a list of likes.
294 public function load() {
295 $likeList = new ViewableLikeList();
296 if ($this->parameters
['lastLikeTime']) {
297 $likeList->getConditionBuilder()->add("like_table.time < ?", array($this->parameters
['lastLikeTime']));
299 if ($this->parameters
['likeType'] == 'received') {
300 $likeList->getConditionBuilder()->add("like_table.objectUserID = ?", array($this->parameters
['userID']));
303 $likeList->getConditionBuilder()->add("like_table.userID = ?", array($this->parameters
['userID']));
305 $likeList->getConditionBuilder()->add("like_table.likeValue = ?", array($this->parameters
['likeValue']));
306 $likeList->readObjects();
307 if (!count($likeList)) {
312 WCF
::getTPL()->assign(array(
313 'likeList' => $likeList
317 'lastLikeTime' => $likeList->getLastLikeTime(),
318 'template' => WCF
::getTPL()->fetch('userProfileLikeItem')
323 * Copies likes from one object id to another.
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']);
335 FROM wcf".WCF_N
."_like_object
336 WHERE objectTypeID = ?
338 $statement = WCF
::getDB()->prepareStatement($sql);
339 $statement->execute(array(
340 $sourceObjectType->objectTypeID
,
341 $this->parameters
['sourceObjectID']
343 $row = $statement->fetchArray();
345 // no (dis-)likes at all
346 if ($row === false) {
350 unset($row['likeObjectID']);
351 $row['objectTypeID'] = $targetObjectType->objectTypeID
;
352 $row['objectID'] = $this->parameters
['targetObjectID'];
353 $newLikeObject = LikeObjectEditor
::create($row);
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 = ?
365 $statement = WCF
::getDB()->prepareStatement($sql);
366 $statement->execute(array(
367 $sourceObjectType->objectTypeID
,
368 $this->parameters
['sourceObjectID']
372 // step 3) update owner
375 if ($newLikeObject->objectUserID
) {
376 $sql = "SELECT COUNT(*) AS count
377 FROM wcf".WCF_N
."_like
378 WHERE objectTypeID = ?
381 $statement = WCF
::getDB()->prepareStatement($sql);
382 $statement->execute(array(
383 $targetObjectType->objectTypeID
,
384 $this->parameters
['targetObjectID'],
387 $row = $statement->fetchArray();
390 // update received likes
391 $userEditor = new UserEditor(new User($newLikeObject->objectUserID
));
392 $userEditor->updateCounters(array(
393 'likesReceived' => $row['count']
396 // add activity points
397 UserActivityPointHandler
::getInstance()->fireEvents('com.woltlab.wcf.like.activityPointEvent.receivedLikes', array($newLikeObject->objectUserID
=> $row['count']));