| 1 |
<?php |
| 2 |
if ( ! defined( 'ABSPATH' ) ) { |
| 3 |
exit; // Exit if accessed directly. |
| 4 |
} |
| 5 |
|
| 6 |
$opt = get_option( 'bbp_core_settings' ); |
| 7 |
$voting_position = $opt['voting_position'] ?? 'below_user'; |
| 8 |
|
| 9 |
|
| 10 |
// Vote Buttons and Score hooks. |
| 11 |
// add_action('bbp_theme_before_topic_author_details', 'bbp_voting_buttons'); |
| 12 |
// add_action('bbp_theme_before_reply_author_details', 'bbp_voting_buttons'); |
| 13 |
add_action( 'bbp_theme_before_topic_title', 'bbp_voting_buttons' ); |
| 14 |
// add_action('bbp_template_before_lead_topic', 'bbp_voting_buttons'); |
| 15 |
|
| 16 |
add_action( 'bbp_theme_before_topic_content', 'bbp_voting_buttons' ); |
| 17 |
|
| 18 |
if ( 'before_content' == $voting_position ) { |
| 19 |
add_action( 'bbp_theme_before_reply_content', 'bbp_voting_buttons' ); |
| 20 |
} elseif ( 'below_user' == $voting_position ) { |
| 21 |
add_action( 'bbp_theme_after_reply_author_details', 'bbp_voting_buttons' ); |
| 22 |
} |
| 23 |
|
| 24 |
// add_filter('bbp_get_topic_author_link', 'bbp_voting_buttons', 9, 3); |
| 25 |
// add_filter('bbp_get_reply_author_link', 'bbp_voting_buttons', 9, 3); |
| 26 |
add_action( 'bbp_voting_cpt', 'bbp_voting_buttons', 10, 1 ); |
| 27 |
|
| 28 |
function bbp_voting_buttons( $post_obj = false ) { |
| 29 |
$opt = get_option( 'bbp_core_settings' ); |
| 30 |
|
| 31 |
$current_action = current_action(); |
| 32 |
|
| 33 |
if ( $current_action === 'bbp_voting_cpt' ) { |
| 34 |
|
| 35 |
// Using a custom hook for a custom post type |
| 36 |
if ( ! $post_obj ) { |
| 37 |
return; |
| 38 |
} |
| 39 |
|
| 40 |
$post = $post_obj; |
| 41 |
|
| 42 |
} else { |
| 43 |
$topic_post_type = bbp_get_topic_post_type(); |
| 44 |
$reply_post_type = bbp_get_reply_post_type(); |
| 45 |
|
| 46 |
if ( in_array( $current_action, [ 'bbp_theme_before_topic_title', 'bbp_template_before_lead_topic', 'bbp_theme_before_topic_content' ] ) ) { |
| 47 |
|
| 48 |
$this_post_type = $topic_post_type; |
| 49 |
} |
| 50 |
|
| 51 |
if ( in_array( $current_action, [ 'bbp_theme_before_reply_content', 'bbp_theme_after_reply_author_details' ] ) ) { |
| 52 |
$this_post_type = bbp_voting_get_current_post_type(); |
| 53 |
} |
| 54 |
|
| 55 |
// Get the post. |
| 56 |
if ( $this_post_type == $topic_post_type ) { |
| 57 |
$post = bbpress()->topic_query->post; |
| 58 |
} |
| 59 |
|
| 60 |
if ( $this_post_type == $reply_post_type ) { |
| 61 |
$post = bbpress()->reply_query->post; |
| 62 |
} |
| 63 |
} |
| 64 |
|
| 65 |
// Do we have a post? |
| 66 |
if ( ! empty( $post ) ) { |
| 67 |
$post_id = $post->ID; |
| 68 |
// Since we're using a filter on the author link, avoid duplicates |
| 69 |
// if($bbp_voting_last_author_link_post_id === $post_id) { |
| 70 |
// Duplicate |
| 71 |
// return $author_link; |
| 72 |
// } else { |
| 73 |
// New, continue, but set the global variable |
| 74 |
// $bbp_voting_last_author_link_post_id = $post_id; |
| 75 |
// } |
| 76 |
if ( $current_action === 'bbp_voting_cpt' ) { |
| 77 |
$post_setting = true; |
| 78 |
$broad_disable = false; |
| 79 |
} else { |
| 80 |
switch ( $this_post_type ) { |
| 81 |
case $topic_post_type: |
| 82 |
$forum_id = bbp_get_topic_forum_id( $post_id ); |
| 83 |
$post_setting = get_post_meta( $forum_id, 'bbp_voting_forum_enable_topics', true ); |
| 84 |
$broad_disable = $opt['is_voting_disabled_topics'] ?? 0; |
| 85 |
break; |
| 86 |
case $reply_post_type: |
| 87 |
$forum_id = bbp_get_reply_forum_id( $post_id ); |
| 88 |
$post_setting = get_post_meta( $forum_id, 'bbp_voting_forum_enable_replies', true ); |
| 89 |
$broad_disable = $opt['is_voting_disabled_replies'] ?? 0; |
| 90 |
break; |
| 91 |
} |
| 92 |
// Filter Hook: 'bbp_voting_allowed_on_forum' |
| 93 |
if ( ! apply_filters( 'bbp_voting_allowed_on_forum', true, $forum_id ) ) { |
| 94 |
return; |
| 95 |
} |
| 96 |
} |
| 97 |
if ( ! empty( $post_setting ) ) { |
| 98 |
// Forum-specific override is set (not Default) |
| 99 |
if ( $post_setting === 'false' ) { |
| 100 |
return; |
| 101 |
} |
| 102 |
} else { |
| 103 |
// Use broad disable settings |
| 104 |
if ( $broad_disable === '0' ) { |
| 105 |
return; |
| 106 |
} |
| 107 |
} |
| 108 |
// Done with "allowed" checks... let's do this |
| 109 |
$score = (int) get_post_meta( $post_id, 'bbp_voting_score', true ); |
| 110 |
$ups = (int) get_post_meta( $post_id, 'bbp_voting_ups', true ); |
| 111 |
$downs = (int) get_post_meta( $post_id, 'bbp_voting_downs', true ); |
| 112 |
// Check for, and correct, discrepancies |
| 113 |
$calc_score = $ups + $downs; |
| 114 |
if ( $score > $calc_score ) { |
| 115 |
$diff = $score - $calc_score; |
| 116 |
$ups += $diff; |
| 117 |
update_post_meta( $post_id, 'bbp_voting_ups', $ups ); |
| 118 |
} |
| 119 |
// Get the weighted score |
| 120 |
// $weighted_score = get_post_meta($post_id, 'bbp_voting_weighted_score', true); |
| 121 |
// Get user's vote by ID or IP |
| 122 |
$voting_log = get_post_meta( $post_id, 'bbp_voting_log', true ); |
| 123 |
$voting_log = is_array( $voting_log ) ? $voting_log : []; // Set up new array |
| 124 |
$client_ip = $_SERVER['REMOTE_ADDR']; |
| 125 |
$identifier = is_user_logged_in() ? get_current_user_id() : $client_ip; |
| 126 |
$existing_vote = array_key_exists( $identifier, $voting_log ) ? $voting_log[ $identifier ] : 0; |
| 127 |
// Admin bypass? |
| 128 |
$is_admin_can_vote_unlimited = $opt['is_admin_can_vote_unlimited'] ?? false; |
| 129 |
$admin_bypass = current_user_can( 'administrator' ) && $is_admin_can_vote_unlimited; |
| 130 |
// View only score? |
| 131 |
// View only for visitors option |
| 132 |
$is_disabled_voting_non_logged = $opt['is_disabled_voting_for_non_logged_users'] ?? false; |
| 133 |
$view_only = ! is_user_logged_in() && $is_disabled_voting_non_logged; |
| 134 |
if ( ! $view_only ) { |
| 135 |
// View only for closed topic option. |
| 136 |
if ( $current_action !== 'bbp_voting_cpt' ) { |
| 137 |
$topic_id = $this_post_type == $topic_post_type ? $post_id : bbp_get_reply_topic_id( $post_id ); |
| 138 |
$topic_status = get_post_status( $topic_id ); |
| 139 |
$is_diabled_closed_topics = $opt['is_disabled_voting_closed_topics'] ?? false; |
| 140 |
$view_only = ( 'closed' == $topic_status && $is_diabled_closed_topics ) ? true : false; |
| 141 |
} |
| 142 |
if ( ! $view_only ) { |
| 143 |
// View only for author of post. |
| 144 |
$is_disabled_own_topic_reply = $opt['is_disabled_voting_own_topic_reply'] ?? false; |
| 145 |
$view_only = ( $is_disabled_own_topic_reply && $post->post_author == get_current_user_ID() ) ? true : false; |
| 146 |
} |
| 147 |
} |
| 148 |
// Show labels? |
| 149 |
// Disable down votes? |
| 150 |
$disable_down = $opt['is_down_votes_disabled'] ?? 0; |
| 151 |
$vote_number_display = $opt['vote_numbers_display'] ?? 'hover'; |
| 152 |
|
| 153 |
// How to display vote numbers? |
| 154 |
$display_vote_nums = 'num-' . $vote_number_display; |
| 155 |
// Start HTML |
| 156 |
$html = ''; |
| 157 |
$float = in_array( current_action(), [ 'bbp_theme_before_reply_content', 'bbp_theme_before_topic_content', 'bbp_voting_cpt' ] ); |
| 158 |
$html .= '<div class="bbp-voting bbp-voting-post-' . $post_id . ( $view_only ? ' view-only' : ( $existing_vote == 1 ? ' voted-up' : ( $existing_vote == -1 ? ' voted-down' : '' ) ) ) . ( $admin_bypass ? ' admin-bypass' : '' ) . ( $float ? ' bbp-voting-float' : '' ) . '">'; |
| 159 |
|
| 160 |
// Adds the word 'helpful' in red above the arrow. |
| 161 |
$is_label = $opt['is_label'] ?? true; |
| 162 |
|
| 163 |
if ( $is_label ) { |
| 164 |
$upvote_label = ! empty( $opt['upvote_label'] ) ? $opt['upvote_label'] : ''; |
| 165 |
$html .= '<div class="bbp-voting-label helpful">' . $upvote_label . '</div>'; |
| 166 |
} |
| 167 |
if ( function_exists( 'is_amp_endpoint' ) && is_amp_endpoint() ) { |
| 168 |
// AMP = No JS |
| 169 |
$post_url = admin_url( 'admin-ajax.php' ); |
| 170 |
// Up vote |
| 171 |
$plusups = $ups ? '+' . $ups : ' '; |
| 172 |
$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 ) . '})"> |
| 173 |
<input type="hidden" name="action" value="bbpress_post_vote_link_clicked"> |
| 174 |
<input type="hidden" name="post_id" value="' . $post_id . '" /> |
| 175 |
<input type="hidden" name="direction" value="1" /> |
| 176 |
<input type="submit" class="nobutton upvote-amp" value="🔺" /> |
| 177 |
<span class="vote up" [text]="voteup' . $post_id . ' ? \'+\' + voteup' . $post_id . ' : \'' . $plusups . '\'">' . $plusups . '</span> |
| 178 |
</form>'; |
| 179 |
// Display current vote count for post |
| 180 |
// $html .= '<div class="score">'. $score. '</div>'; |
| 181 |
// $html .= '<div class="score" style="background-color: rgb('. floor((1 - $score) * 255). ', '.floor($score * 255).', 0); width:'.floor($score * 100).'%;"></div>'; |
| 182 |
// Down vote |
| 183 |
if ( $disable_down === '1' ) { |
| 184 |
$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 ) . '})"> |
| 185 |
<input type="hidden" name="action" value="bbpress_post_vote_link_clicked"> |
| 186 |
<input type="hidden" name="post_id" value="' . $post_id . '" /> |
| 187 |
<input type="hidden" name="direction" value="-1" /> |
| 188 |
<input type="submit" class="nobutton downvote-amp" value="🔻" /> |
| 189 |
<span class="vote down" [text]="votedown' . $post_id . ' || \'' . ( $downs ? $downs : ' ' ) . '\'">' . ( $downs ? $downs : '' ) . '</span> |
| 190 |
</form>'; |
| 191 |
} |
| 192 |
} else { |
| 193 |
// Normal JS AJAX version |
| 194 |
// Up vote |
| 195 |
$html .= '<a class="vote up ' . $display_vote_nums . '" data-votes="' . ( $ups ? '+' . $ups : '' ) . '" onclick="bbpress_post_vote_link_clicked(' . $post_id . ', 1); return false;">Up</a>'; |
| 196 |
// Display current vote count for post |
| 197 |
$html .= '<div class="score">' . $score . '</div>'; |
| 198 |
// Down vote |
| 199 |
if ( $disable_down === '1' ) { |
| 200 |
$html .= '<a class="vote down ' . $display_vote_nums . '" data-votes="' . ( $downs ? $downs : '' ) . '" onclick="bbpress_post_vote_link_clicked(' . $post_id . ', -1); return false;">Down</a>'; |
| 201 |
} |
| 202 |
} |
| 203 |
// adds the words 'not helpful' in red below the arrow |
| 204 |
if ( $disable_down === '1' && $is_label ) { |
| 205 |
$downvote_label = ! empty( $opt['downvote_label'] ) ? $opt['downvote_label'] : ''; |
| 206 |
$html .= '<div class="bbp-voting-label not-helpful">' . $downvote_label . '</div>'; |
| 207 |
} |
| 208 |
if ( $this_post_type == $reply_post_type ) { |
| 209 |
$html = apply_filters( 'bbp_voting_after_reply_voting_buttons', $html, $post_id ); // TODO: take care |
| 210 |
} |
| 211 |
$html .= '</div>'; |
| 212 |
// Special hidden mark after the voting buttons for using regex to strip them off of things that pull excerpts using jQuery text() |
| 213 |
$html .= '<span style="display:none;">::</span>'; |
| 214 |
// return $html . $author_link; |
| 215 |
echo $html; |
| 216 |
} |
| 217 |
} |
| 218 |
|
| 219 |
// Sort by Votes |
| 220 |
|
| 221 |
add_filter( 'bbp_has_topics_query', 'sort_bbpress_posts_by_votes', 99 ); |
| 222 |
add_filter( 'bbp_has_replies_query', 'sort_bbpress_posts_by_votes', 99 ); |
| 223 |
|
| 224 |
function sort_bbpress_posts_by_votes( $args = [] ) { |
| 225 |
$opt = get_option( 'bbp_core_settings' ); |
| 226 |
|
| 227 |
$forum_id = bbp_get_forum_id(); |
| 228 |
// if($forum_id === 0) return $args; |
| 229 |
// $this_post_type = isset($args['post_type']) ? $args['post_type'] : bbp_voting_get_current_post_type(); |
| 230 |
// $this_post_type = bbp_voting_get_current_post_type(); |
| 231 |
$forum_post_type = bbp_get_forum_post_type(); |
| 232 |
$topic_post_type = bbp_get_topic_post_type(); |
| 233 |
switch ( current_filter() ) { |
| 234 |
case 'bbp_has_topics_query': |
| 235 |
$this_post_type = $forum_post_type; |
| 236 |
$post_setting = get_post_meta( $forum_id, 'sort_bbpress_topics_by_votes_on_forum', true ); |
| 237 |
$broad_enable = $opt['is_sort_topic_by_votes'] ?? 0; |
| 238 |
break; |
| 239 |
case 'bbp_has_replies_query': |
| 240 |
$this_post_type = $topic_post_type; |
| 241 |
$post_setting = get_post_meta( $forum_id, 'sort_bbpress_replies_by_votes_on_forum', true ); |
| 242 |
$broad_enable = $opt['is_sort_reply_by_votes'] ?? 0; |
| 243 |
break; |
| 244 |
default: |
| 245 |
return $args; |
| 246 |
} |
| 247 |
// Do "allowed" checks |
| 248 |
if ( isset( $_GET['bbp-voting-sort'] ) ) { |
| 249 |
// Sort dropdown used, skip the rest of the checks |
| 250 |
if ( $_GET['bbp-voting-sort'] === 'best' ) { |
| 251 |
// Proceed with score sorting |
| 252 |
} elseif ( $_GET['bbp-voting-sort'] === 'default' || $_GET['bbp-voting-sort'] === '' ) { |
| 253 |
// bbp default non-score sort |
| 254 |
return $args; |
| 255 |
} |
| 256 |
} else { |
| 257 |
// Sort dropdown not used... check the settings |
| 258 |
if ( ! empty( $post_setting ) ) { |
| 259 |
// Forum-specific override is set (not Default) |
| 260 |
if ( $post_setting === 'false' ) { |
| 261 |
return $args; |
| 262 |
} |
| 263 |
} else { |
| 264 |
// Use broad disable settings |
| 265 |
if ( $broad_enable === '1' ) { |
| 266 |
return $args; |
| 267 |
} |
| 268 |
} |
| 269 |
if ( ! apply_filters( 'bbp_voting_allowed_on_forum', true, $forum_id ) ) { |
| 270 |
return $args; |
| 271 |
} |
| 272 |
} |
| 273 |
// Done with "allowed" checks... let's do this |
| 274 |
// Filter the sort meta key. Default = bbp_voting_score |
| 275 |
$sort_meta_key = apply_filters( 'bbp_voting_sort_meta_key', 'bbp_voting_score' ); |
| 276 |
|
| 277 |
// Reset for testing only ------------------------------------- |
| 278 |
// $argsreset = $args; |
| 279 |
// $query = new WP_Query($argsreset); |
| 280 |
// foreach($query->posts as $reply) { |
| 281 |
// delete_post_meta($reply->ID, $sort_meta_key); |
| 282 |
// } |
| 283 |
// ----------------------------------- |
| 284 |
|
| 285 |
// Find any replies that are missing the bbp_voting_score post meta and fill them with 0 |
| 286 |
$args2 = $args; |
| 287 |
$args2['meta_query'] = [ |
| 288 |
[ |
| 289 |
'key' => $sort_meta_key, |
| 290 |
'compare' => 'NOT EXISTS', |
| 291 |
'value' => '', |
| 292 |
], |
| 293 |
]; |
| 294 |
$query = new WP_Query( $args2 ); |
| 295 |
foreach ( $query->posts as $reply ) { |
| 296 |
$fill_in_default = apply_filters( 'bbp_voting_sort_meta_key_default_value', '0', $reply->ID ); |
| 297 |
update_post_meta( $reply->ID, $sort_meta_key, $fill_in_default ); |
| 298 |
} |
| 299 |
|
| 300 |
// Now that all missing scores are filled in, we can sort the original args by the score |
| 301 |
// $args['meta_key'] = 'bbp_voting_score'; |
| 302 |
// $args['orderby'] = [ |
| 303 |
// 'post_type' => 'DESC', |
| 304 |
// 'meta_value_num' => 'DESC', |
| 305 |
// 'date' => 'DESC' |
| 306 |
// ]; |
| 307 |
unset( $args['meta_key'] ); |
| 308 |
unset( $args['meta_type'] ); |
| 309 |
unset( $args['orderby'] ); |
| 310 |
unset( $args['order'] ); |
| 311 |
$args['meta_query'] = [ |
| 312 |
'relation' => 'AND', |
| 313 |
'score_clause' => [ |
| 314 |
'key' => $sort_meta_key, |
| 315 |
'compare' => 'EXISTS', |
| 316 |
// 'type' => 'DECIMAL' // https://stackoverflow.com/questions/30018711/wordpress-meta-query-not-working-with-decimal-type |
| 317 |
], |
| 318 |
]; |
| 319 |
if ( $sort_meta_key == 'bbp_voting_score' ) { |
| 320 |
$args['meta_query']['score_clause']['type'] = 'NUMERIC'; |
| 321 |
} |
| 322 |
$args['orderby'] = [ |
| 323 |
'post_type' => 'DESC', |
| 324 |
'score_clause' => 'DESC', |
| 325 |
]; |
| 326 |
if ( $this_post_type === $topic_post_type ) { |
| 327 |
// Add Date as another orderby for topics on a forum |
| 328 |
$args['orderby']['date'] = 'ASC'; |
| 329 |
} |
| 330 |
if ( $this_post_type === $forum_post_type ) { |
| 331 |
// Add Freshness as another orderby for topics on a forum |
| 332 |
$args['meta_query']['orderby_freshness'] = [ |
| 333 |
'key' => '_bbp_last_active_time', |
| 334 |
'type' => 'DATETIME', |
| 335 |
]; |
| 336 |
$args['orderby']['orderby_freshness'] = 'DESC'; |
| 337 |
} |
| 338 |
return $args; |
| 339 |
} |
| 340 |
|
| 341 |
add_action( 'init', 'bbp_voting_lead_topic' ); |
| 342 |
function bbp_voting_lead_topic() { |
| 343 |
$opt = get_option( 'bbp_core_settings' ); |
| 344 |
|
| 345 |
if ( $opt['is_lead_topic_broken'] ?? false ) { |
| 346 |
add_filter( 'bbp_show_lead_topic', '__return_true' ); |
| 347 |
} |
| 348 |
} |