WordPress Popular Posts plugin – Add IP Address to the log – Part 2

Part 1: https://life-adventurer.com/2024/05/30/wordpress-popular-posts-plugin-add-ip-address-to-the-log-part-1/

In part 1, I added the IP addresses to WordPress Popular Posts by modifying the plugin directly. It’s not a good practice because the code may be lost whenever we update the plugin. Therefore, in part 2, I will try to achieve the goal by creating a custom plugin.

What we will do

  • Create a custom plugin.
  • When activating the plugin, add new fields to wp_popularpostssummary table.
  • When uninstalling the plugin, remove the new fields.
  • When updating the view count, also updating new fields.
  • I want to save new information: hostname, city, country to wp_popularpostssummary along with ip_address.

Coding

Create a custom plugin

  • create a folder named “wordpress-popular-posts-custom” inside the “wp-content/plugins” folder.
  • create a file named wpp-custom.php
  • add the following to the start of the file
<?php
/*
Plugin Name: WordPress Popular Posts Custom Plugin
Description: Adds a custom field to the wp_popularpostssummary table and handles custom actions.
Version: 1.0
Author: Nguyen Bao Ngoc
*/

// Security check to prevent direct access
if (!defined('ABSPATH')) {
    exit;
}

Activate the plugin

Here we will register an activation hook – the function which will be called when the plugin is activated.

// Activation hook: add the new fields
function wppc_add_custom_fields() {
    global $wpdb;
    $table_name = $wpdb->prefix . 'popularpostssummary';

    $columns = $wpdb->get_results("SHOW COLUMNS FROM " . $table_name, ARRAY_A);
    $existing_columns = array_column($columns, 'Field');

    $columns_to_add = [];

    if (!in_array('ip_address', $existing_columns)) {
        $columns_to_add[] = 'ADD COLUMN ip_address VARCHAR(255) DEFAULT NULL';
    }
    if (!in_array('hostname', $existing_columns)) {
        $columns_to_add[] = 'ADD COLUMN hostname VARCHAR(255) DEFAULT NULL';
    }
    if (!in_array('city', $existing_columns)) {
        $columns_to_add[] = 'ADD COLUMN city VARCHAR(255) DEFAULT NULL';
    }
    if (!in_array('country', $existing_columns)) {
        $columns_to_add[] = 'ADD COLUMN country VARCHAR(255) DEFAULT NULL';
    }
    if (!in_array('org', $existing_columns)) {
        $columns_to_add[] = 'ADD COLUMN org VARCHAR(255) DEFAULT NULL';
    }

    if (!empty($columns_to_add)) {
        $sql = "ALTER TABLE $table_name " . implode(', ', $columns_to_add);
        $wpdb->query($sql);

        if ($wpdb->last_error) {
            error_log('Error adding columns: ' . $wpdb->last_error);
        }
    }
}
register_activation_hook(__FILE__, 'wppc_add_custom_fields');

In that function, we will check the columns of the table and only add if they are not existed.

Uninstall the plugin

For triggering code when uninstalling the plugin, we need another file named uninstall.php. Just create on inside the plugin folder and we will be good.

<?php
// Security check to prevent direct access
if (!defined('WP_UNINSTALL_PLUGIN')) {
    exit;
}

// Load WordPress environment
require_once(ABSPATH . 'wp-admin/includes/upgrade.php');

// Define the table name with the WPDB prefix
global $wpdb;
$table_name = $wpdb->prefix . 'popularpostssummary';

// Check if the table exists and columns to drop exist
$columns = $wpdb->get_results("SHOW COLUMNS FROM $table_name", ARRAY_A);
$existing_columns = array_column($columns, 'Field');

$columns_to_drop = [];

if (in_array('ip_address', $existing_columns)) {
    $columns_to_drop[] = 'DROP COLUMN ip_address';
}
if (in_array('hostname', $existing_columns)) {
    $columns_to_drop[] = 'DROP COLUMN hostname';
}
if (in_array('city', $existing_columns)) {
    $columns_to_drop[] = 'DROP COLUMN city';
}
if (in_array('country', $existing_columns)) {
    $columns_to_drop[] = 'DROP COLUMN country';
}
if (in_array('org', $existing_columns)) {
    $columns_to_drop[] = 'DROP COLUMN org';
}

if (!empty($columns_to_drop)) {
    $sql = "ALTER TABLE $table_name " . implode(', ', $columns_to_drop);
    $wpdb->query($sql);

    if ($wpdb->last_error) {
        error_log('Error dropping columns: ' . $wpdb->last_error);
    }
}

Here we just drop the new columns if they’re existed in the database table.

Update information

There’s one thing I noticed from the last time I modified the code inside WPP plugin

In this plugin, they already added code to call an action for other people who wants to extend the plugin. Really nice.

So, it’s pretty simple now.

// Function to get user IP address
function get_user_ip_from_request() {
    $ipaddress = '';
    if (getenv('HTTP_CLIENT_IP'))
        $ipaddress = getenv('HTTP_CLIENT_IP');
    else if (getenv('HTTP_X_FORWARDED_FOR'))
        $ipaddress = getenv('HTTP_X_FORWARDED_FOR');
    else if (getenv('HTTP_X_FORWARDED'))
        $ipaddress = getenv('HTTP_X_FORWARDED');
    else if (getenv('HTTP_FORWARDED_FOR'))
        $ipaddress = getenv('HTTP_FORWARDED_FOR');
    else if (getenv('HTTP_FORWARDED'))
        $ipaddress = getenv('HTTP_FORWARDED');
    else if (getenv('REMOTE_ADDR'))
        $ipaddress = getenv('REMOTE_ADDR');
    else
        $ipaddress = 'UNKNOWN';
    return $ipaddress;
}

// Function to fetch IP information from ipinfo.io
function get_ip_info($ip_address) {
    $ip_info = @file_get_contents("https://ipinfo.io/" . $ip_address);
    if ($ip_info) {
        return json_decode($ip_info);
    }
    return null;
}

// Implement action wpp_post_update_views
function wppc_wpp_post_update_views($post_id) {
    global $wpdb;
    global $table_name;
    
    $ip_address = get_user_ip_from_request();
    $ip_info = get_ip_info($ip_address);
    
    if ($ip_info) {
        $hostname = isset($ip_info->hostname) ? $ip_info->hostname : 'UNKNOWN';
        $city = isset($ip_info->city) ? $ip_info->city : 'UNKNOWN';
        $country = isset($ip_info->country) ? $ip_info->country : 'UNKNOWN';
        $org = isset($ip_info->org) ? $ip_info->org : 'UNKNOWN';
    } else {
        $hostname = 'UNKNOWN';
        $city = 'UNKNOWN';
        $country = 'UNKNOWN';
        $org = 'UNKNOWN';
    }

    // Update the database with IP address information
    $wpdb->update(
        $table_name,
        array(
            'ip_address' => $ip_address,
            'hostname' => $hostname,
            'city' => $city,
            'country' => $country,
            'org' => $org
        ),
        array('postid' => $post_id),
        array('%s', '%s', '%s', '%s', '%s'),
        array('%d')
    );
    
    if($wpdb->last_error) {
        error_log('Error updating IP information: ' . $wpdb->last_error);
    }
}
add_action('wpp_post_update_views', 'wppc_wpp_post_update_views');

Summary

It works without modifying the original plugin :).

Leave a Reply 0

Your email address will not be published. Required fields are marked *