PluginProbe
bbPress Voting / trunk
bbPress Voting vtrunk
2.1.10.2 2.1.10.3 2.1.10.4 2.1.10.5 2.1.10.6 2.1.11.0 2.1.11.1 2.1.11.10 2.1.11.11 2.1.11.12 2.1.11.2 2.1.11.3 2.1.11.4 2.1.11.5 2.1.11.6 2.1.11.7 2.1.11.8 2.1.11.9 2.1.12.0 2.1.12.1 2.1.12.2 2.1.12.3 2.1.12.7 2.1.13.0 2.1.13.1 All 93 releases
bbp-voting / frontend.php

frontend.php in bbPress Voting trunk, at frontend.php

418 lines 19.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 add_action('init', 'bbp_voting_frontend_hooks');
7 function bbp_voting_frontend_hooks() {
8 if(is_admin()) return;
9 if(apply_filters('bbp_voting_use_filter_hooks_for_buttons', false)) {
10 // Hooks for BuddyBoss Platform ---------------------
11 // Vote Buttons and Score
12 add_action('bbp_theme_before_topic_title', 'bbp_voting_buttons'); // Forum index (HOOK NEEDS TO BE MANUALLY ADDED TO wp-content/themes/buddyboss-child/bbpress/loop-topic-list.php)
13 add_filter('bbp_get_reply_content', 'bbp_voting_buttons_filter', 90, 2);
14 add_filter('bbp_get_topic_content', 'bbp_voting_buttons_filter', 90, 2);
15 } else {
16 // Hooks for standard bbPress ---------------------
17 // Vote Buttons and Score
18 add_action('bbp_theme_before_topic_title', 'bbp_voting_buttons'); // Forum index
19 // add_action('bbp_template_before_lead_topic', 'bbp_voting_buttons');
20 add_action('bbp_theme_before_topic_content', 'bbp_voting_buttons');
21 add_action('bbp_theme_before_reply_content', 'bbp_voting_buttons');
22 }
23 // Shared Hooks ---------------------
24 // Enqueue Scripts
25 add_action('wp_enqueue_scripts', 'bbp_voting_styles');
26 add_action('wp_enqueue_scripts', 'bbp_voting_scripts');
27 // Vote Buttons and Score for Custom Post Type
28 add_action('bbp_voting_cpt', 'bbp_voting_buttons', 10, 1);
29 // Sort by Votes
30 add_filter('bbp_has_topics_query', 'sort_bbpress_posts_by_votes', 99);
31 add_filter('bbp_has_replies_query', 'sort_bbpress_posts_by_votes', 99);
32 add_filter('Bp_Search_Forums_sql', 'sort_bbpress_posts_by_votes', 99, 1);
33 }
34
35 // How to remove voting buttons from topic page
36 // add_action('init', function() {
37 // remove_action('bbp_theme_before_topic_content', 'bbp_voting_buttons');
38 // remove_action('bbp_theme_before_reply_content', 'bbp_voting_buttons');
39 // }, 11);
40
41 // Enqueue Scripts
42
43 function bbp_voting_styles() {
44 wp_enqueue_style( 'bbp-voting-css', plugin_dir_url(__FILE__) . 'css/bbp-voting.css', array(), filemtime(plugin_dir_path(__FILE__) . 'css/bbp-voting.css') );
45 }
46
47 function bbp_voting_scripts() {
48 if(function_exists( 'is_amp_endpoint' ) && is_amp_endpoint()) {
49 // AMP = No JS
50 } else {
51 wp_enqueue_script( 'bbp-voting-js', plugin_dir_url(__FILE__) . 'js/bbp-voting.js', array('jquery'), filemtime(plugin_dir_path(__FILE__). 'js/bbp-voting.js') );
52 wp_localize_script( 'bbp-voting-js', 'bbp_voting_ajax_object', array( 'ajax_url' => admin_url( 'admin-ajax.php' ) ) );
53 }
54 }
55
56 // Body Classes
57
58 add_filter('body_class', function($classes) {
59 if (apply_filters('bbp_voting_buddyboss_css', false)) {
60 // Activate BuddyBoss Theme Compatibility CSS
61 $classes[] = 'bbp-voting-buddyboss-css';
62 }
63 $classes[] = 'bbp-voting-active';
64 return $classes;
65 });
66
67 // Vote Buttons and Score
68
69 function bbp_voting_buttons_filter( $content = '', $reply_id = 0 ) {
70 global $bbp_voting_button_filter_reply_ids;
71 if(!is_array($bbp_voting_button_filter_reply_ids)) {
72 $bbp_voting_button_filter_reply_ids = [];
73 }
74 if(!in_array($reply_id, $bbp_voting_button_filter_reply_ids)) {
75 ob_start();
76 bbp_voting_buttons();
77 $content = ob_get_clean() . $content;
78 $bbp_voting_button_filter_reply_ids[] = $reply_id;
79 }
80 return $content;
81 }
82
83 function bbp_voting_buttons($post_obj = false) {
84 // global $bbp_voting_last_author_link_post_id;
85 $current_action = current_action();
86 $this_post_type = '';
87 if($current_action === 'bbp_voting_cpt') {
88 // Using a custom hook for a custom post type
89 if(!$post_obj) return;
90 $post = $post_obj;
91 } else {
92 // Using a bbPress hook
93 $topic_post_type = bbp_get_topic_post_type();
94 $reply_post_type = bbp_get_reply_post_type();
95 if(in_array($current_action, ['bbp_get_topic_content', 'bbp_theme_before_topic_title', 'bbp_template_before_lead_topic', 'bbp_theme_before_topic_content'])) {
96 // Topic hook will always be the topic
97 $this_post_type = $topic_post_type;
98 }
99 if(in_array($current_action, ['bbp_get_reply_content', 'bbp_theme_before_reply_content'])) {
100 // Reply hook could be topic (OP) or a reply
101 $this_post_type = bbp_voting_get_current_post_type();
102 }
103 // Get the post
104 if(bbp_is_search_results()) {
105 $post = bbpress()->search_query->post;
106 } elseif($this_post_type == $topic_post_type) {
107 $post = bbpress()->topic_query->post;
108 } elseif($this_post_type == $reply_post_type) {
109 $post = bbpress()->reply_query->post;
110 }
111 }
112 // Do we have a post?
113 if(!empty($post)) {
114 $post_id = $post->ID;
115 // Since we're using a filter on the author link, avoid duplicates
116 // if($bbp_voting_last_author_link_post_id === $post_id) {
117 // // Duplicate
118 // return $author_link;
119 // } else {
120 // // New, continue, but set the global variable
121 // $bbp_voting_last_author_link_post_id = $post_id;
122 // }
123 if($current_action === 'bbp_voting_cpt') {
124 $post_setting = true;
125 $broad_disable = false;
126 } else {
127 switch($this_post_type) {
128 case $topic_post_type:
129 $forum_id = bbp_get_topic_forum_id($post_id);
130 $post_setting = get_post_meta($forum_id, 'bbp_voting_forum_enable_topics', true);
131 $broad_disable = apply_filters('bbp_voting_only_replies', false);
132 $disable_forum_index_buttons = is_singular('topic') ? false : apply_filters('bbp_voting_disable_forum_index_buttons', false);
133 break;
134 case $reply_post_type:
135 $forum_id = bbp_get_reply_forum_id($post_id);
136 $post_setting = get_post_meta($forum_id, 'bbp_voting_forum_enable_replies', true);
137 $broad_disable = apply_filters('bbp_voting_only_topics', false);
138 $disable_forum_index_buttons = false;
139 break;
140 }
141 // Filter Hook: 'bbp_voting_allowed_on_forum'
142 if(!apply_filters('bbp_voting_allowed_on_forum', true, $forum_id)) return;
143 }
144 if(!empty($post_setting)) {
145 // Forum-specific override is set (not Default)
146 if($post_setting === 'false') return;
147 } else {
148 // Use broad disable settings
149 if($broad_disable === true) return;
150 // Use broad disable settings
151 if($disable_forum_index_buttons === true) return;
152 }
153 // Done with "allowed" checks... let's do this
154 $score = (int) get_post_meta($post_id, 'bbp_voting_score', true);
155 $weighted_score = get_post_meta($post_id, 'bbp_voting_weighted_score', true);
156 $trending_score = get_post_meta($post_id, 'bbp_voting_trending_score', true);
157 $ups = (int) get_post_meta($post_id, 'bbp_voting_ups', true);
158 $downs = (int) get_post_meta($post_id, 'bbp_voting_downs', true);
159 $votes = get_post_meta($post_id, 'bbp_voting_votes', true);
160 $score_graph = '';
161 if(is_array($votes) && apply_filters('bbp_voting_show_visualization', false)) {
162 if(function_exists('bbp_voting_get_score_graph')) {
163 $score_graph = bbp_voting_get_score_graph($votes, $post_id);
164 }
165 }
166 // Check for, and correct, discrepancies
167 $calc_score = $ups + $downs;
168 if($score > $calc_score) {
169 $diff = $score - $calc_score;
170 $ups += $diff;
171 update_post_meta($post_id, 'bbp_voting_ups', $ups);
172 }
173 // Get user's vote by ID or IP
174 $voting_log = get_post_meta($post_id, 'bbp_voting_log', true);
175 $voting_log = is_array($voting_log) ? $voting_log : array(); // Set up new array
176 $client_ip = $_SERVER['REMOTE_ADDR'];
177 $identifier = is_user_logged_in() ? get_current_user_id() : $client_ip;
178 $existing_vote = array_key_exists($identifier, $voting_log) ? $voting_log[$identifier] : 0;
179 // Admin bypass?
180 $admin_bypass = current_user_can('administrator') && apply_filters('bbp_voting_admin_bypass', false);
181 // View only score?
182 // View only for visitors option
183 $view_only = (!is_user_logged_in() && apply_filters('bbp_voting_disable_voting_for_visitors', false)) ? true : false;
184 if(!$view_only) {
185 // View only for closed topic option
186 if($current_action !== 'bbp_voting_cpt') {
187 $topic_id = $this_post_type == $topic_post_type ? $post_id : bbp_get_reply_topic_id($post_id);
188 $topic_status = get_post_status( $topic_id );
189 $view_only = ($topic_status == 'closed' && apply_filters('bbp_voting_disable_voting_on_closed_topic', false)) ? true : false;
190 }
191 if(!$view_only) {
192 // View only for author of post
193 $view_only = (apply_filters('bbp_voting_disable_author_vote', false) && $post->post_author == get_current_user_ID()) ? true : false;
194 }
195 }
196 // Show labels?
197 $show_labels = apply_filters('bbp_voting_show_labels', true);
198 // Disable down votes?
199 $disable_down = apply_filters('bbp_voting_disable_down_votes', false);
200 // How to display vote numbers?
201 $display_vote_nums = 'num-'. apply_filters('bbp_voting_display_vote_nums', 'hover');
202 // Start HTML
203 $html = '';
204 $float = in_array(current_action(), ['bbp_get_topic_content', 'bbp_get_reply_content', 'bbp_theme_before_reply_content', 'bbp_theme_before_topic_content', 'bbp_voting_cpt']);
205 $html .= '<div class="bbp-voting bbp-voting-post-' . $post_id . (
206 $view_only ? ' view-only' : (
207 $existing_vote == 1 ? ' voted-up' : (
208 $existing_vote == -1 ? ' voted-down' : ''
209 )
210 )
211 ) . (
212 $admin_bypass ? ' admin-bypass' : ''
213 ) . (
214 $float ? ' bbp-voting-float' : ''
215 ) . (
216 $calc_score > 0 ? ' positive' : (
217 $calc_score < 0 ? ' negative' : ''
218 )
219 ) . '">';
220 //adds the word 'helpful' in red above the arrow
221 if($show_labels)
222 $html .= '<div class="bbp-voting-label helpful">'.apply_filters('bbp_voting_helpful', 'Helpful').'</div>';
223 if(function_exists( 'is_amp_endpoint' ) && is_amp_endpoint()) {
224 // AMP = No JS
225 $post_url = admin_url('admin-ajax.php');
226 // Up vote
227 $plusups = $ups ? '+'.$ups : ' ';
228 $html .= '<form name="amp-form' . $post_id . '" method="post" action-xhr="'.$post_url.'" target="_top" on="submit-success: AMP.setState({\'voteup'. $post_id .'\': '.($ups + 1).'})">
229 <input type="hidden" name="action" value="bbpress_post_vote_link_clicked">
230 <input type="hidden" name="post_id" value="' . $post_id . '" />
231 <input type="hidden" name="direction" value="1" />
232 <input type="submit" class="nobutton upvote-amp" value="🔺" />
233 <span class="vote up" [text]="voteup'. $post_id .' ? \'+\' + voteup'. $post_id .' : \''.$plusups.'\'">'.$plusups.'</span>
234 </form>';
235 // Display current vote count for post
236 // $html .= '<div class="score">'. $score. '</div>';
237 // $html .= '<div class="score" style="background-color: rgb('. floor((1 - $score) * 255). ', '.floor($score * 255).', 0); width:'.floor($score * 100).'%;"></div>';
238 $html .= $score_graph;
239 // Down vote
240 if(!$disable_down) $html .= '<form name="amp-form' . $post_id . '" method="post" action-xhr="'.$post_url.'" target="_top" on="submit-success: AMP.setState({\'votedown'. $post_id .'\': '.($downs - 1).'})">
241 <input type="hidden" name="action" value="bbpress_post_vote_link_clicked">
242 <input type="hidden" name="post_id" value="' . $post_id . '" />
243 <input type="hidden" name="direction" value="-1" />
244 <input type="submit" class="nobutton downvote-amp" value="🔻" />
245 <span class="vote down" [text]="votedown'. $post_id .' || \''.($downs ? $downs : ' ').'\'">'.($downs ? $downs : '').'</span>
246 </form>';
247 } else {
248 // Normal JS AJAX version
249 // Up vote
250 $html .= '<a class="vote up '. $display_vote_nums .'" data-votes="'.($ups ? '+'.$ups : '').'" onclick="bbpress_post_vote_link_clicked(' . $post_id . ', 1); return false;">'.__('Up', 'bbp-voting').'</a>';
251 // Display current vote count for post
252 $html .= '<div class="score" data-sort="'. ($weighted_score !== false && $weighted_score !== '' ? round($weighted_score, 3) : $score) .'">'. (defined('BBPVOTINGDEBUG') ? ('simple: '. $score .'<br>weighted: '. round($weighted_score, 3) .'<br>trending: '. round($trending_score, 3) .'<br>ups:'. $ups .'<br>downs: '. $downs) : $score) . '</div>';
253 $html .= $score_graph;
254 // Down vote
255 if(!$disable_down) $html .= '<a class="vote down '. $display_vote_nums .'" data-votes="'.($downs < 0 ? $downs : '').'" onclick="bbpress_post_vote_link_clicked(' . $post_id . ', -1); return false;">'.__('Down', 'bbp-voting').'</a>';
256 }
257 //adds the words 'not helpful' in red below the arrow
258 if(!$disable_down && $show_labels)
259 $html .= '<div class="bbp-voting-label not-helpful">'.apply_filters('bbp_voting_not_helpful', 'Not Helpful').'</div>';
260 if($this_post_type == $reply_post_type)
261 $html = apply_filters('bbp_voting_after_reply_voting_buttons', $html, $post_id);
262 $html = apply_filters('bbp_voting_inside_voting_buttons_filter', $html, $post_id);
263 $html .= '</div>';
264 // Special hidden mark after the voting buttons for using regex to strip them off of things that pull excerpts using jQuery text()
265 $html .= '<span style="display:none;">::</span>';
266 // return $html . $author_link;
267 echo $html;
268 }
269 }
270
271 // Sort by Votes
272
273 function sort_bbpress_posts_by_votes( $args = array() ) {
274 // Handle SQL string passed from BuddyBoss search filter
275 if(!is_array($args)) {
276 return $args;
277 }
278
279 $forum_id = bbp_get_forum_id();
280 // if($forum_id === 0) return $args;
281 // $this_post_type = isset($args['post_type']) ? $args['post_type'] : bbp_voting_get_current_post_type();
282 // $this_post_type = bbp_voting_get_current_post_type();
283 $forum_post_type = bbp_get_forum_post_type();
284 $topic_post_type = bbp_get_topic_post_type();
285 $current_filter = current_filter();
286 switch($current_filter) {
287 case 'bbp_has_topics_query':
288 $this_post_type = $forum_post_type;
289 $post_setting = get_post_meta( $forum_id, 'sort_bbpress_topics_by_votes_on_forum', true);
290 $broad_enable = apply_filters('sort_bbpress_topics_by_votes', false);
291 break;
292 case 'bbp_has_replies_query':
293 $this_post_type = $topic_post_type;
294 $post_setting = get_post_meta( $forum_id, 'sort_bbpress_replies_by_votes_on_forum', true);
295 $broad_enable = apply_filters('sort_bbpress_replies_by_votes', false);
296 break;
297 case 'Bp_Search_Forums_sql':
298 $this_post_type = $topic_post_type;
299 $post_setting = get_post_meta( $forum_id, 'sort_bbpress_topics_by_votes_on_forum', true);
300 $broad_enable = apply_filters('sort_bbpress_replies_by_votes', false);
301 break;
302 default:
303 return $args;
304 }
305 // Do "allowed" checks
306 $bbp_voting_sort = isset($_GET['bbp-voting-sort']) ? (string) $_GET['bbp-voting-sort'] : '';
307 // Validate against an allowlist before passing the value to any filter. Without
308 // this, a 3rd-party consumer of `bbp_voting_sort_meta_key` could be fed a tainted
309 // string that's used as a meta_query key.
310 $allowed_sorts = array('default', 'best', 'trending', '');
311 if(!in_array($bbp_voting_sort, $allowed_sorts, true)) {
312 $bbp_voting_sort = '';
313 }
314 if($bbp_voting_sort !== '') {
315 // Sort dropdown used, skip the rest of the checks
316 if($bbp_voting_sort === 'best' || $bbp_voting_sort === 'trending') {
317 // Proceed with score sorting
318 } elseif($bbp_voting_sort === 'default') {
319 // bbp default non-score sort
320 return $args;
321 }
322 } else {
323 // Sort dropdown not used... check the settings
324 if($post_setting === 'false') {
325 // Forum-specific override is set (not Default)
326 return $args;
327 } elseif($broad_enable === false) {
328 // Use broad disable settings
329 return $args;
330 } elseif(!apply_filters('bbp_voting_allowed_on_forum', true, $forum_id)) {
331 // Voting not allowed on this Forum ID
332 return $args;
333 } elseif(apply_filters('bbp_voting_sort_by_dropdown_default', '') === 'default') {
334 // Sort dropdown default is "default"
335 return $args;
336 }
337
338 }
339 // Done with "allowed" checks... let's do this
340 // Filter the sort meta key. Default = bbp_voting_score
341 $sort_meta_key = apply_filters('bbp_voting_sort_meta_key', 'bbp_voting_score', $bbp_voting_sort);
342
343 // Reset for testing only -------------------------------------
344 // $argsreset = $args;
345 // $query = new WP_Query($argsreset);
346 // foreach($query->posts as $reply) {
347 // delete_post_meta($reply->ID, $sort_meta_key);
348 // }
349 // -----------------------------------
350
351 // Find any replies that are missing the bbp_voting_score post meta and fill them with 0
352 $args2 = $args;
353 $args2['meta_query'] = [
354 [
355 'key' => $sort_meta_key,
356 'compare' => 'NOT EXISTS',
357 'value' => ''
358 ],
359 ];
360 $query = new WP_Query($args2);
361 foreach($query->posts as $reply) {
362 $fill_in_default = apply_filters('bbp_voting_sort_meta_key_default_value', '0', $reply->ID);
363 update_post_meta($reply->ID, $sort_meta_key, $fill_in_default);
364 }
365
366 // Now that all missing scores are filled in, we can sort the original args by the score
367 // $args['meta_key'] = 'bbp_voting_score';
368 // $args['orderby'] = [
369 // 'post_type' => 'DESC',
370 // 'meta_value_num' => 'DESC',
371 // 'date' => 'DESC'
372 // ];
373 unset($args['meta_key']);
374 unset($args['meta_type']);
375 unset($args['orderby']);
376 unset($args['order']);
377 $args['meta_query'] = [
378 'relation' => 'AND',
379 'score_clause' => [
380 'key' => $sort_meta_key,
381 'compare' => 'EXISTS'
382 ]
383 ];
384 if($sort_meta_key == 'bbp_voting_score') {
385 $args['meta_query']['score_clause']['type'] = 'NUMERIC';
386 }
387 if($sort_meta_key == 'bbp_voting_weighted_score') {
388 $args['meta_query']['score_clause']['type'] = 'DECIMAL(5,3)';
389 }
390 if($sort_meta_key == 'bbp_voting_trending_score') {
391 $args['meta_query']['score_clause']['type'] = 'DECIMAL(8,3)';
392 }
393 $args['orderby'] = [
394 'post_type' => 'DESC',
395 'score_clause' => 'DESC'
396 ];
397 if($this_post_type === $topic_post_type) {
398 // Add Date as another orderby for topics on a forum
399 $args['orderby']['date'] = 'ASC';
400 }
401 if($this_post_type === $forum_post_type) {
402 // Add Freshness as another orderby for topics on a forum
403 $args['meta_query']['orderby_freshness'] = [
404 'key' => '_bbp_last_active_time',
405 'type' => 'DATETIME',
406 ];
407 $args['orderby']['orderby_freshness'] = 'DESC';
408 }
409 return $args;
410 }
411
412 add_action('init', 'bbp_voting_lead_topic');
413 function bbp_voting_lead_topic() {
414 if(apply_filters('bbp_voting_lead_topic', false)) {
415 add_filter('bbp_show_lead_topic', '__return_true');
416 }
417 }
418