PluginProbe
Forumax – AI Powered Advanced Community Forum Plugin / 2.5.1
Forumax – AI Powered Advanced Community Forum Plugin v2.5.1
2.5.1 2.5.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 All 31 releases
bbp-core / includes / features / bbp_voting / ajax.php

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

153 lines 5.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 // Process a vote.
7 add_action( 'wp_ajax_bbpress_post_vote_link_clicked', 'bbpress_post_add_vote' );
8 add_action( 'wp_ajax_nopriv_bbpress_post_vote_link_clicked', 'bbpress_post_add_vote' );
9
10 function bbpress_post_add_vote() {
11 // Verify nonce for security
12 check_ajax_referer( 'forumax-nonce', 'nonce' );
13
14 header( 'Content-type: application/json' );
15 $post_id = isset( $_POST['post_id'] ) ? (int) $_POST['post_id'] : 0;
16
17 // Only published/closed topics and replies can be voted on.
18 $post_type = get_post_type( $post_id );
19 if ( ! $post_id || ! in_array( $post_type, [ bbp_get_topic_post_type(), bbp_get_reply_post_type() ], true ) || ! in_array( get_post_status( $post_id ), [ 'publish', 'closed' ], true ) ) {
20 die( json_encode( [ 'error' => 'Invalid post.' ] ) );
21 }
22
23 // View only for visitors.
24 if ( ! is_user_logged_in() && forumax_get_opt( 'is_disabled_voting_for_non_logged_users', false ) ) {
25 die( json_encode( [ 'error' => 'Voting is disabled for visitors.' ] ) );
26 }
27
28 // View only for closed topics
29 $topic_id = bbp_get_reply_topic_id( $post_id );
30 $topic_status = get_post_status( $topic_id );
31 if ( $topic_status == 'closed' && forumax_get_opt( 'is_disabled_voting_closed_topics', false ) ) {
32 die( json_encode( [ 'error' => 'Voting is disabled on closed topics.' ] ) );
33 }
34 // View only for author of post
35 if ( is_user_logged_in() && forumax_get_opt( 'is_disabled_voting_own_topic_reply', false ) && get_post_field( 'post_author', $post_id ) == get_current_user_ID() ) {
36 die( json_encode( [ 'error' => 'Voting is disabled on for the author.' ] ) );
37 }
38 // Direction
39 $direction = isset( $_POST['direction'] ) ? (int) $_POST['direction'] : 0;
40 $direction = in_array( $direction, [ 1, -1 ] ) ? $direction : 0; // Enforce 1 or -1
41
42 // Check if down votes are disabled
43 if ( $direction === -1 && forumax_get_opt( 'is_down_votes_disabled', 0 ) != 1 ) {
44 die( json_encode( [ 'error' => 'Down voting is disabled.' ] ) );
45 }
46
47 // $voting_cookie = unserialize($_COOKIE['bbp_voting']);
48 $voting_log = get_post_meta( $post_id, 'bbp_voting_log', true );
49 $voting_log = is_array( $voting_log ) ? $voting_log : []; // Set up new array
50
51 // Use hashed IP for anonymous users (GDPR compliant - real IP is never stored)
52 $identifier = is_user_logged_in() ? get_current_user_id() : forumax_get_hashed_ip();
53 $legacy_identifier = null;
54
55 // Backward compatibility: Check for legacy raw IP entries (pre-2.3.1)
56 // This allows migration from raw IP to hashed IP without losing vote history
57 if ( ! is_user_logged_in() ) {
58 $raw_ip = forumax_get_raw_ip();
59 if ( $raw_ip && array_key_exists( $raw_ip, $voting_log ) ) {
60 $legacy_identifier = $raw_ip;
61 }
62 }
63
64 $admin_bypass = current_user_can( 'administrator' ) && forumax_get_opt( 'is_admin_can_vote_unlimited', false );
65 $remove_vote = false;
66 $reverse_vote = false;
67 // Admin bypass skips the restriction checks
68 if ( ! $admin_bypass ) {
69 // Check for existing vote - first by new hashed identifier, then by legacy raw IP
70 $check_identifier = array_key_exists( $identifier, $voting_log ) ? $identifier : $legacy_identifier;
71
72 if ( $check_identifier && array_key_exists( $check_identifier, $voting_log ) ) {
73 // Identifier found (either hashed or legacy)
74 if ( $voting_log[ $check_identifier ] == $direction ) {
75 // Voting again in the same direction
76 $remove_vote = true;
77 } elseif ( $voting_log[ $check_identifier ] == $direction * -1 ) {
78 // Changing the vote in different direction
79 $reverse_vote = true;
80 } else {
81 // Changing vote from 0
82 }
83
84 // Migrate legacy raw IP to hashed IP (one-time migration per vote)
85 if ( $legacy_identifier && $check_identifier === $legacy_identifier ) {
86 $voting_log[ $identifier ] = $voting_log[ $legacy_identifier ];
87 unset( $voting_log[ $legacy_identifier ] );
88 update_post_meta( $post_id, 'bbp_voting_log', $voting_log );
89 }
90 }
91 }
92 // All good, add the user's vote
93 // But first get all the data
94 $score = (int) get_post_meta( $post_id, 'bbp_voting_score', true );
95 $ups = $ups_og = (int) get_post_meta( $post_id, 'bbp_voting_ups', true );
96 $downs = $downs_og = (int) get_post_meta( $post_id, 'bbp_voting_downs', true );
97 if ( $direction > 0 ) {
98 // Up vote
99 if ( $remove_vote ) {
100 $ups = $ups - 1;
101 $score = $score - 1;
102 } else {
103 $ups = $ups + 1;
104 $score = $score + 1;
105 }
106 if ( $reverse_vote ) {
107 $downs = $downs + 1;
108 $score = $score + 1;
109 }
110 } elseif ( $direction < 0 ) {
111 // Down vote
112 if ( $remove_vote ) {
113 $downs = $downs + 1;
114 $score = $score + 1;
115 } else {
116 $downs = $downs - 1;
117 $score = $score - 1;
118 }
119 if ( $reverse_vote ) {
120 $ups = $ups - 1;
121 $score = $score - 1;
122 }
123 }
124 // Update the score
125 update_post_meta( $post_id, 'bbp_voting_score', $score );
126 // Update the ups and downs if needed
127 if ( $ups !== $ups_og ) {
128 update_post_meta( $post_id, 'bbp_voting_ups', $ups );
129 }
130 if ( $downs !== $downs_og ) {
131 update_post_meta( $post_id, 'bbp_voting_downs', $downs );
132 }
133 // Hook for additional features like weighted score calculation
134 do_action( 'bbp_voting_process_score_on_vote', $post_id, $ups, $downs );
135 // Log the user's ID or IP
136 $real_direction = $remove_vote ? 0 : $direction;
137 $voting_log[ $identifier ] = $real_direction;
138 update_post_meta( $post_id, 'bbp_voting_log', $voting_log );
139 // Set the cookie
140 // $voting_cookie[$post_id] = true;
141 // setcookie('bbp_voting', serialize($voting_cookie), time() + (86400 * 30 * 365), '/');
142 do_action( 'bbp_voting_voted', $post_id, $real_direction, $score, $identifier );
143 echo json_encode(
144 [
145 'score' => $score,
146 'direction' => $real_direction,
147 'ups' => $ups,
148 'downs' => $downs,
149 ]
150 );
151 exit;
152 }
153