PluginProbe
Forumax – AI Powered Advanced Community Forum Plugin / trunk
Forumax – AI Powered Advanced Community Forum Plugin vtrunk
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 / includes / bbpress-config.php

bbpress-config.php in Forumax – AI Powered Advanced Community Forum Plugin trunk, at includes/bbpress-config.php

438 lines 14.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * bbPress configuration for Forumax
4 *
5 * @package Forumax
6 */
7
8 defined( 'ABSPATH' ) || exit;
9
10 /**
11 * bbPress Replies
12 */
13 add_filter( 'bbp_show_lead_topic', function () {
14 $show_lead[] = 'true';
15 return $show_lead;
16 } );
17
18 /**
19 * bbPress User Role
20 */
21 if ( ! function_exists( 'forumax_bbp_user_role_icon' ) ) {
22 /**
23 * Get modern inline SVG icon markup for a bbPress role.
24 *
25 * @param string $author_role User role label.
26 * @return string
27 */
28 function forumax_get_bbp_role_icon_svg( $author_role = '' ) {
29 switch ( $author_role ) {
30 case 'Keymaster':
31 return '<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M3 8l4 4 5-7 5 7 4-4-2 11H5L3 8z"></path><path d="M8 18h8"></path></svg>';
32 case 'Moderator':
33 return '<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M12 3l7 3v6c0 4.5-3 7.7-7 9-4-1.3-7-4.5-7-9V6l7-3z"></path><path d="M9 12l2 2 4-4"></path></svg>';
34 case 'Participant':
35 return '<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false"><circle cx="12" cy="8.5" r="2.5"></circle><path d="M6.5 17.5c1.3-2.4 3.2-3.5 5.5-3.5s4.2 1.1 5.5 3.5"></path></svg>';
36 case 'Member':
37 return '<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false"><circle cx="12" cy="8" r="2.75"></circle><path d="M6.5 18c1.2-2.6 3.1-3.8 5.5-3.8s4.3 1.2 5.5 3.8"></path><path d="M18.5 6.5l.9.6 1-.1-.6.9.1 1-.9-.6-.9.6.1-1-.6-.9 1 .1z"></path></svg>';
38 case 'Spectator':
39 return '<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M2 12s3.5-6 10-6 10 6 10 6-3.5 6-10 6-10-6-10-6z"></path><circle cx="12" cy="12" r="2.5"></circle></svg>';
40 case 'Blocked':
41 return '<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false"><circle cx="12" cy="12" r="9"></circle><path d="M8.5 8.5l7 7"></path></svg>';
42 default:
43 return '';
44 }
45 }
46
47 /**
48 * Display user role icon based on bbPress role.
49 */
50 function forumax_bbp_user_role_icon() {
51 $author_id = 0;
52
53 if ( bbp_get_reply_id() ) {
54 $author_id = bbp_get_reply_author_id( bbp_get_reply_id() );
55 } elseif ( bbp_get_topic_id() ) {
56 $author_id = bbp_get_topic_author_id( bbp_get_topic_id() );
57 }
58
59 $author_role = ! empty( $author_id ) ? bbp_get_user_display_role( $author_id ) : '';
60 $icon_svg = forumax_get_bbp_role_icon_svg( $author_role );
61
62 if ( ! empty( $icon_svg ) ) {
63 echo '<span class="forumax-role-icon forumax-role-icon--' . esc_attr( sanitize_title( $author_role ) ) . '" aria-hidden="true">' . $icon_svg . '</span>';
64 }
65 }
66 }
67
68 /**
69 * Get author role
70 */
71 if ( ! function_exists( 'forumax_get_bbp_user_role' ) ) {
72 /**
73 * Get the author role for the current topic.
74 *
75 * @return string The author role.
76 */
77 function forumax_get_bbp_user_role( $topic_id = 0 ) {
78 $role = bbp_get_topic_author_role( [
79 'topic_id' => $topic_id,
80 'before' => '',
81 'after' => '',
82 ]);
83 return $role;
84 }
85 }
86
87 /**
88 * Get reply author role
89 */
90 if ( ! function_exists( 'forumax_get_bbp_reply_user_role' ) ) {
91 /**
92 * Get the author role for the current reply.
93 *
94 * @param int $reply_id Reply ID.
95 * @return string The author role.
96 */
97 function forumax_get_bbp_reply_user_role( $reply_id = 0 ) {
98 $role = bbp_get_reply_author_role( [
99 'reply_id' => $reply_id,
100 'before' => '',
101 'after' => '',
102 ] );
103 return $role;
104 }
105 }
106
107 /**
108 * Get topic reply count
109 */
110 if ( ! function_exists( 'forumax_topic_reply_count' ) ) {
111 /**
112 * Output the topic reply count.
113 */
114 function forumax_topic_reply_count() {
115 $get_reply = get_post_meta( get_the_ID(), '_bbp_reply_count', true );
116 $_reply_count = isset( $get_reply ) && ! empty( $get_reply ) ? $get_reply : 0;
117 echo esc_html( $_reply_count );
118 }
119 }
120
121 /**
122 * Display bbp_reply_admin_links() as a dropdown list.
123 */
124 if ( ! function_exists( 'forumax_get_reply_admin_links' ) ) {
125 /**
126 * Get reply admin links as a dropdown.
127 *
128 * @param array $args Arguments for the admin links.
129 * @return string|void Admin links HTML.
130 */
131 function forumax_get_reply_admin_links( $args = [] ) {
132
133 // Parse arguments against default values
134 $r = bbp_parse_args( $args, [
135 'id' => 0,
136 'before' => '<div class="bbp-admin-links-dropdown">',
137 'after' => '</div>',
138 'sep' => '',
139 'links' => [],
140 ], 'get_reply_admin_links' );
141
142 $r['id'] = bbp_get_reply_id( $r['id'] );
143
144 // If post is a topic, return the topic admin links instead
145 if ( bbp_is_topic( $r['id'] ) ) {
146 return forumax_get_topic_admin_links( $args );
147 }
148
149 // If post is not a reply, return
150 if ( ! bbp_is_reply( $r['id'] ) ) {
151 return;
152 }
153
154 // If topic is trashed, do not show admin links
155 if ( bbp_is_topic_trash( bbp_get_reply_topic_id( $r['id'] ) ) ) {
156 return;
157 }
158
159 // If no links were passed, default to the standard
160 if ( empty( $r['links'] ) ) {
161 $r['links'] = apply_filters( 'bbp_reply_admin_links', [
162 'edit' => bbp_get_reply_edit_link( $r ),
163 'move' => bbp_get_reply_move_link( $r ),
164 'split' => bbp_get_topic_split_link( $r ),
165 'trash' => bbp_get_reply_trash_link( $r ),
166 'spam' => bbp_get_reply_spam_link( $r ),
167 'approve' => bbp_get_reply_approve_link( $r ),
168 'reply' => bbp_get_reply_to_link( $r ),
169 ], $r['id'] );
170 }
171
172 // See if links need to be unset
173 $reply_status = bbp_get_reply_status( $r['id'] );
174 if ( in_array( $reply_status, [ bbp_get_spam_status_id(), bbp_get_trash_status_id(), bbp_get_pending_status_id() ], true ) ) {
175
176 // Spam link shouldn't be visible on trashed topics
177 if ( bbp_get_trash_status_id() === $reply_status ) {
178 unset( $r['links']['spam'] );
179
180 // Trash link shouldn't be visible on spam topics
181 } elseif ( bbp_get_spam_status_id() === $reply_status ) {
182 unset( $r['links']['trash'] );
183 }
184 }
185
186 // Build our dropdown menu structure.
187 $menu = '<select name="reply-admin-links" class="frmx-nice-select bbp-admin-dropdown-menu" onchange="if(this.value && this.options[this.selectedIndex].getAttribute(\'data-action\') !== \'edit\') window.location.href=this.value;">';
188
189 // Placeholder (hidden trigger label).
190 $menu .= '<option value="" disabled selected data-action="trigger">' . esc_html__( 'Actions', 'forumax' ) . '</option>';
191
192 // Split links into primary and destructive groups.
193 $destructive_keys = [ 'trash', 'spam', 'approve' ];
194 $primary_links = [];
195 $danger_links = [];
196
197 foreach ( array_filter( $r['links'] ) as $key => $link ) {
198 if ( in_array( $key, $destructive_keys, true ) ) {
199 $danger_links[ $key ] = $link;
200 } else {
201 $primary_links[ $key ] = $link;
202 }
203 }
204
205 // Render primary actions.
206 foreach ( $primary_links as $key => $link ) {
207 preg_match( '/href=(["\'])([^"\']+)\\1/', $link, $matches );
208 $href = ! empty( $matches[2] ) ? $matches[2] : '';
209 $menu .= '<option value="' . esc_url( $href ) . '" class="bbp-admin-dropdown-item" data-action="' . esc_attr( $key ) . '">' . wp_strip_all_tags( $link ) . '</option>';
210 }
211
212 // Visual separator between primary and destructive groups.
213 if ( ! empty( $danger_links ) && ! empty( $primary_links ) ) {
214 $menu .= '<option disabled data-action="separator">──────</option>';
215 }
216
217 // Render destructive actions.
218 foreach ( $danger_links as $key => $link ) {
219 preg_match( '/href=(["\'])([^"\']+)\\1/', $link, $matches );
220 $href = ! empty( $matches[2] ) ? $matches[2] : '';
221 $menu .= '<option value="' . esc_url( $href ) . '" class="bbp-admin-dropdown-item" data-action="' . esc_attr( $key ) . '">' . wp_strip_all_tags( $link ) . '</option>';
222 }
223
224 $menu .= '</select>';
225
226 $retval = $r['before'] . $menu . $r['after'];
227
228 // Filter & return
229 if ( is_user_logged_in() ) {
230 return apply_filters( 'forumax_bbp_get_reply_admin_links', $retval, $r, $args );
231 }
232 }
233 }
234
235 /**
236 * Similar function for topics - to handle the case where a topic is passed to the reply function
237 */
238 if ( ! function_exists( 'forumax_get_topic_admin_links' ) ) {
239 /**
240 * Get topic admin links as a dropdown.
241 *
242 * @param array $args Arguments for the admin links.
243 * @return string|void Admin links HTML.
244 */
245 function forumax_get_topic_admin_links( $args = [] ) {
246 // Parse arguments against default values
247 $r = bbp_parse_args( $args, [
248 'id' => 0,
249 'before' => '<div class="bbp-admin-links-dropdown">',
250 'after' => '</div>',
251 'sep' => '',
252 'links' => [],
253 ], 'get_topic_admin_links' );
254
255 $r['id'] = bbp_get_topic_id( $r['id'] );
256
257 // If not a topic, then return
258 if ( ! bbp_is_topic( $r['id'] ) ) {
259 return;
260 }
261
262 // If no links were passed, get the default ones
263 if ( empty( $r['links'] ) ) {
264 $r['links'] = apply_filters( 'bbp_topic_admin_links', [
265 'edit' => bbp_get_topic_edit_link( $r ),
266 'close' => bbp_get_topic_close_link( $r ),
267 'stick' => bbp_get_topic_stick_link( $r ),
268 'merge' => bbp_get_topic_merge_link( $r ),
269 'trash' => bbp_get_topic_trash_link( $r ),
270 'spam' => bbp_get_topic_spam_link( $r ),
271 'approve' => bbp_get_topic_approve_link( $r ),
272 'reply' => bbp_get_topic_reply_link( $r ),
273 ], $r['id'] );
274 }
275
276 // See if links need to be unset
277 $topic_status = bbp_get_topic_status( $r['id'] );
278 if ( in_array( $topic_status, [ bbp_get_spam_status_id(), bbp_get_trash_status_id(), bbp_get_pending_status_id() ], true ) ) {
279
280 // Spam link shouldn't be visible on trashed topics
281 if ( bbp_get_trash_status_id() === $topic_status ) {
282 unset( $r['links']['spam'] );
283
284 // Trash link shouldn't be visible on spam topics
285 } elseif ( bbp_get_spam_status_id() === $topic_status ) {
286 unset( $r['links']['trash'] );
287 }
288 }
289
290 // Build our dropdown menu structure.
291 $menu = '<select name="topic-admin-links" class="frmx-nice-select bbp-admin-dropdown-menu" onchange="if(this.value && this.options[this.selectedIndex].getAttribute(\'data-action\') !== \'edit\') window.location.href=this.value;">';
292
293 // Placeholder (hidden trigger label).
294 $menu .= '<option value="" disabled selected data-action="trigger">' . esc_html__( 'Actions', 'forumax' ) . '</option>';
295
296 // Split links into primary and destructive groups.
297 $destructive_keys = [ 'trash', 'spam', 'approve' ];
298 $primary_links = [];
299 $danger_links = [];
300
301 foreach ( array_filter( $r['links'] ) as $key => $link ) {
302 if ( in_array( $key, $destructive_keys, true ) ) {
303 $danger_links[ $key ] = $link;
304 } else {
305 $primary_links[ $key ] = $link;
306 }
307 }
308
309 // Render primary actions.
310 foreach ( $primary_links as $key => $link ) {
311 preg_match( '/href=(["\'])([^"\']+)\\1/', $link, $matches );
312 $href = ! empty( $matches[2] ) ? $matches[2] : '';
313 $menu .= '<option value="' . esc_url( $href ) . '" class="bbp-admin-dropdown-item" data-action="' . esc_attr( $key ) . '">' . wp_strip_all_tags( $link ) . '</option>';
314 }
315
316 // Visual separator between primary and destructive groups.
317 if ( ! empty( $danger_links ) && ! empty( $primary_links ) ) {
318 $menu .= '<option disabled data-action="separator">──────</option>';
319 }
320
321 // Render destructive actions.
322 foreach ( $danger_links as $key => $link ) {
323 preg_match( '/href=(["\'])([^"\']+)\\1/', $link, $matches );
324 $href = ! empty( $matches[2] ) ? $matches[2] : '';
325 $menu .= '<option value="' . esc_url( $href ) . '" class="bbp-admin-dropdown-item" data-action="' . esc_attr( $key ) . '">' . wp_strip_all_tags( $link ) . '</option>';
326 }
327
328 $menu .= '</select>';
329
330 $retval = $r['before'] . $menu . $r['after'];
331
332 // Filter & return
333 return apply_filters( 'forumax_bbp_get_topic_admin_links', $retval, $r, $args );
334 }
335 }
336
337 /**
338 * Enqueue the script for sorting bbPress replies
339 */
340 if ( ! function_exists( 'forumax_enqueue_bbp_replies_sorting_script' ) ) {
341 /**
342 * Enqueue replies sorting script.
343 */
344 function forumax_enqueue_bbp_replies_sorting_script() {
345 wp_localize_script( 'bbp-replies-sorting', 'bbp_reply_ajax_obj', [
346 'ajax_url' => admin_url( 'admin-ajax.php' ),
347 'bbp_topic_id' => get_the_ID(),
348 ] );
349 }
350 add_action( 'wp_enqueue_scripts', 'forumax_enqueue_bbp_replies_sorting_script' );
351 }
352
353 if ( ! function_exists( 'forumax_ajax_sort_bbp_replies' ) ) {
354 /**
355 * AJAX handler for sorting replies.
356 */
357 function forumax_ajax_sort_bbp_replies() {
358 check_ajax_referer( 'forumax-nonce', 'nonce' );
359
360 if ( empty( $_POST['topic_id'] ) ) {
361 wp_send_json_error( [ 'message' => 'No topic ID provided.' ] );
362 }
363 $topic_id = intval( $_POST['topic_id'] );
364 $sort = isset( $_POST['sort'] ) ? sanitize_text_field( wp_unslash( $_POST['sort'] ) ) : 'desc';
365
366 // Set $_GET['sort'] for the filter to pick up
367 $_GET['sort'] = $sort;
368
369 // Start output buffering to capture the replies loop HTML
370 ob_start();
371 // Set up bbPress replies loop manually for AJAX context
372 $replies_args = [
373 'post_parent' => $topic_id,
374 'post_type' => bbp_get_reply_post_type(),
375 'orderby' => ( 'vote' === $sort ? 'meta_value_num' : 'date' ),
376 'order' => ( 'asc' === $sort ? 'ASC' : 'DESC' ),
377 'meta_key' => ( 'vote' === $sort ? 'bbp_voting_score' : '' ),
378 'posts_per_page' => -1,
379 ];
380 if ( bbp_has_replies( $replies_args ) ) {
381 while ( bbp_replies() ) :
382 bbp_the_reply();
383 $template_file = plugin_dir_path( __FILE__ ) . '../templates/loop-single-reply.php';
384 if ( file_exists( $template_file ) ) {
385 include $template_file;
386 }
387 endwhile;
388 } else {
389 echo '<div>No replies found.</div>';
390 }
391 $html = ob_get_clean();
392
393 wp_send_json_success( [ 'html' => $html ] );
394 }
395 add_action( 'wp_ajax_sort_bbp_replies', 'forumax_ajax_sort_bbp_replies' );
396 add_action( 'wp_ajax_nopriv_sort_bbp_replies', 'forumax_ajax_sort_bbp_replies' );
397 }
398
399 /**
400 * Remove unnecessary pipe separator from bbPress subscription links.
401 */
402 add_filter( 'bbp_get_user_subscribe_link', 'forumax_remove_subscribe_separator', 10, 1 );
403
404 /**
405 * Remove subscribe separator.
406 *
407 * @param string $html The HTML.
408 * @return string Modified HTML.
409 */
410 function forumax_remove_subscribe_separator( $html ) {
411 $html = str_replace( '&nbsp;|&nbsp;', '', $html );
412 return $html;
413 }
414
415 /**
416 * Restrict visibility of the "modified" notice to the author only.
417 *
418 * @param string $log The log output.
419 * @param int $post_id The post ID.
420 * @return string The log if allowed, empty string otherwise.
421 */
422 function forumax_restrict_revision_log_visibility( $log, $post_id ) {
423 if ( ! is_user_logged_in() ) {
424 return '';
425 }
426
427 $current_user_id = bbp_get_current_user_id();
428 $post = get_post( $post_id );
429
430 if ( ! empty( $post ) && ( int ) $post->post_author === ( int ) $current_user_id ) {
431 return $log;
432 }
433
434 return '';
435 }
436 add_filter( 'bbp_get_reply_revision_log', 'forumax_restrict_revision_log_visibility', 10, 2 );
437 add_filter( 'bbp_get_topic_revision_log', 'forumax_restrict_revision_log_visibility', 10, 2 );
438