Plugin Directory

Changeset 2458244


Ignore:
Timestamp:
01/18/2021 12:04:59 PM (5 years ago)
Author:
eighty20results
Message:

Update to version 6.0 from GitHub

Location:
e20r-members-list
Files:
44 added
28 deleted
20 edited
1 copied

Legend:

Unmodified
Added
Removed
  • e20r-members-list/tags/6.0/README.txt

    r2306383 r2458244  
    1212
    1313Extensible, sortable & bulk action capable members listing tool for Paid Memberships Pro. This plugin is a complete replacement for the "Members List" functionality in PMPro and supports most of the same filters and hooks. The key differences have to do with managing columns. Now you can also use the [standard WordPress filters](https://developer.wordpress.org/reference/classes/wp_list_table/) to columns you can add/remove/make sortable, additional bulk actions, etc.
     14
     15![Release to wordpress.org](https://github.com/eighty20results/e20r-members-list/workflows/Release%20to%20wordpress.org/badge.svg?branch=master)
    1416
    1517== Installation ==
     
    189191== Changelog ==
    190192
     193== 6.0 ==
     194* BUG FIX: Didn't paginate correctly because the LIMIT logic caused us to not return the full number of records for the level/status
     195* BUG FIX: Potentially a fatal PHP error
     196* BUG FIX: Bad path to downloadable archive
     197* BUG FIX: Didn't (always) import the database needed for testing
     198* BUG FIX: Readme directions for installation were imprecise
     199* BUG FIX: Removed copy/paste Utilities module and using git subtree instead
     200* BUG FIX: Updated copyright notice
     201
     202
    191203== 5.10 ==
    192204* BUG FIX: Fatal error in Utilities library
  • e20r-members-list/tags/6.0/class.e20r-members-list.php

    r2306383 r2458244  
    44Plugin URI: https://wordpress.org/plugins/e20r-members-list
    55Description: Extensible, sortable & bulk action capable members listing + export to CSV tool for Paid Memberships Pro.
    6 Version: 5.10
     6Version: 6.0
    77Author: Thomas Sjolshagen @ Eighty / 20 Results by Wicked Strong Chicks, LLC <[email protected]>
    88Author URI: https://eighty20results.com/thomas-sjolshagen/
     
    1111License:
    1212
    13     Copyright 2016 - 2020 (c) Eighty / 20 Results by Wicked Strong Chicks, LLC ([email protected])
     13    Copyright 2016 - 2021 (c) Eighty / 20 Results by Wicked Strong Chicks, LLC ([email protected])
    1414
    1515    This program is free software; you can redistribute it and/or modify
     
    3333
    3434if ( ! defined( 'E20R_MEMBERSLIST_VER' ) ) {
    35     define( 'E20R_MEMBERSLIST_VER', '5.10' );
     35    define( 'E20R_MEMBERSLIST_VER', '6.0' );
    3636}
    3737
  • e20r-members-list/tags/6.0/class/members-list/class.bulk-cancel.php

    r2025537 r2458244  
    11<?php
    22/**
    3  * Copyright (c) 2018-2019 - Eighty / 20 Results by Wicked Strong Chicks.
     3 * Copyright (c) 2018-2021 - Eighty / 20 Results by Wicked Strong Chicks.
    44 * ALL RIGHTS RESERVED
    55 *
     
    2323
    2424class Bulk_Cancel {
    25    
     25
    2626    /**
    2727     * Instance of this class
     
    3636     */
    3737    private $operation = null;
    38    
     38
    3939    /**
    4040     * List of member IDs to update
     
    4343     */
    4444    private $members_to_update = array();
    45    
     45
    4646    /**
    4747     * Bulk_Cancel constructor (singleton)
     
    5151    private function __construct() {
    5252    }
    53    
     53
    5454    /**
    5555     * The __clone() method for Bulk_Cancel() (singleton class)
     
    5858     */
    5959    private function __clone() {}
    60    
     60
    6161    /**
    6262     * Process cancellations for all members/membership_ids
    6363     */
    6464    public function cancel() {
    65        
     65
    6666        // Process all User & level ID for the single action.
    6767        $failed = array();
    68        
     68
    6969        $utils = Utilities::get_instance();
    7070        $utils->log("Cancelling " . count( $this->members_to_update ) . " members");
    71        
     71
    7272        // Process all selected records/members
    7373        foreach ( $this->members_to_update as $key => $cancel_info ) {
    74            
     74
    7575            if ( false == $this->cancel_member( $cancel_info['user_id'], $cancel_info['level_id']  ) ) {
    7676                $failed[] = $cancel_info['user_id']; // FIXME: Add level info for multiple membership levels
    7777            }
    7878        }
    79        
     79
    8080        //Check for errors & display error banner if we got one.
    8181        if ( ! empty( $failed ) ) {
    82            
     82
    8383            $message = sprintf(
    8484                __( "Unable to cancel membership(s) for the following user IDs: %s", "e20r-members-list" ),
    8585                implode( ', ', $failed )
    8686            );
    87            
     87
    8888            if ( function_exists( 'pmpro_setMessage' ) ) {
    8989                pmpro_setMessage( $message, "error" );
     
    9191                global $msg;
    9292                global $msgt;
    93                
     93
    9494                $msg  = $message;
    9595                $msgt = 'error';
    9696            }
    97            
     97
    9898        }
    9999    }
    100    
     100
    101101    /**
    102102     * The cancel member action
     
    108108     */
    109109    public static function cancel_member( $id, $level_id = null ) {
    110        
     110
    111111        if ( function_exists( 'pmpro_cancelMembershipLevel' ) ) {
    112112            return pmpro_cancelMembershipLevel( $level_id, $id, 'admin_cancelled' );
     
    114114            return false;
    115115        }
    116        
     116
    117117    }
    118    
     118
    119119    /**
    120120     * Get or create an instance of the Bulk_Cancel class
     
    123123     */
    124124    public static function get_instance() {
    125        
     125
    126126        if ( is_null( self::$instance ) ) {
    127127            self::$instance = new self;
    128128        }
    129        
     129
    130130        return self::$instance;
    131131    }
    132    
     132
    133133    /**
    134134     * Set the list of members & their levels to update
     
    139139        $this->members_to_update = $member_info;
    140140    }
    141    
     141
    142142    /**
    143143     * Return the list of members being updated
  • e20r-members-list/tags/6.0/class/members-list/class.bulk-update.php

    r2025537 r2458244  
    11<?php
    22/**
    3  * Copyright (c) 2018-2019 - Eighty / 20 Results by Wicked Strong Chicks.
     3 * Copyright (c) 2018-2021 - Eighty / 20 Results by Wicked Strong Chicks.
    44 * ALL RIGHTS RESERVED
    55 *
     
    2424
    2525class Bulk_Update {
    26    
     26
    2727    /**
    2828     * Instance of this class
     
    3131     */
    3232    private static $instance = null;
    33    
     33
    3434    /**
    3535     * Update operation to perform
     
    3838     */
    3939    private $operation = null;
    40    
     40
    4141    /**
    4242     * List of members to update
     
    4545     */
    4646    private $members_to_update = array();
    47    
     47
    4848    /**
    4949     * Bulk_Update constructor (singleton)
     
    5353    private function __construct() {
    5454    }
    55    
     55
    5656    /**
    5757     * __clone() method for Bulk_Update() (singleton class)
     
    6060     */
    6161    private function __clone(){}
    62    
     62
    6363    /**
    6464     * Get or create an instance of the Bulk_Update class
     
    6767     */
    6868    public static function get_instance() {
    69        
     69
    7070        if ( is_null( self::$instance ) ) {
    7171            self::$instance = new self;
    7272        }
    73        
     73
    7474        return self::$instance;
    7575    }
    76    
     76
    7777    /**
    7878     * Handle bulk update (for core member list columns). Triggers action for external bulk update activities/fields
     
    8181     */
    8282    public function update() {
    83        
     83
    8484        $utils         = Utilities::get_instance();
    8585        $update_errors = array();
    8686        $level_failed  = array();
    87        
     87
    8888        $utils->log("User count to update: " . count( $this->members_to_update) );
    8989        $utils->log("Request: " . print_r( $_REQUEST, true ));
    90        
     90
    9191        /**
    9292         * Process build-in edit fields for the specified members to update
    9393         */
    9494        foreach ( $this->members_to_update as $key => $user_info ) {
    95            
     95
    9696            $level_changed  = false;
    9797            $old_user_level = $utils->get_variable( "e20r-members-list-db_membership_id_{$user_info['user_id']}", 0 );
    9898            $new_user_level = $utils->get_variable( "e20r-members-list-new_membership_id_{$user_info['user_id']}", 0 );
    9999            $record_id      = $utils->get_variable( "e20r-members-list-db_record_id_{$user_info['user_id']}", 0 );
    100            
     100
    101101            if ( empty( $user_info['user_id'] ) ) {
    102102                $utils->log("User ID is NULL. Returning!" );
    103103                return false;
    104104            }
    105            
     105
    106106            $utils->log("Have to update level for {$user_info['user_id']}? {$new_user_level}" );
    107            
     107
    108108            // Update the membership level for the user we're processing
    109109            if ( !empty( $new_user_level) && $old_user_level !== $new_user_level ) {
    110                
     110
    111111                if ( false === $this->update_membership( $user_info['user_id'], $old_user_level, $new_user_level ) ) {
    112                    
     112
    113113                    // Add to list of failed updates
    114114                    $level_failed[] = array(
     
    122122                }
    123123            }
    124            
     124
    125125            $old_startdate = $utils->get_variable( "e20r-members-list-db_startdate_{$user_info['user_id']}", '' );
    126126            $new_startdate = $utils->get_variable( "e20r-members-list-new_startdate_{$user_info['user_id']}", '' );
    127            
     127
    128128            $utils->log("Have to update start date for {$user_info['user_id']}? N:{$new_startdate} vs O:{$old_startdate}" );
    129            
     129
    130130            if ( $old_startdate !== $new_startdate ) {
    131                
     131
    132132                if ( empty( $new_startdate ) ) {
    133133                    $utils->log("Error: Start date cannot be empty!, using old start date");
    134134                    $new_startdate = $old_startdate;
    135135                }
    136                
     136
    137137                if ( false === $this->update_date( 'startdate', $user_info['user_id'], $old_user_level, $new_user_level, $new_startdate, $record_id, $level_changed ) ) {
    138138                    $startdate_failed[] = array(
     
    144144                }
    145145            }
    146            
     146
    147147            $old_enddate = $utils->get_variable( "e20r-members-list-db_enddate_{$user_info['user_id']}", '' );
    148148            $new_enddate = $utils->get_variable( "e20r-members-list-new_enddate_{$user_info['user_id']}", '' );
    149            
     149
    150150            $utils->log("Have to update end date for {$user_info['user_id']}? N:{$new_enddate} vs O:{$old_enddate}");
    151            
     151
    152152            if ( $old_enddate !== $new_enddate ) {
    153                
     153
    154154                $utils->log("Updating end date to {$new_enddate}");
    155                
     155
    156156                if ( false === $this->update_date( 'enddate', $user_info['user_id'], $old_user_level, $new_user_level, $new_enddate, $record_id, $level_changed ) ) {
    157157                    $enddate_failed[] = array(
     
    163163                }
    164164            }
    165            
     165
    166166            $old_status = $utils->get_variable( "e20r-members-list-db_status_{$user_info['user_id']}", '' );
    167167            $new_status = $utils->get_variable( "e20r-members-list-new_status_{$user_info['user_id']}", '' );
    168            
     168
    169169            $utils->log("Have to update status for {$user_info['user_id']}? {$new_status}" );
    170            
     170
    171171            if ( $old_status !== $new_status ) {
    172                
     172
    173173                if ( false === $this->update_status( $record_id, $new_status ) ) {
    174174                    $status_failed[] = array(
     
    181181            }
    182182        }
    183        
     183
    184184        /**
    185185         * Trigger action for bulk update (allows external handling of bulk update if needed/desired)
     
    190190         */
    191191        do_action( 'e20r_memberslist_process_bulk_updates', $this->members_to_update );
    192        
     192
    193193        /**
    194194         * Error handling for build-in edit fields
    195195         */
    196196        $msg_template = __( 'Error updating data for %1$s (ID: %2$d). Could not update %3$s from %4$s to %5$s (current membership level: \'%6$s\')', 'e20r-members-list' );
    197        
     197
    198198        if ( ! empty( $level_failed ) ) {
    199            
     199
    200200            foreach ( $level_failed as $info ) {
    201201                $user           = get_user_by( 'ID', $info['user_id'] );
    202202                $new_user_level = pmpro_getLevel( $info['new_level'] );
    203203                $old_user_level = pmpro_getLevel( $info['old_level'] );
    204                
     204
    205205                $update_errors[] = sprintf(
    206206                    $msg_template,
     
    213213                );
    214214            }
    215            
    216         }
    217        
     215
     216        }
     217
    218218        if ( ! empty( $enddate_failed ) ) {
    219219            foreach ( $enddate_failed as $info ) {
    220220                $user       = get_user_by( 'ID', $info['user_id'] );
    221221                $user_level = pmpro_getLevel( $info['level_id'] );
    222                
     222
    223223                $update_errors[] = sprintf(
    224224                    $msg_template,
     
    232232            }
    233233        }
    234        
     234
    235235        if ( ! empty( $startdate_failed ) ) {
    236236            foreach ( $startdate_failed as $info ) {
    237237                $user       = get_user_by( 'ID', $info['user_id'] );
    238238                $user_level = pmpro_getLevel( $info['level_id'] );
    239                
     239
    240240                $update_errors[] = sprintf(
    241241                    $msg_template,
     
    249249            }
    250250        }
    251        
     251
    252252        if ( ! empty( $status_failed ) ) {
    253            
     253
    254254            foreach ( $status_failed as $info ) {
    255255                $user       = get_user_by( 'ID', $info['user_id'] );
    256256                $user_level = pmpro_getLevel( $info['level_id'] );
    257                
     257
    258258                $update_errors[] = sprintf(
    259259                    $msg_template,
     
    267267            }
    268268        }
    269        
     269
    270270        /**
    271271         * Add error messages to back-end info display
    272272         */
    273273        if ( ! empty( $update_errors ) ) {
    274            
     274
    275275            $utils->log("Generated " . count( $update_errors ) . " errors during bulk update!");
    276            
     276
    277277            foreach ( $update_errors as $e_msg ) {
    278278                $utils->log("Error: {$e_msg}");
    279279                $utils->add_message( $e_msg, 'error', 'backend' );
    280280            }
    281            
     281
    282282            // And return false (error)
    283283            return false;
    284284        }
    285        
     285
    286286        // All's good!
    287287        return true;
    288288    }
    289    
     289
    290290    /**
    291291     * Change the membership level for the specified User ID
     
    298298     */
    299299    public function update_membership( $user_id, $current_level_id, $new_level_id ) {
    300        
     300
    301301        // Execute the membership level change for the specified user ID/Level ID
    302302        if ( function_exists( 'pmpro_changeMembershipLevel' ) ) {
     
    306306        }
    307307    }
    308    
     308
    309309    /**
    310310     * Update the specified field name (a date field)
     
    321321     */
    322322    public function update_date( $field_name, $user_id, $current_level, $new_level, $new_date, $record_id = null, $use_new = false ) {
    323        
     323
    324324        $utils = Utilities::get_instance();
    325325        $date = null;
    326        
     326
    327327        // Make sure we received a valid date
    328328        if ( !empty($new_date) && false === $this->validate_date_format( $new_date, 'Y-m-d' ) ) {
    329            
     329
    330330            $user = get_user_by('ID', $user_id );
    331            
     331
    332332            $msg = sprintf(
    333333                __("Invalid date format for %s (record: %d/email: %s)", 'e20r-members-list' ),
     
    336336                $user->user_email
    337337            );
    338            
     338
    339339            $utils->log( $msg );
    340340            $utils->add_message( $msg, 'error', 'backend' );
    341            
     341
    342342            return false;
    343343        }
    344        
     344
    345345        global $wpdb;
    346        
     346
    347347        if ( true === $use_new ) {
    348348            $where        = array( 'membership_id' => $new_level, 'user_id' => $user_id, 'status' => 'active' );
     
    355355            $where_format = array( '%d', '%d', '%s' );
    356356        }
    357        
     357
    358358        if ( !empty( $new_date ) ) {
    359359            if ( true === apply_filters( 'e20r_memberslist_membership_starts_at_midnight', __return_true() ) ) {
     
    364364        }
    365365        $retval = $wpdb->update( $wpdb->pmpro_memberships_users, array( $field_name => $date ), $where, array( '%s' ), $where_format );
    366        
     366
    367367        if ( false === $retval ) {
    368368            return $retval;
    369369        }
    370        
     370
    371371        return true;
    372372    }
    373    
     373
    374374    /**
    375375     * Update the user's Membership status for the specified record
     
    381381     */
    382382    public function update_status( $record_id, $status ) {
    383        
     383
    384384        global $wpdb;
    385        
     385
    386386        $retval = $wpdb->update( $wpdb->pmpro_memberships_users, array( 'status' => $status ), array( 'id' => $record_id ), array( '%s' ), array( '%d' ) );
    387        
     387
    388388        if ( ! empty( $retval ) ) {
    389389            return true;
    390390        }
    391        
     391
    392392        return false;
    393393    }
    394    
     394
    395395    /**
    396396     * Set the list of members to update
     
    401401        $this->members_to_update = $member_info;
    402402    }
    403    
     403
    404404    /**
    405405     * Return the list of members being updated
     
    410410        return $this->members_to_update;
    411411    }
    412    
     412
    413413    /**
    414414     * Return the ongoing operation
     
    419419        return $this->operation;
    420420    }
    421    
     421
    422422    /**
    423423     * Configure/set the Operation for the Bulk Update
     
    428428        $this->operation = $operation;
    429429    }
    430    
     430
    431431    /**
    432432     * Test the date supplied for MySQL compliance
     
    440440     */
    441441    private function validate_date_format( $date, $format = 'Y-m-d' ) {
    442        
     442
    443443        $check_date = \DateTime::createFromFormat( $format, $date );
    444        
     444
    445445        return $check_date && $check_date->format( $format ) == $date;
    446446    }
  • e20r-members-list/tags/6.0/class/members-list/class.export-members.php

    r2228121 r2458244  
    11<?php
    22/**
    3  * Copyright (c) 2018-2019 - Eighty / 20 Results by Wicked Strong Chicks.
     3 * Copyright (c) 2018-2021 - Eighty / 20 Results by Wicked Strong Chicks.
    44 * ALL RIGHTS RESERVED
    55 *
     
    2525
    2626class Export_Members {
    27    
     27
    2828    /**
    2929     * @var array $member_list
    3030     */
    3131    private $member_list = array();
    32    
     32
    3333    /**
    3434     * @var string|null $sql
    3535     */
    3636    private $sql = null;
    37    
     37
    3838    /**
    3939     * @var array $headers
    4040     */
    4141    private $headers = array();
    42    
     42
    4343    /**
    4444     * @var array $csv_headers
    4545     */
    4646    private $csv_headers = array();
    47    
     47
    4848    /**
    4949     * @var array $csv_rows
    5050     */
    5151    private $csv_rows = array();
    52    
     52
    5353    /**
    5454     * @var bool|null|string
    5555     */
    5656    private $file_name = null;
    57    
     57
    5858    /**
    5959     * Cached $member discount information
     
    6262     */
    6363    private $member_discount_info = null;
    64    
     64
    6565    /**
    6666     * Export_Members constructor.
     
    6969     */
    7070    public function __construct( $db_records ) {
    71        
     71
    7272        $this->member_list = $db_records;
    73        
     73
    7474        $this->file_name = $this->create_temp_file();
    75        
     75
    7676        $this->default_columns = array(
    7777            array( "wp_user", "ID" ),
     
    106106            array( "member_level", 'enddate' ),
    107107        );
    108        
     108
    109109        $this->default_columns = apply_filters( 'pmpro_members_list_csv_default_columns', $this->default_columns );
    110110        $this->default_columns = apply_filters( 'e20r-members-list-default-csv-columns', $this->default_columns );
    111        
     111
    112112        /**
    113113         * Map of Database column keys and CSV export column keys
     
    257257            )
    258258        );
    259        
     259
    260260        // Generate the header for the .csv file
    261261        $this->csv_header();
    262262        $this->set_upload_headers();
    263        
     263
    264264        /**
    265265         * Trigger the default 'e20r-members-list-load-export-value' filter handler first
     
    267267        add_filter( 'e20r-members-list-load-export-value', array( $this, 'load_export_value' ), - 1, 3 );
    268268    }
    269    
     269
    270270    /**
    271271     * Create the temporary file name for this export operation
     
    274274     */
    275275    private function create_temp_file() {
    276        
     276
    277277        // Generate a temporary file to store the data in.
    278278        $tmp_dir   = sys_get_temp_dir();
    279279        $file_name = tempnam( $tmp_dir, 'pmpro_ml_' );
    280        
     280
    281281        return $file_name;
    282282    }
    283    
     283
    284284    /**
    285285     * Create the export file header (DB columns)
    286286     */
    287287    private function csv_header() {
    288        
     288
    289289        $utils = Utilities::get_instance();
    290290        $level = $utils->get_variable( 'membership_id', '' );
    291        
     291
    292292        $extra_cols = apply_filters( "pmpro_members_list_csv_extra_columns", array() );
    293        
     293
    294294        if ( ! empty( $extra_cols ) ) {
    295            
     295
    296296            foreach ( $extra_cols as $col_header => $callback ) {
    297297                // $this->header_map[]               = $col_header;
     
    304304            }
    305305        }
    306        
     306
    307307        $header_list       = apply_filters( 'pmpro_members_list_csv_heading', implode( ',', array_keys( $this->header_map ) ) );
    308308        $this->csv_headers = array_map( 'trim', explode( ',', $header_list ) );
    309        
     309
    310310        $utils->log( "Using " . count( $this->csv_headers ) . " header columns" );
    311311    }
    312    
     312
    313313    /**
    314314     * Set headers for .CSV file upload
    315315     */
    316316    private function set_upload_headers() {
    317        
     317
    318318        $this->headers[] = "Content-Type: text/csv";
    319319        $this->headers[] = "Cache-Control: max-age=0, no-cache, no-store";
     
    323323        $this->headers   = apply_filters( 'e20r-memberslist-http-headers', $this->headers );
    324324    }
    325    
     325
    326326    /**
    327327     * Clear old temporary files
    328328     */
    329329    public static function clear_temp_files() {
    330        
     330
    331331        $temp_dir_name = sys_get_temp_dir();
    332332        $utils         = Utilities::get_instance();
    333        
     333
    334334        $files = glob( "{$temp_dir_name}/pmpro_ml_*.csv" );
    335335        $now   = current_time( 'timestamp' );
    336        
     336
    337337        $utils->log( "Notice: Clearing temporary export files (if needed)" );
    338        
     338
    339339        foreach ( $files as $file_name ) {
    340            
     340
    341341            if ( is_file( $file_name ) ) {
    342                
     342
    343343                if ( $now - filemtime( $file_name ) >= DAY_IN_SECONDS ) { // Delete after 1 day
    344344                    unlink( $file_name );
     
    347347        }
    348348    }
    349    
     349
    350350    /**
    351351     * Fetches the data for the export operation
    352352     */
    353353    public function get_data_list() {
    354        
     354
    355355        $utils = Utilities::get_instance();
    356356        $utils->log( "Headers have been sent already..?!? " . ( headers_sent() ? 'Yes' : 'No' ) );
    357        
     357
    358358        /**
    359359         * Filter to set max number of records to process at a time
     
    370370         */
    371371        $max_users_per_loop = apply_filters( 'pmpro_set_max_user_per_export_loop', 2000 );
    372        
     372
    373373        /**
    374374         * Pre-export actions
     
    381381         */
    382382        do_action( 'pmpro_before_members_list_csv_export', $this->member_list );
    383        
     383
    384384        $extra_columns = apply_filters( "pmpro_members_list_csv_extra_columns", array() );
    385        
     385
    386386        $this->add_csv_header_to_file();
    387        
     387
    388388        $i_start     = 0;
    389389        $iterations  = 1;
    390390        $users_found = count( $this->member_list );
    391        
     391
    392392        if ( $users_found >= $max_users_per_loop ) {
    393393            $iterations = ceil( $users_found / $max_users_per_loop );
    394394        }
    395        
     395
    396396        $start      = current_time( 'timestamp' );
    397397        $end        = 0;
    398398        $time_limit = (int) get_cfg_var( 'max_execution_time' );
    399        
     399
    400400        // Split up the export operation in multiple rounds/iterations
    401401        for ( $ic = 1; $ic <= $iterations; $ic ++ ) {
    402            
     402
    403403            // Try to avoid timing out during the export operation
    404404            if ( 0 !== $end ) {
    405                
     405
    406406                $iteration_diff = $end - $start;
    407407                $new_time_limit = ceil( $iteration_diff * $iterations * 1.2 );
    408                
     408
    409409                if ( $time_limit < $new_time_limit ) {
    410410                    $time_limit = $new_time_limit;
     
    412412                }
    413413            }
    414            
     414
    415415            $start = current_time( 'timestamp' );
    416            
     416
    417417            $utils->log( "For iterations: {$i_start} -> " . ( $i_start + $max_users_per_loop ) );
    418            
     418
    419419            $member_list = array_slice( $this->member_list, $i_start, $max_users_per_loop );
    420            
     420
    421421            $utils->log( "Will process " . count( $member_list ) . " member records in iteration {$ic}" );
    422            
     422
    423423            // Increment starting position
    424424            if ( 0 < $iterations ) {
    425425                $i_start += $max_users_per_loop;
    426426            }
    427            
     427
    428428            foreach ( $member_list as $member ) {
    429                
     429
    430430                $csv_record = array();
    431                
     431
    432432                // Cast the Member array to an object
    433433                $member = (object) $member;
    434                
     434
    435435                /**
    436436                 * Fetch any user metadata for the user
    437437                 */
    438438                $member->meta_values = $this->load_user_meta( $member->ID );
    439                
     439
    440440                /**
    441441                 * Fetch/update the CSV export entry for the $member
     
    446446                 */
    447447                $csv_record = apply_filters( 'e20r-members-list-load-export-value', $csv_record, $member );
    448                
     448
    449449                // Add data from extra columns
    450450                if ( ! empty( $extra_columns ) ) {
    451                    
     451
    452452                    foreach ( $extra_columns as $col_heading => $callback ) {
    453                        
     453
    454454                        $val = call_user_func( $callback, $member, $col_heading );
    455455                        $val = ! empty( $val ) ? $val : null;
    456                        
     456
    457457                        $csv_record[ $col_heading ] = $this->enclose( $val );
    458458                    }
    459459                }
    460                
     460
    461461                // $utils->log( "Exportable info : " . print_r( $csv_record, true ) );
    462                
     462
    463463                // Add the data to the list of
    464464                $this->csv_rows[] = $csv_record;
    465                
    466             }
    467            
     465
     466            }
     467
    468468            wp_cache_flush();
    469            
     469
    470470            //need to increase max running time?
    471471            $end = current_time( 'timestamp' );
    472472        }
    473        
     473
    474474        do_action( 'pmpro_after_members_list_csv_export' );
    475475    }
    476    
     476
    477477    /**
    478478     * Add the CSV header to the (new) file
    479479     */
    480480    private function add_csv_header_to_file() {
    481        
     481
    482482        $utils = Utilities::get_instance();
    483        
     483
    484484        // Open our designated temporary file
    485485        $file_handle = fopen( $this->file_name, 'a' );
    486486        $header_type = 'header_key';
    487        
     487
    488488        $utils->log( "Adding " . count( $this->csv_headers ) . " header columns to {$this->file_name}" );
    489        
     489
    490490        //Add the CSV header to the file
    491491        fprintf( $file_handle, '%s',
     
    497497                    $this->csv_headers )
    498498            ) . "\n" );
    499        
     499
    500500        // Close the CSV file for now
    501501        fclose( $file_handle );
    502502    }
    503    
     503
    504504    /**
    505505     * Returns the expected header key for the requested DB Key
     
    512512     */
    513513    private function map_keys( $key, $requested, $column_type = null ) {
    514        
     514
    515515        $utils = Utilities::get_instance();
    516        
     516
    517517        foreach ( $this->header_map as $map_key => $field_def ) {
    518            
     518
    519519            if ( $key === $map_key ) {
    520520                return $field_def[ $requested ];
    521521            }
    522            
     522
    523523            if ( 'header_key' === $requested && $field_def['header_key'] == $key ) {
    524                
     524
    525525                return $map_key;
    526526            }
    527            
     527
    528528            if ( 'db_key' === $requested && $field_def['db_key'] == $key ) {
    529                
    530                
     529
     530
    531531                if ( 'username' === $key ) {
    532532                    return $map_key;
    533533                }
    534                
     534
    535535                return $field_def[ $requested ];
    536536            }
    537537        }
    538        
     538
    539539        $utils->log( "No value (key) found for {$requested} key {$key}" );
    540        
     540
    541541        return null;
    542542    }
    543    
     543
    544544    /**
    545545     * Return all of the user's metadata that we (may) care about
     
    550550     */
    551551    private function load_user_meta( $user_id ) {
    552        
     552
    553553        $meta_values = null;
    554        
     554
    555555        // Returns array of meta keys containing array(s) of meta_values.
    556556        $um_values = get_user_meta( $user_id );
    557        
     557
    558558        // Process user metadata
    559559        if ( ! empty( $um_values ) ) {
    560            
     560
    561561            $meta_values = new \stdClass();
    562            
     562
    563563            foreach ( $um_values as $key => $value ) {
    564                
     564
    565565                $meta_values->{$key} = isset( $value[0] ) ? $value[0] : null;
    566566            }
    567567        }
    568        
     568
    569569        return $meta_values;
    570        
    571     }
    572    
     570
     571    }
     572
    573573    /**
    574574     * Enclose the data we're adding to the export file
     
    581581        return "\"" . str_replace( "\"", "\\\"", $text ) . "\"";
    582582    }
    583    
     583
    584584    /**
    585585     * @param array     $csv_record
     
    589589     */
    590590    public function load_export_value( $csv_record, $member ) {
    591        
     591
    592592        $utils = Utilities::get_instance();
    593        
     593
    594594        $datetime_format = $this->set_datetime_format();
    595595        $level           = $utils->get_variable( 'membership_id', '' );
    596        
     596
    597597        // $utils->log( "For member: " . print_r( $member, true ) );
    598        
     598
    599599        // Process the membership data (by column)
    600600        foreach ( $this->default_columns as $field_def ) {
    601            
     601
    602602            $column_type  = $field_def[0];
    603603            $column_name  = $this->map_keys( $field_def[1], 'db_key', $column_type );
     
    607607                $column_type
    608608            );
    609            
     609
    610610            // Process Join/Start dates for membership
    611611            if ( in_array( $column_name, array( 'user_registered', 'startdate' ) ) ) {
    612                
     612
    613613                $column_value = date(
    614614                    $datetime_format,
     
    618618                );
    619619            }
    620            
     620
    621621            // Process End of membership column
    622622            if ( 'enddate' == $column_name ) {
    623                
     623
    624624                $enddate_value = $column_value;
    625                
     625
    626626                if ( ! is_null( $member->membership_id ) && ! empty( $column_value ) ) {
    627                    
     627
    628628                    // Membership is terminated or about to be terminated
    629629                    if ( in_array( $level, array( "oldmembers", "expired", 'cancelled' ) ) &&
    630630                         ( ! empty( $column_value ) && '0000-00-00 00:00:00' !== $column_value ) ) {
    631                        
     631
    632632                        $enddate_value = apply_filters( "pmpro_memberslist_expires_column", date( $datetime_format, strtotime( $column_value, current_time( 'timestamp' ) ) ), $member );
    633                        
     633
    634634                    }
    635                    
     635
    636636                    if ( ! empty( $member->membership_id ) && ( empty( $column_value ) || '0000-00-00 00:00:00' === $column_value ) ) {
    637637                        $enddate_value = apply_filters( "pmpro_memberslist_expires_column", null, $member );
    638638                    }
    639                    
     639
    640640                    if ( ! empty( $member->membership_id ) && ( ! empty( $column_value ) && '0000-00-00 00:00:00' !== $column_value ) ) {
    641641                        $enddate_value = date( $datetime_format, strtotime( $column_value, current_time( 'timestamp' ) ) );
    642642                    }
    643                    
     643
    644644                    // Save record info for the column
    645645                    $column_value = apply_filters( 'e20r-members-list-expires-col-value', $enddate_value, $member );;
    646646                }
    647647            }
    648            
     648
    649649            /**
    650650             * Fetch the discount code data for this user/member
    651651             */
    652652            if ( ! empty( $member->code_id ) && empty( $this->member_discount_info ) ) {
    653                
     653
    654654                $utils->log( "Grab the discount code data for {$member->ID}/{$member->code_id}" );
    655                
     655
    656656                $this->member_discount_info = self::get_pmpro_discount_code(
    657657                    $member->code_id,
     
    660660                );
    661661            }
    662            
     662
    663663            /**
    664664             * Fetch the discount code value for the user/member
    665665             */
    666666            if ( $column_type === 'pmpro_discount_code' && ! empty( $this->member_discount_info ) ) {
    667                
     667
    668668                $param        = "pmpro_discount_{$column_name}";
    669669                $column_value = $this->member_discount_info->{$param};
    670670            }
    671            
    672            
     671
     672
    673673            if ( empty( $column_value ) ) {
    674674                $column_value = null;
    675675            }
    676            
     676
    677677            // $utils->log( "Saving {$column_name} (looked for {$field_def[1]}): " . print_r( $column_value, true ) );
    678            
     678
    679679            // Save the entry info
    680680            $csv_record[ $column_name ] = $this->enclose( $column_value );
    681681        }
    682        
     682
    683683        // Clear the Discount Info (for the member)
    684684        $this->member_discount_info = null;
    685        
     685
    686686        return $csv_record;
    687687    }
    688    
     688
    689689    /**
    690690     * Configure the format to use for the export datetime value
     
    693693     */
    694694    private function set_datetime_format() {
    695        
     695
    696696        /**
    697697         * Filter to the format for the date (default is the WordPress General Setting value for Date)
     
    705705        $date_format = apply_filters( 'pmpro_memberslist_csv_dateformat', get_option( 'date_format' ) );
    706706        $date_format = apply_filters( 'e20r-members-list-csv-fateformat', $date_format );
    707        
     707
    708708        /**
    709709         * Filter to the format for the time (default is the WordPress General Setting value for Time)
     
    716716         */
    717717        $time_format = apply_filters( 'e20r-members-list-csv-timeformat', get_option( 'time_format' ) );
    718        
     718
    719719        // Assume that we want a valid MySQL DateTime format if date is Y-m-d
    720720        if ( 'Y-m-d' == $date_format && 'H:i' == $time_format ) {
     
    723723            $expected_format = "{$date_format} {$time_format}";
    724724        }
    725        
     725
    726726        /**
    727727         * Filter to the format for the time (default is the WordPress General Setting value for Time)
     
    736736         */
    737737        $datetime_format = apply_filters( 'e20r-members-list-csv-datetime-format', $expected_format, $date_format, $time_format );
    738        
     738
    739739        return $datetime_format;
    740740    }
    741    
     741
    742742    /**
    743743     * Return a value for the specified column (name)
     
    750750     */
    751751    private function get_column_value( $member, $column_name, $column_type ) {
    752        
     752
    753753        $utils       = Utilities::get_instance();
    754754        $dc_col_name = "pmpro_discount_code_";
    755        
     755
    756756        switch ( $column_type ) {
    757            
     757
    758758            case 'wp_user':
    759759            case 'member_level':
     
    762762                $column_value = isset( $member->{$column_name} ) ? $member->{$column_name} : null;
    763763                break;
    764            
     764
    765765            case 'pmpro_discount_code':
    766766                $dc_col_name  = "{$dc_col_name}{$column_name}";
    767767                $column_value = isset( $member->{$column_name} ) ? $member->{$column_name} : null;
    768768                break;
    769            
     769
    770770            case 'meta_values':
    771771                $column_value = isset( $member->meta_values->{$column_name} ) ? $member->meta_values->{$column_name} : null;
    772772                break;
    773            
     773
    774774            default:
    775775                $utils->log( "Using default type (type = {$column_type}) for {$column_name}" );
    776776                $column_value = isset( $member->{$column_type}->{$column_name} ) ? $member->{$column_type}->{$column_name} : null;
    777                
     777
    778778                /**
    779779                 * Let 3rd party define the value to use for a 3rd party defined default column
     
    790790                $column_value = apply_filters( 'e20r-members-list-set-default-column-value', $column_value, $column_name, $column_type, $member );
    791791        }
    792        
     792
    793793        return $column_value;
    794794    }
    795    
     795
    796796    /**
    797797     * Fetch discount code (ID and code) for the code ID/User ID/Level ID combination
     
    804804     */
    805805    public static function get_pmpro_discount_code( $code_id, $user_id, $level_id ) {
    806        
     806
    807807        global $wpdb;
    808        
     808
    809809        $disSql = $wpdb->prepare( "
    810810                SELECT
     
    819819            $user_id
    820820        );
    821        
     821
    822822        $pmpro_discount_code = $wpdb->get_row( $disSql );
    823        
     823
    824824        // Make sure there's data for the discount code info
    825825        if ( empty( $pmpro_discount_code ) ) {
     
    829829            $pmpro_discount_code              = $empty_dc;
    830830        }
    831        
     831
    832832        return $pmpro_discount_code;
    833833    }
    834    
     834
    835835    /**
    836836     * Save the data rows to the temporary Export file
    837837     */
    838838    public function save_data_for_export() {
    839        
     839
    840840        $utils = Utilities::get_instance();
    841841        $utils->log( "Saving " . count( $this->csv_rows ) . " records to {$this->file_name}. " );
    842        
     842
    843843        $fh = fopen( $this->file_name, 'a' );
    844        
     844
    845845        /**
    846846         * @var $row_data -> $csv_entry[ $col_heading ] = $this->enclose( $val );
    847847         */
    848848        foreach ( $this->csv_rows as $row_id => $row_data ) {
    849            
     849
    850850            $data = array();
    851            
     851
    852852            foreach ( $this->csv_headers as $col_key ) {
    853                
     853
    854854                /*
    855855                if ( 'ID' == $col_key ) {
     
    857857                }
    858858                */
    859                
     859
    860860                $col_name = $this->map_keys( $col_key, 'db_key' );
    861                
     861
    862862                $value  = isset( $row_data[ $col_name ] ) ? $row_data[ $col_name ] : $this->enclose( null );
    863863                $data[] = $value;
    864864            }
    865            
     865
    866866            $file_line = implode( ',', $data ) . "\r\n";
    867867            fprintf( $fh, '%s', $file_line );
    868868        }
    869        
     869
    870870        fclose( $fh );
    871871        $utils->log( "Saved data to {$this->file_name}" );
    872872    }
    873    
     873
    874874    /**
    875875     * Send the .CSV to the requesting browser
    876876     */
    877877    public function return_content() {
    878        
     878
    879879        $utils = Utilities::get_instance();
    880880        $utils->log( "Headers have been sent already..?!? " . ( headers_sent() ? 'Yes' : 'No' ) );
     
    882882        // Send the data to the recipient browser
    883883        if ( ! empty( $this->headers ) && false === headers_sent() && file_exists( $this->file_name ) ) {
    884            
     884
    885885            $sent_content = ob_get_clean();
    886886            $utils->log("Browser received: " . print_r( $sent_content, true) );
    887            
     887
    888888            if ( version_compare( phpversion(), '5.3.0', '>' ) ) {
    889                
     889
    890890                //Clear the file cache for the export file
    891891                clearstatcache( true, $this->file_name );
     
    894894                clearstatcache();
    895895            }
    896            
     896
    897897            //Set the download size for the file
    898898            $this->headers[] = "Content-Length: " . filesize( $this->file_name );
    899            
     899
    900900            //Set transmission (PHP) headers
    901901            foreach ( $this->headers as $header ) {
    902902                header( $header . "\r\n" );
    903903            }
    904            
     904
    905905            // Disable compression for the duration of file download
    906906            if ( ini_get( 'zlib.output_compression' ) ) {
    907907                ini_set( 'zlib.output_compression', 'Off' );
    908908            }
    909            
     909
    910910            // Bug fix for Flywheel Hosted like hosts where fpassthru() is disabled
    911911            if ( function_exists( 'fpassthru' ) ) {
     
    917917                readfile( $this->file_name );
    918918            }
    919            
     919
    920920            // Remove the temp file
    921921            unlink( $this->file_name );
    922922            exit();
    923            
     923
    924924        } else {
    925925            $msg = __( "Unable to send the .CSV file to your browser!", 'e20r-members-list' );
     
    928928        }
    929929    }
    930    
     930
    931931    /**
    932932     * Returns the column name to use from the specified $header_name
     
    937937     */
    938938    private function map_header_to_column( $header_name ) {
    939        
     939
    940940        return isset( $this->header_map[ $header_name ]['header_key'] ) ? $this->header_map[ $header_name ]['header_key'] : null;
    941941    }
  • e20r-members-list/tags/6.0/class/members-list/class.members-list-page.php

    r2228121 r2458244  
    11<?php
    22/**
    3  * Copyright (c) 2018-2019 - Eighty / 20 Results by Wicked Strong Chicks.
     3 * Copyright (c) 2018-2021 - Eighty / 20 Results by Wicked Strong Chicks.
    44 * ALL RIGHTS RESERVED
    55 *
     
    2424
    2525class Members_List_Page {
    26    
     26
    2727    /**
    2828     * Instance of the Members_List_Page class (Singleton)
     
    3131     */
    3232    private static $instance = null;
    33    
     33
    3434    /**
    3535     * Holds the list of members (Members_List class)
     
    3737     */
    3838    public $member_list;
    39    
     39
    4040    /**
    4141     * Holds the standard Utilities class
     
    4444     */
    4545    private $utils;
    46    
     46
    4747    /**
    4848     * Members_List_Page constructor. Loads required menu(s) & screen options
     
    5050    private function __construct() {
    5151    }
    52    
     52
    5353    /**
    5454     * Creates or returns an instance of the Members_List_Page class.
     
    5757     */
    5858    public static function get_instance() {
    59        
     59
    6060        if ( null === self::$instance ) {
    6161            self::$instance = new self;
    6262        }
    63        
     63
    6464        return self::$instance;
    6565    }
    66    
     66
    6767    /**
    6868     * Removes the old Member List page & appends a new one to the "Memberships" admin bar node
    6969     */
    7070    public static function admin_bar_menu() {
    71        
     71
    7272        $is_pmpro_v2 = version_compare( PMPRO_VERSION, '2.0', 'ge' );
    73        
     73
    7474        if ( true === $is_pmpro_v2 ) {
    7575            return;
    7676        }
    77        
     77
    7878        global $wp_admin_bar;
    79        
    80        
     79
     80
    8181        if ( ! is_admin_bar_showing() || ( ! is_super_admin() && ( ! current_user_can( 'manage_options' ) ) && ! current_user_can( 'pmpro_memberslist' ) && ! current_user_can( 'e20r_memberslist' ) ) ) {
    8282            if ( ! is_null( self::$instance ) ) {
    8383                self::$instance->utils->log( "Unable to change admin bar (wrong capabilities for user)" );
    8484            }
    85            
     85
    8686            return;
    8787        }
    88        
     88
    8989        $wp_admin_bar->remove_menu( 'pmpro-members-list' );
    9090        $wp_admin_bar->remove_node( 'pmpro-members-list' );
    91        
     91
    9292        //Add the (new) Members List page to the admin_bar menu
    9393        $wp_admin_bar->add_menu( array(
     
    102102        ) );
    103103    }
    104    
     104
    105105    /**
    106106     * Screen Option option(s) for the Members List page.
     
    112112     */
    113113    public static function set_screen( $status, $option, $value ) {
    114        
     114
    115115        self::$instance->utils->log( "Saving screen option (page: {$option})? {$value} vs {$status}" );
    116        
     116
    117117        if ( 'per_page' == $option ) {
    118118            return $value;
    119119        }
    120        
     120
    121121        return $status;
    122122    }
    123    
     123
    124124    /**
    125125     * Load Action and Filter hooks for the Members List page
    126126     */
    127127    public function load_hooks() {
    128        
     128
    129129        $this->utils = Utilities::get_instance();
    130        
     130
    131131        // Filters
    132132        add_filter( 'set-screen-option', array( $this, 'set_screen' ), 10, 3 );
    133133        add_filter( 'set_url_scheme', array( $this, 'add_to_pagination' ), 10, 3 );
    134        
     134
    135135        // Actions
    136136        add_action( 'admin_menu', array( $this, 'plugin_menu' ), 9999 );
     
    138138        // add_action( 'admin_bar_menu', array( $this, 'admin_bar_menu' ), 9999 );
    139139        add_action( 'admin_enqueue_scripts', array( $this, 'load_scripts_styles' ) );
    140        
    141     }
    142    
     140
     141    }
     142
    143143    /**
    144144     * Load the custom CSS and JavaScript for the Members List
    145145     */
    146146    public function load_scripts_styles( $hook_suffix ) {
    147        
     147
    148148        if ( is_admin() && ( ! defined( 'DOING_AJAX' ) || false == DOING_AJAX ) && 1 === preg_match( '/(pmpro|e20r)-memberslist/', $hook_suffix ) ) {
    149            
     149
    150150            wp_enqueue_style( 'jquery-ui', '//cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.css' );
    151151            wp_enqueue_script( 'jquery-ui-datepicker' );
    152            
     152
    153153            wp_enqueue_style( 'e20r-memberslist-page', plugins_url( "/css/e20r-memberslist-page.css", __FILE__ ), array( 'pmpro_admin' ), E20R_MEMBERSLIST_VER );
    154            
     154
    155155            wp_register_script( 'e20r-memberslist-page', plugins_url( "/js/e20r-memberslist-page.js", __FILE__ ), array( 'jquery' ), E20R_MEMBERSLIST_VER, true );
    156            
     156
    157157            // $is_pmpro_v2 = version_compare( PMPRO_VERSION, '2.0', 'ge' );
    158158            // $url         = ( false === $is_pmpro_v2 ) ? 'e20r-memberslist' : 'pmpro-memberslist';
    159            
     159
    160160            wp_localize_script( 'e20r-memberslist-page', 'e20rml',
    161161                array(
     
    168168                )
    169169            );
    170            
     170
    171171            wp_enqueue_script( 'e20r-memberslist-page' );
    172172        }
    173173    }
    174    
     174
    175175    /**
    176176     * Point Members List menu handler(s) to this plugin
    177177     */
    178178    public function plugin_menu() {
    179      
     179
    180180        $this->utils->log( "Headers sent? " . ( headers_sent() ? 'Yes' : 'No' ) );
    181        
    182        
     181
     182
    183183        $pmpro_menu_slug = 'pmpro-membershiplevels';
    184184        $is_pmpro_v2     = version_compare( PMPRO_VERSION, '2.0', 'ge' );
    185        
     185
    186186        if ( defined( 'PMPRO_VERSION' ) && $is_pmpro_v2 ) {
    187187            $pmpro_menu_slug = 'pmpro-dashboard';
    188188        }
    189        
     189
    190190        $this->utils->log( "Remove the default members list page.. (under: {$pmpro_menu_slug})" );
    191        
     191
    192192        // Just replace the action that loads the PMPro Members List
    193        
     193
    194194        $hookname = get_plugin_page_hookname( 'pmpro-memberslist', $pmpro_menu_slug );
    195195        $this->utils->log("Found hook name: {$hookname}. Sent yet? " . (headers_sent() ? 'Yes' : 'No') );
     
    197197        add_action( $hookname, array( $this, 'memberslist_settings_page' ), 11 );
    198198        add_action( "load-memberships_page_pmpro-memberslist", array( $this, 'screen_option' ), 9999 );
    199        
     199
    200200        /*
    201201        // Unhook old members list functionality (pre v2.0 of PMPro)
    202202        if ( false == ( $page = remove_submenu_page( $pmpro_menu_slug, 'pmpro-memberslist' ) ) ) {
    203            
     203
    204204            $this->utils->log( "Unable to remove the default membership levels page!" );
    205205            pmpro_setMessage( __( 'Error while attempting to reassign member list menu', E20R_Members_List::plugin_slug ), 'error' );
    206            
     206
    207207            return;
    208208        }
    209        
     209
    210210        // Load the (new) WP_Table_List based Members List
    211211        $hook = add_submenu_page(
     
    217217            array( $this, 'memberslist_settings_page' )
    218218        );
    219        
     219
    220220        // Show error if we're unable to update the members list
    221221        if ( false === $hook ) {
    222            
     222
    223223            $this->utils->log( "Unable to load the replacement Members List page!" );
    224224            pmpro_setMessage( __( "Unable to load Members List menu entry", "e20r-members-list" ), "error" );
    225            
     225
    226226            return;
    227227        }
    228        
     228
    229229        // Process the screen option
    230230        add_action( "load-memberships_page_pmpro-memberslist", array( $this, 'screen_option' ), 9999 );
    231231        */
    232232    }
    233    
     233
    234234    /**
    235235     * Add parameters to limit/include records to any members list page URI
     
    242242     */
    243243    public function add_to_pagination( $url, $scheme, $original_scheme ) {
    244        
     244
    245245        $page = $this->utils->get_variable( 'page', '' );
    246        
     246
    247247        if ( 1 === preg_match( "/{$_SERVER['HTTP_HOST']}\/wp-admin\/admin.php\?page=pmpro-memberslist/i", $url ) ) {
    248            
     248
    249249            $arg_list = array();
    250            
     250
    251251            $level = $this->utils->get_variable( 'level', '' );
    252252            $find  = $this->utils->get_variable( 'find', '' );
    253            
     253
    254254            if ( ! empty( $level ) ) {
    255255                $arg_list['level'] = $level;
    256256            }
    257            
     257
    258258            if ( ! empty( $find ) ) {
    259259                $arg_list['find'] = $find;
    260260            }
    261            
     261
    262262            /**
    263263             * @filter e20r_memberslist_pagination_args - Add filtering to the URI (to preserve it for pagination ,etc)
     
    266266             */
    267267            $arg_list = apply_filters( 'e20r_memberslist_pagination_args', $arg_list );
    268            
     268
    269269            // Encode the new URI variables
    270270            foreach ( $arg_list as $a_key => $value ) {
    271271                $arg_list[ $a_key ] = urlencode_deep( urldecode_deep( $value ) );
    272272            }
    273            
     273
    274274            $url = add_query_arg( $arg_list, $url );
    275275        }
    276        
     276
    277277        return $url;
    278278    }
    279    
     279
    280280    /**
    281281     * Configure options to use for "Screen Options" on Members_List_Page page.
    282282     */
    283283    public function screen_option() {
    284        
     284
    285285        $options = 'per_page';
    286        
     286
    287287        $args = array(
    288288            'label'   => _x( "Members per page", "members per page (screen options)", "e20r-members-list" ),
     
    290290            'option'  => $options,
    291291        );
    292        
     292
    293293        add_screen_option( $options, $args );
    294        
     294
    295295        $this->member_list = new Members_List();
    296296    }
    297    
     297
    298298    /**
    299299     * Load the e20rMembersList page content
    300300     */
    301301    public function memberslist_settings_page() {
    302        
     302
    303303        $this->utils->log("Have we sent content? " . (headers_sent() ? 'yes' : 'no'));
     304
     305        if ( ! function_exists( 'pmpro_loadTemplate' ) ) {
     306            $this->utils->log("Fatal: Paid Memberships Pro is not loaded on site!");
     307            return "";
     308        }
     309
    304310        global $pmpro_msg;
    305311        global $pmpro_msgt;
    306        
     312
    307313        // TODO: Fix this to match required request variables.
    308314        $search = $this->utils->get_variable( 'find', '' );
    309315        $level  = $this->utils->get_variable( 'level', '' );
    310        
     316
    311317        echo pmpro_loadTemplate( 'admin_header', 'local', 'adminpages' );
    312        
     318
    313319        $search_array = apply_filters( 'e20r_memberslist_exportcsv_search_args', array(
    314320                'action' => 'memberslist_csv',
     
    318324            )
    319325        );
    320        
     326
    321327        $csv_url = add_query_arg(
    322328            $search_array,
    323329            get_admin_url( get_current_blog_id(), 'admin-ajax.php' )
    324330        );
    325        
     331
    326332        $e20r_error_msgs   = $this->utils->get_message( 'error' );
    327333        $e20r_warning_msgs = $this->utils->get_message( 'warning' );
    328334        $e20r_info_msgs    = $this->utils->get_message( 'info' );
    329        
     335
    330336        $top_list = array(
    331337            'active' => __( 'Active Members', E20R_Members_List::plugin_slug ),
    332338            'all'    => __( 'All Members', E20R_Members_List::plugin_slug ),
    333339        );
    334        
     340
    335341        $bottom_list = array(
    336342            'cancelled'  => __( 'Cancelled Members', 'paid-membership-pro' ),
     
    338344            'oldmembers' => __( 'Old Members', 'paid-membership-pro' ),
    339345        );
    340        
     346
    341347        $level_list = array();
    342        
    343         $list = function_exists( 'pmpro_getAllLevels' ) ? pmpro_getAllLevels( true, true ) : array();
    344        
     348
     349        $list = function_exists( 'pmpro_getAllLevels' ) ?
     350                pmpro_getAllLevels( true, true ) :
     351                array();
     352
    345353        foreach ( $list as $item ) {
    346354            $level_list[ $item->id ] = $item->name;
    347355        }
    348        
     356
    349357        $option_list = $top_list + $level_list + $bottom_list;
    350        
     358
    351359        if ( ! empty( $pmpro_msg ) ) { ?>
    352360
     
    383391                        $label      = __( 'Update List', E20R_Members_List::plugin_slug );
    384392                        $button_def = 'button';
    385                        
     393
    386394                        if ( isset( $_REQUEST['find'] ) && ! empty( $_REQUEST['find'] ) ) {
    387                            
     395
    388396                            $label      = __( 'Clear Search', E20R_Members_List::plugin_slug );
    389397                            $button_def .= " button-primary";
     
    421429            </form>
    422430        </div>
    423        
     431
    424432        <?php
    425433        echo pmpro_loadTemplate( 'admin_footer', 'local', 'adminpages' );
    426434    }
    427    
     435
    428436    /**
    429437     * Deactivated __clone() method for the Members_List_Page class
     
    431439    private function __clone() {
    432440    }
    433    
     441
    434442}
  • e20r-members-list/tags/6.0/class/members-list/class.members-list.php

    r2306383 r2458244  
    33 * License:
    44
    5     Copyright 2016-2019 - Eighty / 20 Results by Wicked Strong Chicks, LLC ([email protected])
     5    Copyright 2016-2021 - Eighty / 20 Results by Wicked Strong Chicks, LLC ([email protected])
    66
    77    This program is free software; you can redistribute it and/or modify
     
    7373     */
    7474    private $total_members_found = null;
     75
     76    /**
     77     * The total number of records in the PMPro Membership DB
     78     *
     79     * @var int $total_member_records
     80     */
     81    private $total_member_records = 0;
     82
     83    /**
     84     * The status of the membership when searching for totals
     85     *
     86     * @var string $membership_status
     87     */
     88    private $membership_status = 'active';
     89
    7590    /**
    7691     * The completed SQL query used to generate the membership list
     
    176191        $this->action = $this->utils->get_variable( 'action', '' );
    177192
     193        if ( ! empty( $level ) ) {
     194            switch ($level) {
     195                case 'cancelled':
     196                    $this->membership_status = array( 'cancelled' );
     197                    break;
     198                case 'expired':
     199                    $this->membership_status = array( 'expired' );
     200                    break;
     201                case 'old':
     202                    $this->membership_status = array( 'cancelled', 'expired' );
     203                    break;
     204                default:
     205                    $this->membership_status = array('active');
     206            }
     207        }
    178208        /**
    179209         * The default Members List columns to display (with labels)
     
    204234        }
    205235
     236        $this->total_member_records = $this->get_member_record_count();
     237
    206238        /**
    207239         * Prepare the Export bulk action
     
    211243            add_action( 'e20r_memberslist_process_action', array( $this, 'export_members' ), 10, 3 );
    212244        }
     245    }
     246
     247    /**
     248     * Private function to capture the count of records in the membership database
     249     *
     250     * @return int|null
     251     */
     252    private function get_member_record_count() {
     253
     254        $status = $this->utils->get_variable( 'level', 'active' );
     255
     256        // Get SQL for all records in the paginated data
     257        $this->generate_member_sql( $status );
     258        $records = $this->get_members( -1, -1, $status );
     259
     260        return is_countable( $records ) ? count( $records ) : 0;
    213261    }
    214262
     
    294342
    295343        // Do we need to limit?
    296         $level = $this->utils->get_variable( 'level', '' );
    297 
    298         if ( empty( $level ) ) {
    299             $level = 'active';
    300         }
     344        $level = $this->utils->get_variable( 'level', 'active' );
    301345
    302346        // Get the current page number
     
    309353        // BUG FIX: Handle situation(s) where there are no records found
    310354        if ( null !== $this->items ) {
    311             $total_items = count($this->items );
    312355            $this->utils->log(
    313356                sprintf(
    314357                "Configure pagination for %d total records and %d counted (returned) records",
    315                 $total_items,
     358                $this->total_member_records,
    316359                (is_countable( $this->items ) ? count( $this->items ) : 0)
    317360                )
     
    323366        $this->set_pagination_args(
    324367            array(
    325                 'total_items' => $total_items,
     368                'total_items' => $this->total_member_records,
    326369                'per_page'    => $per_page,
    327                 'total_pages' => ceil( $total_items / $per_page ),
     370                'total_pages' => ceil( $this->total_member_records / $per_page ),
    328371            )
    329372        );
     
    593636        global $wpdb;
    594637
    595         $this->generate_member_sql( $per_page, $page_number, $status );
     638        // Get Pagination SQL
     639        $this->sqlQuery = $this->generate_member_sql( $status, $per_page, $page_number, );
    596640
    597641        // Fetch the data
    598         $result                    = $wpdb->get_results( $this->sqlQuery, ARRAY_A );
     642        $result = $wpdb->get_results( $this->sqlQuery, ARRAY_A );
     643
    599644        if ( ! empty( $result ) ) {
    600645            $this->utils->log("Found records in DB...");
    601646            $this->total_members_found = $wpdb->num_rows;
    602647        }
    603         /*
    604         if ( ! empty( $result ) ) {
    605             $this->total_members_found = $result->num_rows;
    606             // $this->total_members_found = $wpdb->get_var( "SELECT FOUND_ROWS() AS found_rows" );
    607         }
    608         */
    609648
    610649        // Return the result set unless an error occurred.
     
    640679     * @param int    $page_number
    641680     * @param string $status
    642      */
    643     private function generate_member_sql( $per_page, $page_number, $status = 'active' ) {
     681     *
     682     * @return string - Returns the SQL statement
     683     */
     684    private function generate_member_sql( $status = 'active', $per_page = -1, $page_number = -1 ) {
    644685
    645686        $this->utils->log( "Called by: " . $this->utils->_who_called_me() );
     
    839880        ";
    840881
    841         // Define the SQL statement
    842         $this->sqlQuery = $sql . self::$sql_from;
    843 
    844         $this->utils->log( "SQL for fetching membership records:\n {$this->sqlQuery}" );
     882        // Created the SQL statement
     883        $sqlQuery = $sql . self::$sql_from;
     884
     885        $this->utils->log( "SQL for fetching membership records:\n {$sqlQuery}" );
     886        return $sqlQuery;
    845887    }
    846888
  • e20r-members-list/tags/6.0/class/members-list/class.sort-by-meta.php

    r2025537 r2458244  
    11<?php
    22/**
    3  * Copyright (c) 2018-2019 - Eighty / 20 Results by Wicked Strong Chicks.
     3 * Copyright (c) 2018-2021 - Eighty / 20 Results by Wicked Strong Chicks.
    44 * ALL RIGHTS RESERVED
    55 *
     
    2121
    2222if ( ! class_exists( 'E20R\Members_List\Support\Sort_By_Meta' ) ) {
    23    
     23
    2424    class Sort_By_Meta {
    25        
     25
    2626        private $meta_key;
    27        
     27
    2828        private $order = 'DESC';
    29        
     29
    3030        /**
    3131         * Sort_Meta constructor.
     
    3838            $this->order    = strtoupper( $order );
    3939        }
    40        
     40
    4141        /**
    4242         * @param array $a
     
    4848         */
    4949        public function sort_records( $a, $b ) {
    50            
     50
    5151            // $utils = Utilities::get_instance();
    5252            // $utils->log( "A: " . print_r( $a, true));
    5353            // $utils->log("B: " . print_r( $b, true));
    54            
     54
    5555            $a_user_id = is_array( $a ) ? $a['user_id'] : ( is_a( $a, '\WP_User' ) ? $a->ID : null );
    5656            $b_user_id = is_array( $b ) ? $b['user_id'] : ( is_a( $b, '\WP_User' ) ? $b->ID : null );
    57            
     57
    5858            if ( is_null($a_user_id ) || is_null( $b_user_id ) ) {
    5959                return false;
    6060            }
    61            
     61
    6262            // Check if the field specified exists in the data
    6363            if ( ! isset( $a[ $this->meta_key ] ) ) {
    6464                $a_value = get_user_meta( $a_user_id, $this->meta_key, true );
    65                
     65
    6666            } else {
    6767                $a_value = $b[ $this->meta_key ];
    6868            }
    69            
     69
    7070            if ( ! isset( $b[ $this->meta_key ] ) ) {
    7171                $b_value = get_user_meta( $b_user_id, $this->meta_key, true );
     
    7373                $b_value = $b[ $this->meta_key ];
    7474            }
    75            
     75
    7676            if ( $a_value == $b_value ) {
    7777                return 0;
    7878            }
    79            
     79
    8080            if ( 'DESC' == $this->order ) {
    8181                return ( $a_value > $b_value ? 1 : - 1 );
    8282            }
    83            
     83
    8484            if ( 'ASC' == $this->order ) {
    8585                return ( $a_value < $b_value ? 1 : - 1 );
    8686            }
    87            
    88            
     87
     88
    8989        }
    90        
     90
    9191    }
    9292}
  • e20r-members-list/tags/6.0/class/members-list/css/e20r-memberslist-page.css

    r2025537 r2458244  
    11/*
    2  *  Copyright (c) 2018-2019. - Eighty / 20 Results by Wicked Strong Chicks.
     2 *  Copyright (c) 2018-2021. - Eighty / 20 Results by Wicked Strong Chicks.
    33 *  ALL RIGHTS RESERVED
    44 *
  • e20r-members-list/tags/6.0/class/members-list/js/e20r-memberslist-page.js

    r2228121 r2458244  
    22 * License:
    33
    4     Copyright 2016-2019 - Eighty / 20 Results by Wicked Strong Chicks, LLC ([email protected])
     4    Copyright 2016-2021 - Eighty / 20 Results by Wicked Strong Chicks, LLC ([email protected])
    55
    66    This program is free software; you can redistribute it and/or modify
  • e20r-members-list/trunk/README.txt

    r2306383 r2458244  
    1212
    1313Extensible, sortable & bulk action capable members listing tool for Paid Memberships Pro. This plugin is a complete replacement for the "Members List" functionality in PMPro and supports most of the same filters and hooks. The key differences have to do with managing columns. Now you can also use the [standard WordPress filters](https://developer.wordpress.org/reference/classes/wp_list_table/) to columns you can add/remove/make sortable, additional bulk actions, etc.
     14
     15![Release to wordpress.org](https://github.com/eighty20results/e20r-members-list/workflows/Release%20to%20wordpress.org/badge.svg?branch=master)
    1416
    1517== Installation ==
     
    189191== Changelog ==
    190192
     193== 6.0 ==
     194* BUG FIX: Didn't paginate correctly because the LIMIT logic caused us to not return the full number of records for the level/status
     195* BUG FIX: Potentially a fatal PHP error
     196* BUG FIX: Bad path to downloadable archive
     197* BUG FIX: Didn't (always) import the database needed for testing
     198* BUG FIX: Readme directions for installation were imprecise
     199* BUG FIX: Removed copy/paste Utilities module and using git subtree instead
     200* BUG FIX: Updated copyright notice
     201
     202
    191203== 5.10 ==
    192204* BUG FIX: Fatal error in Utilities library
  • e20r-members-list/trunk/class.e20r-members-list.php

    r2306383 r2458244  
    44Plugin URI: https://wordpress.org/plugins/e20r-members-list
    55Description: Extensible, sortable & bulk action capable members listing + export to CSV tool for Paid Memberships Pro.
    6 Version: 5.10
     6Version: 6.0
    77Author: Thomas Sjolshagen @ Eighty / 20 Results by Wicked Strong Chicks, LLC <[email protected]>
    88Author URI: https://eighty20results.com/thomas-sjolshagen/
     
    1111License:
    1212
    13     Copyright 2016 - 2020 (c) Eighty / 20 Results by Wicked Strong Chicks, LLC ([email protected])
     13    Copyright 2016 - 2021 (c) Eighty / 20 Results by Wicked Strong Chicks, LLC ([email protected])
    1414
    1515    This program is free software; you can redistribute it and/or modify
     
    3333
    3434if ( ! defined( 'E20R_MEMBERSLIST_VER' ) ) {
    35     define( 'E20R_MEMBERSLIST_VER', '5.10' );
     35    define( 'E20R_MEMBERSLIST_VER', '6.0' );
    3636}
    3737
  • e20r-members-list/trunk/class/members-list/class.bulk-cancel.php

    r2025537 r2458244  
    11<?php
    22/**
    3  * Copyright (c) 2018-2019 - Eighty / 20 Results by Wicked Strong Chicks.
     3 * Copyright (c) 2018-2021 - Eighty / 20 Results by Wicked Strong Chicks.
    44 * ALL RIGHTS RESERVED
    55 *
     
    2323
    2424class Bulk_Cancel {
    25    
     25
    2626    /**
    2727     * Instance of this class
     
    3636     */
    3737    private $operation = null;
    38    
     38
    3939    /**
    4040     * List of member IDs to update
     
    4343     */
    4444    private $members_to_update = array();
    45    
     45
    4646    /**
    4747     * Bulk_Cancel constructor (singleton)
     
    5151    private function __construct() {
    5252    }
    53    
     53
    5454    /**
    5555     * The __clone() method for Bulk_Cancel() (singleton class)
     
    5858     */
    5959    private function __clone() {}
    60    
     60
    6161    /**
    6262     * Process cancellations for all members/membership_ids
    6363     */
    6464    public function cancel() {
    65        
     65
    6666        // Process all User & level ID for the single action.
    6767        $failed = array();
    68        
     68
    6969        $utils = Utilities::get_instance();
    7070        $utils->log("Cancelling " . count( $this->members_to_update ) . " members");
    71        
     71
    7272        // Process all selected records/members
    7373        foreach ( $this->members_to_update as $key => $cancel_info ) {
    74            
     74
    7575            if ( false == $this->cancel_member( $cancel_info['user_id'], $cancel_info['level_id']  ) ) {
    7676                $failed[] = $cancel_info['user_id']; // FIXME: Add level info for multiple membership levels
    7777            }
    7878        }
    79        
     79
    8080        //Check for errors & display error banner if we got one.
    8181        if ( ! empty( $failed ) ) {
    82            
     82
    8383            $message = sprintf(
    8484                __( "Unable to cancel membership(s) for the following user IDs: %s", "e20r-members-list" ),
    8585                implode( ', ', $failed )
    8686            );
    87            
     87
    8888            if ( function_exists( 'pmpro_setMessage' ) ) {
    8989                pmpro_setMessage( $message, "error" );
     
    9191                global $msg;
    9292                global $msgt;
    93                
     93
    9494                $msg  = $message;
    9595                $msgt = 'error';
    9696            }
    97            
     97
    9898        }
    9999    }
    100    
     100
    101101    /**
    102102     * The cancel member action
     
    108108     */
    109109    public static function cancel_member( $id, $level_id = null ) {
    110        
     110
    111111        if ( function_exists( 'pmpro_cancelMembershipLevel' ) ) {
    112112            return pmpro_cancelMembershipLevel( $level_id, $id, 'admin_cancelled' );
     
    114114            return false;
    115115        }
    116        
     116
    117117    }
    118    
     118
    119119    /**
    120120     * Get or create an instance of the Bulk_Cancel class
     
    123123     */
    124124    public static function get_instance() {
    125        
     125
    126126        if ( is_null( self::$instance ) ) {
    127127            self::$instance = new self;
    128128        }
    129        
     129
    130130        return self::$instance;
    131131    }
    132    
     132
    133133    /**
    134134     * Set the list of members & their levels to update
     
    139139        $this->members_to_update = $member_info;
    140140    }
    141    
     141
    142142    /**
    143143     * Return the list of members being updated
  • e20r-members-list/trunk/class/members-list/class.bulk-update.php

    r2025537 r2458244  
    11<?php
    22/**
    3  * Copyright (c) 2018-2019 - Eighty / 20 Results by Wicked Strong Chicks.
     3 * Copyright (c) 2018-2021 - Eighty / 20 Results by Wicked Strong Chicks.
    44 * ALL RIGHTS RESERVED
    55 *
     
    2424
    2525class Bulk_Update {
    26    
     26
    2727    /**
    2828     * Instance of this class
     
    3131     */
    3232    private static $instance = null;
    33    
     33
    3434    /**
    3535     * Update operation to perform
     
    3838     */
    3939    private $operation = null;
    40    
     40
    4141    /**
    4242     * List of members to update
     
    4545     */
    4646    private $members_to_update = array();
    47    
     47
    4848    /**
    4949     * Bulk_Update constructor (singleton)
     
    5353    private function __construct() {
    5454    }
    55    
     55
    5656    /**
    5757     * __clone() method for Bulk_Update() (singleton class)
     
    6060     */
    6161    private function __clone(){}
    62    
     62
    6363    /**
    6464     * Get or create an instance of the Bulk_Update class
     
    6767     */
    6868    public static function get_instance() {
    69        
     69
    7070        if ( is_null( self::$instance ) ) {
    7171            self::$instance = new self;
    7272        }
    73        
     73
    7474        return self::$instance;
    7575    }
    76    
     76
    7777    /**
    7878     * Handle bulk update (for core member list columns). Triggers action for external bulk update activities/fields
     
    8181     */
    8282    public function update() {
    83        
     83
    8484        $utils         = Utilities::get_instance();
    8585        $update_errors = array();
    8686        $level_failed  = array();
    87        
     87
    8888        $utils->log("User count to update: " . count( $this->members_to_update) );
    8989        $utils->log("Request: " . print_r( $_REQUEST, true ));
    90        
     90
    9191        /**
    9292         * Process build-in edit fields for the specified members to update
    9393         */
    9494        foreach ( $this->members_to_update as $key => $user_info ) {
    95            
     95
    9696            $level_changed  = false;
    9797            $old_user_level = $utils->get_variable( "e20r-members-list-db_membership_id_{$user_info['user_id']}", 0 );
    9898            $new_user_level = $utils->get_variable( "e20r-members-list-new_membership_id_{$user_info['user_id']}", 0 );
    9999            $record_id      = $utils->get_variable( "e20r-members-list-db_record_id_{$user_info['user_id']}", 0 );
    100            
     100
    101101            if ( empty( $user_info['user_id'] ) ) {
    102102                $utils->log("User ID is NULL. Returning!" );
    103103                return false;
    104104            }
    105            
     105
    106106            $utils->log("Have to update level for {$user_info['user_id']}? {$new_user_level}" );
    107            
     107
    108108            // Update the membership level for the user we're processing
    109109            if ( !empty( $new_user_level) && $old_user_level !== $new_user_level ) {
    110                
     110
    111111                if ( false === $this->update_membership( $user_info['user_id'], $old_user_level, $new_user_level ) ) {
    112                    
     112
    113113                    // Add to list of failed updates
    114114                    $level_failed[] = array(
     
    122122                }
    123123            }
    124            
     124
    125125            $old_startdate = $utils->get_variable( "e20r-members-list-db_startdate_{$user_info['user_id']}", '' );
    126126            $new_startdate = $utils->get_variable( "e20r-members-list-new_startdate_{$user_info['user_id']}", '' );
    127            
     127
    128128            $utils->log("Have to update start date for {$user_info['user_id']}? N:{$new_startdate} vs O:{$old_startdate}" );
    129            
     129
    130130            if ( $old_startdate !== $new_startdate ) {
    131                
     131
    132132                if ( empty( $new_startdate ) ) {
    133133                    $utils->log("Error: Start date cannot be empty!, using old start date");
    134134                    $new_startdate = $old_startdate;
    135135                }
    136                
     136
    137137                if ( false === $this->update_date( 'startdate', $user_info['user_id'], $old_user_level, $new_user_level, $new_startdate, $record_id, $level_changed ) ) {
    138138                    $startdate_failed[] = array(
     
    144144                }
    145145            }
    146            
     146
    147147            $old_enddate = $utils->get_variable( "e20r-members-list-db_enddate_{$user_info['user_id']}", '' );
    148148            $new_enddate = $utils->get_variable( "e20r-members-list-new_enddate_{$user_info['user_id']}", '' );
    149            
     149
    150150            $utils->log("Have to update end date for {$user_info['user_id']}? N:{$new_enddate} vs O:{$old_enddate}");
    151            
     151
    152152            if ( $old_enddate !== $new_enddate ) {
    153                
     153
    154154                $utils->log("Updating end date to {$new_enddate}");
    155                
     155
    156156                if ( false === $this->update_date( 'enddate', $user_info['user_id'], $old_user_level, $new_user_level, $new_enddate, $record_id, $level_changed ) ) {
    157157                    $enddate_failed[] = array(
     
    163163                }
    164164            }
    165            
     165
    166166            $old_status = $utils->get_variable( "e20r-members-list-db_status_{$user_info['user_id']}", '' );
    167167            $new_status = $utils->get_variable( "e20r-members-list-new_status_{$user_info['user_id']}", '' );
    168            
     168
    169169            $utils->log("Have to update status for {$user_info['user_id']}? {$new_status}" );
    170            
     170
    171171            if ( $old_status !== $new_status ) {
    172                
     172
    173173                if ( false === $this->update_status( $record_id, $new_status ) ) {
    174174                    $status_failed[] = array(
     
    181181            }
    182182        }
    183        
     183
    184184        /**
    185185         * Trigger action for bulk update (allows external handling of bulk update if needed/desired)
     
    190190         */
    191191        do_action( 'e20r_memberslist_process_bulk_updates', $this->members_to_update );
    192        
     192
    193193        /**
    194194         * Error handling for build-in edit fields
    195195         */
    196196        $msg_template = __( 'Error updating data for %1$s (ID: %2$d). Could not update %3$s from %4$s to %5$s (current membership level: \'%6$s\')', 'e20r-members-list' );
    197        
     197
    198198        if ( ! empty( $level_failed ) ) {
    199            
     199
    200200            foreach ( $level_failed as $info ) {
    201201                $user           = get_user_by( 'ID', $info['user_id'] );
    202202                $new_user_level = pmpro_getLevel( $info['new_level'] );
    203203                $old_user_level = pmpro_getLevel( $info['old_level'] );
    204                
     204
    205205                $update_errors[] = sprintf(
    206206                    $msg_template,
     
    213213                );
    214214            }
    215            
    216         }
    217        
     215
     216        }
     217
    218218        if ( ! empty( $enddate_failed ) ) {
    219219            foreach ( $enddate_failed as $info ) {
    220220                $user       = get_user_by( 'ID', $info['user_id'] );
    221221                $user_level = pmpro_getLevel( $info['level_id'] );
    222                
     222
    223223                $update_errors[] = sprintf(
    224224                    $msg_template,
     
    232232            }
    233233        }
    234        
     234
    235235        if ( ! empty( $startdate_failed ) ) {
    236236            foreach ( $startdate_failed as $info ) {
    237237                $user       = get_user_by( 'ID', $info['user_id'] );
    238238                $user_level = pmpro_getLevel( $info['level_id'] );
    239                
     239
    240240                $update_errors[] = sprintf(
    241241                    $msg_template,
     
    249249            }
    250250        }
    251        
     251
    252252        if ( ! empty( $status_failed ) ) {
    253            
     253
    254254            foreach ( $status_failed as $info ) {
    255255                $user       = get_user_by( 'ID', $info['user_id'] );
    256256                $user_level = pmpro_getLevel( $info['level_id'] );
    257                
     257
    258258                $update_errors[] = sprintf(
    259259                    $msg_template,
     
    267267            }
    268268        }
    269        
     269
    270270        /**
    271271         * Add error messages to back-end info display
    272272         */
    273273        if ( ! empty( $update_errors ) ) {
    274            
     274
    275275            $utils->log("Generated " . count( $update_errors ) . " errors during bulk update!");
    276            
     276
    277277            foreach ( $update_errors as $e_msg ) {
    278278                $utils->log("Error: {$e_msg}");
    279279                $utils->add_message( $e_msg, 'error', 'backend' );
    280280            }
    281            
     281
    282282            // And return false (error)
    283283            return false;
    284284        }
    285        
     285
    286286        // All's good!
    287287        return true;
    288288    }
    289    
     289
    290290    /**
    291291     * Change the membership level for the specified User ID
     
    298298     */
    299299    public function update_membership( $user_id, $current_level_id, $new_level_id ) {
    300        
     300
    301301        // Execute the membership level change for the specified user ID/Level ID
    302302        if ( function_exists( 'pmpro_changeMembershipLevel' ) ) {
     
    306306        }
    307307    }
    308    
     308
    309309    /**
    310310     * Update the specified field name (a date field)
     
    321321     */
    322322    public function update_date( $field_name, $user_id, $current_level, $new_level, $new_date, $record_id = null, $use_new = false ) {
    323        
     323
    324324        $utils = Utilities::get_instance();
    325325        $date = null;
    326        
     326
    327327        // Make sure we received a valid date
    328328        if ( !empty($new_date) && false === $this->validate_date_format( $new_date, 'Y-m-d' ) ) {
    329            
     329
    330330            $user = get_user_by('ID', $user_id );
    331            
     331
    332332            $msg = sprintf(
    333333                __("Invalid date format for %s (record: %d/email: %s)", 'e20r-members-list' ),
     
    336336                $user->user_email
    337337            );
    338            
     338
    339339            $utils->log( $msg );
    340340            $utils->add_message( $msg, 'error', 'backend' );
    341            
     341
    342342            return false;
    343343        }
    344        
     344
    345345        global $wpdb;
    346        
     346
    347347        if ( true === $use_new ) {
    348348            $where        = array( 'membership_id' => $new_level, 'user_id' => $user_id, 'status' => 'active' );
     
    355355            $where_format = array( '%d', '%d', '%s' );
    356356        }
    357        
     357
    358358        if ( !empty( $new_date ) ) {
    359359            if ( true === apply_filters( 'e20r_memberslist_membership_starts_at_midnight', __return_true() ) ) {
     
    364364        }
    365365        $retval = $wpdb->update( $wpdb->pmpro_memberships_users, array( $field_name => $date ), $where, array( '%s' ), $where_format );
    366        
     366
    367367        if ( false === $retval ) {
    368368            return $retval;
    369369        }
    370        
     370
    371371        return true;
    372372    }
    373    
     373
    374374    /**
    375375     * Update the user's Membership status for the specified record
     
    381381     */
    382382    public function update_status( $record_id, $status ) {
    383        
     383
    384384        global $wpdb;
    385        
     385
    386386        $retval = $wpdb->update( $wpdb->pmpro_memberships_users, array( 'status' => $status ), array( 'id' => $record_id ), array( '%s' ), array( '%d' ) );
    387        
     387
    388388        if ( ! empty( $retval ) ) {
    389389            return true;
    390390        }
    391        
     391
    392392        return false;
    393393    }
    394    
     394
    395395    /**
    396396     * Set the list of members to update
     
    401401        $this->members_to_update = $member_info;
    402402    }
    403    
     403
    404404    /**
    405405     * Return the list of members being updated
     
    410410        return $this->members_to_update;
    411411    }
    412    
     412
    413413    /**
    414414     * Return the ongoing operation
     
    419419        return $this->operation;
    420420    }
    421    
     421
    422422    /**
    423423     * Configure/set the Operation for the Bulk Update
     
    428428        $this->operation = $operation;
    429429    }
    430    
     430
    431431    /**
    432432     * Test the date supplied for MySQL compliance
     
    440440     */
    441441    private function validate_date_format( $date, $format = 'Y-m-d' ) {
    442        
     442
    443443        $check_date = \DateTime::createFromFormat( $format, $date );
    444        
     444
    445445        return $check_date && $check_date->format( $format ) == $date;
    446446    }
  • e20r-members-list/trunk/class/members-list/class.export-members.php

    r2228121 r2458244  
    11<?php
    22/**
    3  * Copyright (c) 2018-2019 - Eighty / 20 Results by Wicked Strong Chicks.
     3 * Copyright (c) 2018-2021 - Eighty / 20 Results by Wicked Strong Chicks.
    44 * ALL RIGHTS RESERVED
    55 *
     
    2525
    2626class Export_Members {
    27    
     27
    2828    /**
    2929     * @var array $member_list
    3030     */
    3131    private $member_list = array();
    32    
     32
    3333    /**
    3434     * @var string|null $sql
    3535     */
    3636    private $sql = null;
    37    
     37
    3838    /**
    3939     * @var array $headers
    4040     */
    4141    private $headers = array();
    42    
     42
    4343    /**
    4444     * @var array $csv_headers
    4545     */
    4646    private $csv_headers = array();
    47    
     47
    4848    /**
    4949     * @var array $csv_rows
    5050     */
    5151    private $csv_rows = array();
    52    
     52
    5353    /**
    5454     * @var bool|null|string
    5555     */
    5656    private $file_name = null;
    57    
     57
    5858    /**
    5959     * Cached $member discount information
     
    6262     */
    6363    private $member_discount_info = null;
    64    
     64
    6565    /**
    6666     * Export_Members constructor.
     
    6969     */
    7070    public function __construct( $db_records ) {
    71        
     71
    7272        $this->member_list = $db_records;
    73        
     73
    7474        $this->file_name = $this->create_temp_file();
    75        
     75
    7676        $this->default_columns = array(
    7777            array( "wp_user", "ID" ),
     
    106106            array( "member_level", 'enddate' ),
    107107        );
    108        
     108
    109109        $this->default_columns = apply_filters( 'pmpro_members_list_csv_default_columns', $this->default_columns );
    110110        $this->default_columns = apply_filters( 'e20r-members-list-default-csv-columns', $this->default_columns );
    111        
     111
    112112        /**
    113113         * Map of Database column keys and CSV export column keys
     
    257257            )
    258258        );
    259        
     259
    260260        // Generate the header for the .csv file
    261261        $this->csv_header();
    262262        $this->set_upload_headers();
    263        
     263
    264264        /**
    265265         * Trigger the default 'e20r-members-list-load-export-value' filter handler first
     
    267267        add_filter( 'e20r-members-list-load-export-value', array( $this, 'load_export_value' ), - 1, 3 );
    268268    }
    269    
     269
    270270    /**
    271271     * Create the temporary file name for this export operation
     
    274274     */
    275275    private function create_temp_file() {
    276        
     276
    277277        // Generate a temporary file to store the data in.
    278278        $tmp_dir   = sys_get_temp_dir();
    279279        $file_name = tempnam( $tmp_dir, 'pmpro_ml_' );
    280        
     280
    281281        return $file_name;
    282282    }
    283    
     283
    284284    /**
    285285     * Create the export file header (DB columns)
    286286     */
    287287    private function csv_header() {
    288        
     288
    289289        $utils = Utilities::get_instance();
    290290        $level = $utils->get_variable( 'membership_id', '' );
    291        
     291
    292292        $extra_cols = apply_filters( "pmpro_members_list_csv_extra_columns", array() );
    293        
     293
    294294        if ( ! empty( $extra_cols ) ) {
    295            
     295
    296296            foreach ( $extra_cols as $col_header => $callback ) {
    297297                // $this->header_map[]               = $col_header;
     
    304304            }
    305305        }
    306        
     306
    307307        $header_list       = apply_filters( 'pmpro_members_list_csv_heading', implode( ',', array_keys( $this->header_map ) ) );
    308308        $this->csv_headers = array_map( 'trim', explode( ',', $header_list ) );
    309        
     309
    310310        $utils->log( "Using " . count( $this->csv_headers ) . " header columns" );
    311311    }
    312    
     312
    313313    /**
    314314     * Set headers for .CSV file upload
    315315     */
    316316    private function set_upload_headers() {
    317        
     317
    318318        $this->headers[] = "Content-Type: text/csv";
    319319        $this->headers[] = "Cache-Control: max-age=0, no-cache, no-store";
     
    323323        $this->headers   = apply_filters( 'e20r-memberslist-http-headers', $this->headers );
    324324    }
    325    
     325
    326326    /**
    327327     * Clear old temporary files
    328328     */
    329329    public static function clear_temp_files() {
    330        
     330
    331331        $temp_dir_name = sys_get_temp_dir();
    332332        $utils         = Utilities::get_instance();
    333        
     333
    334334        $files = glob( "{$temp_dir_name}/pmpro_ml_*.csv" );
    335335        $now   = current_time( 'timestamp' );
    336        
     336
    337337        $utils->log( "Notice: Clearing temporary export files (if needed)" );
    338        
     338
    339339        foreach ( $files as $file_name ) {
    340            
     340
    341341            if ( is_file( $file_name ) ) {
    342                
     342
    343343                if ( $now - filemtime( $file_name ) >= DAY_IN_SECONDS ) { // Delete after 1 day
    344344                    unlink( $file_name );
     
    347347        }
    348348    }
    349    
     349
    350350    /**
    351351     * Fetches the data for the export operation
    352352     */
    353353    public function get_data_list() {
    354        
     354
    355355        $utils = Utilities::get_instance();
    356356        $utils->log( "Headers have been sent already..?!? " . ( headers_sent() ? 'Yes' : 'No' ) );
    357        
     357
    358358        /**
    359359         * Filter to set max number of records to process at a time
     
    370370         */
    371371        $max_users_per_loop = apply_filters( 'pmpro_set_max_user_per_export_loop', 2000 );
    372        
     372
    373373        /**
    374374         * Pre-export actions
     
    381381         */
    382382        do_action( 'pmpro_before_members_list_csv_export', $this->member_list );
    383        
     383
    384384        $extra_columns = apply_filters( "pmpro_members_list_csv_extra_columns", array() );
    385        
     385
    386386        $this->add_csv_header_to_file();
    387        
     387
    388388        $i_start     = 0;
    389389        $iterations  = 1;
    390390        $users_found = count( $this->member_list );
    391        
     391
    392392        if ( $users_found >= $max_users_per_loop ) {
    393393            $iterations = ceil( $users_found / $max_users_per_loop );
    394394        }
    395        
     395
    396396        $start      = current_time( 'timestamp' );
    397397        $end        = 0;
    398398        $time_limit = (int) get_cfg_var( 'max_execution_time' );
    399        
     399
    400400        // Split up the export operation in multiple rounds/iterations
    401401        for ( $ic = 1; $ic <= $iterations; $ic ++ ) {
    402            
     402
    403403            // Try to avoid timing out during the export operation
    404404            if ( 0 !== $end ) {
    405                
     405
    406406                $iteration_diff = $end - $start;
    407407                $new_time_limit = ceil( $iteration_diff * $iterations * 1.2 );
    408                
     408
    409409                if ( $time_limit < $new_time_limit ) {
    410410                    $time_limit = $new_time_limit;
     
    412412                }
    413413            }
    414            
     414
    415415            $start = current_time( 'timestamp' );
    416            
     416
    417417            $utils->log( "For iterations: {$i_start} -> " . ( $i_start + $max_users_per_loop ) );
    418            
     418
    419419            $member_list = array_slice( $this->member_list, $i_start, $max_users_per_loop );
    420            
     420
    421421            $utils->log( "Will process " . count( $member_list ) . " member records in iteration {$ic}" );
    422            
     422
    423423            // Increment starting position
    424424            if ( 0 < $iterations ) {
    425425                $i_start += $max_users_per_loop;
    426426            }
    427            
     427
    428428            foreach ( $member_list as $member ) {
    429                
     429
    430430                $csv_record = array();
    431                
     431
    432432                // Cast the Member array to an object
    433433                $member = (object) $member;
    434                
     434
    435435                /**
    436436                 * Fetch any user metadata for the user
    437437                 */
    438438                $member->meta_values = $this->load_user_meta( $member->ID );
    439                
     439
    440440                /**
    441441                 * Fetch/update the CSV export entry for the $member
     
    446446                 */
    447447                $csv_record = apply_filters( 'e20r-members-list-load-export-value', $csv_record, $member );
    448                
     448
    449449                // Add data from extra columns
    450450                if ( ! empty( $extra_columns ) ) {
    451                    
     451
    452452                    foreach ( $extra_columns as $col_heading => $callback ) {
    453                        
     453
    454454                        $val = call_user_func( $callback, $member, $col_heading );
    455455                        $val = ! empty( $val ) ? $val : null;
    456                        
     456
    457457                        $csv_record[ $col_heading ] = $this->enclose( $val );
    458458                    }
    459459                }
    460                
     460
    461461                // $utils->log( "Exportable info : " . print_r( $csv_record, true ) );
    462                
     462
    463463                // Add the data to the list of
    464464                $this->csv_rows[] = $csv_record;
    465                
    466             }
    467            
     465
     466            }
     467
    468468            wp_cache_flush();
    469            
     469
    470470            //need to increase max running time?
    471471            $end = current_time( 'timestamp' );
    472472        }
    473        
     473
    474474        do_action( 'pmpro_after_members_list_csv_export' );
    475475    }
    476    
     476
    477477    /**
    478478     * Add the CSV header to the (new) file
    479479     */
    480480    private function add_csv_header_to_file() {
    481        
     481
    482482        $utils = Utilities::get_instance();
    483        
     483
    484484        // Open our designated temporary file
    485485        $file_handle = fopen( $this->file_name, 'a' );
    486486        $header_type = 'header_key';
    487        
     487
    488488        $utils->log( "Adding " . count( $this->csv_headers ) . " header columns to {$this->file_name}" );
    489        
     489
    490490        //Add the CSV header to the file
    491491        fprintf( $file_handle, '%s',
     
    497497                    $this->csv_headers )
    498498            ) . "\n" );
    499        
     499
    500500        // Close the CSV file for now
    501501        fclose( $file_handle );
    502502    }
    503    
     503
    504504    /**
    505505     * Returns the expected header key for the requested DB Key
     
    512512     */
    513513    private function map_keys( $key, $requested, $column_type = null ) {
    514        
     514
    515515        $utils = Utilities::get_instance();
    516        
     516
    517517        foreach ( $this->header_map as $map_key => $field_def ) {
    518            
     518
    519519            if ( $key === $map_key ) {
    520520                return $field_def[ $requested ];
    521521            }
    522            
     522
    523523            if ( 'header_key' === $requested && $field_def['header_key'] == $key ) {
    524                
     524
    525525                return $map_key;
    526526            }
    527            
     527
    528528            if ( 'db_key' === $requested && $field_def['db_key'] == $key ) {
    529                
    530                
     529
     530
    531531                if ( 'username' === $key ) {
    532532                    return $map_key;
    533533                }
    534                
     534
    535535                return $field_def[ $requested ];
    536536            }
    537537        }
    538        
     538
    539539        $utils->log( "No value (key) found for {$requested} key {$key}" );
    540        
     540
    541541        return null;
    542542    }
    543    
     543
    544544    /**
    545545     * Return all of the user's metadata that we (may) care about
     
    550550     */
    551551    private function load_user_meta( $user_id ) {
    552        
     552
    553553        $meta_values = null;
    554        
     554
    555555        // Returns array of meta keys containing array(s) of meta_values.
    556556        $um_values = get_user_meta( $user_id );
    557        
     557
    558558        // Process user metadata
    559559        if ( ! empty( $um_values ) ) {
    560            
     560
    561561            $meta_values = new \stdClass();
    562            
     562
    563563            foreach ( $um_values as $key => $value ) {
    564                
     564
    565565                $meta_values->{$key} = isset( $value[0] ) ? $value[0] : null;
    566566            }
    567567        }
    568        
     568
    569569        return $meta_values;
    570        
    571     }
    572    
     570
     571    }
     572
    573573    /**
    574574     * Enclose the data we're adding to the export file
     
    581581        return "\"" . str_replace( "\"", "\\\"", $text ) . "\"";
    582582    }
    583    
     583
    584584    /**
    585585     * @param array     $csv_record
     
    589589     */
    590590    public function load_export_value( $csv_record, $member ) {
    591        
     591
    592592        $utils = Utilities::get_instance();
    593        
     593
    594594        $datetime_format = $this->set_datetime_format();
    595595        $level           = $utils->get_variable( 'membership_id', '' );
    596        
     596
    597597        // $utils->log( "For member: " . print_r( $member, true ) );
    598        
     598
    599599        // Process the membership data (by column)
    600600        foreach ( $this->default_columns as $field_def ) {
    601            
     601
    602602            $column_type  = $field_def[0];
    603603            $column_name  = $this->map_keys( $field_def[1], 'db_key', $column_type );
     
    607607                $column_type
    608608            );
    609            
     609
    610610            // Process Join/Start dates for membership
    611611            if ( in_array( $column_name, array( 'user_registered', 'startdate' ) ) ) {
    612                
     612
    613613                $column_value = date(
    614614                    $datetime_format,
     
    618618                );
    619619            }
    620            
     620
    621621            // Process End of membership column
    622622            if ( 'enddate' == $column_name ) {
    623                
     623
    624624                $enddate_value = $column_value;
    625                
     625
    626626                if ( ! is_null( $member->membership_id ) && ! empty( $column_value ) ) {
    627                    
     627
    628628                    // Membership is terminated or about to be terminated
    629629                    if ( in_array( $level, array( "oldmembers", "expired", 'cancelled' ) ) &&
    630630                         ( ! empty( $column_value ) && '0000-00-00 00:00:00' !== $column_value ) ) {
    631                        
     631
    632632                        $enddate_value = apply_filters( "pmpro_memberslist_expires_column", date( $datetime_format, strtotime( $column_value, current_time( 'timestamp' ) ) ), $member );
    633                        
     633
    634634                    }
    635                    
     635
    636636                    if ( ! empty( $member->membership_id ) && ( empty( $column_value ) || '0000-00-00 00:00:00' === $column_value ) ) {
    637637                        $enddate_value = apply_filters( "pmpro_memberslist_expires_column", null, $member );
    638638                    }
    639                    
     639
    640640                    if ( ! empty( $member->membership_id ) && ( ! empty( $column_value ) && '0000-00-00 00:00:00' !== $column_value ) ) {
    641641                        $enddate_value = date( $datetime_format, strtotime( $column_value, current_time( 'timestamp' ) ) );
    642642                    }
    643                    
     643
    644644                    // Save record info for the column
    645645                    $column_value = apply_filters( 'e20r-members-list-expires-col-value', $enddate_value, $member );;
    646646                }
    647647            }
    648            
     648
    649649            /**
    650650             * Fetch the discount code data for this user/member
    651651             */
    652652            if ( ! empty( $member->code_id ) && empty( $this->member_discount_info ) ) {
    653                
     653
    654654                $utils->log( "Grab the discount code data for {$member->ID}/{$member->code_id}" );
    655                
     655
    656656                $this->member_discount_info = self::get_pmpro_discount_code(
    657657                    $member->code_id,
     
    660660                );
    661661            }
    662            
     662
    663663            /**
    664664             * Fetch the discount code value for the user/member
    665665             */
    666666            if ( $column_type === 'pmpro_discount_code' && ! empty( $this->member_discount_info ) ) {
    667                
     667
    668668                $param        = "pmpro_discount_{$column_name}";
    669669                $column_value = $this->member_discount_info->{$param};
    670670            }
    671            
    672            
     671
     672
    673673            if ( empty( $column_value ) ) {
    674674                $column_value = null;
    675675            }
    676            
     676
    677677            // $utils->log( "Saving {$column_name} (looked for {$field_def[1]}): " . print_r( $column_value, true ) );
    678            
     678
    679679            // Save the entry info
    680680            $csv_record[ $column_name ] = $this->enclose( $column_value );
    681681        }
    682        
     682
    683683        // Clear the Discount Info (for the member)
    684684        $this->member_discount_info = null;
    685        
     685
    686686        return $csv_record;
    687687    }
    688    
     688
    689689    /**
    690690     * Configure the format to use for the export datetime value
     
    693693     */
    694694    private function set_datetime_format() {
    695        
     695
    696696        /**
    697697         * Filter to the format for the date (default is the WordPress General Setting value for Date)
     
    705705        $date_format = apply_filters( 'pmpro_memberslist_csv_dateformat', get_option( 'date_format' ) );
    706706        $date_format = apply_filters( 'e20r-members-list-csv-fateformat', $date_format );
    707        
     707
    708708        /**
    709709         * Filter to the format for the time (default is the WordPress General Setting value for Time)
     
    716716         */
    717717        $time_format = apply_filters( 'e20r-members-list-csv-timeformat', get_option( 'time_format' ) );
    718        
     718
    719719        // Assume that we want a valid MySQL DateTime format if date is Y-m-d
    720720        if ( 'Y-m-d' == $date_format && 'H:i' == $time_format ) {
     
    723723            $expected_format = "{$date_format} {$time_format}";
    724724        }
    725        
     725
    726726        /**
    727727         * Filter to the format for the time (default is the WordPress General Setting value for Time)
     
    736736         */
    737737        $datetime_format = apply_filters( 'e20r-members-list-csv-datetime-format', $expected_format, $date_format, $time_format );
    738        
     738
    739739        return $datetime_format;
    740740    }
    741    
     741
    742742    /**
    743743     * Return a value for the specified column (name)
     
    750750     */
    751751    private function get_column_value( $member, $column_name, $column_type ) {
    752        
     752
    753753        $utils       = Utilities::get_instance();
    754754        $dc_col_name = "pmpro_discount_code_";
    755        
     755
    756756        switch ( $column_type ) {
    757            
     757
    758758            case 'wp_user':
    759759            case 'member_level':
     
    762762                $column_value = isset( $member->{$column_name} ) ? $member->{$column_name} : null;
    763763                break;
    764            
     764
    765765            case 'pmpro_discount_code':
    766766                $dc_col_name  = "{$dc_col_name}{$column_name}";
    767767                $column_value = isset( $member->{$column_name} ) ? $member->{$column_name} : null;
    768768                break;
    769            
     769
    770770            case 'meta_values':
    771771                $column_value = isset( $member->meta_values->{$column_name} ) ? $member->meta_values->{$column_name} : null;
    772772                break;
    773            
     773
    774774            default:
    775775                $utils->log( "Using default type (type = {$column_type}) for {$column_name}" );
    776776                $column_value = isset( $member->{$column_type}->{$column_name} ) ? $member->{$column_type}->{$column_name} : null;
    777                
     777
    778778                /**
    779779                 * Let 3rd party define the value to use for a 3rd party defined default column
     
    790790                $column_value = apply_filters( 'e20r-members-list-set-default-column-value', $column_value, $column_name, $column_type, $member );
    791791        }
    792        
     792
    793793        return $column_value;
    794794    }
    795    
     795
    796796    /**
    797797     * Fetch discount code (ID and code) for the code ID/User ID/Level ID combination
     
    804804     */
    805805    public static function get_pmpro_discount_code( $code_id, $user_id, $level_id ) {
    806        
     806
    807807        global $wpdb;
    808        
     808
    809809        $disSql = $wpdb->prepare( "
    810810                SELECT
     
    819819            $user_id
    820820        );
    821        
     821
    822822        $pmpro_discount_code = $wpdb->get_row( $disSql );
    823        
     823
    824824        // Make sure there's data for the discount code info
    825825        if ( empty( $pmpro_discount_code ) ) {
     
    829829            $pmpro_discount_code              = $empty_dc;
    830830        }
    831        
     831
    832832        return $pmpro_discount_code;
    833833    }
    834    
     834
    835835    /**
    836836     * Save the data rows to the temporary Export file
    837837     */
    838838    public function save_data_for_export() {
    839        
     839
    840840        $utils = Utilities::get_instance();
    841841        $utils->log( "Saving " . count( $this->csv_rows ) . " records to {$this->file_name}. " );
    842        
     842
    843843        $fh = fopen( $this->file_name, 'a' );
    844        
     844
    845845        /**
    846846         * @var $row_data -> $csv_entry[ $col_heading ] = $this->enclose( $val );
    847847         */
    848848        foreach ( $this->csv_rows as $row_id => $row_data ) {
    849            
     849
    850850            $data = array();
    851            
     851
    852852            foreach ( $this->csv_headers as $col_key ) {
    853                
     853
    854854                /*
    855855                if ( 'ID' == $col_key ) {
     
    857857                }
    858858                */
    859                
     859
    860860                $col_name = $this->map_keys( $col_key, 'db_key' );
    861                
     861
    862862                $value  = isset( $row_data[ $col_name ] ) ? $row_data[ $col_name ] : $this->enclose( null );
    863863                $data[] = $value;
    864864            }
    865            
     865
    866866            $file_line = implode( ',', $data ) . "\r\n";
    867867            fprintf( $fh, '%s', $file_line );
    868868        }
    869        
     869
    870870        fclose( $fh );
    871871        $utils->log( "Saved data to {$this->file_name}" );
    872872    }
    873    
     873
    874874    /**
    875875     * Send the .CSV to the requesting browser
    876876     */
    877877    public function return_content() {
    878        
     878
    879879        $utils = Utilities::get_instance();
    880880        $utils->log( "Headers have been sent already..?!? " . ( headers_sent() ? 'Yes' : 'No' ) );
     
    882882        // Send the data to the recipient browser
    883883        if ( ! empty( $this->headers ) && false === headers_sent() && file_exists( $this->file_name ) ) {
    884            
     884
    885885            $sent_content = ob_get_clean();
    886886            $utils->log("Browser received: " . print_r( $sent_content, true) );
    887            
     887
    888888            if ( version_compare( phpversion(), '5.3.0', '>' ) ) {
    889                
     889
    890890                //Clear the file cache for the export file
    891891                clearstatcache( true, $this->file_name );
     
    894894                clearstatcache();
    895895            }
    896            
     896
    897897            //Set the download size for the file
    898898            $this->headers[] = "Content-Length: " . filesize( $this->file_name );
    899            
     899
    900900            //Set transmission (PHP) headers
    901901            foreach ( $this->headers as $header ) {
    902902                header( $header . "\r\n" );
    903903            }
    904            
     904
    905905            // Disable compression for the duration of file download
    906906            if ( ini_get( 'zlib.output_compression' ) ) {
    907907                ini_set( 'zlib.output_compression', 'Off' );
    908908            }
    909            
     909
    910910            // Bug fix for Flywheel Hosted like hosts where fpassthru() is disabled
    911911            if ( function_exists( 'fpassthru' ) ) {
     
    917917                readfile( $this->file_name );
    918918            }
    919            
     919
    920920            // Remove the temp file
    921921            unlink( $this->file_name );
    922922            exit();
    923            
     923
    924924        } else {
    925925            $msg = __( "Unable to send the .CSV file to your browser!", 'e20r-members-list' );
     
    928928        }
    929929    }
    930    
     930
    931931    /**
    932932     * Returns the column name to use from the specified $header_name
     
    937937     */
    938938    private function map_header_to_column( $header_name ) {
    939        
     939
    940940        return isset( $this->header_map[ $header_name ]['header_key'] ) ? $this->header_map[ $header_name ]['header_key'] : null;
    941941    }
  • e20r-members-list/trunk/class/members-list/class.members-list-page.php

    r2228121 r2458244  
    11<?php
    22/**
    3  * Copyright (c) 2018-2019 - Eighty / 20 Results by Wicked Strong Chicks.
     3 * Copyright (c) 2018-2021 - Eighty / 20 Results by Wicked Strong Chicks.
    44 * ALL RIGHTS RESERVED
    55 *
     
    2424
    2525class Members_List_Page {
    26    
     26
    2727    /**
    2828     * Instance of the Members_List_Page class (Singleton)
     
    3131     */
    3232    private static $instance = null;
    33    
     33
    3434    /**
    3535     * Holds the list of members (Members_List class)
     
    3737     */
    3838    public $member_list;
    39    
     39
    4040    /**
    4141     * Holds the standard Utilities class
     
    4444     */
    4545    private $utils;
    46    
     46
    4747    /**
    4848     * Members_List_Page constructor. Loads required menu(s) & screen options
     
    5050    private function __construct() {
    5151    }
    52    
     52
    5353    /**
    5454     * Creates or returns an instance of the Members_List_Page class.
     
    5757     */
    5858    public static function get_instance() {
    59        
     59
    6060        if ( null === self::$instance ) {
    6161            self::$instance = new self;
    6262        }
    63        
     63
    6464        return self::$instance;
    6565    }
    66    
     66
    6767    /**
    6868     * Removes the old Member List page & appends a new one to the "Memberships" admin bar node
    6969     */
    7070    public static function admin_bar_menu() {
    71        
     71
    7272        $is_pmpro_v2 = version_compare( PMPRO_VERSION, '2.0', 'ge' );
    73        
     73
    7474        if ( true === $is_pmpro_v2 ) {
    7575            return;
    7676        }
    77        
     77
    7878        global $wp_admin_bar;
    79        
    80        
     79
     80
    8181        if ( ! is_admin_bar_showing() || ( ! is_super_admin() && ( ! current_user_can( 'manage_options' ) ) && ! current_user_can( 'pmpro_memberslist' ) && ! current_user_can( 'e20r_memberslist' ) ) ) {
    8282            if ( ! is_null( self::$instance ) ) {
    8383                self::$instance->utils->log( "Unable to change admin bar (wrong capabilities for user)" );
    8484            }
    85            
     85
    8686            return;
    8787        }
    88        
     88
    8989        $wp_admin_bar->remove_menu( 'pmpro-members-list' );
    9090        $wp_admin_bar->remove_node( 'pmpro-members-list' );
    91        
     91
    9292        //Add the (new) Members List page to the admin_bar menu
    9393        $wp_admin_bar->add_menu( array(
     
    102102        ) );
    103103    }
    104    
     104
    105105    /**
    106106     * Screen Option option(s) for the Members List page.
     
    112112     */
    113113    public static function set_screen( $status, $option, $value ) {
    114        
     114
    115115        self::$instance->utils->log( "Saving screen option (page: {$option})? {$value} vs {$status}" );
    116        
     116
    117117        if ( 'per_page' == $option ) {
    118118            return $value;
    119119        }
    120        
     120
    121121        return $status;
    122122    }
    123    
     123
    124124    /**
    125125     * Load Action and Filter hooks for the Members List page
    126126     */
    127127    public function load_hooks() {
    128        
     128
    129129        $this->utils = Utilities::get_instance();
    130        
     130
    131131        // Filters
    132132        add_filter( 'set-screen-option', array( $this, 'set_screen' ), 10, 3 );
    133133        add_filter( 'set_url_scheme', array( $this, 'add_to_pagination' ), 10, 3 );
    134        
     134
    135135        // Actions
    136136        add_action( 'admin_menu', array( $this, 'plugin_menu' ), 9999 );
     
    138138        // add_action( 'admin_bar_menu', array( $this, 'admin_bar_menu' ), 9999 );
    139139        add_action( 'admin_enqueue_scripts', array( $this, 'load_scripts_styles' ) );
    140        
    141     }
    142    
     140
     141    }
     142
    143143    /**
    144144     * Load the custom CSS and JavaScript for the Members List
    145145     */
    146146    public function load_scripts_styles( $hook_suffix ) {
    147        
     147
    148148        if ( is_admin() && ( ! defined( 'DOING_AJAX' ) || false == DOING_AJAX ) && 1 === preg_match( '/(pmpro|e20r)-memberslist/', $hook_suffix ) ) {
    149            
     149
    150150            wp_enqueue_style( 'jquery-ui', '//cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.css' );
    151151            wp_enqueue_script( 'jquery-ui-datepicker' );
    152            
     152
    153153            wp_enqueue_style( 'e20r-memberslist-page', plugins_url( "/css/e20r-memberslist-page.css", __FILE__ ), array( 'pmpro_admin' ), E20R_MEMBERSLIST_VER );
    154            
     154
    155155            wp_register_script( 'e20r-memberslist-page', plugins_url( "/js/e20r-memberslist-page.js", __FILE__ ), array( 'jquery' ), E20R_MEMBERSLIST_VER, true );
    156            
     156
    157157            // $is_pmpro_v2 = version_compare( PMPRO_VERSION, '2.0', 'ge' );
    158158            // $url         = ( false === $is_pmpro_v2 ) ? 'e20r-memberslist' : 'pmpro-memberslist';
    159            
     159
    160160            wp_localize_script( 'e20r-memberslist-page', 'e20rml',
    161161                array(
     
    168168                )
    169169            );
    170            
     170
    171171            wp_enqueue_script( 'e20r-memberslist-page' );
    172172        }
    173173    }
    174    
     174
    175175    /**
    176176     * Point Members List menu handler(s) to this plugin
    177177     */
    178178    public function plugin_menu() {
    179      
     179
    180180        $this->utils->log( "Headers sent? " . ( headers_sent() ? 'Yes' : 'No' ) );
    181        
    182        
     181
     182
    183183        $pmpro_menu_slug = 'pmpro-membershiplevels';
    184184        $is_pmpro_v2     = version_compare( PMPRO_VERSION, '2.0', 'ge' );
    185        
     185
    186186        if ( defined( 'PMPRO_VERSION' ) && $is_pmpro_v2 ) {
    187187            $pmpro_menu_slug = 'pmpro-dashboard';
    188188        }
    189        
     189
    190190        $this->utils->log( "Remove the default members list page.. (under: {$pmpro_menu_slug})" );
    191        
     191
    192192        // Just replace the action that loads the PMPro Members List
    193        
     193
    194194        $hookname = get_plugin_page_hookname( 'pmpro-memberslist', $pmpro_menu_slug );
    195195        $this->utils->log("Found hook name: {$hookname}. Sent yet? " . (headers_sent() ? 'Yes' : 'No') );
     
    197197        add_action( $hookname, array( $this, 'memberslist_settings_page' ), 11 );
    198198        add_action( "load-memberships_page_pmpro-memberslist", array( $this, 'screen_option' ), 9999 );
    199        
     199
    200200        /*
    201201        // Unhook old members list functionality (pre v2.0 of PMPro)
    202202        if ( false == ( $page = remove_submenu_page( $pmpro_menu_slug, 'pmpro-memberslist' ) ) ) {
    203            
     203
    204204            $this->utils->log( "Unable to remove the default membership levels page!" );
    205205            pmpro_setMessage( __( 'Error while attempting to reassign member list menu', E20R_Members_List::plugin_slug ), 'error' );
    206            
     206
    207207            return;
    208208        }
    209        
     209
    210210        // Load the (new) WP_Table_List based Members List
    211211        $hook = add_submenu_page(
     
    217217            array( $this, 'memberslist_settings_page' )
    218218        );
    219        
     219
    220220        // Show error if we're unable to update the members list
    221221        if ( false === $hook ) {
    222            
     222
    223223            $this->utils->log( "Unable to load the replacement Members List page!" );
    224224            pmpro_setMessage( __( "Unable to load Members List menu entry", "e20r-members-list" ), "error" );
    225            
     225
    226226            return;
    227227        }
    228        
     228
    229229        // Process the screen option
    230230        add_action( "load-memberships_page_pmpro-memberslist", array( $this, 'screen_option' ), 9999 );
    231231        */
    232232    }
    233    
     233
    234234    /**
    235235     * Add parameters to limit/include records to any members list page URI
     
    242242     */
    243243    public function add_to_pagination( $url, $scheme, $original_scheme ) {
    244        
     244
    245245        $page = $this->utils->get_variable( 'page', '' );
    246        
     246
    247247        if ( 1 === preg_match( "/{$_SERVER['HTTP_HOST']}\/wp-admin\/admin.php\?page=pmpro-memberslist/i", $url ) ) {
    248            
     248
    249249            $arg_list = array();
    250            
     250
    251251            $level = $this->utils->get_variable( 'level', '' );
    252252            $find  = $this->utils->get_variable( 'find', '' );
    253            
     253
    254254            if ( ! empty( $level ) ) {
    255255                $arg_list['level'] = $level;
    256256            }
    257            
     257
    258258            if ( ! empty( $find ) ) {
    259259                $arg_list['find'] = $find;
    260260            }
    261            
     261
    262262            /**
    263263             * @filter e20r_memberslist_pagination_args - Add filtering to the URI (to preserve it for pagination ,etc)
     
    266266             */
    267267            $arg_list = apply_filters( 'e20r_memberslist_pagination_args', $arg_list );
    268            
     268
    269269            // Encode the new URI variables
    270270            foreach ( $arg_list as $a_key => $value ) {
    271271                $arg_list[ $a_key ] = urlencode_deep( urldecode_deep( $value ) );
    272272            }
    273            
     273
    274274            $url = add_query_arg( $arg_list, $url );
    275275        }
    276        
     276
    277277        return $url;
    278278    }
    279    
     279
    280280    /**
    281281     * Configure options to use for "Screen Options" on Members_List_Page page.
    282282     */
    283283    public function screen_option() {
    284        
     284
    285285        $options = 'per_page';
    286        
     286
    287287        $args = array(
    288288            'label'   => _x( "Members per page", "members per page (screen options)", "e20r-members-list" ),
     
    290290            'option'  => $options,
    291291        );
    292        
     292
    293293        add_screen_option( $options, $args );
    294        
     294
    295295        $this->member_list = new Members_List();
    296296    }
    297    
     297
    298298    /**
    299299     * Load the e20rMembersList page content
    300300     */
    301301    public function memberslist_settings_page() {
    302        
     302
    303303        $this->utils->log("Have we sent content? " . (headers_sent() ? 'yes' : 'no'));
     304
     305        if ( ! function_exists( 'pmpro_loadTemplate' ) ) {
     306            $this->utils->log("Fatal: Paid Memberships Pro is not loaded on site!");
     307            return "";
     308        }
     309
    304310        global $pmpro_msg;
    305311        global $pmpro_msgt;
    306        
     312
    307313        // TODO: Fix this to match required request variables.
    308314        $search = $this->utils->get_variable( 'find', '' );
    309315        $level  = $this->utils->get_variable( 'level', '' );
    310        
     316
    311317        echo pmpro_loadTemplate( 'admin_header', 'local', 'adminpages' );
    312        
     318
    313319        $search_array = apply_filters( 'e20r_memberslist_exportcsv_search_args', array(
    314320                'action' => 'memberslist_csv',
     
    318324            )
    319325        );
    320        
     326
    321327        $csv_url = add_query_arg(
    322328            $search_array,
    323329            get_admin_url( get_current_blog_id(), 'admin-ajax.php' )
    324330        );
    325        
     331
    326332        $e20r_error_msgs   = $this->utils->get_message( 'error' );
    327333        $e20r_warning_msgs = $this->utils->get_message( 'warning' );
    328334        $e20r_info_msgs    = $this->utils->get_message( 'info' );
    329        
     335
    330336        $top_list = array(
    331337            'active' => __( 'Active Members', E20R_Members_List::plugin_slug ),
    332338            'all'    => __( 'All Members', E20R_Members_List::plugin_slug ),
    333339        );
    334        
     340
    335341        $bottom_list = array(
    336342            'cancelled'  => __( 'Cancelled Members', 'paid-membership-pro' ),
     
    338344            'oldmembers' => __( 'Old Members', 'paid-membership-pro' ),
    339345        );
    340        
     346
    341347        $level_list = array();
    342        
    343         $list = function_exists( 'pmpro_getAllLevels' ) ? pmpro_getAllLevels( true, true ) : array();
    344        
     348
     349        $list = function_exists( 'pmpro_getAllLevels' ) ?
     350                pmpro_getAllLevels( true, true ) :
     351                array();
     352
    345353        foreach ( $list as $item ) {
    346354            $level_list[ $item->id ] = $item->name;
    347355        }
    348        
     356
    349357        $option_list = $top_list + $level_list + $bottom_list;
    350        
     358
    351359        if ( ! empty( $pmpro_msg ) ) { ?>
    352360
     
    383391                        $label      = __( 'Update List', E20R_Members_List::plugin_slug );
    384392                        $button_def = 'button';
    385                        
     393
    386394                        if ( isset( $_REQUEST['find'] ) && ! empty( $_REQUEST['find'] ) ) {
    387                            
     395
    388396                            $label      = __( 'Clear Search', E20R_Members_List::plugin_slug );
    389397                            $button_def .= " button-primary";
     
    421429            </form>
    422430        </div>
    423        
     431
    424432        <?php
    425433        echo pmpro_loadTemplate( 'admin_footer', 'local', 'adminpages' );
    426434    }
    427    
     435
    428436    /**
    429437     * Deactivated __clone() method for the Members_List_Page class
     
    431439    private function __clone() {
    432440    }
    433    
     441
    434442}
  • e20r-members-list/trunk/class/members-list/class.members-list.php

    r2306383 r2458244  
    33 * License:
    44
    5     Copyright 2016-2019 - Eighty / 20 Results by Wicked Strong Chicks, LLC ([email protected])
     5    Copyright 2016-2021 - Eighty / 20 Results by Wicked Strong Chicks, LLC ([email protected])
    66
    77    This program is free software; you can redistribute it and/or modify
     
    7373     */
    7474    private $total_members_found = null;
     75
     76    /**
     77     * The total number of records in the PMPro Membership DB
     78     *
     79     * @var int $total_member_records
     80     */
     81    private $total_member_records = 0;
     82
     83    /**
     84     * The status of the membership when searching for totals
     85     *
     86     * @var string $membership_status
     87     */
     88    private $membership_status = 'active';
     89
    7590    /**
    7691     * The completed SQL query used to generate the membership list
     
    176191        $this->action = $this->utils->get_variable( 'action', '' );
    177192
     193        if ( ! empty( $level ) ) {
     194            switch ($level) {
     195                case 'cancelled':
     196                    $this->membership_status = array( 'cancelled' );
     197                    break;
     198                case 'expired':
     199                    $this->membership_status = array( 'expired' );
     200                    break;
     201                case 'old':
     202                    $this->membership_status = array( 'cancelled', 'expired' );
     203                    break;
     204                default:
     205                    $this->membership_status = array('active');
     206            }
     207        }
    178208        /**
    179209         * The default Members List columns to display (with labels)
     
    204234        }
    205235
     236        $this->total_member_records = $this->get_member_record_count();
     237
    206238        /**
    207239         * Prepare the Export bulk action
     
    211243            add_action( 'e20r_memberslist_process_action', array( $this, 'export_members' ), 10, 3 );
    212244        }
     245    }
     246
     247    /**
     248     * Private function to capture the count of records in the membership database
     249     *
     250     * @return int|null
     251     */
     252    private function get_member_record_count() {
     253
     254        $status = $this->utils->get_variable( 'level', 'active' );
     255
     256        // Get SQL for all records in the paginated data
     257        $this->generate_member_sql( $status );
     258        $records = $this->get_members( -1, -1, $status );
     259
     260        return is_countable( $records ) ? count( $records ) : 0;
    213261    }
    214262
     
    294342
    295343        // Do we need to limit?
    296         $level = $this->utils->get_variable( 'level', '' );
    297 
    298         if ( empty( $level ) ) {
    299             $level = 'active';
    300         }
     344        $level = $this->utils->get_variable( 'level', 'active' );
    301345
    302346        // Get the current page number
     
    309353        // BUG FIX: Handle situation(s) where there are no records found
    310354        if ( null !== $this->items ) {
    311             $total_items = count($this->items );
    312355            $this->utils->log(
    313356                sprintf(
    314357                "Configure pagination for %d total records and %d counted (returned) records",
    315                 $total_items,
     358                $this->total_member_records,
    316359                (is_countable( $this->items ) ? count( $this->items ) : 0)
    317360                )
     
    323366        $this->set_pagination_args(
    324367            array(
    325                 'total_items' => $total_items,
     368                'total_items' => $this->total_member_records,
    326369                'per_page'    => $per_page,
    327                 'total_pages' => ceil( $total_items / $per_page ),
     370                'total_pages' => ceil( $this->total_member_records / $per_page ),
    328371            )
    329372        );
     
    593636        global $wpdb;
    594637
    595         $this->generate_member_sql( $per_page, $page_number, $status );
     638        // Get Pagination SQL
     639        $this->sqlQuery = $this->generate_member_sql( $status, $per_page, $page_number, );
    596640
    597641        // Fetch the data
    598         $result                    = $wpdb->get_results( $this->sqlQuery, ARRAY_A );
     642        $result = $wpdb->get_results( $this->sqlQuery, ARRAY_A );
     643
    599644        if ( ! empty( $result ) ) {
    600645            $this->utils->log("Found records in DB...");
    601646            $this->total_members_found = $wpdb->num_rows;
    602647        }
    603         /*
    604         if ( ! empty( $result ) ) {
    605             $this->total_members_found = $result->num_rows;
    606             // $this->total_members_found = $wpdb->get_var( "SELECT FOUND_ROWS() AS found_rows" );
    607         }
    608         */
    609648
    610649        // Return the result set unless an error occurred.
     
    640679     * @param int    $page_number
    641680     * @param string $status
    642      */
    643     private function generate_member_sql( $per_page, $page_number, $status = 'active' ) {
     681     *
     682     * @return string - Returns the SQL statement
     683     */
     684    private function generate_member_sql( $status = 'active', $per_page = -1, $page_number = -1 ) {
    644685
    645686        $this->utils->log( "Called by: " . $this->utils->_who_called_me() );
     
    839880        ";
    840881
    841         // Define the SQL statement
    842         $this->sqlQuery = $sql . self::$sql_from;
    843 
    844         $this->utils->log( "SQL for fetching membership records:\n {$this->sqlQuery}" );
     882        // Created the SQL statement
     883        $sqlQuery = $sql . self::$sql_from;
     884
     885        $this->utils->log( "SQL for fetching membership records:\n {$sqlQuery}" );
     886        return $sqlQuery;
    845887    }
    846888
  • e20r-members-list/trunk/class/members-list/class.sort-by-meta.php

    r2025537 r2458244  
    11<?php
    22/**
    3  * Copyright (c) 2018-2019 - Eighty / 20 Results by Wicked Strong Chicks.
     3 * Copyright (c) 2018-2021 - Eighty / 20 Results by Wicked Strong Chicks.
    44 * ALL RIGHTS RESERVED
    55 *
     
    2121
    2222if ( ! class_exists( 'E20R\Members_List\Support\Sort_By_Meta' ) ) {
    23    
     23
    2424    class Sort_By_Meta {
    25        
     25
    2626        private $meta_key;
    27        
     27
    2828        private $order = 'DESC';
    29        
     29
    3030        /**
    3131         * Sort_Meta constructor.
     
    3838            $this->order    = strtoupper( $order );
    3939        }
    40        
     40
    4141        /**
    4242         * @param array $a
     
    4848         */
    4949        public function sort_records( $a, $b ) {
    50            
     50
    5151            // $utils = Utilities::get_instance();
    5252            // $utils->log( "A: " . print_r( $a, true));
    5353            // $utils->log("B: " . print_r( $b, true));
    54            
     54
    5555            $a_user_id = is_array( $a ) ? $a['user_id'] : ( is_a( $a, '\WP_User' ) ? $a->ID : null );
    5656            $b_user_id = is_array( $b ) ? $b['user_id'] : ( is_a( $b, '\WP_User' ) ? $b->ID : null );
    57            
     57
    5858            if ( is_null($a_user_id ) || is_null( $b_user_id ) ) {
    5959                return false;
    6060            }
    61            
     61
    6262            // Check if the field specified exists in the data
    6363            if ( ! isset( $a[ $this->meta_key ] ) ) {
    6464                $a_value = get_user_meta( $a_user_id, $this->meta_key, true );
    65                
     65
    6666            } else {
    6767                $a_value = $b[ $this->meta_key ];
    6868            }
    69            
     69
    7070            if ( ! isset( $b[ $this->meta_key ] ) ) {
    7171                $b_value = get_user_meta( $b_user_id, $this->meta_key, true );
     
    7373                $b_value = $b[ $this->meta_key ];
    7474            }
    75            
     75
    7676            if ( $a_value == $b_value ) {
    7777                return 0;
    7878            }
    79            
     79
    8080            if ( 'DESC' == $this->order ) {
    8181                return ( $a_value > $b_value ? 1 : - 1 );
    8282            }
    83            
     83
    8484            if ( 'ASC' == $this->order ) {
    8585                return ( $a_value < $b_value ? 1 : - 1 );
    8686            }
    87            
    88            
     87
     88
    8989        }
    90        
     90
    9191    }
    9292}
  • e20r-members-list/trunk/class/members-list/css/e20r-memberslist-page.css

    r2025537 r2458244  
    11/*
    2  *  Copyright (c) 2018-2019. - Eighty / 20 Results by Wicked Strong Chicks.
     2 *  Copyright (c) 2018-2021. - Eighty / 20 Results by Wicked Strong Chicks.
    33 *  ALL RIGHTS RESERVED
    44 *
  • e20r-members-list/trunk/class/members-list/js/e20r-memberslist-page.js

    r2228121 r2458244  
    22 * License:
    33
    4     Copyright 2016-2019 - Eighty / 20 Results by Wicked Strong Chicks, LLC ([email protected])
     4    Copyright 2016-2021 - Eighty / 20 Results by Wicked Strong Chicks, LLC ([email protected])
    55
    66    This program is free software; you can redistribute it and/or modify
Note: See TracChangeset for help on using the changeset viewer.