PluginProbe
Forumax – AI Powered Advanced Community Forum Plugin / 2.0.0
Forumax – AI Powered Advanced Community Forum Plugin v2.0.0
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 / features / bbp_voting / frontend.php

frontend.php in Forumax – AI Powered Advanced Community Forum Plugin 2.0.0, at includes/features/bbp_voting/frontend.php

351 lines 11.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 if ( ! defined( 'ABSPATH' ) ) {
3 exit; // Exit if accessed directly.
4 }
5
6 // Vote Buttons and Score hooks.
7 add_action( 'bbp_theme_after_topic_author_details', 'bbp_voting_buttons' ); // �
8 New Hook
9 add_action( 'bbp_theme_after_reply_author_details', 'bbp_voting_buttons' );
10 add_action( 'bbp_voting_cpt', 'bbp_voting_buttons', 10, 1 );
11
12 function bbp_voting_buttons( $post_obj = false ) {
13 // Don't show voting buttons on user profile pages
14 if ( function_exists( 'bbp_is_single_user' ) && bbp_is_single_user() ) {
15 return;
16 }
17
18 $current_action = current_action();
19 $topic_post_type = bbp_get_topic_post_type();
20 $reply_post_type = bbp_get_reply_post_type();
21 $this_post_type = '';
22 $post = null;
23
24 // Get post object based on context
25 if ( $current_action === 'bbp_voting_cpt' ) {
26 if ( ! $post_obj ) return;
27 $post = $post_obj;
28 } else {
29 // Determine post type from current action
30 if ( in_array( $current_action, [
31 'bbp_theme_before_topic_title',
32 'bbp_template_before_lead_topic',
33 'bbp_theme_after_topic_author_details'
34 ] ) ) {
35 $this_post_type = $topic_post_type;
36 $post = bbpress()->topic_query->post;
37 } elseif ( in_array( $current_action, [
38 'bbp_theme_before_reply_content',
39 'bbp_theme_after_reply_author_details'
40 ] ) ) {
41 $this_post_type = bbp_voting_get_current_post_type();
42 $post = bbpress()->reply_query->post;
43 }
44
45 // Exit if unknown context or no post
46 if ( empty( $this_post_type ) || empty( $post ) ) return;
47
48 // Check forum settings
49 $forum_id = ($this_post_type === $topic_post_type)
50 ? bbp_get_topic_forum_id( $post->ID )
51 : bbp_get_reply_forum_id( $post->ID );
52
53 // Check if voting is allowed on this forum
54 if ( ! apply_filters( 'bbp_voting_allowed_on_forum', true, $forum_id ) ) return;
55
56 // Get post-specific settings
57 $post_setting = ($this_post_type === $topic_post_type)
58 ? get_post_meta( $forum_id, 'bbp_voting_forum_enable_topics', true )
59 : get_post_meta( $forum_id, 'bbp_voting_forum_enable_replies', true );
60
61 $broad_disable = ($this_post_type === $topic_post_type)
62 ? forumax_get_opt( 'is_voting_disabled_topics', 0 )
63 : forumax_get_opt( 'is_voting_disabled_replies', 0 );
64
65 // Check if voting is disabled
66 if ( ! empty( $post_setting ) && $post_setting === 'false' ) return;
67 if ( empty( $post_setting ) && $broad_disable === '0' ) return;
68 }
69
70 $post_id = $post->ID;
71
72 $score = (int) get_post_meta( $post_id, 'bbp_voting_score', true );
73 $ups = (int) get_post_meta( $post_id, 'bbp_voting_ups', true );
74 $downs = (int) get_post_meta( $post_id, 'bbp_voting_downs', true );
75
76 $calc_score = $ups + $downs;
77 if ( $score > $calc_score ) {
78 $diff = $score - $calc_score;
79 $ups += $diff;
80 update_post_meta( $post_id, 'bbp_voting_ups', $ups );
81 }
82
83 $voting_log = get_post_meta( $post_id, 'bbp_voting_log', true );
84 $voting_log = is_array( $voting_log ) ? $voting_log : [];
85 $client_ip = $_SERVER['REMOTE_ADDR'];
86 $identifier = is_user_logged_in() ? get_current_user_id() : $client_ip;
87 $existing_vote = $voting_log[ $identifier ] ?? 0;
88
89 // Check if admin can bypass voting restrictions
90 $admin_bypass = current_user_can( 'administrator' ) &&
91 forumax_get_opt( 'is_admin_can_vote_unlimited', false );
92
93 // Determine if this is view-only mode
94 $view_only = ! is_user_logged_in() &&
95 forumax_get_opt( 'is_disabled_voting_for_non_logged_users', false );
96
97 // Additional view-only checks for regular context (not CPT)
98 if ( ! $view_only && $current_action !== 'bbp_voting_cpt' ) {
99 // Check if topic is closed and voting on closed topics is disabled
100 $topic_id = ( $this_post_type === $topic_post_type ) ?
101 $post_id : bbp_get_reply_topic_id( $post_id );
102
103 if ( get_post_status( $topic_id ) === 'closed' &&
104 forumax_get_opt( 'is_disabled_voting_closed_topics', false ) ) {
105 $view_only = true;
106 }
107
108 // Check if voting on own posts is disabled
109 if ( ! $view_only &&
110 forumax_get_opt( 'is_disabled_voting_own_topic_reply', false ) &&
111 $post->post_author == get_current_user_id() ) {
112 $view_only = true;
113 }
114 }
115
116 $disable_down = forumax_get_opt( 'is_down_votes_disabled', 0 );
117 $vote_number_display = forumax_get_opt( 'vote_numbers_display', 'hover' );
118 $display_vote_nums = 'num-' . $vote_number_display;
119
120 // Determine if floating style should be applied
121 $float = in_array( $current_action, [
122 'bbp_theme_before_reply_content',
123 'bbp_voting_cpt'
124 ] );
125
126 // Build CSS classes for the voting container
127 $vote_classes = [
128 'bbp-voting',
129 'bbp-voting-post-' . $post_id,
130 get_post_type( $post_id )
131 ];
132
133 if ( $view_only ) {
134 $vote_classes[] = 'view-only';
135 } elseif ( $existing_vote == 1 ) {
136 $vote_classes[] = 'voted-up';
137 } elseif ( $existing_vote == -1 ) {
138 $vote_classes[] = 'voted-down';
139 }
140
141 if ( $admin_bypass ) $vote_classes[] = 'admin-bypass';
142 if ( $float ) $vote_classes[] = 'bbp-voting-float';
143
144 // Start building HTML
145 $html = '<div class="' . implode(' ', $vote_classes) . '">';
146
147 // Add label if enabled
148 $is_label = forumax_get_opt( 'is_label', true );
149 if ( $is_label ) {
150 $upvote_label = forumax_get_opt( 'upvote_label' );
151 if ( $upvote_label ) {
152 $html .= '<div class="bbp-voting-label helpful">' . esc_html( $upvote_label ) . '</div>';
153 }
154 }
155
156 // Generate voting HTML based on whether we're in AMP mode or not
157 if ( function_exists( 'is_amp_endpoint' ) && is_amp_endpoint() ) {
158 // AMP version of voting buttons
159 $post_url = admin_url( 'admin-ajax.php' );
160 $plusups = $ups ? '+' . $ups : ' ';
161
162 // Upvote form
163 $html .= sprintf(
164 '<form name="amp-form%1$s" method="post" action-xhr="%2$s" target="_top" on="submit-success: AMP.setState({\'voteup%1$s\': %3$s})">
165 <input type="hidden" name="action" value="bbpress_post_vote_link_clicked">
166 <input type="hidden" name="post_id" value="%4$s" />
167 <input type="hidden" name="direction" value="1" />
168 <input type="submit" class="nobutton upvote-amp" value="🔺" />
169 <span class="vote up" [text]="voteup%1$s ? \'+\' + voteup%1$s : \'%5$s\'">%5$s</span>
170 </form>',
171 $post_id,
172 esc_url( $post_url ),
173 ( $ups + 1 ),
174 esc_attr( $post_id ),
175 esc_html( $plusups )
176 );
177
178 // Downvote form (if enabled)
179 if ( $disable_down === '1' ) {
180 $html .= sprintf(
181 '<form name="amp-form%1$s" method="post" action-xhr="%2$s" target="_top" on="submit-success: AMP.setState({\'votedown%1$s\': %3$s})">
182 <input type="hidden" name="action" value="bbpress_post_vote_link_clicked">
183 <input type="hidden" name="post_id" value="%4$s" />
184 <input type="hidden" name="direction" value="-1" />
185 <input type="submit" class="nobutton downvote-amp" value="🔻" />
186 <span class="vote down" [text]="votedown%1$s || \'%5$s\'">%6$s</span>
187 </form>',
188 $post_id,
189 esc_url( $post_url ),
190 ( $downs - 1 ),
191 esc_attr( $post_id ),
192 esc_html( $downs ? $downs : ' ' ),
193 esc_html( $downs ? $downs : '' )
194 );
195 }
196 } else {
197 // Standard version of voting buttons
198 $html .= '<a class="vote up ' . esc_attr( $display_vote_nums ) . '" data-votes="' .
199 ( $ups ? '+' . $ups : '' ) . '" onclick="bbpress_post_vote_link_clicked(' .
200 $post_id . ', 1); return false;">Up</a>';
201
202 $html .= '<div class="score">' . $score . '</div>';
203
204 if ( $disable_down === '1' ) {
205 $html .= '<a class="vote down ' . esc_attr( $display_vote_nums ) . '" data-votes="' .
206 ( $downs ? $downs : '' ) . '" onclick="bbpress_post_vote_link_clicked(' .
207 $post_id . ', -1); return false;">Down</a>';
208 }
209 }
210
211 if ( $disable_down === '1' && $is_label ) {
212 $downvote_label = forumax_get_opt( 'downvote_label' );
213 if ( $downvote_label ) {
214 $html .= '<div class="bbp-voting-label not-helpful">' . esc_html( $downvote_label ) . '</div>';
215 }
216 }
217
218 // Apply filter for reply voting buttons
219 if ( $this_post_type === $reply_post_type ) {
220 $html = apply_filters( 'bbp_voting_after_reply_voting_buttons', $html, $post_id );
221 }
222
223 // Close the voting container
224 $html .= '</div>';
225
226 echo wp_kses_post( $html );
227 }
228
229
230 // Sort by Votes
231
232 add_filter( 'bbp_has_topics_query', 'sort_bbpress_posts_by_votes', 99 );
233 add_filter( 'bbp_has_replies_query', 'sort_bbpress_posts_by_votes', 99 );
234
235 function sort_bbpress_posts_by_votes( $args = [] ) {
236 $forum_id = bbp_get_forum_id();
237 $forum_post_type = bbp_get_forum_post_type();
238 $topic_post_type = bbp_get_topic_post_type();
239
240 // Determine post type and settings based on current filter
241 $current_filter = current_filter();
242 switch ( $current_filter ) {
243 case 'bbp_has_topics_query':
244 $this_post_type = $forum_post_type;
245 $post_setting = get_post_meta( $forum_id, 'sort_bbpress_topics_by_votes_on_forum', true );
246 $broad_enable = forumax_get_opt( 'is_sort_topic_by_votes', 0 );
247 break;
248 case 'bbp_has_replies_query':
249 $this_post_type = $topic_post_type;
250 $post_setting = get_post_meta( $forum_id, 'sort_bbpress_replies_by_votes_on_forum', true );
251 $broad_enable = forumax_get_opt( 'is_sort_reply_by_votes', 0 );
252 break;
253 default:
254 return $args;
255 }
256
257 // Check if we should apply vote sorting
258 $apply_sorting = false;
259
260 // Check URL parameter first
261 if ( isset( $_GET['bbp-voting-sort'] ) ) {
262 if ( $_GET['bbp-voting-sort'] === 'best' ) {
263 $apply_sorting = true;
264 } elseif ( $_GET['bbp-voting-sort'] === 'default' || $_GET['bbp-voting-sort'] === '' ) {
265 return $args;
266 }
267 } else {
268 // Check forum settings
269 if ( ! empty( $post_setting ) ) {
270 if ( $post_setting !== 'false' ) {
271 $apply_sorting = true;
272 }
273 } elseif ( $broad_enable !== '1' ) {
274 $apply_sorting = true;
275 }
276
277 // Check if voting is allowed on this forum
278 if ( ! apply_filters( 'bbp_voting_allowed_on_forum', true, $forum_id ) ) {
279 $apply_sorting = false;
280 }
281 }
282
283 // Return original args if sorting should not be applied
284 if ( ! $apply_sorting ) {
285 return $args;
286 }
287
288 // Get the meta key to sort by
289 $sort_meta_key = apply_filters( 'bbp_voting_sort_meta_key', 'bbp_voting_score' );
290
291 // Find and fill any posts missing the sort meta key
292 $missing_meta_query = [
293 'meta_query' => [
294 [
295 'key' => $sort_meta_key,
296 'compare' => 'NOT EXISTS',
297 'value' => '',
298 ],
299 ],
300 ];
301
302 $query = new WP_Query( array_merge( $args, $missing_meta_query ) );
303 foreach ( $query->posts as $post ) {
304 $default_value = apply_filters( 'bbp_voting_sort_meta_key_default_value', '0', $post->ID );
305 update_post_meta( $post->ID, $sort_meta_key, $default_value );
306 }
307
308 // Clear existing sort parameters
309 $args = array_diff_key( $args, array_flip( ['meta_key', 'meta_type', 'orderby', 'order'] ) );
310
311 // Set up meta query for sorting
312 $args['meta_query'] = [
313 'relation' => 'AND',
314 'score_clause' => [
315 'key' => $sort_meta_key,
316 'compare' => 'EXISTS',
317 ],
318 ];
319
320 // Set numeric type for score meta if using the default key
321 if ( $sort_meta_key === 'bbp_voting_score' ) {
322 $args['meta_query']['score_clause']['type'] = 'NUMERIC';
323 }
324
325 // Set up orderby parameters
326 $args['orderby'] = [
327 'post_type' => 'DESC',
328 'score_clause' => 'DESC',
329 ];
330
331 // Add additional sorting parameters based on post type
332 if ( $this_post_type === $topic_post_type ) {
333 $args['orderby']['date'] = 'ASC';
334 } elseif ( $this_post_type === $forum_post_type ) {
335 $args['meta_query']['orderby_freshness'] = [
336 'key' => '_bbp_last_active_time',
337 'type' => 'DATETIME',
338 ];
339 $args['orderby']['orderby_freshness'] = 'DESC';
340 }
341
342 return $args;
343 }
344
345 add_action( 'init', 'bbp_voting_lead_topic' );
346 function bbp_voting_lead_topic() {
347 if ( forumax_get_opt( 'is_lead_topic_broken', false ) ) {
348 add_filter( 'bbp_show_lead_topic', '__return_true' );
349 }
350 }
351