PluginProbe
Forumax – AI Powered Advanced Community Forum Plugin / 2.4.1
Forumax – AI Powered Advanced Community Forum Plugin v2.4.1
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 / ajax.php

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

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