PluginProbe
wpForo Forum / 3.1.5
wpForo Forum v3.1.5
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 / widgets / RecentPosts.php

RecentPosts.php in wpForo Forum 3.1.5, at widgets/RecentPosts.php

479 lines 28.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace wpforo\widgets;
4
5 use WP_Widget;
6
7 class RecentPosts extends WP_Widget {
8 private $default_instance = [];
9 private $orderby_fields = [];
10 private $order_fields = [];
11
12 function __construct() {
13 parent::__construct( 'wpforo_recent_posts', 'wpForo Recent Posts', [ 'description' => 'Your forum\'s recent posts.' ] );
14 $this->init_local_vars();
15 add_action( 'wp_ajax_wpforo_load_ajax_widget_RecentPosts', [ $this, 'load_ajax_widget' ] );
16 add_action( 'wp_ajax_nopriv_wpforo_load_ajax_widget_RecentPosts', [ $this, 'load_ajax_widget' ] );
17 if( is_admin() ) {
18 add_action( 'wp_ajax_wpforo_get_forum_tree', [ $this, 'get_forum_tree' ] );
19 }
20 }
21
22 private function init_local_vars() {
23 $this->default_instance = [
24 'boardid' => 0,
25 'title' => 'Recent Posts',
26 'forumids' => [],
27 'orderby' => 'created',
28 'order' => 'DESC',
29 'count' => 9,
30 'limit_per_topic' => 0,
31 'display_avatar' => true,
32 'forumids_filter' => false,
33 'current_forumid_filter' => false,
34 'exclude_firstposts' => false,
35 'display_only_unread' => false,
36 'display_new_indicator' => false,
37 'refresh_interval' => 0,
38 'excerpt_length' => 55,
39 ];
40 $this->orderby_fields = [
41 'created' => __( 'Created Date', 'wpforo' ),
42 'modified' => __( 'Modified Date', 'wpforo' ),
43 ];
44 $this->order_fields = [
45 'DESC' => __( 'DESC', 'wpforo' ),
46 'ASC' => __( 'ASC', 'wpforo' ),
47 'RAND' => __( 'Random', 'wpforo' ),
48 ];
49 }
50
51 private function add_post_cache_filter( $post_args ) {
52 if( $post_args['order'] === 'RAND' ) {
53 add_filter( 'wpforo_cache_post', '__return_false' );
54 }
55 }
56
57 private function remove_post_cache_filter( $post_args ) {
58 if( $post_args['order'] === 'RAND' ) {
59 remove_filter( 'wpforo_cache_post', '__return_false' );
60 }
61 }
62
63 public function get_widget( $instance, $post_args ) {
64 $this->add_post_cache_filter( $post_args );
65 $is_user_logged_in = (bool) WPF()->current_userid;
66 $post_args['private'] = ( ! $is_user_logged_in || ! WPF()->usergroup->can( 'aum' ) ) ? 0 : null;
67 $post_args['status'] = ( ! $is_user_logged_in || ! WPF()->usergroup->can( 'aum' ) ) ? 0 : null;
68 $print_avatar = $instance['display_avatar'] && wpforo_setting( 'profiles', 'avatars' ) && WPF()->usergroup->can( 'va' );
69
70 ob_start();
71 if( $post_args['limit_per_topic'] ) {
72 if( $instance['display_only_unread'] && $is_user_logged_in ) {
73 $grouped_postids = WPF()->post->get_unread_posts( $post_args, $post_args['row_count'] );
74 } else {
75 $grouped_postids = WPF()->post->get_posts( $post_args );
76 }
77 if( ! empty( $grouped_postids ) ) {
78 $grouped_postids = implode( ',', $grouped_postids );
79 $postids = array_filter( array_map( 'wpforo_bigintval', explode( ',', $grouped_postids ) ) );
80 rsort( $postids );
81 foreach( $postids as $postid ) {
82 $class = '';
83 $post = wpforo_post( $postid );
84 if( ! wpfval( $post, 'forumid' ) ) continue;
85 if( ! WPF()->post->view_access( $post ) ) continue;
86 $current = $post['topicid'] == wpfval( WPF()->current_object, 'topicid' );
87 if( ! $current ) {
88 $class = 'class="' . ( $instance['display_only_unread'] ? 'wpf-unread-post' : wpforo_unread( $post['topicid'], 'post', false, $post['postid'] ) ) . '"';
89 }
90 $member = wpforo_member( $post );
91 ?>
92 <li <?php echo $class; ?>>
93 <div class="wpforo-list-item ">
94 <?php if( $print_avatar ): ?>
95 <div class="wpforo-list-item-left">
96 <?php echo wpforo_user_avatar( $member ); ?>
97 </div>
98 <?php endif; ?>
99 <div class="wpforo-list-item-right" <?php if( ! $print_avatar ): ?> style="width: 100%"<?php endif; ?>>
100 <p class="posttitle">
101 <a href="<?php echo esc_url( (string) $post['url'] ) ?>"><?php
102 if( $t = esc_html( trim( (string) $post['title'] ) ) ) {
103 echo $t;
104 } else {
105 echo wpforo_phrase( 'RE', false, 'default' ) . ': ' . esc_html( trim( (string) wpforo_topic( $post['topicid'], 'title' ) ) );
106 } ?>
107 </a>
108 <?php if( ! $current && $instance['display_new_indicator'] ) wpforo_unread_button( $post['topicid'], '', true, $post['postid'] ) ?>
109 </p>
110 <p class="posttext"><?php echo esc_html( wpforo_text( $post['body'], $instance['excerpt_length'], false ) ); ?></p>
111 <p class="postuser"><?php wpforo_phrase( 'by' ) ?> <?php wpforo_member_link( $member ) ?>
112 , <span style="white-space: nowrap;"><?php wpforo_date( $post['created'] ) ?></span></p>
113 </div>
114 <div class="wpf-clear"></div>
115 </div>
116 </li>
117 <?php
118 }
119 } else {
120 $error_message = ( $instance['display_only_unread'] ) ? 'No new posts found' : 'No posts found';
121 echo '<li class="wpf-no-post-found">' . wpforo_phrase( $error_message, false ) . '</li>';
122 }
123 } else {
124 if( $instance['display_only_unread'] && $is_user_logged_in ) {
125 $recent_posts = WPF()->post->get_unread_posts( $post_args, $post_args['row_count'] );
126 } else {
127 $recent_posts = WPF()->post->get_posts( $post_args );
128 }
129 if( ! empty( $recent_posts ) ) {
130 foreach( $recent_posts as $post ) {
131 $class = '';
132 $post_url = wpforo_post( $post['postid'], 'url' );
133 $member = wpforo_member( $post );
134 $current = $post['topicid'] == wpfval( WPF()->current_object, 'topicid' );
135 if( ! $current ) {
136 $class = 'class="' . ( $instance['display_only_unread'] ? 'wpf-unread-post' : wpforo_unread( $post['topicid'], 'post', false, $post['postid'] ) ) . '"';
137 }
138 ?>
139 <li <?php echo $class; ?>>
140 <div class="wpforo-list-item">
141 <?php if( $print_avatar ): ?>
142 <div class="wpforo-list-item-left">
143 <?php echo wpforo_user_avatar( $member ); ?>
144 </div>
145 <?php endif; ?>
146 <div class="wpforo-list-item-right" <?php if( ! $print_avatar ): ?> style="width:100%"<?php endif; ?>>
147 <p class="posttitle">
148 <a href="<?php echo esc_url( (string) $post_url ) ?>"><?php
149 if( $t = esc_html( trim( (string) $post['title'] ) ) ) {
150 echo $t;
151 } else {
152 echo wpforo_phrase( 'RE', false, 'default' ) . ': ' . esc_html( trim( (string) wpforo_topic( $post['topicid'], 'title' ) ) );
153 } ?>
154 </a>
155 <?php if( ! $current && $instance['display_new_indicator'] ) wpforo_unread_button( $post['topicid'], '', true, $post['postid'] ) ?>
156 </p>
157 <p class="posttext"><?php echo esc_html( wpforo_text( $post['body'], $instance['excerpt_length'], false ) ); ?></p>
158 <p class="postuser"><?php wpforo_phrase( 'by' ) ?> <?php wpforo_member_link( $member ) ?>
159 , <span style="white-space: nowrap;"><?php wpforo_date( $post['created'] ) ?></span></p>
160 </div>
161 <div class="wpf-clear"></div>
162 </div>
163 </li>
164 <?php
165 }
166 } else {
167 $error_message = ( $instance['display_only_unread'] ) ? 'No new posts found' : 'No posts found';
168 echo '<li class="wpf-no-post-found">' . wpforo_phrase( $error_message, false ) . '</li>';
169 }
170 }
171
172 $this->remove_post_cache_filter( $post_args );
173
174 return sprintf( '<ul>%1$s</ul>', ob_get_clean() );
175 }
176
177 public function load_ajax_widget() {
178 $_POST = wp_unslash( $_POST );
179 $instance = json_decode( (string) wpfval( $_POST, 'instance' ), true );
180 $post_args = json_decode( (string) wpfval( $_POST, 'post_args' ), true );
181
182 // SECURITY FIX: Sanitize and validate all user-controlled parameters
183 if( is_array( $post_args ) ) {
184 // Remove dangerous 'where' parameter
185 unset( $post_args['where'] );
186
187 // Force permission checks — prevents check_private=false injection
188 $post_args['check_private'] = true;
189
190 // SECURITY: Strip forumid (singular) to force use of forumids (array)
191 // forumid bypasses access_filter() which only runs when forumid is null
192 unset( $post_args['forumid'] );
193
194 // Cap row_count to prevent resource exhaustion
195 if( isset( $post_args['row_count'] ) ) {
196 $post_args['row_count'] = min( 50, max( 1, intval( $post_args['row_count'] ) ) );
197 }
198
199 // Validate 'orderby' parameter against whitelist
200 if( isset( $post_args['orderby'] ) ) {
201 if( ! key_exists( $post_args['orderby'], $this->orderby_fields ) ) {
202 $post_args['orderby'] = $this->default_instance['orderby'];
203 }
204 }
205
206 // Validate 'order' parameter against whitelist
207 if( isset( $post_args['order'] ) ) {
208 if( ! key_exists( $post_args['order'], $this->order_fields ) ) {
209 $post_args['order'] = $this->default_instance['order'];
210 }
211 }
212
213 // SECURITY: coerce id-list fields to integer arrays so a serialized
214 // payload from an unauthenticated POST can never reach
215 // wpforo_parse_args() / unserialize() downstream. Defense in depth
216 // alongside the allowed_classes=>false hardening in wpforo_parse_args.
217 foreach( [ 'forumids', 'include', 'exclude', 'postids' ] as $idfield ) {
218 if( isset( $post_args[ $idfield ] ) ) {
219 $post_args[ $idfield ] = is_array( $post_args[ $idfield ] )
220 ? array_map( 'intval', $post_args[ $idfield ] )
221 : [];
222 }
223 }
224 }
225
226 wp_send_json_success( [ 'html' => $this->get_widget( $instance, $post_args ) ] );
227 }
228
229 public function widget( $args, $instance ) {
230 wp_enqueue_script( 'wpforo-widgets-js' );
231 $is_user_logged_in = (bool) WPF()->current_userid;
232 $instance = wpforo_parse_args( $instance, $this->default_instance );
233 if( $instance['display_only_unread'] ) {
234 $display_widget = $is_user_logged_in;
235 $display_widget = apply_filters( 'wpforo_widget_display_recent_posts', $display_widget );
236 } else {
237 $display_widget = true;
238 }
239 if( ! $display_widget ) return;
240
241 if( $instance['current_forumid_filter'] && $instance['boardid'] === WPF()->board->get_current( 'boardid' ) && $current_forumid = wpfval(
242 WPF()->current_object,
243 'forumid'
244 ) ) {
245 $instance['forumids'] = (array) $current_forumid;
246 }
247 $data = [
248 'boardid' => $instance['boardid'],
249 'action' => 'wpforo_load_ajax_widget_RecentPosts',
250 'instance' => $instance,
251 'post_args' => [
252 'forumids' => ( $instance['forumids'] ?: $this->default_instance['forumids'] ),
253 'orderby' => ( key_exists( $instance['orderby'], $this->orderby_fields ) ? $instance['orderby'] : $this->default_instance['orderby'] ),
254 'order' => ( key_exists( $instance['order'], $this->order_fields ) ? $instance['order'] : $this->default_instance['order'] ),
255 'row_count' => ( intval( $instance['count'] ) ?: $this->default_instance['count'] ),
256 'limit_per_topic' => ( intval( $instance['limit_per_topic'] ) ?: $this->default_instance['limit_per_topic'] ),
257 'is_first_post' => $instance['exclude_firstposts'] ? false : null,
258 'check_private' => true,
259 ],
260 ];
261 if( WPF()->board->get_current( 'boardid' ) === $instance['boardid'] ) {
262 $html = $this->get_widget( $data['instance'], $data['post_args'] );
263 $onload = false;
264 } else {
265 $html = '<div style="text-align: center; font-size: 20px;"><i class="fas fa-spinner fa-spin"></i></div>';
266 $onload = true;
267 $data['referer'] = home_url();
268 }
269
270 $json = wp_json_encode( $data );
271 echo $args['before_widget'] . '<div id="wpf-widget-recent-replies" class="wpforo-widget-wrap">';
272 if( ! empty( $instance['title'] ) ) echo $args['before_title'] . apply_filters( 'widget_title', $instance['title'] ) . $args['after_title'];
273 echo '<div class="wpforo-widget-content wpforo-ajax-widget ' . ( ! $onload ? 'wpforo-ajax-widget-onload-false' : '' ) . '" data-json="' . esc_attr(
274 $json
275 ) . '">' . $html . '</div></div>' . $args['after_widget'];
276 }
277
278 public function form( $instance ) {
279 $instance = wpforo_parse_args( $instance, $this->default_instance );
280 $title = (string) $instance['title'];
281 $boardid = (int) $instance['boardid'];
282 $selected = array_unique( array_filter( array_map( 'intval', (array) $instance['forumids'] ) ) );
283 $orderby = (string) $instance['orderby'];
284 $order = (string) $instance['order'];
285 $count = (int) $instance['count'];
286 $limit_per_topic = (int) $instance['limit_per_topic'];
287 $display_avatar = (bool) $instance['display_avatar'];
288 $forumids_filter = (bool) $instance['forumids_filter'];
289 $current_forumid_filter = (bool) $instance['current_forumid_filter'];
290 $exclude_firstposts = (bool) $instance['exclude_firstposts'];
291 $display_only_unread = (bool) $instance['display_only_unread'];
292 $display_new_indicator = (bool) $instance['display_new_indicator'];
293 $refresh_interval = (int) $instance['refresh_interval'];
294 $excerpt_length = (int) $instance['excerpt_length'];
295 WPF()->change_board( $boardid );
296 ?>
297 <style>
298 .wpf-wdg-wrapper .wpf_wdg_forumids_wrap {
299 display: none !important;
300 }
301
302 .wpf-wdg-wrapper input.wpf_wdg_forumids_filter_1:checked ~ .wpf_wdg_forumids_wrap {
303 display: block !important;
304 }
305
306 .wpf_wdg_limit_per_topic {
307 width: 53px;
308 }
309 </style>
310 <div class="wpf-wdg-wrapper">
311 <p>
312 <label for="<?php echo $this->get_field_id( 'title' ) ?>"><?php _e( 'Title', 'wpforo' ); ?>:</label>
313 <input id="<?php echo $this->get_field_id( 'title' ) ?>" class="widefat"
314 name="<?php echo esc_attr( $this->get_field_name( 'title' ) ); ?>" type="text"
315 value="<?php echo esc_attr( $title ); ?>">
316 </p>
317 <p>
318 <label for="<?php echo $this->get_field_id( 'boardid' ) ?>"></label>
319 <select id="<?php echo $this->get_field_id( 'boardid' ) ?>" class="wpf_wdg_boardid" name="<?php echo esc_attr( $this->get_field_name( 'boardid' ) ); ?>">
320 <?php echo WPF()->board->dropdown( $boardid ) ?>
321 </select>
322 </p>
323 <div>
324 <span><?php _e( 'Filter by forums', 'wpforo' ); ?> :</span>
325
326 <label for="<?php echo $this->get_field_id( 'forumids_filter' ) ?>_1"><?php _e( 'Yes', 'wpforo' ); ?></label>
327 <input id="<?php echo $this->get_field_id( 'forumids_filter' ) ?>_1" value="1" class="wpf_wdg_forumids_filter_1"
328 name="<?php echo esc_attr( $this->get_field_name( 'forumids_filter' ) ); ?>" <?php checked( $forumids_filter ); ?> type="radio">
329
330 <label for="<?php echo $this->get_field_id( 'forumids_filter' ) ?>_0"><?php _e( 'No', 'wpforo' ); ?></label>
331 <input id="<?php echo $this->get_field_id( 'forumids_filter' ) ?>_0" value="0" class="wpf_wdg_forumids_filter_0"
332 name="<?php echo esc_attr( $this->get_field_name( 'forumids_filter' ) ); ?>" <?php checked( $forumids_filter, false ); ?> type="radio">
333
334 <div class="wpf_wdg_forumids_wrap">
335 <label for="<?php echo $this->get_field_id( 'forumids' ) ?>"></label>
336 <select id="<?php echo $this->get_field_id( 'forumids' ) ?>" class="wpf_wdg_forumids" name="<?php echo esc_attr( $this->get_field_name( 'forumids' ) ); ?>[]" multiple>
337 <?php WPF()->forum->tree( 'select_box', false, $selected ) ?>
338 </select>
339 </div>
340 </div>
341 <p>
342 <span><?php _e( 'Autofilter by current forum', 'wpforo' ); ?> : </span>
343
344 <label for="<?php echo $this->get_field_id( 'current_forumid_filter' ) ?>_1"><?php _e( 'Yes', 'wpforo' ); ?></label>
345 <input id="<?php echo $this->get_field_id( 'current_forumid_filter' ) ?>_1" name="<?php echo esc_attr( $this->get_field_name( 'current_forumid_filter' ) ); ?>" value="1" <?php checked(
346 $current_forumid_filter
347 ); ?> type="radio">
348
349 <label for="<?php echo $this->get_field_id( 'current_forumid_filter' ) ?>_0"><?php _e( 'No', 'wpforo' ); ?></label>
350 <input id="<?php echo $this->get_field_id( 'current_forumid_filter' ) ?>_0" name="<?php echo esc_attr( $this->get_field_name( 'current_forumid_filter' ) ); ?>" value="0" <?php checked(
351 $current_forumid_filter,
352 false
353 ); ?> type="radio">
354 </p>
355 <p>
356 <label for="<?php echo $this->get_field_id( 'orderby' ) ?>"><?php _e( 'Order by', 'wpforo' ); ?>
357 :</label>
358 <select class="wpf_wdg_orderby" name="<?php echo esc_attr( $this->get_field_name( 'orderby' ) ); ?>"
359 id="<?php echo $this->get_field_id( 'orderby' ) ?>" <?php echo( $limit_per_topic ? 'disabled' : '' ) ?>>
360 <?php foreach( $this->orderby_fields as $orderby_key => $orderby_field ) : ?>
361 <option value="<?php echo $orderby_key; ?>"<?php echo( $orderby_key == $orderby ? ' selected' : '' ); ?>><?php echo $orderby_field; ?></option>
362 <?php endforeach; ?>
363 </select>
364 <label>
365 <select class="wpf_wdg_order"
366 name="<?php echo esc_attr( $this->get_field_name( 'order' ) ); ?>" <?php echo( $limit_per_topic ? 'disabled' : '' ) ?>>
367 <?php foreach( $this->order_fields as $order_key => $order_field ) : ?>
368 <option value="<?php echo $order_key; ?>"<?php echo( $order_key == $order ? ' selected' : '' ); ?>><?php echo $order_field; ?></option>
369 <?php endforeach; ?>
370 </select>
371 </label>
372 </p>
373 <p>
374 <label for="<?php echo $this->get_field_id( 'limit_per_topic' ) ?>"><?php _e( 'Limit Per Topic', 'wpforo' ); ?></label>&nbsp;
375 <input id="<?php echo $this->get_field_id( 'limit_per_topic' ) ?>" class="wpf_wdg_limit_per_topic"
376 type="number" min="0"
377 name="<?php echo esc_attr( $this->get_field_name( 'limit_per_topic' ) ); ?>"
378 value="<?php echo esc_attr( $limit_per_topic ); ?>">
379 <span style="color: #aaa;"><?php _e( 'set 0 to remove this limit', 'wpforo' ) ?></span>
380 </p>
381 <p>
382 <label for="<?php echo $this->get_field_id( 'count' ) ?>"><?php _e( 'Number of Items', 'wpforo' ); ?></label>&nbsp;
383 <input id="<?php echo $this->get_field_id( 'count' ) ?>" type="number" min="1" style="width: 53px;"
384 name="<?php echo esc_attr( $this->get_field_name( 'count' ) ); ?>"
385 value="<?php echo esc_attr( $count ); ?>">
386 </p>
387 <p>
388 <label for="<?php echo $this->get_field_id( 'excerpt_length' ) ?>"><?php _e( 'Excerpt Length', 'wpforo' ); ?></label>&nbsp;
389 <input id="<?php echo $this->get_field_id( 'excerpt_length' ) ?>" type="number" min="0" style="display: inline-block; width: 53px;"
390 name="<?php echo esc_attr( $this->get_field_name( 'excerpt_length' ) ); ?>" value="<?php echo esc_attr( $excerpt_length ); ?>">
391 <span style="color: #ccc"><?php _e( 'Set 0 to disable autorefresh', 'wpforo' ) ?></span>
392 </p>
393 <p>
394 <span><?php _e( 'Display with avatars', 'wpforo' ); ?> : </span>
395
396 <label for="<?php echo $this->get_field_id( 'display_avatar' ) ?>_1"><?php _e( 'Yes', 'wpforo' ); ?></label>
397 <input id="<?php echo $this->get_field_id( 'display_avatar' ) ?>_1" value="1" <?php checked( $display_avatar ); ?> type="radio"
398 name="<?php echo esc_attr( $this->get_field_name( 'display_avatar' ) ); ?>">
399
400 <label for="<?php echo $this->get_field_id( 'display_avatar' ) ?>_0"><?php _e( 'No', 'wpforo' ); ?></label>
401 <input id="<?php echo $this->get_field_id( 'display_avatar' ) ?>_0" value="0" <?php checked( $display_avatar, false ); ?> type="radio"
402 name="<?php echo esc_attr( $this->get_field_name( 'display_avatar' ) ); ?>">
403 </p>
404 <p>
405 <span><?php _e( 'Exclude First Posts', 'wpforo' ); ?></span>
406 <label for="<?php echo $this->get_field_id( 'exclude_firstposts' ) ?>_1"><?php _e( 'Yes', 'wpforo' ); ?></label>
407 <input id="<?php echo $this->get_field_id( 'exclude_firstposts' ) ?>_1" value="1" <?php checked( $exclude_firstposts ); ?> type="radio"
408 name="<?php echo esc_attr( $this->get_field_name( 'exclude_firstposts' ) ); ?>">
409
410 <label for="<?php echo $this->get_field_id( 'exclude_firstposts' ) ?>_0"><?php _e( 'No', 'wpforo' ); ?></label>
411 <input id="<?php echo $this->get_field_id( 'exclude_firstposts' ) ?>_0" value="0" <?php checked( $exclude_firstposts, false ); ?> type="radio"
412 name="<?php echo esc_attr( $this->get_field_name( 'exclude_firstposts' ) ); ?>">
413 </p>
414 <p>
415 <span><?php _e( 'Display Only Unread Posts', 'wpforo' ); ?></span>
416 <label for="<?php echo $this->get_field_id( 'display_only_unread' ) ?>_1"><?php _e( 'Yes', 'wpforo' ); ?></label>
417 <input id="<?php echo $this->get_field_id( 'display_only_unread' ) ?>_1" value="1" <?php checked( $display_only_unread ); ?> type="radio"
418 name="<?php echo esc_attr( $this->get_field_name( 'display_only_unread' ) ); ?>">
419
420 <label for="<?php echo $this->get_field_id( 'display_only_unread' ) ?>_0"><?php _e( 'No', 'wpforo' ); ?></label>
421 <input id="<?php echo $this->get_field_id( 'display_only_unread' ) ?>_0" value="0" <?php checked( $display_only_unread, false ); ?> type="radio"
422 name="<?php echo esc_attr( $this->get_field_name( 'display_only_unread' ) ); ?>">
423 </p>
424 <p>
425 <span><?php _e( 'Display [new] indicator', 'wpforo' ); ?> : </span>
426
427 <label for="<?php echo $this->get_field_id( 'display_new_indicator' ) ?>_1"><?php _e( 'Yes', 'wpforo' ); ?></label>
428 <input id="<?php echo $this->get_field_id( 'display_new_indicator' ) ?>_1" value="1" <?php checked( $display_new_indicator ); ?> type="radio"
429 name="<?php echo esc_attr( $this->get_field_name( 'display_new_indicator' ) ); ?>">
430
431 <label for="<?php echo $this->get_field_id( 'display_new_indicator' ) ?>_0"><?php _e( 'No', 'wpforo' ); ?></label>
432 <input id="<?php echo $this->get_field_id( 'display_new_indicator' ) ?>_0" value="0" <?php checked( $display_new_indicator, false ); ?> type="radio"
433 name="<?php echo esc_attr( $this->get_field_name( 'display_new_indicator' ) ); ?>">
434 </p>
435 <p>
436 <label for="<?php echo $this->get_field_id( 'refresh_interval' ) ?>"><?php _e( 'Auto Refresh Interval Seconds', 'wpforo' ); ?></label>&nbsp;
437 <input id="<?php echo $this->get_field_id( 'refresh_interval' ) ?>" type="number" min="0" style="display: inline-block; width: 53px;"
438 name="<?php echo esc_attr( $this->get_field_name( 'refresh_interval' ) ); ?>" value="<?php echo esc_attr( $refresh_interval ); ?>">
439 <span style="color: #ccc"><?php _e( 'Set 0 to disable autorefresh', 'wpforo' ) ?></span>
440 </p>
441 </div>
442 <?php
443 }
444
445 public function update( $new_instance, $old_instance ) {
446 $new_instance = wpforo_parse_args( $new_instance, $this->default_instance );
447 $instance = [];
448 $instance['title'] = strip_tags( (string) $new_instance['title'] );
449 $instance['boardid'] = (int) $new_instance['boardid'];
450 $instance['forumids_filter'] = (bool) (int) $new_instance['forumids_filter'];
451 $instance['forumids'] = array_unique( array_filter( array_map( 'intval', (array) $new_instance['forumids'] ) ) );
452 $instance['orderby'] = ( ! empty( $new_instance['orderby'] ) && key_exists(
453 $new_instance['orderby'],
454 $this->orderby_fields
455 ) ) ? $new_instance['orderby'] : $this->default_instance['orderby'];
456 $instance['order'] = ( ! empty( $new_instance['order'] ) && key_exists(
457 $new_instance['order'],
458 $this->order_fields
459 ) ) ? $new_instance['order'] : $this->default_instance['order'];
460 $instance['count'] = (int) $new_instance['count'];
461 $instance['display_avatar'] = (bool) (int) $new_instance['display_avatar'];
462 $instance['current_forumid_filter'] = (bool) (int) $new_instance['current_forumid_filter'];
463 $instance['limit_per_topic'] = (int) $new_instance['limit_per_topic'];
464 $instance['exclude_firstposts'] = (bool) (int) $new_instance['exclude_firstposts'];
465 $instance['display_only_unread'] = (bool) (int) $new_instance['display_only_unread'];
466 $instance['display_new_indicator'] = (bool) (int) $new_instance['display_new_indicator'];
467 $instance['refresh_interval'] = (int) $new_instance['refresh_interval'];
468 $instance['excerpt_length'] = (int) $new_instance['excerpt_length'];
469
470 return $instance;
471 }
472
473 public function get_forum_tree() {
474 ob_start();
475 WPF()->forum->tree( 'select_box', false, [] );
476 wp_send_json_success( [ 'html' => ob_get_clean() ] );
477 }
478 }
479