Commit | Line | Data |
---|---|---|
15aeb641 JR |
1 | <?php |
2 | declare(strict_types=1); | |
3 | namespace wcf\data\reaction; | |
4 | use wcf\data\like\IRestrictedLikeObjectTypeProvider; | |
5 | use wcf\data\like\LikeEditor; | |
6 | use wcf\data\like\ViewableLikeList; | |
7 | use wcf\data\reaction\type\ReactionType; | |
8 | use wcf\data\reaction\type\ReactionTypeCache; | |
9 | use wcf\data\AbstractDatabaseObjectAction; | |
10 | use wcf\system\exception\IllegalLinkException; | |
11 | use wcf\system\exception\PermissionDeniedException; | |
12 | use wcf\system\exception\UserInputException; | |
13 | use wcf\system\reaction\ReactionHandler; | |
14 | use 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 | */ | |
29 | class 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 | } |