1 | <?php |
||
2 | |||
3 | /** |
||
4 | * Used to allow users to like or unlike a post or an entire topic |
||
5 | * |
||
6 | * @package ElkArte Forum |
||
7 | * @copyright ElkArte Forum contributors |
||
8 | * @license BSD http://opensource.org/licenses/BSD-3-Clause (see accompanying LICENSE.txt file) |
||
9 | * |
||
10 | * @version 2.0 dev |
||
11 | * |
||
12 | */ |
||
13 | |||
14 | namespace ElkArte\Controller; |
||
15 | |||
16 | use ElkArte\AbstractController; |
||
17 | use ElkArte\Action; |
||
18 | use ElkArte\Exceptions\Exception; |
||
19 | use ElkArte\Languages\Txt; |
||
20 | use ElkArte\MembersList; |
||
21 | use ElkArte\Notifications\Notifications; |
||
22 | use ElkArte\Notifications\NotificationsTask; |
||
23 | use ElkArte\User; |
||
24 | |||
25 | /** |
||
26 | * This class contains one likable use, which allows members to like a post |
||
27 | * |
||
28 | * @package Likes |
||
29 | */ |
||
30 | class Likes extends AbstractController |
||
31 | { |
||
32 | /** @var array Holds the ajax response */ |
||
33 | protected $_likes_response = []; |
||
34 | |||
35 | /** @var int The id of the message being liked */ |
||
36 | protected $_id_liked; |
||
37 | |||
38 | /** |
||
39 | * Entry point function for likes, permission checks, just makes sure its on |
||
40 | */ |
||
41 | public function pre_dispatch() |
||
42 | { |
||
43 | global $modSettings; |
||
44 | |||
45 | // If likes are disabled, we don't go any further |
||
46 | if (empty($modSettings['likes_enabled'])) |
||
47 | 4 | { |
|
48 | throw new Exception('feature_disabled', true); |
||
49 | 4 | } |
|
50 | } |
||
51 | |||
52 | 4 | /** |
|
53 | * Default action method, if a specific methods was not |
||
54 | * directly called already. Simply forwards to likepost. |
||
55 | * |
||
56 | 4 | * @see AbstractController::action_index |
|
57 | */ |
||
58 | public function action_index() |
||
59 | { |
||
60 | global $context; |
||
61 | |||
62 | $subActions = array( |
||
63 | 'likepost' => array($this, 'action_likepost'), |
||
64 | 'unlikepost' => array($this, 'action_unlikepost'), |
||
65 | 'likestats' => array($this, 'action_likestats'), |
||
66 | ); |
||
67 | |||
68 | // We may or may not like you. |
||
69 | $action = new Action('likes'); |
||
70 | $subAction = $action->initialize($subActions, 'likepost'); |
||
71 | $context['sub_action'] = $subAction; |
||
72 | |||
73 | $action->dispatch($subAction); |
||
74 | } |
||
75 | |||
76 | /** |
||
77 | * Likes a post due to its awesomeness |
||
78 | * |
||
79 | * What it does: |
||
80 | * |
||
81 | * - Permission checks are done in prepare_likes |
||
82 | * - It redirects back to the referrer afterward. |
||
83 | * - It is accessed via ?action=like,sa=likepost |
||
84 | */ |
||
85 | public function action_likepost() |
||
86 | { |
||
87 | global $topic; |
||
88 | |||
89 | if ($this->getApi() === 'json') |
||
90 | { |
||
91 | $this->action_likepost_api(); |
||
92 | return; |
||
93 | } |
||
94 | |||
95 | $this->_doLikePost('+', 'likemsg'); |
||
96 | |||
97 | redirectexit('topic=' . $topic . '.msg' . $this->_id_liked . '#msg' . $this->_id_liked); |
||
98 | } |
||
99 | 2 | ||
100 | /** |
||
101 | 2 | * Actually perform the "like" operation. |
|
102 | * |
||
103 | 2 | * Fills $_likes_response that can be used by likeResponse() in order to |
|
104 | * return a JSON response |
||
105 | * |
||
106 | 2 | * @param string $sign '+' or '-' |
|
107 | 2 | * @param string $type the type of like 'likemsg' or 'rlikemsg' |
|
108 | * |
||
109 | * @return bool |
||
110 | 2 | */ |
|
111 | protected function _doLikePost($sign, $type) |
||
112 | 2 | { |
|
113 | 2 | global $modSettings; |
|
114 | |||
115 | $this->_id_liked = $this->_req->getPost('msg', 'intval', (isset($this->_req->query->msg) ? (int) $this->_req->query->msg : 0)); |
||
116 | 2 | ||
117 | 2 | // We like these |
|
118 | require_once(SUBSDIR . '/Likes.subs.php'); |
||
119 | require_once(SUBSDIR . '/Messages.subs.php'); |
||
120 | 2 | ||
121 | // Have to be able to access it to like/unlike it |
||
122 | if ($this->prepare_like() && canAccessMessage($this->_id_liked)) |
||
123 | { |
||
124 | $liked_message = basicMessageInfo($this->_id_liked, true, true); |
||
125 | if ($liked_message && empty($liked_message['locked'])) |
||
126 | { |
||
127 | // Like it |
||
128 | $likeResult = likePost($this->user->id, $liked_message, $sign); |
||
129 | |||
130 | // Lets add in a mention to the member that just had their post liked/unliked |
||
131 | if (($likeResult === true) && !empty($modSettings['mentions_enabled'])) |
||
132 | 2 | { |
|
133 | $notifier = Notifications::instance(); |
||
134 | $notifier->add(new NotificationsTask( |
||
135 | $type, |
||
136 | $this->_id_liked, |
||
137 | $this->user->id, |
||
138 | array('id_members' => array($liked_message['id_member']), 'rlike_notif' => $type === 'rlikemsg', 'subject' => $liked_message['subject']) |
||
139 | )); |
||
140 | } |
||
141 | |||
142 | 2 | return true; |
|
143 | } |
||
144 | 2 | } |
|
145 | |||
146 | 2 | return false; |
|
147 | } |
||
148 | |||
149 | 2 | /** |
|
150 | * Checks that few things are in order (in addition to permissions) for likes. |
||
151 | */ |
||
152 | 2 | private function prepare_like() |
|
153 | 2 | { |
|
154 | global $modSettings, $txt; |
||
155 | |||
156 | 2 | $check = true; |
|
157 | |||
158 | // Valid request |
||
159 | 2 | checkSession('get'); |
|
160 | |||
161 | // If you're a guest or simply can't do this, we stop |
||
162 | 2 | is_not_guest(); |
|
163 | isAllowedTo('like_posts'); |
||
164 | |||
165 | // Load up the helpers |
||
166 | require_once(SUBSDIR . '/Likes.subs.php'); |
||
167 | |||
168 | // Maintain our log |
||
169 | 2 | clearLikes(empty($modSettings['likeWaitTime']) ? 0 : $modSettings['likeWaitTime']); |
|
170 | |||
171 | // Not a moderator/administrator then we do some checking |
||
172 | if (!empty($modSettings['likeRestrictAdmins']) || !allowedTo('moderate_forum')) |
||
173 | { |
||
174 | // Find out if this user has done this recently... |
||
175 | 2 | $check = lastLikeOn($this->user->id); |
|
176 | } |
||
177 | |||
178 | // Past the post threshold? |
||
179 | if ($this->user->is_admin === false && !empty($modSettings['likeMinPosts']) && $this->user->posts < $modSettings['likeMinPosts']) |
||
180 | { |
||
181 | $check = false; |
||
182 | } |
||
183 | 2 | ||
184 | // If they have exceeded their limits, provide a message for the ajax response |
||
185 | if ($check === false) |
||
186 | { |
||
187 | Txt::load('Errors'); |
||
188 | $wait = $modSettings['likeWaitTime'] > 60 ? round($modSettings['likeWaitTime'] / 60, 2) : $modSettings['likeWaitTime']; |
||
189 | $error = sprintf($txt['like_wait_time'], $wait, ($modSettings['likeWaitTime'] < 60 ? strtolower($txt['minutes']) : $txt['hours'])); |
||
190 | $this->_likes_response = array('result' => false, 'data' => $error); |
||
191 | } |
||
192 | 2 | ||
193 | return $check; |
||
194 | 2 | } |
|
195 | |||
196 | /** |
||
197 | 2 | * Liking a post via ajax |
|
198 | * |
||
199 | * Calls the standard like method and then the api return method |
||
200 | */ |
||
201 | public function action_likepost_api() |
||
202 | { |
||
203 | global $txt; |
||
204 | |||
205 | // An error if not possible to like. |
||
206 | 2 | if (!$this->_doLikePost('+', 'likemsg') && empty($this->_likes_response)) { |
|
207 | 2 | Txt::load('Errors'); |
|
208 | $this->_likes_response = array('result' => false, 'data' => $txt['like_unlike_error']); |
||
209 | } |
||
210 | |||
211 | $this->likeResponse(); |
||
212 | } |
||
213 | 2 | ||
214 | /** |
||
215 | 2 | * When liking / unliking via ajax, clears the templates and returns a json |
|
216 | * response to the page |
||
217 | */ |
||
218 | 2 | private function likeResponse() |
|
219 | 2 | { |
|
220 | global $context, $txt; |
||
221 | |||
222 | 2 | // Make room for ajax |
|
223 | setJsonTemplate(); |
||
224 | 2 | ||
225 | 2 | // No errors, build the new button tag |
|
226 | 2 | if (empty($this->_likes_response)) |
|
227 | 2 | { |
|
228 | 2 | $details = loadLikes($this->_id_liked, true); |
|
229 | 2 | $count = empty($details) ? 0 : $details[$this->_id_liked]['count']; |
|
230 | 2 | $youLiked = $count !== 0 && array_key_exists(User::$info->id , $details[$this->_id_liked]['member']); |
|
0 ignored issues
–
show
Bug
Best Practice
introduced
by
![]() |
|||
231 | 2 | $text = $count !== 0 ? ($youLiked ? $txt['unlike_post'] : $txt['likes']) : $txt['like_post']; |
|
232 | 2 | $title = empty($details) ? '' : $txt['liked_by'] . ' ' . implode(', ', $details[$this->_id_liked]['member']); |
|
233 | $this->_likes_response = [ |
||
234 | 'result' => true, |
||
235 | 'text' => $text, |
||
236 | 'count' => $count, |
||
237 | 2 | 'title' => $title |
|
238 | 2 | ]; |
|
239 | } |
||
240 | |||
241 | // Provide the response |
||
242 | $context['json_data'] = $this->_likes_response; |
||
243 | } |
||
244 | |||
245 | /** |
||
246 | * Un liking a post via ajax |
||
247 | * |
||
248 | * Calls the standard unlike method and then the api return method |
||
249 | */ |
||
250 | public function action_unlikepost_api() |
||
251 | { |
||
252 | global $txt; |
||
253 | |||
254 | // An error if not possible to like. |
||
255 | if (!$this->_doLikePost('-', 'rlikemsg') && empty($this->_likes_response)) { |
||
256 | Txt::load('Errors'); |
||
257 | $this->_likes_response = array('result' => false, 'data' => $txt['like_unlike_error']); |
||
258 | } |
||
259 | |||
260 | $this->likeResponse(); |
||
261 | } |
||
262 | |||
263 | /** |
||
264 | * Unlikes a post that you previously liked ... no negatives though, hurts feelings :'( |
||
265 | * |
||
266 | * - It redirects back to the referrer afterward. |
||
267 | * - It is accessed via ?action=like,sa=unlikepost. |
||
268 | */ |
||
269 | public function action_unlikepost() |
||
270 | { |
||
271 | global $topic; |
||
272 | |||
273 | if ($this->getApi() === 'json') |
||
274 | { |
||
275 | $this->action_unlikepost_api(); |
||
276 | return; |
||
277 | } |
||
278 | |||
279 | $this->_doLikePost('-', 'rlikemsg'); |
||
280 | |||
281 | // No longer liked, return to whence you came |
||
282 | if (!isset($this->_req->query->profile)) |
||
283 | { |
||
284 | redirectexit('topic=' . $topic . '.msg' . $this->_id_liked . '#msg' . $this->_id_liked); |
||
285 | } |
||
286 | else |
||
287 | { |
||
288 | 2 | redirectexit('action=profile;area=showlikes;sa=given;u=' . $this->user->id); |
|
289 | } |
||
290 | } |
||
291 | 2 | ||
292 | /** |
||
293 | 2 | * Dispatch to show all the posts you liked OR all your posts liked |
|
294 | */ |
||
295 | public function action_showProfileLikes() |
||
296 | { |
||
297 | // Load in our helper functions |
||
298 | require_once(SUBSDIR . '/Likes.subs.php'); |
||
299 | 2 | ||
300 | if ($this->_req->getQuery('sa') === 'received') |
||
301 | 2 | { |
|
302 | $this->_action_showReceived(); |
||
303 | } |
||
304 | else |
||
305 | { |
||
306 | $this->_action_showGiven(); |
||
307 | } |
||
308 | } |
||
309 | |||
310 | /** |
||
311 | * Shows all posts that others have liked of theirs |
||
312 | */ |
||
313 | private function _action_showReceived() |
||
314 | { |
||
315 | global $context, $txt; |
||
316 | |||
317 | $memID = currentMemberID(); |
||
318 | $name = MembersList::get($memID)->real_name; |
||
0 ignored issues
–
show
The property
real_name does not exist on anonymous//sources/ElkArte/MembersList.php$0 . Since you implemented __get , consider adding a @property annotation.
![]() |
|||
319 | |||
320 | // Build the listoption array to display the data |
||
321 | $listOptions = array( |
||
322 | 'id' => 'view_likes', |
||
323 | 'title' => $txt['likes'], |
||
324 | 'items_per_page' => 25, |
||
325 | 'no_items_label' => $txt['likes_none_received'], |
||
326 | 'base_href' => getUrl('profile', ['action' => 'profile', 'area' => 'showlikes', 'sa' => 'received', 'u' => $memID, 'name' => $name]), |
||
327 | 'default_sort_col' => 'subject', |
||
328 | 'get_items' => array( |
||
329 | 'function' => fn($start, $items_per_page, $sort, $memberID) => $this->list_loadLikesReceived($start, $items_per_page, $sort, $memberID), |
||
330 | 'params' => array( |
||
331 | $memID, |
||
332 | ), |
||
333 | ), |
||
334 | 'get_count' => array( |
||
335 | 'function' => fn($memberID, $given) => $this->list_getLikesCount($memberID, $given), |
||
336 | 'params' => array( |
||
337 | $memID, |
||
338 | false, |
||
339 | ), |
||
340 | ), |
||
341 | 'columns' => array( |
||
342 | 'subject' => array( |
||
343 | 'header' => array( |
||
344 | 'value' => $txt['subject'], |
||
345 | ), |
||
346 | 'data' => array( |
||
347 | 'db' => 'subject', |
||
348 | ), |
||
349 | 'sort' => array( |
||
350 | 'default' => 'm.subject DESC', |
||
351 | 'reverse' => 'm.subject', |
||
352 | ), |
||
353 | ), |
||
354 | 'name' => array( |
||
355 | 'header' => array( |
||
356 | 'value' => $txt['board'], |
||
357 | ), |
||
358 | 'data' => array( |
||
359 | 'db' => 'name', |
||
360 | ), |
||
361 | 'sort' => array( |
||
362 | 'default' => 'b.name', |
||
363 | 'reverse' => 'b.name DESC', |
||
364 | ), |
||
365 | ), |
||
366 | 'likes' => array( |
||
367 | 'header' => array( |
||
368 | 'value' => $txt['likes'], |
||
369 | ), |
||
370 | 'data' => array( |
||
371 | 'db' => 'likes', |
||
372 | ), |
||
373 | 'sort' => array( |
||
374 | 'default' => 'likes', |
||
375 | 'reverse' => 'likes DESC', |
||
376 | ), |
||
377 | ), |
||
378 | 'action' => array( |
||
379 | 'header' => array( |
||
380 | 'value' => $txt['show'], |
||
381 | 'class' => 'centertext', |
||
382 | ), |
||
383 | 'data' => array( |
||
384 | 'function' => static function ($row) { |
||
385 | global $txt; |
||
386 | return '<a href="' . $row['who'] . '" title="' . $txt['likes_show_who'] . '"><i class="icon i-users"></i></a>'; |
||
387 | }, |
||
388 | 'class' => 'centertext', |
||
389 | 'style' => 'width: 10%', |
||
390 | ), |
||
391 | ), |
||
392 | ), |
||
393 | ); |
||
394 | |||
395 | // Menu tabs |
||
396 | $context[$context['profile_menu_name']]['object']->prepareTabData([ |
||
397 | 'title' => $txt['likes'], |
||
398 | 'description' => $txt['likes_received'], |
||
399 | 'class' => 'i-thumbsup', |
||
400 | ]); |
||
401 | |||
402 | // Set the context values |
||
403 | $context['page_title'] = $txt['likes']; |
||
404 | $context['sub_template'] = 'show_list'; |
||
405 | $context['default_list'] = 'view_likes'; |
||
406 | |||
407 | // Create the list. |
||
408 | createList($listOptions); |
||
409 | } |
||
410 | |||
411 | /** |
||
412 | * Callback for createList() |
||
413 | * Returns a list of received likes based on posts |
||
414 | * |
||
415 | * @param int $start The item to start with (for pagination purposes) |
||
416 | * @param int $items_per_page The number of items to show per page |
||
417 | * @param string $sort A string indicating how to sort the results |
||
418 | * @param int $memberID |
||
419 | * |
||
420 | * @return array |
||
421 | */ |
||
422 | public function list_loadLikesReceived($start, $items_per_page, $sort, $memberID) |
||
423 | { |
||
424 | // Get a list of all posts (of a members) that have been liked |
||
425 | return likesPostsReceived($start, $items_per_page, $sort, $memberID); |
||
426 | } |
||
427 | |||
428 | /** |
||
429 | * Callback for createList(), |
||
430 | * Returns the number of likes a member has given if given = true |
||
431 | * else the number of posts (not likes) of theirs that have been liked |
||
432 | * |
||
433 | * @param int $memberID |
||
434 | * @param bool $given |
||
435 | 2 | * |
|
436 | * @return int |
||
437 | 2 | */ |
|
438 | public function list_getLikesCount($memberID, $given) |
||
439 | { |
||
440 | return likesCount($memberID, $given); |
||
441 | } |
||
442 | |||
443 | 2 | /** |
|
444 | * Shows all posts that they have liked |
||
445 | 2 | */ |
|
446 | private function _action_showGiven() |
||
447 | 2 | { |
|
448 | 2 | global $context, $txt; |
|
449 | |||
450 | $memID = currentMemberID(); |
||
451 | $name = MembersList::get($memID)->real_name; |
||
0 ignored issues
–
show
The property
real_name does not exist on anonymous//sources/ElkArte/MembersList.php$0 . Since you implemented __get , consider adding a @property annotation.
![]() |
|||
452 | 2 | ||
453 | 2 | // Build the listoption array to display the like data |
|
454 | 2 | $listOptions = array( |
|
455 | 2 | 'id' => 'view_likes', |
|
456 | 2 | 'title' => $txt['likes'], |
|
457 | 2 | 'items_per_page' => 25, |
|
458 | 'no_items_label' => $txt['likes_none_given'], |
||
459 | 'base_href' => getUrl('profile', ['action' => 'profile', 'area' => 'showlikes', 'sa' => 'given', 'u' => $memID, 'name' => $name]), |
||
460 | 2 | 'default_sort_col' => 'subject', |
|
461 | 2 | 'get_items' => array( |
|
462 | 'function' => fn($start, $items_per_page, $sort, $memberID) => $this->list_loadLikesPosts($start, $items_per_page, $sort, $memberID), |
||
463 | 2 | 'params' => array( |
|
464 | $memID, |
||
465 | ), |
||
466 | ), |
||
467 | 'get_count' => array( |
||
468 | 2 | 'function' => fn($memberID, $given) => $this->list_getLikesCount($memberID, $given), |
|
469 | 2 | 'params' => array( |
|
470 | $memID, |
||
471 | 2 | true |
|
472 | ), |
||
473 | ), |
||
474 | 'columns' => array( |
||
475 | 'subject' => array( |
||
476 | 'header' => array( |
||
477 | 'value' => $txt['subject'], |
||
478 | 2 | ), |
|
479 | 'data' => array( |
||
480 | 'db' => 'subject', |
||
481 | ), |
||
482 | 'sort' => array( |
||
483 | 'default' => 'm.subject DESC', |
||
484 | 'reverse' => 'm.subject', |
||
485 | ), |
||
486 | ), |
||
487 | 'name' => array( |
||
488 | 'header' => array( |
||
489 | 'value' => $txt['board'], |
||
490 | 2 | ), |
|
491 | 'data' => array( |
||
492 | 'db' => 'name', |
||
493 | ), |
||
494 | 'sort' => array( |
||
495 | 'default' => 'b.name ', |
||
496 | 'reverse' => 'b.name DESC', |
||
497 | ), |
||
498 | ), |
||
499 | 'poster_name' => array( |
||
500 | 'header' => array( |
||
501 | 'value' => $txt['username'], |
||
502 | 2 | ), |
|
503 | 'data' => array( |
||
504 | 'db' => 'poster_name', |
||
505 | ), |
||
506 | 'sort' => array( |
||
507 | 'default' => 'm.poster_name ', |
||
508 | 'reverse' => 'm.poster_name DESC', |
||
509 | ), |
||
510 | ), |
||
511 | 'action' => array( |
||
512 | 'header' => array( |
||
513 | 'value' => $txt['delete'], |
||
514 | 2 | 'class' => 'centertext', |
|
515 | 2 | ), |
|
516 | 'data' => array( |
||
517 | 'function' => static function ($row) { |
||
518 | global $txt; |
||
519 | return '<a href="' . $row['delete'] . '" onclick="return confirm(\'' . $txt['likes_confirm_delete'] . '\');" title="' . $txt['likes_delete'] . '"><i class="icon i-delete"></i></a>'; |
||
520 | }, |
||
521 | 'class' => 'centertext', |
||
522 | 2 | 'style' => 'width: 10%', |
|
523 | 2 | ), |
|
524 | 2 | ), |
|
525 | ), |
||
526 | ); |
||
527 | |||
528 | // Menu tabs |
||
529 | $context[$context['profile_menu_name']]['object']->prepareTabData([ |
||
530 | 'title' => $txt['likes'], |
||
531 | 2 | 'description' => $txt['likes_given'], |
|
532 | 2 | 'class' => 'i-thumbsup', |
|
533 | 2 | ]); |
|
534 | |||
535 | // Set the context values |
||
536 | $context['page_title'] = $txt['likes']; |
||
537 | 2 | $context['sub_template'] = 'show_list'; |
|
538 | 2 | $context['default_list'] = 'view_likes'; |
|
539 | 2 | ||
540 | // Create the list. |
||
541 | createList($listOptions); |
||
542 | 2 | } |
|
543 | 2 | ||
544 | /** |
||
545 | * Callback for createList() |
||
546 | * Returns a list of liked posts for a member |
||
547 | * |
||
548 | * @param int $start The item to start with (for pagination purposes) |
||
549 | * @param int $items_per_page The number of items to show per page |
||
550 | * @param string $sort A string indicating how to sort the results |
||
551 | * @param int $memberID |
||
552 | * |
||
553 | * @return array |
||
554 | */ |
||
555 | public function list_loadLikesPosts($start, $items_per_page, $sort, $memberID) |
||
556 | 2 | { |
|
557 | // Get all of our liked posts |
||
558 | return likesPostsGiven($start, $items_per_page, $sort, $memberID); |
||
559 | 2 | } |
|
560 | |||
561 | /** |
||
562 | * Function to return an array of users that liked a particular message. |
||
563 | * |
||
564 | * - Used in profile so a user can see the full list of members, vs the |
||
565 | * truncated (optional) one shown in message display |
||
566 | * - Accessed by ?action=likes;sa=showWhoLiked;msg=x |
||
567 | */ |
||
568 | public function action_showWhoLiked() |
||
569 | { |
||
570 | global $context, $txt; |
||
571 | |||
572 | require_once(SUBSDIR . '/Likes.subs.php'); |
||
573 | Txt::load('Profile'); |
||
574 | |||
575 | // Get the message in question |
||
576 | $message = $this->_req->getQuery('msg', 'intval', 0); |
||
577 | |||
578 | // Build the listoption array to display the data |
||
579 | $listOptions = array( |
||
580 | 'id' => 'view_likers', |
||
581 | 'title' => $txt['likes_by'], |
||
582 | 'items_per_page' => 25, |
||
583 | 'no_items_label' => $txt['likes_none_given'], |
||
584 | 'base_href' => getUrl('action', ['action' => 'likes', 'sa' => 'showWhoLiked', 'msg' => $message]), |
||
585 | 'default_sort_col' => 'member', |
||
586 | 'get_items' => array( |
||
587 | 'function' => fn($start, $items_per_page, $sort, $messageID) => $this->list_loadPostLikers($start, $items_per_page, $sort, $messageID), |
||
588 | 'params' => array( |
||
589 | $message, |
||
590 | ), |
||
591 | ), |
||
592 | 'get_count' => array( |
||
593 | 'function' => fn($messageID) => $this->list_getMessageLikeCount($messageID), |
||
594 | 'params' => array( |
||
595 | $message, |
||
596 | ), |
||
597 | ), |
||
598 | 'columns' => array( |
||
599 | 'member' => array( |
||
600 | 'header' => array( |
||
601 | 'value' => $txt['members'], |
||
602 | 'class' => 'lefttext', |
||
603 | ), |
||
604 | 'data' => array( |
||
605 | 'db' => 'link', |
||
606 | ), |
||
607 | 'sort' => array( |
||
608 | 'default' => 'm.real_name DESC', |
||
609 | 'reverse' => 'm.real_name', |
||
610 | ), |
||
611 | ), |
||
612 | ), |
||
613 | 'additional_rows' => array( |
||
614 | array( |
||
615 | 'position' => 'below_table_data', |
||
616 | 'class' => 'submitbutton', |
||
617 | 'value' => '<a class="linkbutton" href="javascript:history.go(-1)">' . $txt['back'] . '</a>', |
||
618 | ), |
||
619 | ), |
||
620 | ); |
||
621 | |||
622 | // Set the context values |
||
623 | $context['page_title'] = $txt['likes_by']; |
||
624 | $context['sub_template'] = 'show_list'; |
||
625 | $context['default_list'] = 'view_likers'; |
||
626 | |||
627 | // Create the list. |
||
628 | createList($listOptions); |
||
629 | } |
||
630 | |||
631 | /** |
||
632 | * Callback for createList() |
||
633 | * Returns a list of members that liked a post |
||
634 | * |
||
635 | * @param int $start The item to start with (for pagination purposes) |
||
636 | * @param int $items_per_page The number of items to show per page |
||
637 | * @param string $sort A string indicating how to sort the results |
||
638 | * @param int $messageID |
||
639 | * |
||
640 | * @return array |
||
641 | */ |
||
642 | public function list_loadPostLikers($start, $items_per_page, $sort, $messageID) |
||
643 | { |
||
644 | // Get a list of this posts likers |
||
645 | return postLikers($start, $items_per_page, $sort, $messageID); |
||
646 | } |
||
647 | |||
648 | /** |
||
649 | * Callback for createList(), |
||
650 | * Returns the number of likes a message has received |
||
651 | * |
||
652 | * @param int $messageID |
||
653 | * |
||
654 | * @return int |
||
655 | */ |
||
656 | public function list_getMessageLikeCount($messageID) |
||
657 | { |
||
658 | return messageLikeCount($messageID); |
||
659 | } |
||
660 | |||
661 | /** |
||
662 | * Like stats controller function, used by API calls. |
||
663 | * |
||
664 | * What it does: |
||
665 | * |
||
666 | * - Validates whether user is allowed to see stats or not. |
||
667 | * - Decides which tab data to fetch and show to user. |
||
668 | */ |
||
669 | public function action_likestats_api() |
||
670 | { |
||
671 | global $context; |
||
672 | |||
673 | checkSession('get'); |
||
674 | |||
675 | Txt::load('LikePosts'); |
||
676 | |||
677 | $subActions = array( |
||
678 | 'messagestats' => array($this, 'action_messageStats'), |
||
679 | 'topicstats' => array($this, 'action_topicStats'), |
||
680 | 'boardstats' => array($this, 'action_boardStats'), |
||
681 | 'mostlikesreceiveduserstats' => array($this, 'action_mostLikesReceivedUserStats'), |
||
682 | 'mostlikesgivenuserstats' => array($this, 'action_mostLikesGivenUserStats'), |
||
683 | ); |
||
684 | |||
685 | // Set up the action controller |
||
686 | $action = new Action('likesstats'); |
||
687 | |||
688 | // Pick the correct sub-action, call integrate_sa_likesstats |
||
689 | $subAction = $action->initialize($subActions, 'messagestats', 'area'); |
||
690 | $context['sub_action'] = $subAction; |
||
691 | |||
692 | // Call the right function for this sub-action. |
||
693 | $action->dispatch($subAction); |
||
694 | } |
||
695 | |||
696 | /** |
||
697 | * Like stats controller function. |
||
698 | * |
||
699 | * What it does: |
||
700 | * |
||
701 | * - Validates whether user is allowed to see stats or not. |
||
702 | * - Presents a general page without data that will be fully loaded by API calls. |
||
703 | * - Used when call is made from the main menu selection |
||
704 | */ |
||
705 | public function action_likestats() |
||
706 | { |
||
707 | global $context, $txt, $modSettings; |
||
708 | |||
709 | require_once(SUBSDIR . '/Likes.subs.php'); |
||
710 | |||
711 | // Likes are not on, your quest for statistics ends here |
||
712 | if (empty($modSettings['likes_enabled'])) |
||
713 | { |
||
714 | throw new Exception('feature_disabled', true); |
||
715 | } |
||
716 | |||
717 | // Worthy to view like statistics? |
||
718 | isAllowedTo('like_posts_stats'); |
||
719 | |||
720 | if ($this->getApi() === 'json') |
||
721 | { |
||
722 | $this->action_likestats_api(); |
||
723 | return; |
||
724 | } |
||
725 | |||
726 | // Load the required files |
||
727 | Txt::load('LikePosts'); |
||
728 | loadJavascriptFile('like_posts.js'); |
||
729 | theme()->getTemplates()->load('LikePostsStats'); |
||
730 | |||
731 | // Template and tab data |
||
732 | $context['page_title'] = $txt['like_post_stats']; |
||
733 | $context['like_posts']['tab_desc'] = $txt['like_posts_stats_desc']; |
||
734 | $context['lp_stats_tabs'] = array( |
||
735 | 'messagestats' => array( |
||
736 | 'label' => $txt['like_post_message'], |
||
737 | 'id' => 'messagestats', |
||
738 | ), |
||
739 | 'topicstats' => array( |
||
740 | 'label' => $txt['like_post_topic'], |
||
741 | 'id' => 'topicstats', |
||
742 | ), |
||
743 | 'boardstats' => array( |
||
744 | 'label' => $txt['like_post_board'], |
||
745 | 'id' => 'boardstats', |
||
746 | ), |
||
747 | 'usergivenstats' => array( |
||
748 | 'label' => $txt['like_post_tab_mlmember'], |
||
749 | 'id' => 'mostlikesreceiveduserstats', |
||
750 | ), |
||
751 | 'userreceivedstats' => array( |
||
752 | 'label' => $txt['like_post_tab_mlgmember'], |
||
753 | 'id' => 'mostlikesgivenuserstats', |
||
754 | ), |
||
755 | ); |
||
756 | $context['sub_template'] = 'lp_stats'; |
||
757 | } |
||
758 | |||
759 | /** |
||
760 | * Determines the most liked message in the system |
||
761 | * |
||
762 | * What it does: |
||
763 | * |
||
764 | * - Fetches the most liked message data |
||
765 | * - Returns the data via ajax |
||
766 | */ |
||
767 | public function action_messageStats() |
||
768 | { |
||
769 | global $txt; |
||
770 | |||
771 | // Lets get the statistics! |
||
772 | $data = dbMostLikedMessage(); |
||
773 | |||
774 | // Set the response |
||
775 | if (!empty($data)) |
||
776 | { |
||
777 | $this->_likes_response = array('result' => true, 'data' => $data); |
||
778 | } |
||
779 | else |
||
780 | { |
||
781 | $this->_likes_response = array('result' => false, 'error' => $txt['like_post_error_something_wrong']); |
||
782 | } |
||
783 | |||
784 | // Off we go |
||
785 | $this->likeResponse(); |
||
786 | } |
||
787 | |||
788 | /** |
||
789 | * Determine the most liked topics in the system |
||
790 | * |
||
791 | * What it does: |
||
792 | * |
||
793 | * - Gets the most liked topics in the system |
||
794 | * - Returns the data via ajax |
||
795 | */ |
||
796 | public function action_topicStats() |
||
797 | { |
||
798 | global $txt; |
||
799 | |||
800 | $data = dbMostLikedTopic(); |
||
801 | |||
802 | if (!empty($data)) |
||
803 | { |
||
804 | $this->_likes_response = array('result' => true, 'data' => $data); |
||
805 | } |
||
806 | else |
||
807 | { |
||
808 | $this->_likes_response = array('result' => false, 'error' => $txt['like_post_error_something_wrong']); |
||
809 | } |
||
810 | |||
811 | $this->likeResponse(); |
||
812 | } |
||
813 | |||
814 | /** |
||
815 | * Fetches the most liked board data |
||
816 | * Returns the data via ajax |
||
817 | */ |
||
818 | public function action_boardStats() |
||
819 | { |
||
820 | global $txt; |
||
821 | |||
822 | $data = dbMostLikedBoard(); |
||
823 | |||
824 | if (!empty($data)) |
||
825 | { |
||
826 | $this->_likes_response = array('result' => true, 'data' => $data); |
||
827 | } |
||
828 | else |
||
829 | { |
||
830 | $this->_likes_response = array('result' => false, 'error' => $txt['like_post_error_something_wrong']); |
||
831 | } |
||
832 | |||
833 | $this->likeResponse(); |
||
834 | } |
||
835 | |||
836 | /** |
||
837 | * Fetches the data for the highest likes received user |
||
838 | * Returns the data via ajax |
||
839 | */ |
||
840 | public function action_mostLikesReceivedUserStats() |
||
841 | { |
||
842 | global $txt; |
||
843 | |||
844 | $data = dbMostLikesReceivedUser(); |
||
845 | |||
846 | if (!empty($data)) |
||
847 | { |
||
848 | $this->_likes_response = array('result' => true, 'data' => $data); |
||
849 | } |
||
850 | else |
||
851 | { |
||
852 | $this->_likes_response = array('result' => false, 'error' => $txt['like_post_error_something_wrong']); |
||
853 | } |
||
854 | |||
855 | $this->likeResponse(); |
||
856 | } |
||
857 | |||
858 | /** |
||
859 | * Retrieves the most like giving user |
||
860 | * |
||
861 | * Returns the data via ajax |
||
862 | */ |
||
863 | public function action_mostLikesGivenUserStats() |
||
864 | { |
||
865 | global $txt; |
||
866 | |||
867 | $data = dbMostLikesGivenUser(); |
||
868 | |||
869 | if (!empty($data)) |
||
870 | { |
||
871 | $this->_likes_response = array('result' => true, 'data' => $data); |
||
872 | } |
||
873 | else |
||
874 | { |
||
875 | $this->_likes_response = array('result' => false, 'error' => $txt['like_post_error_something_wrong']); |
||
876 | } |
||
877 | |||
878 | $this->likeResponse(); |
||
879 | } |
||
880 | } |
||
881 |