PluginProbe
wpForo Forum / 2.3.0
wpForo Forum v2.3.0
3.1.5 3.1.4 3.1.2 3.1.1 3.1.0 3.0.9 3.0.8 3.0.7 trunk 1.0.0 1.0.1 1.0.2 1.1.0 1.1.1 1.1.2 1.2.0 1.3.0 1.3.1 1.4.0 1.4.1 1.4.10 1.4.11 1.4.12 1.4.13 1.4.2 All 137 releases
wpforo / classes / Activity.php

Activity.php in wpForo Forum 2.3.0, at classes/Activity.php

726 lines 25.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace wpforo\classes;
4
5 use stdClass;
6
7 // Exit if accessed directly
8 if( ! defined( 'ABSPATH' ) ) exit;
9
10 class Activity {
11 private $default;
12 public $activity;
13 private $actions;
14 public $notifications = [];
15
16 public function __construct() {
17 add_action( 'wpforo_after_init', [ $this, 'init' ] );
18 }
19
20 public function init() {
21 $this->init_defaults();
22 $this->activity = $this->default->activity;
23 $this->init_hooks();
24 $this->init_actions();
25 if( is_user_logged_in() && wpforo_setting( 'notifications', 'notifications' ) ) {
26 $this->notifications = $this->get_notifications();
27 }
28 }
29
30 private function init_actions() {
31 $this->actions = [
32 'edit_topic' => [
33 'title' => wpforo_phrase( 'Edit Topic', false ),
34 'icon' => '',
35 'description' => wpforo_phrase( 'This topic was modified %s by %s', false ),
36 'before' => '<div class="wpf-post-edited"><i class="far fa-edit"></i>',
37 'after' => '</div>',
38 ],
39 'edit_post' => [
40 'title' => wpforo_phrase( 'Edit Post', false ),
41 'icon' => '',
42 'description' => wpforo_phrase( 'This post was modified %s by %s', false ),
43 'before' => '<div class="wpf-post-edited"><i class="far fa-edit"></i>',
44 'after' => '</div>',
45 ],
46 'new_reply' => [
47 'title' => wpforo_phrase( 'New Reply', false ),
48 'icon' => '<i class="fas fa-reply fa-rotate-180"></i>',
49 'description' => wpforo_phrase( 'New reply from %1$s, %2$s', false ),
50 'before' => '<li class="wpf-new_reply">',
51 'after' => '</li>',
52 ],
53 'new_like' => [
54 'title' => wpforo_phrase( 'New Like', false ),
55 'icon' => '<i class="fas fa-heart"></i>',
56 'description' => wpforo_phrase( 'New like from %1$s, %2$s', false ),
57 'before' => '<li class="wpf-new_like">',
58 'after' => '</li>',
59 ],
60 'new_dislike' => [
61 'title' => wpforo_phrase( 'New Dislike', false ),
62 'icon' => '<i class="fas fa-heart-crack"></i>',
63 'description' => wpforo_phrase( 'New dislike from %1$s, %2$s', false ),
64 'before' => '<li class="wpf-new_dislike">',
65 'after' => '</li>',
66 ],
67 'new_up_vote' => [
68 'title' => wpforo_phrase( 'New Up Vote', false ),
69 'icon' => '<i class="fas fa-arrow-alt-circle-up"></i>',
70 'description' => wpforo_phrase( 'New up vote from %1$s, %2$s', false ),
71 'before' => '<li class="wpf-new_up_vote">',
72 'after' => '</li>',
73 ],
74 'new_down_vote' => [
75 'title' => wpforo_phrase( 'New Down Vote', false ),
76 'icon' => '<i class="fas fa-arrow-alt-circle-down"></i>',
77 'description' => wpforo_phrase( 'New down vote from %1$s, %2$s', false ),
78 'before' => '<li class="wpf-new_down_vote">',
79 'after' => '</li>',
80 ],
81 'new_mention' => [
82 'title' => wpforo_phrase( 'New User Mentioning', false ),
83 'icon' => '<i class="fas fa-at"></i>',
84 'description' => wpforo_phrase( '%1$s has mentioned you, %2$s', false ),
85 'before' => '<li class="wpf-new_mention">',
86 'after' => '</li>',
87 ],
88 'default' => [
89 'title' => wpforo_phrase( 'New Notification', false ),
90 'icon' => '<i class="fas fa-bell"></i>',
91 'description' => wpforo_phrase( 'New notification from %1$s, %2$s', false ),
92 'before' => '<li class="wpf-new_note">',
93 'after' => '</li>',
94 ],
95 ];
96
97 $this->actions = apply_filters( 'wpforo_register_actions', $this->actions );
98 }
99
100 private function init_defaults() {
101 $this->default = new stdClass();
102 $this->default->activity = [
103 'id' => 0,
104 'type' => '',
105 'itemid' => 0,
106 'itemtype' => '',
107 'itemid_second' => 0,
108 'userid' => 0,
109 'name' => '',
110 'email' => '',
111 'date' => 0,
112 'content' => '',
113 'permalink' => '',
114 'new' => 0,
115 ];
116 $this->default->activity_format = [
117 'id' => '%d',
118 'type' => '%s',
119 'itemid' => '%d',
120 'itemtype' => '%s',
121 'itemid_second' => '%d',
122 'userid' => '%d',
123 'name' => '%s',
124 'email' => '%s',
125 'date' => '%d',
126 'content' => '%s',
127 'permalink' => '%s',
128 'new' => '%d',
129 ];
130 $this->default->sql_select_args = [
131 'type' => null,
132 'userid' => null,
133 'itemtype' => null,
134 'new' => null,
135 'include' => [],
136 'exclude' => [],
137 'userids_include' => [],
138 'userids_exclude' => [],
139 'types_include' => [],
140 'types_exclude' => [],
141 'itemids_include' => [],
142 'itemids_exclude' => [],
143 'itemtypes_include' => [],
144 'itemtypes_exclude' => [],
145 'emails_include' => [],
146 'emails_exclude' => [],
147 'orderby' => 'id',
148 'order' => 'ASC',
149 'offset' => null,
150 'row_count' => null,
151 ];
152
153 $this->default = apply_filters( 'wpforo_activity_after_init_defaults', $this->default );
154 }
155
156 private function init_hooks() {
157 if( wpforo_setting( 'posting', 'edit_topic' ) ) {
158 add_action( 'wpforo_after_edit_topic', [ $this, 'after_edit_topic' ] );
159 }
160 if( wpforo_setting( 'posting', 'edit_post' ) ) {
161 add_action( 'wpforo_after_edit_post', [ $this, 'after_edit_post' ] );
162 }
163
164 if( WPF()->current_userid && wpforo_setting( 'notifications', 'notifications' ) ) {
165 if( wpforo_setting( 'notifications', 'notifications_bar' ) ) {
166 add_action( 'wpforo_before_search_toggle', [ $this, 'bell' ] );
167 }
168 add_action( 'wpforo_after_add_post', [ $this, 'after_add_post' ], 10, 2 );
169 add_action( 'wpforo_post_status_update', [ $this, 'update_notification' ], 10, 2 );
170 add_action( 'wpforo_like', [ $this, 'after_like' ] );
171 add_action( 'wpforo_dislike', [ $this, 'after_dislike' ] );
172 add_action( 'wpforo_undo_like', [ $this, 'after_undo_like' ] );
173 add_action( 'wpforo_undo_dislike', [ $this, 'after_undo_dislike' ] );
174 add_action( 'wpforo_vote', [ $this, 'after_vote' ], 10, 2 );
175 }
176 }
177
178 private function filter_built_html_rows( $rows ) {
179 $_rows = [];
180 foreach( $rows as $row_key => $row ) {
181 $in_array = false;
182 if( $_rows ) {
183 foreach( $_rows as $_row_key => $_row ) {
184 if( in_array( $row, $_row ) ) {
185 $in_array = true;
186 $match_key = $_row_key;
187 break;
188 }
189 }
190 }
191 if( $in_array && isset( $match_key ) ) {
192 $_rows[ $match_key ]['times'] ++;
193 } else {
194 $_rows[ $row_key ]['html'] = $row;
195 $_rows[ $row_key ]['times'] = 1;
196 }
197 }
198
199 $rows = [];
200 foreach( $_rows as $_row ) {
201 $times = '';
202 if( $_row['times'] > 1 ) {
203 $times = ' ' . sprintf(
204 wpforo_phrase( '%d times', false ),
205 $_row['times']
206 );
207 }
208
209 $rows[] = sprintf( $_row['html'], $times );
210 }
211
212 $limit = wpforo_setting( 'posting', 'edit_log_display_limit' );
213 if( $limit ) $rows = array_slice( $rows, ( - 1 * $limit ), $limit );
214
215 return $rows;
216 }
217
218 private function parse_activity( $data ) {
219 return apply_filters( 'wpforo_activty_parse_activity', array_merge( $this->default->activity, $data ) );
220 }
221
222 private function parse_args( $args ) {
223 $args = wpforo_parse_args( $args, $this->default->sql_select_args );
224
225 $args['include'] = wpforo_parse_args( $args['include'] );
226 $args['exclude'] = wpforo_parse_args( $args['exclude'] );
227
228 $args['userids_include'] = wpforo_parse_args( $args['userids_include'] );
229 $args['userids_exclude'] = wpforo_parse_args( $args['userids_exclude'] );
230
231 $args['types_include'] = wpforo_parse_args( $args['types_include'] );
232 $args['types_exclude'] = wpforo_parse_args( $args['types_exclude'] );
233
234 $args['itemids_include'] = wpforo_parse_args( $args['itemids_include'] );
235 $args['itemids_exclude'] = wpforo_parse_args( $args['itemids_exclude'] );
236
237 $args['itemtypes_include'] = wpforo_parse_args( $args['itemtypes_include'] );
238 $args['itemtypes_exclude'] = wpforo_parse_args( $args['itemtypes_exclude'] );
239
240 $args['emails_include'] = wpforo_parse_args( $args['emails_include'] );
241 $args['emails_exclude'] = wpforo_parse_args( $args['emails_exclude'] );
242
243 return $args;
244 }
245
246 private function build_sql_select( $args ) {
247 $args = $this->parse_args( $args );
248
249 $wheres = [];
250
251 if( ! is_null( $args['type'] ) ) $wheres[] = "`type` = '" . esc_sql( $args['type'] ) . "'";
252 if( ! is_null( $args['itemtype'] ) ) $wheres[] = "`itemtype` = '" . esc_sql( $args['itemtype'] ) . "'";
253 if( ! is_null( $args['userid'] ) ) $wheres[] = "`userid` = " . intval( $args['userid'] );
254 if( ! is_null( $args['new'] ) ) $wheres[] = "`new` = " . intval( $args['new'] );
255
256 if( ! empty( $args['include'] ) ) $wheres[] = "`id` IN(" . implode( ',', array_map( 'wpforo_bigintval', $args['include'] ) ) . ")";
257 if( ! empty( $args['exclude'] ) ) $wheres[] = "`id` NOT IN(" . implode( ',', array_map( 'wpforo_bigintval', $args['exclude'] ) ) . ")";
258
259 if( ! empty( $args['userids_include'] ) ) $wheres[] = "`userid` IN(" . implode( ',', array_map( 'wpforo_bigintval', $args['userids_include'] ) ) . ")";
260 if( ! empty( $args['userids_exclude'] ) ) $wheres[] = "`userid` NOT IN(" . implode( ',', array_map( 'wpforo_bigintval', $args['userids_exclude'] ) ) . ")";
261
262 if( ! empty( $args['types_include'] ) ) $wheres[] = "`type` IN('" . implode( "','", array_map( 'trim', $args['types_include'] ) ) . "')";
263 if( ! empty( $args['types_exclude'] ) ) $wheres[] = "`type` NOT IN('" . implode( "','", array_map( 'trim', $args['types_exclude'] ) ) . "')";
264
265 if( ! empty( $args['itemids_include'] ) ) $wheres[] = "`itemid` IN(" . implode( ',', array_map( 'wpforo_bigintval', $args['itemids_include'] ) ) . ")";
266 if( ! empty( $args['itemids_exclude'] ) ) $wheres[] = "`itemid` NOT IN(" . implode( ',', array_map( 'wpforo_bigintval', $args['itemids_exclude'] ) ) . ")";
267
268 if( ! empty( $args['itemtypes_include'] ) ) $wheres[] = "`itemtype` IN('" . implode( "','", array_map( 'trim', $args['itemtypes_include'] ) ) . "')";
269 if( ! empty( $args['itemtypes_exclude'] ) ) $wheres[] = "`itemtype` NOT IN('" . implode( "','", array_map( 'trim', $args['itemtypes_exclude'] ) ) . "')";
270
271 if( ! empty( $args['emails_include'] ) ) $wheres[] = "`email` IN('" . implode( "','", array_map( 'trim', $args['emails_include'] ) ) . "')";
272 if( ! empty( $args['emails_exclude'] ) ) $wheres[] = "`email` NOT IN('" . implode( "','", array_map( 'trim', $args['emails_exclude'] ) ) . "')";
273
274 $sql = "SELECT * FROM " . WPF()->tables->activity;
275 if( $wheres ) $sql .= " WHERE " . implode( " AND ", $wheres );
276 $sql .= " ORDER BY " . $args['orderby'] . " " . $args['order'];
277 if( $args['row_count'] ) {
278 if( ! empty( $args['offset'] ) ) {
279 $sql .= " LIMIT " . wpforo_bigintval( $args['offset'] ) . "," . wpforo_bigintval( $args['row_count'] );
280 } else {
281 $sql .= " LIMIT " . wpforo_bigintval( $args['row_count'] );
282 }
283 }
284
285 return $sql;
286 }
287
288 public function get_activity( $args ) {
289 if( ! $args ) return false;
290
291 return $this->parse_activity( (array) WPF()->db->get_row( $this->build_sql_select( $args ), ARRAY_A ) );
292 }
293
294 public function get_activities( $args ) {
295 if( ! $args ) return [];
296
297 return array_map( [ $this, 'parse_activity' ], (array) WPF()->db->get_results( $this->build_sql_select( $args ), ARRAY_A ) );
298 }
299
300 public function after_edit_topic( $topic ) {
301 $data = [
302 'type' => 'edit_topic',
303 'itemid' => $topic['topicid'],
304 'itemtype' => 'topic',
305 'userid' => WPF()->current_userid,
306 'name' => WPF()->current_user_display_name,
307 'email' => WPF()->current_user_email,
308 'permalink' => wpforo_topic( $topic['topicid'], 'url' ),
309 ];
310
311 $this->add( $data );
312 }
313
314 public function after_edit_post( $post ) {
315 $data = [
316 'type' => 'edit_post',
317 'itemid' => $post['postid'],
318 'itemtype' => 'post',
319 'userid' => WPF()->current_userid,
320 'name' => WPF()->current_user_display_name,
321 'email' => WPF()->current_user_email,
322 'permalink' => wpforo_post( $post['postid'], 'url' ),
323 ];
324
325 $this->add( $data );
326 }
327
328 public function after_add_post( $post, $topic ) {
329 $this->add_notification_new_reply( 'new_reply', $post, $topic );
330 }
331
332 private function add( $data ) {
333 if( empty( $data ) ) return false;
334 $activity = array_merge( $this->default->activity, $data );
335 unset( $activity['id'] );
336
337 if( ! $activity['type'] || ! $activity['itemid'] || ! $activity['itemtype'] ) return false;
338 if( ! $activity['date'] ) $activity['date'] = time();
339
340 $activity = apply_filters( 'wpforo_add_activity_data_filter', $activity );
341 do_action( 'wpforo_before_add_activity', $activity );
342
343 $activity = wpforo_array_ordered_intersect_key( $activity, $this->default->activity_format );
344 if( WPF()->db->insert(
345 WPF()->tables->activity,
346 $activity,
347 wpforo_array_ordered_intersect_key( $this->default->activity_format, $activity )
348 ) ) {
349 $activity['id'] = WPF()->db->insert_id;
350 do_action( 'wpforo_after_add_activity', $activity );
351
352 return $activity['id'];
353 }
354
355 return false;
356 }
357
358 private function edit( $data, $where ) {
359 if( empty( $data ) || empty( $where ) ) return false;
360 if( is_numeric( $where ) ) $where = [ 'id' => $where ];
361 $data = (array) $data;
362 $where = (array) $where;
363
364 $data = apply_filters( 'wpforo_activity_edit_data_filter', $data );
365 $where = apply_filters( 'wpforo_activity_edit_where_filter', $where );
366 do_action( 'wpforo_before_edit_activity', $data, $where );
367
368 $data = wpforo_array_ordered_intersect_key( $data, $this->default->activity_format );
369 $where = wpforo_array_ordered_intersect_key( $where, $this->default->activity_format );
370 if( false !== WPF()->db->update(
371 WPF()->tables->activity,
372 $data,
373 $where,
374 wpforo_array_ordered_intersect_key( $this->default->activity_format, $data ),
375 wpforo_array_ordered_intersect_key( $this->default->activity_format, $where )
376 ) ) {
377 do_action( 'wpforo_after_edit_activity', $data, $where );
378
379 return true;
380 }
381
382 return false;
383 }
384
385 private function delete( $where ) {
386 if( empty( $where ) ) return false;
387 if( is_numeric( $where ) ) $where = [ 'id' => $where ];
388 $where = (array) $where;
389
390 $where = apply_filters( 'wpforo_activity_delete_where_filter', $where );
391 do_action( 'wpforo_before_delete_activity', $where );
392
393 $where = wpforo_array_ordered_intersect_key( $where, $this->default->activity_format );
394 if( false !== WPF()->db->delete(
395 WPF()->tables->activity,
396 $where,
397 wpforo_array_ordered_intersect_key( $this->default->activity_format, $where )
398 ) ) {
399 do_action( 'wpforo_after_delete_activity', $where );
400
401 return true;
402 }
403
404 return false;
405 }
406
407 public function build( $itemtype, $itemid, $type, $echo = false ) {
408 $rows = [];
409 $args = [
410 'itemtypes_include' => $itemtype,
411 'itemids_include' => $itemid,
412 'types_include' => $type,
413 ];
414 if( $activities = $this->get_activities( $args ) ) {
415 foreach( $activities as $activity ) {
416 switch( $activity['type'] ) {
417 case 'edit_topic':
418 case 'edit_post':
419 $rows[] = $this->_build_edit_topic_edit_post( $activity );
420 break;
421 }
422 }
423 }
424
425 $rows = $this->filter_built_html_rows( $rows );
426
427 $html = ( $rows ? implode( '', $rows ) : '' );
428 if( $echo ) echo $html;
429
430 return $html;
431 }
432
433 private function _build_edit_topic_edit_post( $activity ) {
434 $html = '';
435 $type = $activity['type'];
436 $userid = $activity['userid'];
437 $date = wpforo_date( $activity['date'], 'ago', false ) . '%s';
438
439 if( $userid ) {
440 $profile_url = wpforo_member( $userid, 'profile_url' );
441 $display_name = wpforo_member( $userid, 'display_name' );
442 $user = sprintf( '<a href="%s">%s</a>', $profile_url, $display_name );
443 } else {
444 $user = $activity['name'] ?: wpforo_phrase( 'Guest', false );
445 }
446
447 if( wpfval( $this->actions, $type, 'before' ) ) {
448 $html = $this->actions[ $type ]['before'];
449 $html = apply_filters( 'wpforo_activity_action_html_before', $html, $activity );
450 }
451 if( wpfval( $this->actions, $type, 'description' ) ) {
452 $html .= sprintf( $this->actions[ $activity['type'] ]['description'], $date, str_replace( '%', '%%', $user ) );
453 $html = apply_filters( 'wpforo_activity_action_html', $html, $activity );
454 }
455 if( wpfval( $this->actions, $type, 'after' ) ) {
456 $html .= $this->actions[ $type ]['after'];
457 $html = apply_filters( 'wpforo_activity_action_html_after', $html, $activity );
458 }
459
460 return $html;
461 }
462
463 public function bell( $class = 'wpf-alerts' ) {
464 wp_enqueue_script( 'wpforo-widgets-js' );
465
466 $class = ( ! $class ) ? 'wpf-alerts' : $class;
467 $count = ( ! empty( $this->notifications ) ) ? count( $this->notifications ) : 0;
468 $phrase = ( $count > 1 ) ? wpforo_phrase( 'You have new notifications', false ) : wpforo_phrase( 'You have a new notification', false );
469 $tooltip = ' wpf-tooltip="' . esc_attr( $phrase ) . '" wpf-tooltip-size="middle"';
470 ?>
471 <div class="<?php echo esc_attr( $class ) ?> <?php echo ( $count ) ? 'wpf-new' : ''; ?>">
472 <?php if( $count ): ?>
473 <div class="wpf-bell" <?php echo $tooltip ?>>
474 <i class="fas fa-bell"></i>
475 <span class="wpf-alerts-count"><?php echo $count ?></span>
476 </div>
477 <?php else: ?>
478 <div class="wpf-bell">
479 <i class="far fa-bell"></i>
480 </div>
481 <?php endif; ?>
482 </div>
483 <?php
484 }
485
486 public function notifications() {
487 ?>
488 <div class="wpf-notifications">
489 <div class="wpf-notification-head">
490 <i class="far fa-bell"></i> <?php wpforo_phrase( 'Notifications' ) ?>
491 </div>
492 <div class="wpf-notification-content">
493 <div class="wpf-nspin"><i class="fas fa-spinner fa-spin"></i></div>
494 </div>
495 <div class="wpf-notification-actions">
496 <span class="wpf-action wpf-notification-action-clear-all" data-foro_n="<?php echo wp_create_nonce( 'wpforo_clear_notifications' ) ?>"><?php wpforo_phrase( 'Clear all' ) ?></span>
497 </div>
498 </div>
499 <?php
500 }
501
502 public function notifications_list( $echo = true ) {
503 $items = [];
504 $list_html = '';
505 if( ! empty( $this->notifications ) && is_array( $this->notifications ) ) {
506 $list_html .= '<ul>';
507 foreach( $this->notifications as $n ) {
508 if( $type = wpfval( $n, 'type' ) ) {
509 $html = wpfval( $this->actions, $type ) ? $this->actions[ $type ] : $this->actions['default'];
510 $items[ $n['id'] ] = $html['before'];
511 if( wpfval( $n, 'itemid_second' ) ) {
512 $member = wpforo_member( $n['itemid_second'] );
513 $member_name = wpfval( $member, 'display_name' ) ? $member['display_name'] : wpforo_phrase( 'Guest', false );
514 } else {
515 $member_name = wpfval( $n, 'name' ) ? $n['name'] : wpforo_phrase( 'Guest', false );
516 }
517 if( strpos( (string) $n['permalink'], '#' ) === false ) {
518 $n['permalink'] = wp_nonce_url( $n['permalink'] . '?_nread=' . $n['id'], 'wpforo_mark_notification_read', 'foro_n' );
519 } else {
520 $n['permalink'] = str_replace( '#', '?_nread=' . $n['id'] . '#', $n['permalink'] );
521 $n['permalink'] = wp_nonce_url( $n['permalink'], 'wpforo_mark_notification_read', 'foro_n' );
522 }
523 $date = wpforo_date( $n['date'], 'ago', false );
524 $length = apply_filters( 'wpforo_notification_description_length', 40 );
525 $items[ $n['id'] ] .= '<div class="wpf-nleft">' . $html['icon'] . '</div>';
526 $items[ $n['id'] ] .= '<div class="wpf-nright">';
527 $items[ $n['id'] ] .= '<a href="' . esc_url_raw( $n['permalink'] ) . '">';
528 $items[ $n['id'] ] .= sprintf( $html['description'], '<strong>' . $member_name . '</strong>', $date );
529 $items[ $n['id'] ] .= '</a>';
530 $items[ $n['id'] ] .= '<div class="wpf-ndesc">' . stripslashes( wpforo_text( (string) $n['content'], $length, false ) ) . '</div>';
531 $items[ $n['id'] ] .= '</div>';
532 $items[ $n['id'] ] .= $html['after'];
533 }
534 }
535 $items = apply_filters( 'wpforo_notifications_list', $items );
536 $list_html .= implode( "\r\n", $items );
537 $list_html .= '</ul>';
538 } else {
539 $list_html = $this->get_no_notifications_html();
540 }
541 if( $echo ) echo $list_html;
542
543 return $list_html;
544 }
545
546 public function get_no_notifications_html() {
547 return '<div class="wpf-no-notification">' . wpforo_phrase( 'You have no new notifications', false ) . '</div>';
548 }
549
550 public function get_notifications() {
551 $args = [ 'itemtype' => 'alert', 'userid' => WPF()->current_userid, 'row_count' => 100, 'orderby' => 'date', 'order' => 'DESC' ];
552 $args = apply_filters( 'wpforo_get_notifications_args', $args );
553
554 return $this->get_activities( $args );
555 }
556
557 public function add_notification_new_reply( $type, $post, $topic = [] ): void {
558 if( ! wpfval( $post, 'status' ) ) {
559 $notification = [
560 'type' => $type,
561 'itemid' => $post['postid'],
562 'itemtype' => 'alert',
563 'itemid_second' => $post['userid'],
564 'name' => $post['name'],
565 'email' => $post['email'],
566 'content' => $post['title'],
567 'permalink' => $post['posturl'],
568 'new' => 1,
569 ];
570 // Notify replied person
571 $replied_post = wpforo_post( $post['parentid'] );
572 if( ! empty( $replied_post ) && wpfval( $replied_post, 'userid' ) != wpfval( $post, 'userid' ) ) {
573 $notification['userid'] = $replied_post['userid'];
574 $notification = apply_filters( 'wpforo_add_notification_new_reply_data', $notification, $type, $post, $topic, $replied_post );
575 $this->add( $notification );
576 }
577 // Notify the topic author
578 if( ! empty( $topic ) && $topic['userid'] != $post['userid'] && ! ( ! empty( $replied_post ) && $topic['userid'] == $replied_post['userid'] ) ) {
579 $notification['userid'] = $topic['userid'];
580 $notification = apply_filters( 'wpforo_add_notification_new_reply_data', $notification, $type, $post, $topic, $replied_post );
581 $this->add( $notification );
582 }
583 }
584 }
585
586 public function add_notification( $type, $args ): void {
587 if( $args['userid'] != WPF()->current_userid ) {
588 $length = apply_filters( 'wpforo_notification_saved_description_length', 50 );
589 $notification = [
590 'type' => $type,
591 'itemid' => $args['itemid'],
592 'itemtype' => 'alert',
593 'itemid_second' => WPF()->current_userid,
594 'userid' => $args['userid'],
595 'name' => WPF()->current_user_display_name,
596 'email' => WPF()->current_user_email,
597 'content' => wpforo_text( $args['content'], $length, false ),
598 'permalink' => ( wpfval( $args, 'permalink' ) ? $args['permalink'] : '#' ),
599 'new' => 1,
600 ];
601 $notification = apply_filters( 'wpforo_add_notification_data', $notification, $type, $args );
602 $this->add( $notification );
603 }
604 }
605
606 public function after_like( $post ): void {
607 if( $post ) {
608 $args = [
609 'itemid' => $post['postid'],
610 'userid' => $post['userid'],
611 'content' => $post['body'],
612 'permalink' => WPF()->post->get_url( $post['postid'] ),
613 ];
614 $this->add_notification( 'new_like', $args );
615 }
616 }
617
618 public function after_dislike( $post ): void {
619 if( $post ) {
620 $args = [
621 'itemid' => $post['postid'],
622 'userid' => $post['userid'],
623 'content' => $post['body'],
624 'permalink' => WPF()->post->get_url( $post['postid'] ),
625 ];
626 $this->add_notification( 'new_dislike', $args );
627 }
628 }
629
630 public function after_undo_like( $post ) {
631 $args = [
632 'type' => 'new_like',
633 'itemid' => $post['postid'],
634 'itemtype' => 'alert',
635 'itemid_second' => WPF()->current_userid,
636 ];
637 $this->delete_notification( $args );
638 }
639
640 public function after_undo_dislike( $post ) {
641 $args = [
642 'type' => 'new_dislike',
643 'itemid' => $post['postid'],
644 'itemtype' => 'alert',
645 'itemid_second' => WPF()->current_userid,
646 ];
647 $this->delete_notification( $args );
648 }
649
650 public function after_vote( $reaction, $post ) {
651 if( $post ) {
652 if( $reaction == 1 ) {
653 $args = [
654 'itemid' => $post['postid'],
655 'userid' => $post['userid'],
656 'content' => $post['body'],
657 'permalink' => WPF()->post->get_url( $post['postid'] ),
658 ];
659 $this->add_notification( 'new_up_vote', $args );
660 $args = [
661 'type' => 'new_down_vote',
662 'itemid' => $post['postid'],
663 'itemtype' => 'alert',
664 'itemid_second' => WPF()->current_userid,
665 ];
666 $this->delete_notification( $args );
667 } elseif( $reaction == - 1 ) {
668 $args = [
669 'itemid' => $post['postid'],
670 'userid' => $post['userid'],
671 'content' => $post['body'],
672 'permalink' => WPF()->post->get_url( $post['postid'] ),
673 ];
674 $this->add_notification( 'new_down_vote', $args );
675 $args = [
676 'type' => 'new_up_vote',
677 'itemid' => $post['postid'],
678 'itemtype' => 'alert',
679 'itemid_second' => WPF()->current_userid,
680 ];
681 $this->delete_notification( $args );
682 }
683 }
684 }
685
686 public function delete_notification( $args ) {
687 $this->delete( $args );
688 }
689
690 public function update_notification( $post, $status ) {
691 $post['status'] = $status = intval($status);
692 $post['posturl'] = WPF()->post->get_url( $post['postid'] );
693 if( wpfval( $post, 'topicid' ) ) {
694 $topic = WPF()->topic->get_topic( $post['topicid'] );
695 if( $status ) {
696 $args = [
697 'type' => 'new_reply',
698 'itemid' => $post['postid'],
699 'itemtype' => 'alert',
700 ];
701 $this->delete_notification( $args );
702 } else {
703 $this->add_notification_new_reply( 'new_reply', $post, $topic );
704 }
705 }
706 }
707
708 public function read_notification( $id, $userid = null ) {
709 $userid = is_null( $userid ) ? WPF()->current_userid : $userid;
710 $args = [
711 'id' => $id,
712 'userid' => $userid,
713 ];
714 $this->delete_notification( $args );
715 }
716
717 public function clear_notifications( $userid = null ) {
718 $userid = is_null( $userid ) ? WPF()->current_userid : $userid;
719 $args = [
720 'userid' => $userid,
721 ];
722 $this->delete_notification( $args );
723 }
724
725 }
726