0

This code is saved in ./child-theme/includes/show_coupon_usage.php and then in functions.php it's required if the user is an admin.

<?php

if (!defined('ABSPATH')) {
    exit;
}

//Our class extends the WP_List_Table class, so we need to make sure that it's there
if (!class_exists('WP_List_Table')) {
    require_once(ABSPATH . 'wp-admin/includes/class-wp-list-table.php');
}

class Coupon_Usage_Table extends WP_List_Table
{

   /**
    * Constructor, we override the parent to pass our own arguments
    * We usually focus on three parameters: singular and plural labels, as well as whether the class supports AJAX.
    */
    function __construct()
    {
        parent::__construct(array(
        'singular'=> 'coupon_usage', //Singular label
        'plural' => 'coupon_usages', //plural label, also this well be one of the table css class
        'ajax'   => false //We won't support Ajax for this table
        ));

        $this->prepare_items();
        $this->display();
    }

    function no_items()
    {
        _e('This coupon hasn\'t been used yet.');
    }

    /**
     * Prepare the table with different parameters, pagination, columns and table elements
     */
    function prepare_items()
    {
        global $thepostid, $post, $wpdb, $_wp_column_headers;

        $columns = $this->get_columns();
        $hidden = $this->get_hidden_columns();
        $sortable = $this->get_sortable_columns();

        $thepostid = empty($thepostid) ? $post->ID : $thepostid;

        // Get username, user ID and how many times did they use this coupon.
        $query = $wpdb->prepare("SELECT u.user_login as username, pm.meta_value as user_id,   COUNT(1) as timesused FROM {$wpdb->prefix}_posts p LEFT JOIN {$wpdb->prefix}_postmeta pm ON p.ID = pm.post_id LEFT JOIN {$wpdb->prefix}_users  u ON u.ID = pm.meta_value WHERE p.post_type = 'shop_coupon' AND p.ID = %d AND pm.meta_key = '_used_by' GROUP BY pm.meta_value;", array($thepostid));

        $this->items = $wpdb->get_results($query);
        $this->_column_headers = array($columns, $hidden, $sortable);

    }

    /**
     * Define the columns that are going to be used in the table
     * @return array $columns, the array of columns to use with the table
     */
    function get_columns()
    {
        return $columns = array(
          'username'=>__('Name'),
          'timesused'=>__('Times Used')
        );
    }

    /**
     * Define which columns are hidden
     *
     * @return Array
     */
    public function get_hidden_columns()
    {
        return array();
    }

    /**
     * Define the sortable columns
     *
     * @return Array
     */
    public function get_sortable_columns()
    {
        return array();
    }

    function column_default($item, $column_name)
    {
        switch ($column_name) {
            case 'username':
                $actions = array(
                    'edit'      => sprintf('<a href="/wp-admin/user-edit.php?user_id=%s">Edit</a>', $item->user_id),
                    'orders'    => sprintf('<a href="/wp-admin/edit.php?post_status=all&post_type=shop_order&_customer_user=%s">Orders</a>', $item->user_id),
                );
                return sprintf('%1$s %2$s', $item->username, $this->row_actions($actions));
            case 'timesused':
                return sprintf('%1$s', $item->timesused);
            default:
                return print_r($item, true).' - '.print_r($column_name, true) ;
        }
    }
}

add_filter('woocommerce_coupon_data_tabs', 'admin_coupon_options_tabs', 20, 1);
add_action('woocommerce_coupon_data_panels', 'admin_coupon_options_panels', 10, 0);


//Add tabs to the coupon option page
function admin_coupon_options_tabs($tabs)
{

        $tabs['show_who_used'] = array(
                'label'  => __('Who used it?', 'woocommerce-coupon-usage'),
                'target' => 'woocommerce_coupon_usage',
                'class'  => 'woocommerce_coupon_usage',
        );

        return $tabs;
}


//Add panels to the coupon option page
function admin_coupon_options_panels()
{
    echo '<div id="woocommerce_coupon_usage" class="panel woocommerce_options_panel">';
    $wp_list_table = new Coupon_Usage_Table();
    echo '</div>';
}

The code works fine, I can see the data I want in coupons that have already been created programatically. The problem is when I go to create one via the "Add Coupon" button or if I try to edit an existing one.

I get the The link you followed has expired. error.

Google only shows stuff about upload_max_size, post_max_size and max_execution_time but it doesn't seems to have anything to do with my case.

I also don't use a nonce in my code since it's purely presenting information, it takes no input.

Anyone knows what might be going on? WP_DEBUG doesn't show anything useful.

Edit: Checking the POST data sent with and without the code active on the same coupon I see this:

This is with my code active

_wp_original_http_referer: 
_wpnonce: 4d92197b82
_wpnonce: e5b47d577d

referredby: 

This is with my code inactive

_wp_original_http_referer: https://example.net/wp-admin/edit.php?post_type=shop_coupon

_wpnonce: e5b47d577d

referredby: https://example.net/wp-admin/edit.php?post_type=shop_coupon
0

The problem was the nonce, answered by @Daniel Antunes here.

Let me help you! Overwrite the parent method display_tablenav of WP_List_Table class removing the wp_nonce_field execution.

/**
 * Generates the table navigation above or bellow the table and removes the
 * _wp_http_referrer and _wpnonce because it generates a error about URL too large
 * 
 * @param string $which 
 * @return void
 */
function display_tablenav( $which ) 
{
    ?>
    <div class="tablenav <?php echo esc_attr( $which ); ?>">

        <div class="alignleft actions">
            <?php $this->bulk_actions(); ?>
        </div>
        <?php
        $this->extra_tablenav( $which );
        $this->pagination( $which );
        ?>
        <br class="clear" />
    </div>
    <?php
}

I'm not sure how to do this "Repeated question" thing to link to his answer, feel free to do that if you know how.

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.