'Your forum\'s recent topics.' ] ); $this->init_local_vars(); add_action( 'wp_ajax_wpforo_load_ajax_widget_RecentTopics', [ $this, 'load_ajax_widget' ] ); add_action( 'wp_ajax_nopriv_wpforo_load_ajax_widget_RecentTopics', [ $this, 'load_ajax_widget' ] ); if( is_admin() ) { add_action( 'wp_ajax_wpforo_get_forum_tree', [ $this, 'get_forum_tree' ] ); } } private function init_local_vars() { $this->default_instance = [ 'boardid' => 0, 'title' => 'Recent Topics', 'forumids' => [], 'orderby' => 'created', 'order' => 'DESC', 'count' => 9, 'display_avatar' => true, 'forumids_filter' => false, 'current_forumid_filter' => false, 'goto_unread' => false, 'refresh_interval' => 0, ]; $this->orderby_fields = [ 'created' => __( 'Created Date', 'wpforo' ), 'modified' => __( 'Modified Date', 'wpforo' ), 'posts' => __( 'Posts Count', 'wpforo' ), 'views' => __( 'Views Count', 'wpforo' ), ]; $this->order_fields = [ 'DESC' => __( 'DESC', 'wpforo' ), 'ASC' => __( 'ASC', 'wpforo' ), 'RAND' => __( 'Random', 'wpforo' ), ]; } private function add_topic_cache_filter( $topic_args ) { if( $topic_args['order'] === 'RAND' ) { add_filter( 'wpforo_cache_topic', '__return_false' ); } } private function remove_topic_cache_filter( $topic_args ) { if( $topic_args['order'] === 'RAND' ) { remove_filter( 'wpforo_cache_topic', '__return_false' ); } } public function get_widget( $instance, $topic_args ) { $this->add_topic_cache_filter( $topic_args ); $is_user_logged_in = (bool) WPF()->current_userid; $topic_args['private'] = ( ! $is_user_logged_in || ! WPF()->usergroup->can( 'aum' ) ) ? 0 : null;; $topic_args['status'] = ( ! $is_user_logged_in || ! WPF()->usergroup->can( 'aum' ) ) ? 0 : null; $row_count = (int) wpfval( $topic_args, 'row_count' ); $topics = []; $topic_args['offset'] = 0; while( $row_count && count( $topics ) < $row_count ) { if( ! ( $_topics = WPF()->topic->get_topics( $topic_args ) ) ) break; $topics = array_merge( $topics, $_topics ); $topic_args['offset'] += $row_count; } array_splice( $topics, $row_count ); $print_avatar = $instance['display_avatar'] && wpforo_setting( 'profiles', 'avatars' ) && WPF()->usergroup->can( 'va' ); $lis = ''; foreach( $topics as $topic ) { $topic_url = wpforo_topic( $topic['topicid'], 'url' ); $member = wpforo_member( $topic ); $lis .= sprintf( '
  • %1$s

    %3$s

    %4$s %5$s %6$s

  • ', ( $print_avatar ? sprintf( '
    %1$s
    ', wpforo_user_avatar( $member ) ) : '' ), ( ! $print_avatar ? 'style="width: 100%"' : '' ), ( wpfval( $instance, 'goto_unread' ) ? wpforo_topic_title( $topic, $topic_url, '{p}{au}{t}{/a}', false ) . ( $topic['topicid'] != wpfval( WPF()->current_object, 'topicid' ) ? wpforo_unread_button( $topic['topicid'], $topic_url, false ) : '' ) : wpforo_topic_title( $topic, $topic_url, '{p}{a}{t}{/a}', false ) ), wpforo_phrase( 'by', false ), wpforo_member_link( $member, '', 30, '', false ), esc_html( wpforo_date( $topic['created'], 'ago', false ) ) ); } $this->remove_topic_cache_filter( $topic_args ); return sprintf( '', $lis ); } public function load_ajax_widget() { $_POST = wp_unslash( $_POST ); $instance = json_decode( (string) wpfval( $_POST, 'instance' ), true ); $topic_args = json_decode( (string) wpfval( $_POST, 'topic_args' ), true ); // SECURITY FIX: Sanitize and validate all user-controlled parameters if( is_array( $topic_args ) ) { // Remove dangerous 'where' parameter unset( $topic_args['where'] ); // Validate 'orderby' parameter against whitelist if( isset( $topic_args['orderby'] ) ) { if( ! key_exists( $topic_args['orderby'], $this->orderby_fields ) ) { $topic_args['orderby'] = $this->default_instance['orderby']; } } // Validate 'order' parameter against whitelist if( isset( $topic_args['order'] ) ) { if( ! key_exists( $topic_args['order'], $this->order_fields ) ) { $topic_args['order'] = $this->default_instance['order']; } } // SECURITY: coerce id-list fields to integer arrays so a serialized // payload from an unauthenticated POST can never reach // wpforo_parse_args() / unserialize() downstream. Defense in depth // alongside the allowed_classes=>false hardening in wpforo_parse_args. foreach( [ 'forumids', 'include', 'exclude' ] as $idfield ) { if( isset( $topic_args[ $idfield ] ) ) { $topic_args[ $idfield ] = is_array( $topic_args[ $idfield ] ) ? array_map( 'intval', $topic_args[ $idfield ] ) : []; } } } wp_send_json_success( [ 'html' => $this->get_widget( $instance, $topic_args ) ] ); } public function widget( $args, $instance ) { wp_enqueue_script( 'wpforo-widgets-js' ); $instance = wpforo_parse_args( $instance, $this->default_instance ); if( $instance['current_forumid_filter'] && $instance['boardid'] === WPF()->board->get_current( 'boardid' ) && $current_forumid = wpfval( WPF()->current_object, 'forumid' ) ) { $instance['forumids'] = (array) $current_forumid; } $data = [ 'boardid' => $instance['boardid'], 'action' => 'wpforo_load_ajax_widget_RecentTopics', 'instance' => $instance, 'topic_args' => [ 'forumids' => ( $instance['forumids'] ?: $this->default_instance['forumids'] ), 'orderby' => ( key_exists( $instance['orderby'], $this->orderby_fields ) ? $instance['orderby'] : $this->default_instance['orderby'] ), 'order' => ( key_exists( $instance['order'], $this->order_fields ) ? $instance['order'] : $this->default_instance['order'] ), 'row_count' => ( ( $count = intval( $instance['count'] ) ) ? $count : $this->default_instance['count'] ), ], ]; if( WPF()->board->get_current( 'boardid' ) === $instance['boardid'] ) { $html = $this->get_widget( $data['instance'], $data['topic_args'] ); $onload = false; } else { $html = '
    '; $onload = true; $data['referer'] = home_url(); } $json = wp_json_encode( $data ); echo $args['before_widget'] . '
    '; if( ! empty( $instance['title'] ) ) echo $args['before_title'] . apply_filters( 'widget_title', $instance['title'] ) . $args['after_title']; echo '
    ' . $html . '
    ' . $args['after_widget']; } public function form( $instance ) { $instance = wpforo_parse_args( $instance, $this->default_instance ); $title = (string) $instance['title']; $boardid = (int) $instance['boardid']; $selected = array_unique( array_filter( array_map( 'intval', (array) $instance['forumids'] ) ) ); $orderby = (string) $instance['orderby']; $order = (string) $instance['order']; $count = (int) $instance['count']; $display_avatar = (bool) $instance['display_avatar']; $forumids_filter = (bool) $instance['forumids_filter']; $current_forumid_filter = (bool) $instance['current_forumid_filter']; $goto_unread = (bool) $instance['goto_unread']; $refresh_interval = (int) $instance['refresh_interval']; WPF()->change_board( $boardid ); ?>

    : type="radio"> type="radio">

    : type="radio"> type="radio">

     

    : type="radio" name="get_field_name( 'display_avatar' ) ); ?>"> type="radio" name="get_field_name( 'display_avatar' ) ); ?>">

    : type="radio" name="get_field_name( 'goto_unread' ) ); ?>"> type="radio" name="get_field_name( 'goto_unread' ) ); ?>">

     

    default_instance ); $instance = []; $instance['title'] = strip_tags( (string) $new_instance['title'] ); $instance['boardid'] = (int) $new_instance['boardid']; $instance['forumids_filter'] = (bool) (int) $new_instance['forumids_filter']; $instance['forumids'] = array_unique( array_filter( array_map( 'intval', (array) $new_instance['forumids'] ) ) ); $instance['orderby'] = ( ! empty( $new_instance['orderby'] ) && key_exists( $new_instance['orderby'], $this->orderby_fields ) ) ? $new_instance['orderby'] : $this->default_instance['orderby']; $instance['order'] = ( ! empty( $new_instance['order'] ) && key_exists( $new_instance['order'], $this->order_fields ) ) ? $new_instance['order'] : $this->default_instance['order']; $instance['count'] = (int) $new_instance['count']; $instance['display_avatar'] = (bool) (int) $new_instance['display_avatar']; $instance['current_forumid_filter'] = (bool) (int) $new_instance['current_forumid_filter']; $instance['goto_unread'] = (bool) (int) $new_instance['goto_unread']; $instance['refresh_interval'] = (int) $new_instance['refresh_interval']; return $instance; } public function get_forum_tree() { ob_start(); WPF()->forum->tree( 'select_box', false, [] ); wp_send_json_success( [ 'html' => ob_get_clean() ] ); } }