PluginProbe
Forumax – AI Powered Advanced Community Forum Plugin / 2.4.3
Forumax – AI Powered Advanced Community Forum Plugin v2.4.3
2.4.4 2.4.3 2.4.2 2.4.1 2.4.0 trunk 1.0.8 1.1.0 1.2.1 1.2.2 1.2.3 1.2.4 1.2.5 1.2.6 1.2.7 1.2.8 1.2.9 1.3.0 1.3.1 1.3.2 1.3.3 1.4.0 1.4.1 2.0.0 2.1.0 All 29 releases
bbp-core / widgets / Forumax_Active_Members.php

Forumax_Active_Members.php in Forumax – AI Powered Advanced Community Forum Plugin 2.4.3, at widgets/Forumax_Active_Members.php

250 lines 7.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 namespace Forumax\WpWidgets;
3
4 use WP_Widget;
5
6 /**
7 * Class Forumax_Active_Members
8 * Displays a list of recently active members who participated in the current topic.
9 * This widget is only visible on single topic pages.
10 *
11 * @package Forumax\WpWidgets
12 */
13 class Forumax_Active_Members extends WP_Widget {
14
15 /**
16 * Forumax Active Members Widget
17 *
18 * Registers the active members widget.
19 */
20 public function __construct() {
21 $widget_ops = apply_filters( 'forumax_active_members_widget_options', array(
22 'classname' => 'forumax_active_members_widget',
23 'description' => esc_html__( 'Displays members who participated in the current topic. Only visible on single topic pages.', 'forumax' ),
24 'customize_selective_refresh' => true,
25 ) );
26
27 parent::__construct(
28 'forumax_active_members',
29 esc_html__( '(Forumax) Active Members', 'forumax' ),
30 $widget_ops
31 );
32 }
33
34 /**
35 * Register the widget.
36 */
37 public static function register_widget() {
38 register_widget( __CLASS__ );
39 }
40
41 /**
42 * Displays the output — list of active members in the current topic.
43 *
44 * Only renders on single topic pages. On all other pages,
45 * the widget silently returns without any output.
46 *
47 * @param array $args Widget display arguments.
48 * @param array $instance Widget instance settings.
49 */
50 public function widget( $args = array(), $instance = array() ) {
51
52 wp_enqueue_style( 'bbpc-forum' );
53
54 // Only display on single topic pages.
55 if ( ! function_exists( 'bbp_is_single_topic' ) || ! bbp_is_single_topic() ) {
56 return;
57 }
58
59 $topic_id = bbp_get_topic_id();
60
61 if ( empty( $topic_id ) ) {
62 return;
63 }
64
65 // Get widget settings.
66 $settings = $this->parse_settings( $instance );
67
68 // Apply standard WordPress title filter.
69 $settings['title'] = apply_filters( 'widget_title', $settings['title'], $instance, $this->id_base );
70
71 // Forumax-specific filter.
72 $settings['title'] = apply_filters( 'forumax_active_members_widget_title', $settings['title'], $instance, $this->id_base );
73
74 // Fetch unique participant user IDs for this topic.
75 $member_ids = $this->get_topic_participants( $topic_id, (int) $settings['max_shown'] );
76
77 // Bail if no participants found.
78 if ( empty( $member_ids ) ) {
79 return;
80 }
81
82 $avatar_size = absint( $settings['avatar_size'] );
83
84 echo $args['before_widget']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
85
86 if ( ! empty( $settings['title'] ) ) {
87 echo $args['before_title'] . $settings['title'] . $args['after_title']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
88 }
89 ?>
90
91 <ul class="frmx-active-members frmx-list-unstyled">
92
93 <?php foreach ( $member_ids as $user_id ) :
94 $user = get_userdata( $user_id );
95
96 if ( ! $user ) {
97 continue;
98 }
99
100 $profile_url = function_exists( 'bbp_get_user_profile_url' )
101 ? bbp_get_user_profile_url( $user_id )
102 : get_author_posts_url( $user_id );
103 $display_name = $user->display_name;
104 ?>
105
106 <li class="frmx-active-member-item" data-frmx-tooltip="<?php echo esc_attr( $display_name ); ?>">
107 <a href="<?php echo esc_url( $profile_url ); ?>"
108 class="frmx-active-member-link"
109 style="width: <?php echo esc_attr( $avatar_size ); ?>px; height: <?php echo esc_attr( $avatar_size ); ?>px;">
110 <?php echo get_avatar( $user_id, $avatar_size ); ?>
111 </a>
112 </li>
113
114 <?php endforeach; ?>
115
116 </ul>
117
118 <?php
119 echo $args['after_widget']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
120 }
121
122 /**
123 * Get unique participant IDs for a given topic.
124 *
125 * Combines the topic author with reply authors, returns unique IDs
126 * ordered by most recent activity (latest reply first).
127 *
128 * @param int $topic_id The topic ID.
129 * @param int $max_shown Maximum number of members to return.
130 * @return array Array of unique user IDs.
131 */
132 private function get_topic_participants( $topic_id, $max_shown ) {
133 global $wpdb;
134
135 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
136 $results = $wpdb->get_col(
137 $wpdb->prepare(
138 "SELECT DISTINCT post_author
139 FROM {$wpdb->posts}
140 WHERE post_parent = %d
141 AND post_type = %s
142 AND post_status IN ( 'publish', 'closed' )
143 ORDER BY post_date DESC",
144 $topic_id,
145 bbp_get_reply_post_type()
146 )
147 );
148
149 // Include the topic author at the beginning.
150 $topic_author = get_post_field( 'post_author', $topic_id );
151
152 if ( ! empty( $topic_author ) ) {
153 // Remove topic author from results if already present, then prepend.
154 $results = array_diff( $results, array( $topic_author ) );
155 array_unshift( $results, $topic_author );
156 }
157
158 // Remove invalid (0) IDs and limit.
159 $results = array_filter( $results );
160 $results = array_slice( $results, 0, $max_shown );
161
162 return array_map( 'absint', $results );
163 }
164
165 /**
166 * Update the widget options.
167 *
168 * @param array $new_instance The new instance options.
169 * @param array $old_instance The old instance options.
170 * @return array Updated instance.
171 */
172 public function update( $new_instance = array(), $old_instance = array() ) {
173 $instance = $old_instance;
174 $instance['title'] = strip_tags( $new_instance['title'] );
175 $instance['max_shown'] = (int) $new_instance['max_shown'];
176 $instance['avatar_size'] = absint( $new_instance['avatar_size'] );
177
178 return $instance;
179 }
180
181 /**
182 * Output the widget options form.
183 *
184 * @param array $instance Current widget instance settings.
185 */
186 public function form( $instance = array() ) {
187
188 // Get widget settings.
189 $settings = $this->parse_settings( $instance );
190 ?>
191
192 <p>
193 <label for="<?php echo esc_attr( $this->get_field_id( 'title' ) ); ?>">
194 <?php esc_html_e( 'Title:', 'forumax' ); ?>
195 <input class="widefat"
196 id="<?php echo esc_attr( $this->get_field_id( 'title' ) ); ?>"
197 name="<?php echo esc_attr( $this->get_field_name( 'title' ) ); ?>"
198 type="text"
199 value="<?php echo esc_attr( $settings['title'] ); ?>" />
200 </label>
201 </p>
202
203 <p>
204 <label for="<?php echo esc_attr( $this->get_field_id( 'max_shown' ) ); ?>">
205 <?php esc_html_e( 'Maximum members to show:', 'forumax' ); ?>
206 <input class="widefat"
207 id="<?php echo esc_attr( $this->get_field_id( 'max_shown' ) ); ?>"
208 name="<?php echo esc_attr( $this->get_field_name( 'max_shown' ) ); ?>"
209 type="number"
210 min="1"
211 max="50"
212 value="<?php echo esc_attr( $settings['max_shown'] ); ?>" />
213 </label>
214 </p>
215
216 <p>
217 <label for="<?php echo esc_attr( $this->get_field_id( 'avatar_size' ) ); ?>">
218 <?php esc_html_e( 'Avatar size (px):', 'forumax' ); ?>
219 <input class="widefat"
220 id="<?php echo esc_attr( $this->get_field_id( 'avatar_size' ) ); ?>"
221 name="<?php echo esc_attr( $this->get_field_name( 'avatar_size' ) ); ?>"
222 type="number"
223 min="16"
224 max="96"
225 value="<?php echo esc_attr( $settings['avatar_size'] ); ?>" />
226 </label>
227 </p>
228
229 <p>
230 <small><?php esc_html_e( 'This widget is only visible on single topic pages.', 'forumax' ); ?></small>
231 </p>
232
233 <?php
234 }
235
236 /**
237 * Merge the widget settings into defaults array.
238 *
239 * @param array $instance Current instance settings.
240 * @return array Parsed settings with defaults applied.
241 */
242 public function parse_settings( $instance = array() ) {
243 return bbp_parse_args( $instance, array(
244 'title' => esc_html__( 'Active Members', 'forumax' ),
245 'max_shown' => 8,
246 'avatar_size' => 60,
247 ), 'forumax_active_members_widget_settings' );
248 }
249 }
250