Fixed time zone calculation issue
[GitHub/WoltLab/WCF.git] / wcfsetup / install / files / lib / data / like / LikeAction.class.php
1 <?php
2 namespace wcf\data\like;
3 use wcf\data\AbstractDatabaseObjectAction;
4 use wcf\system\exception\PermissionDeniedException;
5 use wcf\system\exception\UserInputException;
6 use wcf\system\like\LikeHandler;
7 use wcf\system\user\activity\event\UserActivityEventHandler;
8 use wcf\system\user\GroupedUserList;
9 use wcf\system\WCF;
10
11 /**
12 * Executes like-related actions.
13 *
14 * @author Alexander Ebert
15 * @copyright 2001-2014 WoltLab GmbH
16 * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
17 * @package com.woltlab.wcf
18 * @subpackage data.like
19 * @category Community Framework
20 */
21 class LikeAction extends AbstractDatabaseObjectAction {
22 /**
23 * @see \wcf\data\AbstractDatabaseObjectAction::$allowGuestAccess
24 */
25 protected $allowGuestAccess = array('getLikeDetails');
26
27 /**
28 * @see \wcf\data\AbstractDatabaseObjectAction::$className
29 */
30 protected $className = 'wcf\data\like\LikeEditor';
31
32 /**
33 * likeable object
34 * @var \wcf\data\like\object\ILikeObject
35 */
36 public $likeableObject = null;
37
38 /**
39 * object type object
40 * @var \wcf\data\object\type\ObjectType
41 */
42 public $objectType = null;
43
44 /**
45 * like object type provider object
46 * @var \wcf\data\like\ILikeObjectTypeProvider
47 */
48 public $objectTypeProvider = null;
49
50 /**
51 * Validates parameters to fetch like details.
52 */
53 public function validateGetLikeDetails() {
54 $this->validateObjectParameters();
55 }
56
57 /**
58 * Returns like details.
59 *
60 * @return array<string>
61 */
62 public function getLikeDetails() {
63 $sql = "SELECT userID, likeValue
64 FROM wcf".WCF_N."_like
65 WHERE objectID = ?
66 AND objectTypeID = ?
67 ORDER BY time DESC";
68 $statement = WCF::getDB()->prepareStatement($sql);
69 $statement->execute(array(
70 $this->parameters['data']['objectID'],
71 $this->objectType->objectTypeID
72 ));
73 $data = array(
74 Like::LIKE => array(),
75 Like::DISLIKE => array()
76 );
77 while ($row = $statement->fetchArray()) {
78 $data[$row['likeValue']][] = $row['userID'];
79 }
80
81 $values = array();
82 if (!empty($data[Like::LIKE])) {
83 $values[Like::LIKE] = new GroupedUserList(WCF::getLanguage()->get('wcf.like.details.like'));
84 $values[Like::LIKE]->addUserIDs($data[Like::LIKE]);
85 }
86 if (!empty($data[Like::DISLIKE])) {
87 $values[Like::DISLIKE] = new GroupedUserList(WCF::getLanguage()->get('wcf.like.details.dislike'));
88 $values[Like::DISLIKE]->addUserIDs($data[Like::DISLIKE]);
89 }
90
91 // load user profiles
92 GroupedUserList::loadUsers();
93
94 WCF::getTPL()->assign(array(
95 'groupedUsers' => $values
96 ));
97
98 return array(
99 'containerID' => $this->parameters['data']['containerID'],
100 'template' => WCF::getTPL()->fetch('groupedUserList')
101 );
102 }
103
104 /**
105 * Validates parameters for like-related actions.
106 */
107 public function validateLike() {
108 $this->validateObjectParameters();
109
110 // check permissions
111 if (!WCF::getUser()->userID || !WCF::getSession()->getPermission('user.like.canLike')) {
112 throw new PermissionDeniedException();
113 }
114
115 // check if liking own content but forbidden by configuration
116 $this->likeableObject = $this->objectTypeProvider->getObjectByID($this->parameters['data']['objectID']);
117 $this->likeableObject->setObjectType($this->objectType);
118 if (!LIKE_ALLOW_FOR_OWN_CONTENT && ($this->likeableObject->getUserID() == WCF::getUser()->userID)) {
119 throw new PermissionDeniedException();
120 }
121 }
122
123 /**
124 * @see \wcf\data\like\LikeAction::updateLike()
125 */
126 public function like() {
127 return $this->updateLike(Like::LIKE);
128 }
129
130 /**
131 * @see \wcf\data\like\LikeAction::validateLike()
132 */
133 public function validateDislike() {
134 if (!LIKE_ENABLE_DISLIKE) {
135 throw new PermissionDeniedException();
136 }
137
138 $this->validateLike();
139 }
140
141 /**
142 * @see \wcf\data\like\LikeAction::updateLike()
143 */
144 public function dislike() {
145 return $this->updateLike(Like::DISLIKE);
146 }
147
148 /**
149 * Sets like/dislike for an object, executing this method again with the same parameters
150 * will revert the status (removing like/dislike).
151 *
152 * @return array
153 */
154 protected function updateLike($likeValue) {
155 $likeData = LikeHandler::getInstance()->like($this->likeableObject, WCF::getUser(), $likeValue);
156
157 // handle activity event
158 if (UserActivityEventHandler::getInstance()->getObjectTypeID($this->objectType->objectType.'.recentActivityEvent')) {
159 if ($likeData['data']['liked'] == 1) {
160 UserActivityEventHandler::getInstance()->fireEvent($this->objectType->objectType.'.recentActivityEvent', $this->parameters['data']['objectID']);
161 }
162 else {
163 UserActivityEventHandler::getInstance()->removeEvents($this->objectType->objectType.'.recentActivityEvent', array($this->parameters['data']['objectID']));
164 }
165 }
166
167 // get stats
168 return array(
169 'likes' => ($likeData['data']['likes'] === null) ? 0 : $likeData['data']['likes'],
170 'dislikes' => ($likeData['data']['dislikes'] === null) ? 0 : $likeData['data']['dislikes'],
171 'cumulativeLikes' => ($likeData['data']['cumulativeLikes'] === null) ? 0 : $likeData['data']['cumulativeLikes'],
172 'isLiked' => ($likeData['data']['liked'] == 1) ? 1 : 0,
173 'isDisliked' => ($likeData['data']['liked'] == -1) ? 1 : 0,
174 'containerID' => $this->parameters['data']['containerID'],
175 'newValue' => $likeData['newValue'],
176 'oldValue' => $likeData['oldValue'],
177 'users' => $likeData['users']
178 );
179 }
180
181 /**
182 * Validates permissions for given object.
183 */
184 protected function validateObjectParameters() {
185 if (!MODULE_LIKE) {
186 throw new PermissionDeniedException();
187 }
188
189 $this->readString('containerID', false, 'data');
190 $this->readInteger('objectID', false, 'data');
191 $this->readString('objectType', false, 'data');
192
193 $this->objectType = LikeHandler::getInstance()->getObjectType($this->parameters['data']['objectType']);
194 if ($this->objectType === null) {
195 throw new UserInputException('objectType');
196 }
197
198 $this->objectTypeProvider = $this->objectType->getProcessor();
199 $this->likeableObject = $this->objectTypeProvider->getObjectByID($this->parameters['data']['objectID']);
200 $this->likeableObject->setObjectType($this->objectType);
201 if (!$this->objectTypeProvider->checkPermissions($this->likeableObject)) {
202 throw new PermissionDeniedException();
203 }
204 }
205 }