init_defaults(); $this->activity = $this->default->activity; $this->init_hooks(); $this->init_actions(); if( is_user_logged_in() && wpforo_setting( 'notifications', 'notifications' ) ) { $this->notifications = $this->get_notifications(); } } private function init_actions() { $this->actions = [ 'edit_topic' => [ 'title' => wpforo_phrase( 'Edit Topic', false ), 'icon' => '', 'description' => wpforo_phrase( 'This topic was modified %s by %s', false ), 'before' => '
', 'after' => '
', ], 'edit_post' => [ 'title' => wpforo_phrase( 'Edit Post', false ), 'icon' => '', 'description' => wpforo_phrase( 'This post was modified %s by %s', false ), 'before' => '
', 'after' => '
', ], 'new_reply' => [ 'title' => wpforo_phrase( 'New Reply', false ), 'icon' => '', 'description' => wpforo_phrase( 'New reply from %1$s, %2$s', false ), 'before' => '
  • ', 'after' => '
  • ', ], 'new_like' => [ 'title' => wpforo_phrase( 'New Like', false ), 'icon' => '', 'description' => wpforo_phrase( 'New like from %1$s, %2$s', false ), 'before' => '
  • ', 'after' => '
  • ', ], 'new_dislike' => [ 'title' => wpforo_phrase( 'New Dislike', false ), 'icon' => '', 'description' => wpforo_phrase( 'New dislike from %1$s, %2$s', false ), 'before' => '
  • ', 'after' => '
  • ', ], 'new_up_vote' => [ 'title' => wpforo_phrase( 'New Up Vote', false ), 'icon' => '', 'description' => wpforo_phrase( 'New up vote from %1$s, %2$s', false ), 'before' => '
  • ', 'after' => '
  • ', ], 'new_down_vote' => [ 'title' => wpforo_phrase( 'New Down Vote', false ), 'icon' => '', 'description' => wpforo_phrase( 'New down vote from %1$s, %2$s', false ), 'before' => '
  • ', 'after' => '
  • ', ], 'new_mention' => [ 'title' => wpforo_phrase( 'New User Mentioning', false ), 'icon' => '', 'description' => wpforo_phrase( '%1$s has mentioned you, %2$s', false ), 'before' => '
  • ', 'after' => '
  • ', ], 'default' => [ 'title' => wpforo_phrase( 'New Notification', false ), 'icon' => '', 'description' => wpforo_phrase( 'New notification from %1$s, %2$s', false ), 'before' => '
  • ', 'after' => '
  • ', ], ]; $this->actions = apply_filters( 'wpforo_register_actions', $this->actions ); } private function init_defaults() { $this->default = new stdClass(); $this->default->activity = [ 'id' => 0, 'type' => '', 'itemid' => 0, 'itemtype' => '', 'itemid_second' => 0, 'userid' => 0, 'name' => '', 'email' => '', 'date' => 0, 'content' => '', 'permalink' => '', 'new' => 0, ]; $this->default->activity_format = [ 'id' => '%d', 'type' => '%s', 'itemid' => '%d', 'itemtype' => '%s', 'itemid_second' => '%d', 'userid' => '%d', 'name' => '%s', 'email' => '%s', 'date' => '%d', 'content' => '%s', 'permalink' => '%s', 'new' => '%d', ]; $this->default->sql_select_args = [ 'type' => null, 'userid' => null, 'itemtype' => null, 'new' => null, 'include' => [], 'exclude' => [], 'userids_include' => [], 'userids_exclude' => [], 'types_include' => [], 'types_exclude' => [], 'itemids_include' => [], 'itemids_exclude' => [], 'itemtypes_include' => [], 'itemtypes_exclude' => [], 'emails_include' => [], 'emails_exclude' => [], 'orderby' => 'id', 'order' => 'ASC', 'offset' => null, 'row_count' => null, ]; $this->default = apply_filters( 'wpforo_activity_after_init_defaults', $this->default ); } private function init_hooks() { if( wpforo_setting( 'posting', 'edit_topic' ) ) { add_action( 'wpforo_after_edit_topic', [ $this, 'after_edit_topic' ] ); } if( wpforo_setting( 'posting', 'edit_post' ) ) { add_action( 'wpforo_after_edit_post', [ $this, 'after_edit_post' ] ); } if( WPF()->current_userid && wpforo_setting( 'notifications', 'notifications' ) ) { if( wpforo_setting( 'notifications', 'notifications_bar' ) ) { add_action( 'wpforo_before_search_toggle', [ $this, 'bell' ] ); } add_action( 'wpforo_after_add_post', [ $this, 'after_add_post' ], 10, 2 ); add_action( 'wpforo_post_status_update', [ $this, 'update_notification' ], 10, 2 ); add_action( 'wpforo_like', [ $this, 'after_like' ] ); add_action( 'wpforo_dislike', [ $this, 'after_dislike' ] ); add_action( 'wpforo_undo_like', [ $this, 'after_undo_like' ] ); add_action( 'wpforo_undo_dislike', [ $this, 'after_undo_dislike' ] ); add_action( 'wpforo_vote', [ $this, 'after_vote' ], 10, 2 ); } } private function filter_built_html_rows( $rows ) { $_rows = []; foreach( $rows as $row_key => $row ) { $in_array = false; if( $_rows ) { foreach( $_rows as $_row_key => $_row ) { if( in_array( $row, $_row ) ) { $in_array = true; $match_key = $_row_key; break; } } } if( $in_array && isset( $match_key ) ) { $_rows[ $match_key ]['times'] ++; } else { $_rows[ $row_key ]['html'] = $row; $_rows[ $row_key ]['times'] = 1; } } $rows = []; foreach( $_rows as $_row ) { $times = ''; if( $_row['times'] > 1 ) { $times = ' ' . sprintf( wpforo_phrase( '%d times', false ), $_row['times'] ); } $rows[] = sprintf( $_row['html'], $times ); } $limit = wpforo_setting( 'posting', 'edit_log_display_limit' ); if( $limit ) $rows = array_slice( $rows, ( - 1 * $limit ), $limit ); return $rows; } private function parse_activity( $data ) { return apply_filters( 'wpforo_activty_parse_activity', array_merge( $this->default->activity, $data ) ); } private function parse_args( $args ) { $args = wpforo_parse_args( $args, $this->default->sql_select_args ); $args['include'] = wpforo_parse_args( $args['include'] ); $args['exclude'] = wpforo_parse_args( $args['exclude'] ); $args['userids_include'] = wpforo_parse_args( $args['userids_include'] ); $args['userids_exclude'] = wpforo_parse_args( $args['userids_exclude'] ); $args['types_include'] = wpforo_parse_args( $args['types_include'] ); $args['types_exclude'] = wpforo_parse_args( $args['types_exclude'] ); $args['itemids_include'] = wpforo_parse_args( $args['itemids_include'] ); $args['itemids_exclude'] = wpforo_parse_args( $args['itemids_exclude'] ); $args['itemtypes_include'] = wpforo_parse_args( $args['itemtypes_include'] ); $args['itemtypes_exclude'] = wpforo_parse_args( $args['itemtypes_exclude'] ); $args['emails_include'] = wpforo_parse_args( $args['emails_include'] ); $args['emails_exclude'] = wpforo_parse_args( $args['emails_exclude'] ); return $args; } private function build_sql_select( $args ) { $args = $this->parse_args( $args ); $wheres = []; if( ! is_null( $args['type'] ) ) $wheres[] = "`type` = '" . esc_sql( $args['type'] ) . "'"; if( ! is_null( $args['itemtype'] ) ) $wheres[] = "`itemtype` = '" . esc_sql( $args['itemtype'] ) . "'"; if( ! is_null( $args['userid'] ) ) $wheres[] = "`userid` = " . intval( $args['userid'] ); if( ! is_null( $args['new'] ) ) $wheres[] = "`new` = " . intval( $args['new'] ); if( ! empty( $args['include'] ) ) $wheres[] = "`id` IN(" . implode( ',', array_map( 'wpforo_bigintval', $args['include'] ) ) . ")"; if( ! empty( $args['exclude'] ) ) $wheres[] = "`id` NOT IN(" . implode( ',', array_map( 'wpforo_bigintval', $args['exclude'] ) ) . ")"; if( ! empty( $args['userids_include'] ) ) $wheres[] = "`userid` IN(" . implode( ',', array_map( 'wpforo_bigintval', $args['userids_include'] ) ) . ")"; if( ! empty( $args['userids_exclude'] ) ) $wheres[] = "`userid` NOT IN(" . implode( ',', array_map( 'wpforo_bigintval', $args['userids_exclude'] ) ) . ")"; if( ! empty( $args['types_include'] ) ) $wheres[] = "`type` IN('" . implode( "','", array_map( 'trim', $args['types_include'] ) ) . "')"; if( ! empty( $args['types_exclude'] ) ) $wheres[] = "`type` NOT IN('" . implode( "','", array_map( 'trim', $args['types_exclude'] ) ) . "')"; if( ! empty( $args['itemids_include'] ) ) $wheres[] = "`itemid` IN(" . implode( ',', array_map( 'wpforo_bigintval', $args['itemids_include'] ) ) . ")"; if( ! empty( $args['itemids_exclude'] ) ) $wheres[] = "`itemid` NOT IN(" . implode( ',', array_map( 'wpforo_bigintval', $args['itemids_exclude'] ) ) . ")"; if( ! empty( $args['itemtypes_include'] ) ) $wheres[] = "`itemtype` IN('" . implode( "','", array_map( 'trim', $args['itemtypes_include'] ) ) . "')"; if( ! empty( $args['itemtypes_exclude'] ) ) $wheres[] = "`itemtype` NOT IN('" . implode( "','", array_map( 'trim', $args['itemtypes_exclude'] ) ) . "')"; if( ! empty( $args['emails_include'] ) ) $wheres[] = "`email` IN('" . implode( "','", array_map( 'trim', $args['emails_include'] ) ) . "')"; if( ! empty( $args['emails_exclude'] ) ) $wheres[] = "`email` NOT IN('" . implode( "','", array_map( 'trim', $args['emails_exclude'] ) ) . "')"; $sql = "SELECT * FROM " . WPF()->tables->activity; if( $wheres ) $sql .= " WHERE " . implode( " AND ", $wheres ); $sql .= " ORDER BY " . $args['orderby'] . " " . $args['order']; if( $args['row_count'] ) { if( ! empty( $args['offset'] ) ) { $sql .= " LIMIT " . wpforo_bigintval( $args['offset'] ) . "," . wpforo_bigintval( $args['row_count'] ); } else { $sql .= " LIMIT " . wpforo_bigintval( $args['row_count'] ); } } return $sql; } public function get_activity( $args ) { if( ! $args ) return false; return $this->parse_activity( (array) WPF()->db->get_row( $this->build_sql_select( $args ), ARRAY_A ) ); } public function get_activities( $args ) { if( ! $args ) return []; return array_map( [ $this, 'parse_activity' ], (array) WPF()->db->get_results( $this->build_sql_select( $args ), ARRAY_A ) ); } public function after_edit_topic( $topic ) { $data = [ 'type' => 'edit_topic', 'itemid' => $topic['topicid'], 'itemtype' => 'topic', 'userid' => WPF()->current_userid, 'name' => WPF()->current_user_display_name, 'email' => WPF()->current_user_email, 'permalink' => wpforo_topic( $topic['topicid'], 'url' ), ]; $this->add( $data ); } public function after_edit_post( $post ) { $data = [ 'type' => 'edit_post', 'itemid' => $post['postid'], 'itemtype' => 'post', 'userid' => WPF()->current_userid, 'name' => WPF()->current_user_display_name, 'email' => WPF()->current_user_email, 'permalink' => wpforo_post( $post['postid'], 'url' ), ]; $this->add( $data ); } public function after_add_post( $post, $topic ) { $this->add_notification_new_reply( 'new_reply', $post, $topic ); } private function add( $data ) { if( empty( $data ) ) return false; $activity = array_merge( $this->default->activity, $data ); unset( $activity['id'] ); if( ! $activity['type'] || ! $activity['itemid'] || ! $activity['itemtype'] ) return false; if( ! $activity['date'] ) $activity['date'] = time(); $activity = apply_filters( 'wpforo_add_activity_data_filter', $activity ); do_action( 'wpforo_before_add_activity', $activity ); $activity = wpforo_array_ordered_intersect_key( $activity, $this->default->activity_format ); if( WPF()->db->insert( WPF()->tables->activity, $activity, wpforo_array_ordered_intersect_key( $this->default->activity_format, $activity ) ) ) { $activity['id'] = WPF()->db->insert_id; do_action( 'wpforo_after_add_activity', $activity ); return $activity['id']; } return false; } private function edit( $data, $where ) { if( empty( $data ) || empty( $where ) ) return false; if( is_numeric( $where ) ) $where = [ 'id' => $where ]; $data = (array) $data; $where = (array) $where; $data = apply_filters( 'wpforo_activity_edit_data_filter', $data ); $where = apply_filters( 'wpforo_activity_edit_where_filter', $where ); do_action( 'wpforo_before_edit_activity', $data, $where ); $data = wpforo_array_ordered_intersect_key( $data, $this->default->activity_format ); $where = wpforo_array_ordered_intersect_key( $where, $this->default->activity_format ); if( false !== WPF()->db->update( WPF()->tables->activity, $data, $where, wpforo_array_ordered_intersect_key( $this->default->activity_format, $data ), wpforo_array_ordered_intersect_key( $this->default->activity_format, $where ) ) ) { do_action( 'wpforo_after_edit_activity', $data, $where ); return true; } return false; } private function delete( $where ) { if( empty( $where ) ) return false; if( is_numeric( $where ) ) $where = [ 'id' => $where ]; $where = (array) $where; $where = apply_filters( 'wpforo_activity_delete_where_filter', $where ); do_action( 'wpforo_before_delete_activity', $where ); $where = wpforo_array_ordered_intersect_key( $where, $this->default->activity_format ); if( false !== WPF()->db->delete( WPF()->tables->activity, $where, wpforo_array_ordered_intersect_key( $this->default->activity_format, $where ) ) ) { do_action( 'wpforo_after_delete_activity', $where ); return true; } return false; } public function build( $itemtype, $itemid, $type, $echo = false ) { $rows = []; $args = [ 'itemtypes_include' => $itemtype, 'itemids_include' => $itemid, 'types_include' => $type, ]; if( $activities = $this->get_activities( $args ) ) { foreach( $activities as $activity ) { switch( $activity['type'] ) { case 'edit_topic': case 'edit_post': $rows[] = $this->_build_edit_topic_edit_post( $activity ); break; } } } $rows = $this->filter_built_html_rows( $rows ); $html = ( $rows ? implode( '', $rows ) : '' ); if( $echo ) echo $html; return $html; } private function _build_edit_topic_edit_post( $activity ) { $html = ''; $type = $activity['type']; $userid = $activity['userid']; $date = wpforo_date( $activity['date'], 'ago', false ) . '%s'; if( $userid ) { $profile_url = wpforo_member( $userid, 'profile_url' ); $display_name = wpforo_member( $userid, 'display_name' ); $user = sprintf( '%s', $profile_url, $display_name ); } else { $user = $activity['name'] ?: wpforo_phrase( 'Guest', false ); } if( wpfval( $this->actions, $type, 'before' ) ) { $html = $this->actions[ $type ]['before']; $html = apply_filters( 'wpforo_activity_action_html_before', $html, $activity ); } if( wpfval( $this->actions, $type, 'description' ) ) { $html .= sprintf( $this->actions[ $activity['type'] ]['description'], $date, str_replace( '%', '%%', $user ) ); $html = apply_filters( 'wpforo_activity_action_html', $html, $activity ); } if( wpfval( $this->actions, $type, 'after' ) ) { $html .= $this->actions[ $type ]['after']; $html = apply_filters( 'wpforo_activity_action_html_after', $html, $activity ); } return $html; } public function bell( $class = 'wpf-alerts' ) { wp_enqueue_script( 'wpforo-widgets-js' ); $class = ( ! $class ) ? 'wpf-alerts' : $class; $count = ( ! empty( $this->notifications ) ) ? count( $this->notifications ) : 0; $phrase = ( $count > 1 ) ? wpforo_phrase( 'You have new notifications', false ) : wpforo_phrase( 'You have a new notification', false ); $tooltip = ' wpf-tooltip="' . esc_attr( $phrase ) . '" wpf-tooltip-size="middle"'; ?>
    >
    notifications ) && is_array( $this->notifications ) ) { $list_html .= ''; } else { $list_html = $this->get_no_notifications_html(); } if( $echo ) echo $list_html; return $list_html; } public function get_no_notifications_html() { return '
    ' . wpforo_phrase( 'You have no new notifications', false ) . '
    '; } public function get_notifications() { $args = [ 'itemtype' => 'alert', 'userid' => WPF()->current_userid, 'row_count' => 100, 'orderby' => 'date', 'order' => 'DESC' ]; $args = apply_filters( 'wpforo_get_notifications_args', $args ); return $this->get_activities( $args ); } public function add_notification_new_reply( $type, $post, $topic = [] ): void { if( ! wpfval( $post, 'status' ) ) { $notification = [ 'type' => $type, 'itemid' => $post['postid'], 'itemtype' => 'alert', 'itemid_second' => $post['userid'], 'name' => $post['name'], 'email' => $post['email'], 'content' => $post['title'], 'permalink' => $post['posturl'], 'new' => 1, ]; // Notify replied person $replied_post = wpforo_post( $post['parentid'] ); if( ! empty( $replied_post ) && wpfval( $replied_post, 'userid' ) != wpfval( $post, 'userid' ) ) { $notification['userid'] = $replied_post['userid']; $notification = apply_filters( 'wpforo_add_notification_new_reply_data', $notification, $type, $post, $topic, $replied_post ); $this->add( $notification ); } // Notify the topic author if( ! empty( $topic ) && $topic['userid'] != $post['userid'] && ! ( ! empty( $replied_post ) && $topic['userid'] == $replied_post['userid'] ) ) { $notification['userid'] = $topic['userid']; $notification = apply_filters( 'wpforo_add_notification_new_reply_data', $notification, $type, $post, $topic, $replied_post ); $this->add( $notification ); } } } public function add_notification( $type, $args ): void { if( $args['userid'] != WPF()->current_userid ) { $length = apply_filters( 'wpforo_notification_saved_description_length', 50 ); $notification = [ 'type' => $type, 'itemid' => $args['itemid'], 'itemtype' => 'alert', 'itemid_second' => WPF()->current_userid, 'userid' => $args['userid'], 'name' => WPF()->current_user_display_name, 'email' => WPF()->current_user_email, 'content' => wpforo_text( $args['content'], $length, false ), 'permalink' => ( wpfval( $args, 'permalink' ) ? $args['permalink'] : '#' ), 'new' => 1, ]; $notification = apply_filters( 'wpforo_add_notification_data', $notification, $type, $args ); $this->add( $notification ); } } public function after_like( $post ): void { if( $post ) { $args = [ 'itemid' => $post['postid'], 'userid' => $post['userid'], 'content' => $post['body'], 'permalink' => WPF()->post->get_url( $post['postid'] ), ]; $this->add_notification( 'new_like', $args ); } } public function after_dislike( $post ): void { if( $post ) { $args = [ 'itemid' => $post['postid'], 'userid' => $post['userid'], 'content' => $post['body'], 'permalink' => WPF()->post->get_url( $post['postid'] ), ]; $this->add_notification( 'new_dislike', $args ); } } public function after_undo_like( $post ) { $args = [ 'type' => 'new_like', 'itemid' => $post['postid'], 'itemtype' => 'alert', 'itemid_second' => WPF()->current_userid, ]; $this->delete_notification( $args ); } public function after_undo_dislike( $post ) { $args = [ 'type' => 'new_dislike', 'itemid' => $post['postid'], 'itemtype' => 'alert', 'itemid_second' => WPF()->current_userid, ]; $this->delete_notification( $args ); } public function after_vote( $reaction, $post ) { if( $post ) { if( $reaction == 1 ) { $args = [ 'itemid' => $post['postid'], 'userid' => $post['userid'], 'content' => $post['body'], 'permalink' => WPF()->post->get_url( $post['postid'] ), ]; $this->add_notification( 'new_up_vote', $args ); $args = [ 'type' => 'new_down_vote', 'itemid' => $post['postid'], 'itemtype' => 'alert', 'itemid_second' => WPF()->current_userid, ]; $this->delete_notification( $args ); } elseif( $reaction == - 1 ) { $args = [ 'itemid' => $post['postid'], 'userid' => $post['userid'], 'content' => $post['body'], 'permalink' => WPF()->post->get_url( $post['postid'] ), ]; $this->add_notification( 'new_down_vote', $args ); $args = [ 'type' => 'new_up_vote', 'itemid' => $post['postid'], 'itemtype' => 'alert', 'itemid_second' => WPF()->current_userid, ]; $this->delete_notification( $args ); } } } public function delete_notification( $args ) { $this->delete( $args ); } public function update_notification( $post, $status ) { $post['status'] = $status = intval($status); $post['posturl'] = WPF()->post->get_url( $post['postid'] ); if( wpfval( $post, 'topicid' ) ) { $topic = WPF()->topic->get_topic( $post['topicid'] ); if( $status ) { $args = [ 'type' => 'new_reply', 'itemid' => $post['postid'], 'itemtype' => 'alert', ]; $this->delete_notification( $args ); } else { $this->add_notification_new_reply( 'new_reply', $post, $topic ); } } } public function read_notification( $id, $userid = null ) { $userid = is_null( $userid ) ? WPF()->current_userid : $userid; $args = [ 'id' => $id, 'userid' => $userid, ]; $this->delete_notification( $args ); } public function clear_notifications( $userid = null ) { $userid = is_null( $userid ) ? WPF()->current_userid : $userid; $args = [ 'userid' => $userid, ]; $this->delete_notification( $args ); } }