Add user profile reaction list
[GitHub/WoltLab/WCF.git] / wcfsetup / install / files / lib / data / reaction / ReactionAction.class.php
CommitLineData
15aeb641
JR
1<?php
2declare(strict_types=1);
3namespace wcf\data\reaction;
4use wcf\data\like\IRestrictedLikeObjectTypeProvider;
5use wcf\data\like\LikeEditor;
6use wcf\data\like\ViewableLikeList;
7use wcf\data\reaction\type\ReactionType;
8use wcf\data\reaction\type\ReactionTypeCache;
9use wcf\data\AbstractDatabaseObjectAction;
10use wcf\system\exception\IllegalLinkException;
11use wcf\system\exception\PermissionDeniedException;
12use wcf\system\exception\UserInputException;
13use wcf\system\reaction\ReactionHandler;
14use wcf\system\WCF;
15
16/**
17 * Executes reaction-related actions.
18 *
19 * @author Joshua Ruesweg
20 * @copyright 2001-2018 WoltLab GmbH
21 * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
22 * @package WoltLabSuite\Core\Data\Reaction
23 * @since 3.2
24 *
25 * @method Like create()
26 * @method LikeEditor[] getObjects()
27 * @method LikeEditor getSingleObject()
28 */
29class ReactionAction extends AbstractDatabaseObjectAction {
30 /**
31 * @inheritDoc
32 */
33 protected $allowGuestAccess = ['getReactionDetails'];
34
35 /**
36 * @inheritDoc
37 */
38 protected $className = LikeEditor::class;
39
40 /**
41 * likeable object
42 * @var \wcf\data\like\object\ILikeObject
43 */
44 public $likeableObject = null;
45
46 /**
47 * object type object
48 * @var \wcf\data\object\type\ObjectType
49 */
50 public $objectType = null;
51
52 /**
53 * like object type provider object
54 * @var ILikeObjectTypeProvider
55 */
56 public $objectTypeProvider = null;
57
58 /**
59 * reaction type for the reaction
60 * @var ReactionType
61 */
62 public $reactionType = null;
63
64 /**
65 * Validates parameters to fetch like details.
66 */
67 public function validateGetReactionDetails() {
68 $this->validateObjectParameters();
69
70 $this->readInteger('reactionTypeID');
71 $this->readInteger('pageNo');
72
73 $this->reactionType = ReactionTypeCache::getInstance()->getReactionTypeByID($this->parameters['reactionTypeID']);
74
75 if ($this->reactionType === null) {
76 throw new IllegalLinkException();
77 }
78 }
79
80 /**
81 * Returns like details.
82 *
83 * @return string[]
84 */
85 public function getReactionDetails(): array {
86 $likeList = new ViewableLikeList();
87 $likeList->getConditionBuilder()->add('objectID = ?', [$this->parameters['data']['objectID']]);
88 $likeList->getConditionBuilder()->add('objectTypeID = ?', [$this->objectType->objectTypeID]);
89 $likeList->getConditionBuilder()->add('reactionTypeID = ?', [$this->reactionType->reactionTypeID]);
90 $likeList->sqlLimit = 25;
91 $likeList->sqlOffset = ($this->parameters['pageNo'] - 1) * 10;
92 $likeList->sqlOrderBy = 'time DESC';
93 $pageCount = ceil($likeList->countObjects() / 10);
94 $likeList->readObjects();
95
96 WCF::getTPL()->assign([
97 'reactionUserList' => $likeList->getObjects(),
98 'reactions' => ReactionTypeCache::getInstance()->getEnabledReactionTypes(),
99 'reactionTypeID' => $this->reactionType->reactionTypeID
100 ]);
101
102 return [
103 'reactionTypeID' => $this->reactionType->reactionTypeID,
104 'pageNo' => $this->parameters['pageNo'],
105 'pageCount' => $pageCount,
106 'template' => WCF::getTPL()->fetch('reactionTabbedUserList'),
107 'title' => WCF::getLanguage()->get('wcf.reactions.summary.title')
108 ];
109 }
110
111 /**
112 * Validates permissions for given object.
113 */
114 protected function validateObjectParameters() {
115 if (!MODULE_LIKE) {
116 throw new IllegalLinkException();
117 }
118
119 $this->readString('containerID', false, 'data');
120 $this->readInteger('objectID', false, 'data');
121 $this->readString('objectType', false, 'data');
122
123 $this->objectType = ReactionHandler::getInstance()->getObjectType($this->parameters['data']['objectType']);
124 if ($this->objectType === null) {
125 throw new UserInputException('objectType');
126 }
127
128 $this->objectTypeProvider = $this->objectType->getProcessor();
129 $this->likeableObject = $this->objectTypeProvider->getObjectByID($this->parameters['data']['objectID']);
130 $this->likeableObject->setObjectType($this->objectType);
131 if ($this->objectTypeProvider instanceof IRestrictedLikeObjectTypeProvider) {
132 if (!$this->objectTypeProvider->canViewLikes($this->likeableObject)) {
133 throw new PermissionDeniedException();
134 }
135 }
136 else if (!$this->objectTypeProvider->checkPermissions($this->likeableObject)) {
137 throw new PermissionDeniedException();
138 }
139 }
140
141 /**
142 * React on an given object with the given reactionType.
143 *
144 * @return array
145 */
146 public function react(): array {
147 $reactionData = ReactionHandler::getInstance()->react($this->likeableObject, WCF::getUser(), $this->reactionType->reactionTypeID);
148
149 // get stats
150 return [
151 'reactions' => $reactionData['cachedReactions'],
152 'objectID' => $this->likeableObject->getObjectID(),
153 'objectType' => $this->parameters['data']['objectType'],
154 'reactionTypeID' => $reactionData['reactionTypeID'],
155 'containerID' => $this->parameters['data']['containerID'],
156 ];
157 }
158
159 /**
160 * Validates the 'react' method.
161 */
162 public function validateReact() {
163 $this->validateObjectParameters();
164
165 $this->readInteger('reactionTypeID', false);
166
167 $this->reactionType = ReactionTypeCache::getInstance()->getReactionTypeByID($this->parameters['reactionTypeID']);
168
169 if (!$this->reactionType->reactionTypeID || $this->reactionType->isDisabled) {
170 throw new IllegalLinkException();
171 }
172
173 // check permissions
174 if (!WCF::getUser()->userID || !WCF::getSession()->getPermission('user.like.canLike')) {
175 throw new PermissionDeniedException();
176 }
177
178 // check if liking own content but forbidden by configuration
179 $this->likeableObject = $this->objectTypeProvider->getObjectByID($this->parameters['data']['objectID']);
180 $this->likeableObject->setObjectType($this->objectType);
181 if (!LIKE_ALLOW_FOR_OWN_CONTENT && ($this->likeableObject->getUserID() == WCF::getUser()->userID)) {
182 throw new PermissionDeniedException();
183 }
184
185 if ($this->objectTypeProvider instanceof IRestrictedLikeObjectTypeProvider) {
186 if (!$this->objectTypeProvider->canLike($this->likeableObject)) {
187 throw new PermissionDeniedException();
188 }
189 }
190 }
e3bfe7d4
JR
191
192 /**
193 * Validates parameters to load reactions.
194 */
195 public function validateLoad() {
196 $this->readInteger('lastLikeTime', true);
197 $this->readInteger('userID');
198 $this->readInteger('reactionTypeID');
199 $this->readString('targetType');
200 }
201
202 /**
203 * Loads a list of reactions.
204 *
205 * @return array
206 */
207 public function load() {
208 $likeList = new ViewableLikeList();
209 if ($this->parameters['lastLikeTime']) {
210 $likeList->getConditionBuilder()->add("like_table.time < ?", [$this->parameters['lastLikeTime']]);
211 }
212 if ($this->parameters['targetType'] == 'received') {
213 $likeList->getConditionBuilder()->add("like_table.objectUserID = ?", [$this->parameters['userID']]);
214 }
215 else {
216 $likeList->getConditionBuilder()->add("like_table.userID = ?", [$this->parameters['userID']]);
217 }
218 $likeList->getConditionBuilder()->add("like_table.reactionTypeID = ?", [$this->parameters['reactionTypeID']]);
219 $likeList->readObjects();
220
221 if (!count($likeList)) {
222 return [];
223 }
224
225 // parse template
226 WCF::getTPL()->assign([
227 'likeList' => $likeList
228 ]);
229
230 return [
231 'lastLikeTime' => $likeList->getLastLikeTime(),
232 'template' => WCF::getTPL()->fetch('userProfileLikeItem')
233 ];
234 }
15aeb641 235}