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
← All changes | includes/features/bbp_voting/ajax.php +152 -122 1.2.6 → 2.5.1 View file →
@@ -1,122 +1,152 @@
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 - header( 'Content-type: application/json' );
12 - $post_id = (int) $_POST['post_id'];
13 -
14 - // View only for visitors.
15 - if ( ! is_user_logged_in() && apply_filters( 'bbp_voting_disable_voting_for_visitors', false ) ) {
16 - die( json_encode( [ 'error' => 'Voting is disabled for visitors.' ] ) );
17 - }
18 -
19 - // View only for closed topics
20 - $topic_id = bbp_get_reply_topic_id( $post_id );
21 - $topic_status = get_post_status( $topic_id );
22 - if ( $topic_status == 'closed' && apply_filters( 'bbp_voting_disable_voting_on_closed_topic', false ) ) {
23 - die( json_encode( [ 'error' => 'Voting is disabled on closed topics.' ] ) );
24 - }
25 - // View only for author of post
26 - if ( is_user_logged_in() && apply_filters( 'bbp_voting_disable_author_vote', false ) && get_post_field( 'post_author', $post_id ) == get_current_user_ID() ) {
27 - die( json_encode( [ 'error' => 'Voting is disabled on for the author.' ] ) );
28 - }
29 - // Direction
30 - $direction = (int) $_POST['direction'];
31 - $direction = in_array( $direction, [ 1, -1 ] ) ? $direction : 0; // Enforce 1 or -1
32 - // $voting_cookie = unserialize($_COOKIE['bbp_voting']);
33 - $voting_log = get_post_meta( $post_id, 'bbp_voting_log', true );
34 - $voting_log = is_array( $voting_log ) ? $voting_log : []; // Set up new array
35 - $client_ip = $_SERVER['REMOTE_ADDR'];
36 - $identifier = is_user_logged_in() ? get_current_user_id() : $client_ip;
37 - $admin_bypass = current_user_can( 'administrator' ) && apply_filters( 'bbp_voting_admin_bypass', false );
38 - $remove_vote = false;
39 - $reverse_vote = false;
40 - // Admin bypass skips the restriction checks
41 - if ( ! $admin_bypass ) {
42 - // Catch user voted already (by cookie)
43 - // if(isset($voting_cookie[$post_id])) {
44 - // echo 'Not allowed to vote twice';
45 - // exit;
46 - // } else {
47 - // Catch user voted already (by user ID or IP)
48 - if ( array_key_exists( $identifier, $voting_log ) ) {
49 - // Identifier found
50 - if ( $voting_log[ $identifier ] == $direction ) {
51 - // Voting again in the same direction
52 - $remove_vote = true;
53 - } elseif ( $voting_log[ $identifier ] == $direction * -1 ) {
54 - // Changing the vote in different direction
55 - $reverse_vote = true;
56 - } else {
57 - // Changing vote from 0
58 - }
59 - }
60 - // }
61 - }
62 - // All good, add the user's vote
63 - // But first get all the data
64 - $score = (int) get_post_meta( $post_id, 'bbp_voting_score', true );
65 - $ups = $ups_og = (int) get_post_meta( $post_id, 'bbp_voting_ups', true );
66 - $downs = $downs_og = (int) get_post_meta( $post_id, 'bbp_voting_downs', true );
67 - if ( $direction > 0 ) {
68 - // Up vote
69 - if ( $remove_vote ) {
70 - $ups = $ups - 1;
71 - $score = $score - 1;
72 - } else {
73 - $ups = $ups + 1;
74 - $score = $score + 1;
75 - }
76 - if ( $reverse_vote ) {
77 - $downs = $downs + 1;
78 - $score = $score + 1;
79 - }
80 - } elseif ( $direction < 0 ) {
81 - // Down vote
82 - if ( $remove_vote ) {
83 - $downs = $downs + 1;
84 - $score = $score + 1;
85 - } else {
86 - $downs = $downs - 1;
87 - $score = $score - 1;
88 - }
89 - if ( $reverse_vote ) {
90 - $ups = $ups - 1;
91 - $score = $score - 1;
92 - }
93 - }
94 - // Update the score
95 - update_post_meta( $post_id, 'bbp_voting_score', $score );
96 - // Update the ups and downs if needed
97 - if ( $ups !== $ups_og ) {
98 - update_post_meta( $post_id, 'bbp_voting_ups', $ups );
99 - }
100 - if ( $downs !== $downs_og ) {
101 - update_post_meta( $post_id, 'bbp_voting_downs', $downs );
102 - }
103 - // Hook for additional features like weighted score calculation
104 - do_action( 'bbp_voting_process_score_on_vote', $post_id, $ups, $downs );
105 - // Log the user's ID or IP
106 - $real_direction = $remove_vote ? 0 : $direction;
107 - $voting_log[ $identifier ] = $real_direction;
108 - update_post_meta( $post_id, 'bbp_voting_log', $voting_log );
109 - // Set the cookie
110 - // $voting_cookie[$post_id] = true;
111 - // setcookie('bbp_voting', serialize($voting_cookie), time() + (86400 * 30 * 365), '/');
112 - do_action( 'bbp_voting_voted', $post_id, $real_direction, $score, $identifier );
113 - echo json_encode(
114 - [
115 - 'score' => $score,
116 - 'direction' => $real_direction,
117 - 'ups' => $ups,
118 - 'downs' => $downs,
119 - ]
120 - );
121 - exit;
122 -}
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 +}