Search code examples
javascriptphpajaxwordpressrequest

WordPress PHP script not correctly being called by Javascript


I've redacted some info that's not relevant.

I have a WordPress site and I've made a plugin meant for updating a database I've created. To put it simply I have a tool and I want to limit the amount of times a user can use that tool. So to do this I created a database with a user id and usage count column. I have another script which checks this database and if the usage column is a certain amount it won't let the user use the tool and that works fine.

The issue I am facing is when I open the link to the plugin in the browser that's https://REDACTED.com/wp-content/plugins/track_user_usage/track_user_usage.php it gets the user id and updates the database successfully with no problem but when I try and make it request the php script from a simple javascript/html script I created for a test it says success but doesn't update the database.

Here is my PHP plugin with some stuff redacted:

<?php
/*
Plugin Name: Track User Usage
Plugin URL: REDACTED
Description: 
Version: 1.0
Author: REDACTED
*/

define('DB_SERVER2', 'REDACTED');
define('DB_USERNAME2', 'REDACTED');
define('DB_PASSWORD2', 'REDACTED');
define('DB_NAME2', 'REDACTED');

// Establish a persistent database connection
$conn = new mysqli(DB_SERVER2, DB_USERNAME2, DB_PASSWORD2, DB_NAME2);
$conn->autocommit(TRUE);
$conn->real_query("SET NAMES 'utf8'");

// Checking connection
if ($conn->connect_error) {
    die('Database connection failed: ' . $conn->connect_error);
}

function process_request() {

    global $conn;

    if ( ! defined( 'ABSPATH' ) ) {
        define( 'ABSPATH', '/home/REDACTED/REDACTED.com/' );
    }

     if ($_SERVER['REQUEST_METHOD'] !== 'GET') {
     
        return;
    }

    include_once ABSPATH . '/wp-load.php';
    $userid = get_current_user_id();

    if ($userid == 0) {
        return;
    }

    $user_id = $userid; 
    $created_at = date('Y-m-d H:i:s'); 

    // Check if the user already exists in the table
    $sql_check_user = "SELECT * FROM tool_usage WHERE user_id = ?";
    $stmt_check_user = $conn->prepare($sql_check_user);
    $stmt_check_user->bind_param("i", $user_id);
    $stmt_check_user->execute();
    $result = $stmt_check_user->get_result();

    if ($result->num_rows > 0) {
        // User exists, update the usage count
        $sql_update_usage = "UPDATE tool_usage SET usage_count = usage_count + 1 WHERE user_id = ?";
        $stmt_update_usage = $conn->prepare($sql_update_usage);
        $stmt_update_usage->bind_param("i", $user_id);
        if ($stmt_update_usage->execute()) {
            
        } else {
            
        }
    } else {
        // User doesn't exist, insert a new record
        $usage_count = 1; // Initial usage count
        $sql_insert = "INSERT INTO tool_usage (user_id, usage_count, created_at) VALUES (?, ?, ?)";
        $stmt_insert = $conn->prepare($sql_insert);
        $stmt_insert->bind_param("iis", $user_id, $usage_count, $created_at);
        if ($stmt_insert->execute()) {
            
        } else {
            
        }
    }

    $stmt_check_user->close();
}

process_request();

$conn->close();
?>

If you are wondering why there are some else statements with nothing there it's because there was echo statements but those were causing some issues for some reason so I just deleted them because I don't really need them, but they were saying success.

And here is my simple test HTML/Javascript code:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Track User Usage</title>
    <script>
        function trackUserUsage() {
            fetch('https://www.REDACTED.com/wp-content/plugins/track_user_usage/track_user_usage.php')
                .then(data => {
                    if (data.success) {
                        console.log('PHP script called successfully:', data);
                    } else {
                        console.error('PHP script error:', data);
                    }
                })
                .catch(error => {
                    console.error('Error calling PHP script:', error);
                });
        }
    </script>
</head>
<body>
    <button onclick="trackUserUsage()">Track User Usage</button>
</body>
</html>

I've tried a bunch of different ways for the Javascript and PHP for the past few hours with no success.


Solution

  • Thanks for the help everyone I used the rest api endpoint and nonce and some cookie thing and all is working well.

    I used this in the PHP script + some other changes to the main function

    function set_nonce_cookies($request) {
        $cookie_name = 'rest_nonce';
        $cookie_value = wp_create_nonce('wp_rest');
        $cookie_exp = 0;
        $cookie_path = "/";
        $cookie_domain = "";
        $cookie_secure = true;
        $cookie_http_only = false;
        setcookie($cookie_name, $cookie_value, $cookie_exp, $cookie_path, $cookie_domain, $cookie_secure, $cookie_http_only);
    }
    
    add_action('rest_api_init', 'set_nonce_cookies');
    
    function register_track_user_usage_endpoint() {
        register_rest_route('wp/v2', '/track-usage', array(
            'methods' => 'GET',
            'callback' => 'track_user_usage',
        ));
    }
    
    add_action('rest_api_init', 'register_track_user_usage_endpoint');
    
    
    function track_user_usage($request) {
        $nonce = $request->get_header('X-WP-Nonce');
        if (!wp_verify_nonce($nonce, 'wp_rest')) {
            return new WP_Error('rest_forbidden', 'Invalid nonce.', array('status' => 403));
        }
    
        if (!is_user_logged_in()) {
            return new WP_Error('rest_forbidden', 'User is not logged in.', array('status' => 403));
        }
    
        $userid = get_current_user_id();
    
        if ($userid == 0) {
            return new WP_Error('unauthorized', 'User is not logged in', array('status' => 401));
        }
    
        $response_data = array(
            'nonce' => $nonce
        );
        
        // Rest of code
    

    And I used this for the Javascript:

    function trackUserUsage() {
                const url = 'https://www.REDACTED.com/wp-json/wp/v2/track-usage';
                const nonce = Cookies.get('rest_nonce');
    
                fetch(url, {
                    method: 'GET',
                    headers: {
                        'Content-Type': 'application/json',
                        'X-WP-Nonce': nonce
                    },
                    credentials: 'include'
                })
                .then(response => response.json())
                .then(data => {
                    console.log(data);
                })
                .catch(error => console.error('Error:', error));
            }