installed plugin Easy Digital Downloads version 3.1.0.3

This commit is contained in:
2022-11-27 15:03:07 +00:00
committed by Gitium
parent 555673545b
commit c5dce2cec6
1200 changed files with 238970 additions and 0 deletions

View File

@ -0,0 +1,164 @@
<?php
/**
* API Requests Log View Class
*
* @package EDD
* @subpackage Admin/Reports
* @copyright Copyright (c) 2018, Easy Digital Downloads, LLC
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
* @since 1.5
*/
// Exit if accessed directly
defined( 'ABSPATH' ) || exit;
/**
* EDD_API_Request_Log_Table List Table Class
*
* @since 1.5
* @since 3.0 Updated to use the custom tables and new query classes.
*/
class EDD_API_Request_Log_Table extends EDD_Base_Log_List_Table {
/**
* Log type
*
* @var string
*/
protected $log_type = 'api_requests';
/**
* Get things started
*
* @since 1.5
* @see WP_List_Table::__construct()
*/
public function __construct() {
parent::__construct();
}
/**
* Retrieve the table columns
*
* @since 1.5
* @return array $columns Array of all the list table columns
*/
public function get_columns() {
return array(
'ID' => __( 'Log ID', 'easy-digital-downloads' ),
'details' => __( 'Request Details', 'easy-digital-downloads' ),
'version' => __( 'API Version', 'easy-digital-downloads' ),
'ip' => __( 'Request IP', 'easy-digital-downloads' ),
'speed' => __( 'Request Speed', 'easy-digital-downloads' ),
'date' => __( 'Date', 'easy-digital-downloads' )
);
}
/**
* Gets the name of the primary column.
*
* @since 2.5
* @access protected
*
* @return string Name of the primary column.
*/
protected function get_primary_column_name() {
return 'ID';
}
/**
* This function renders most of the columns in the list table.
*
* @since 1.5
*
* @param array $item Contains all the data of the api request
* @param string $column_name The name of the column
*
* @return string Column Name
*/
public function column_default( $item, $column_name ) {
switch ( $column_name ) {
case 'ip':
return '<a href="' . esc_url( 'https://ipinfo.io/' . esc_attr( $item['ip'] ) ) . '" target="_blank" rel="noopener noreferrer">' . esc_html( $item['ip'] ) . '</a>';
default:
return $item[ $column_name ];
}
}
/**
* Output Error Message column
*
* @since 1.5
* @param array $item Contains all the data of the log
* @return void
*/
public function column_details( $item ) {
?>
<a href="#TB_inline?width=640&amp;inlineId=log-details-<?php echo esc_attr( $item['ID'] ); ?>" class="thickbox"><?php esc_html_e( 'View Request', 'easy-digital-downloads' ); ?></a>
<div id="log-details-<?php echo absint( $item['ID'] ); ?>" style="display:none;">
<?php
$request = $item['request'];
$error = $item['error'];
echo '<p><strong>' . __( 'API Request:', 'easy-digital-downloads' ) . '</strong></p>';
echo '<div>' . $request . '</div>';
if ( ! empty( $error ) ) {
echo '<p><strong>' . __( 'Error', 'easy-digital-downloads' ) . '</strong></p>';
echo '<div>' . esc_html( $error ) . '</div>';
}
echo '<p><strong>' . __( 'API User:', 'easy-digital-downloads' ) . '</strong></p>';
echo '<div>' . $item['user_id'] . '</div>';
echo '<p><strong>' . __( 'API Key:', 'easy-digital-downloads' ) . '</strong></p>';
echo '<div>' . $item['api_key'] . '</div>';
echo '<p><strong>' . __( 'Request Date:', 'easy-digital-downloads' ) . '</strong></p>';
echo '<div>' . $item['date'] . '</div>';
?>
</div>
<?php
}
/**
* Gets the log entries for the current view
*
* @since 1.5
*
* @return array $logs_data Array of all the Log entries
*/
public function get_logs( $log_query = array() ) {
$logs_data = array();
$logs = edd_get_api_request_logs( $log_query );
if ( $logs ) {
foreach ( $logs as $log ) {
/** @var $log EDD\Logs\Api_Request_Log */
$logs_data[] = array(
'ID' => $log->id,
'version' => $log->version,
'speed' => $log->time,
'ip' => $log->ip,
'date' => $log->date_created,
'api_key' => $log->api_key,
'request' => $log->request,
'error' => $log->error,
'user_id' => $log->user_id,
);
}
}
return $logs_data;
}
/**
* Get the total number of items
*
* @since 3.0
*
* @param array $log_query
*
* @return int
*/
public function get_total( $log_query = array() ) {
return edd_count_api_request_logs( $log_query );
}
}

View File

@ -0,0 +1,560 @@
<?php
/**
* Base Log List Table.
*
* @package EDD
* @subpackage Admin/Reports
* @copyright Copyright (c) 2018, Easy Digital Downloads, LLC
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
* @since 1.4.4
* @since 3.0 Updated to use the custom tables.
*/
// Exit if accessed directly
defined( 'ABSPATH' ) || exit;
use EDD\Admin\List_Table;
/**
* EDD_Base_Log_List_Table Class
*
* @since 3.0
*/
class EDD_Base_Log_List_Table extends List_Table {
/**
* Log type
*
* @var string
*/
protected $log_type = 'logs';
/**
* Get things started
*
* @since 3.0
* @see WP_List_Table::__construct()
*/
public function __construct() {
parent::__construct( array(
'singular' => 'log',
'plural' => 'logs',
'ajax' => false
) );
$this->filter_bar_hooks();
}
/**
* Generate the table navigation above or below the table
*
* Removes the referrer nonce from parent class.
*
* @since 3.0.0
* @param string $which
*/
protected function display_tablenav( $which ) {
?>
<div class="tablenav <?php echo esc_attr( $which ); ?>">
<?php if ( $this->has_items() ) : ?>
<div class="alignleft actions bulkactions">
<?php $this->bulk_actions( $which ); ?>
</div>
<?php endif;
$this->extra_tablenav( $which );
$this->pagination( $which ); ?>
<br class="clear" />
</div><?php
}
/**
* Hook in filter bar actions
*
* @since 3.0
*/
private function filter_bar_hooks() {
add_action( 'edd_admin_filter_bar_logs', array( $this, 'filter_bar_items' ) );
add_action( 'edd_after_admin_filter_bar_logs', array( $this, 'filter_bar_searchbox' ) );
}
/**
* Gets the name of the primary column.
*
* @since 3.0
* @access protected
*
* @return string Name of the primary column.
*/
protected function get_primary_column_name() {
return 'id';
}
/**
* Return the current log view
*
* @since 3.0
* @return string
*/
public function get_filtered_view() {
return isset( $_GET['view'] ) && array_key_exists( $_GET['view'], edd_log_default_views() )
? sanitize_text_field( $_GET['view'] )
: 'file_downloads';
}
/**
* Return the user we are filtering logs by, if any
*
* @since 3.0
* @return mixed int If User ID, string If Email/Login
*/
public function get_filtered_user() {
return isset( $_GET['user'] ) ? absint( $_GET['user'] ) : false;
}
/**
* Return the customer we are filtering logs by, if any
*
* @since 3.0
* @return int|string|false int If customer ID, string If Email, false if not present
*/
public function get_filtered_customer() {
$ret = false;
if ( isset( $_GET['customer'] ) ) {
$customer = new EDD_Customer( sanitize_text_field( $_GET['customer'] ) );
if ( ! empty( $customer->id ) ) {
$ret = $customer->id;
}
}
return $ret;
}
/**
* Return the start-date of the filter
*
* @since 3.0
*
* @return string Start date to filter by
*/
public function get_filtered_start_date() {
return sanitize_text_field( $this->get_request_var( 'start-date', null ) );
}
/**
* Return the end-date of the filter
*
* @since 3.0
*
* @return string End date to filter by
*/
public function get_filtered_end_date() {
return sanitize_text_field( $this->get_request_var( 'end-date', null ) );
}
/**
* Return the ID of the download we're filtering logs by
*
* @since 3.0
*
* @return int Download ID.
*/
public function get_filtered_download() {
return absint( $this->get_request_var( 'download', false ) );
}
/**
* Return the ID of the payment we're filtering logs by
*
* @since 3.0
*
* @return int Payment ID.
*/
public function get_filtered_payment() {
return absint( $this->get_request_var( 'payment', false ) );
}
/**
* Gets the meta query for the log query.
*
* This is used to return log entries that match our search query, user query, or download query.
*
* @since 3.0
*
* @return array $meta_query
*/
public function get_meta_query() {
return array();
}
/**
* Outputs the log views.
*
* @since 3.0
*/
public function bulk_actions( $which = '' ) {
return;
}
/**
* Renders the Reports page views drop down
*
* @since 3.0
* @return void
*/
public function log_views() {
$views = edd_log_default_views();
$current_view = $this->get_filtered_view(); ?>
<select id="edd-logs-view" name="view">
<?php foreach ( $views as $view_id => $label ) : ?>
<option value="<?php echo esc_attr( $view_id ); ?>" <?php selected( $view_id, $current_view ); ?>><?php echo esc_html( $label ); ?></option>
<?php endforeach; ?>
</select>
<?php
/**
* Fires immediately after the logs view actions are rendered in the Logs screen.
*
* @since 3.0
*/
do_action( 'edd_log_view_actions' );
?>
<input type="hidden" name="customer" value="<?php echo $this->get_filtered_customer(); ?>" />
<input type="hidden" name="post_type" value="download" />
<input type="hidden" name="page" value="edd-tools" />
<input type="hidden" name="tab" value="logs" />
<?php
}
/**
* Sets up the downloads filter
*
* @since 3.0
* @since 3.1 Accepts a download ID to filter by for the selected value.
*
* @param int $download The filtered download ID, default: 0.
*
* @return void
*/
public function downloads_filter( $download = 0 ) {
$args = array(
'id' => 'edd-log-download-filter',
'name' => 'download',
'chosen' => true,
);
if ( ! empty( $download ) ) {
$args['selected'] = $download;
}
echo EDD()->html->product_dropdown( $args );
}
/**
* Gets the log entries for the current view
*
* @since 3.0
*
* @return array $logs_data Array of all the logs.
*/
function get_logs( $log_query = array() ) {
return array();
}
/**
* Get the total number of items
*
* @since 3.0
*
* @param array $log_query
*
* @return int
*/
public function get_total( $log_query = array() ) {
return count( array() );
}
/**
* Empty method to hide view links on all logs table
*
* @since 3.0
*/
public function get_views() {
// Intentionally empty
}
/**
* Retrieves the logs data.
*
* @since 3.0
*
* @return array Logs data.
*/
public function get_data() {
$log_query = $this->get_query_args();
return $this->get_logs( $log_query );
}
/**
* Setup the final data for the table.
*
* @since 3.0
*/
public function prepare_items() {
$this->_column_headers = array(
$this->get_columns(),
array(),
$this->get_sortable_columns()
);
$this->items = $this->get_data();
$log_query = $this->get_query_args( false );
$total_items = $this->get_total( $log_query );
$this->set_pagination_args( array(
'total_pages' => ceil( $total_items / $this->per_page ),
'total_items' => $total_items,
'per_page' => $this->per_page,
) );
}
/**
* Return array of query arguments
*
* @since 3.0
*
* @param bool $paginate Whether to add pagination arguments
*
* @return array
*/
protected function get_query_args( $paginate = true ) {
// Defaults
$retval = array(
'product_id' => $this->get_filtered_download(),
'customer_id' => $this->get_filtered_customer(),
'order_id' => $this->get_filtered_payment(),
'meta_query' => $this->get_meta_query(),
);
// Search
$search = $this->get_search();
if ( ! empty( $search ) ) {
if ( filter_var( $search, FILTER_VALIDATE_IP ) ) {
$retval['ip'] = $search;
} elseif ( is_email( $search ) ) {
if ( 'api_requests' === $this->log_type ) {
// API requests are linked to user accounts, so we're checking user data here.
$user = get_user_by( 'email', $search );
if ( ! empty( $user->ID ) ) {
$retval['user_id'] = $user->ID;
} else {
// This is a fallback to help ensure an invalid email will produce zero results.
$retval['search'] = $search;
}
} else {
// All other logs are linked to customers.
$customer = edd_get_customer_by( 'email', $search );
if ( ! empty( $customer->id ) ) {
$retval['customer_id'] = $customer->id;
} else {
// This is a fallback to help ensure an invalid email will produce zero results.
$retval['search'] = $search;
}
}
} elseif ( 'api_requests' === $this->log_type && 32 === strlen( $search ) ) {
// Look for an API key
$retval['api_key'] = $search;
} elseif ( 'api_requests' === $this->log_type && stristr( $search, 'token:' ) ) {
// Look for an API token
$retval['token'] = str_ireplace( 'token:', '', $search );
} elseif ( is_numeric( $search ) ) {
if ( 'api_requests' === $this->log_type ) {
// API requests are linked to user accounts, so we're checking user data here.
$user = get_user_by( 'email', $search );
if ( ! empty( $user->ID ) ) {
$retval['user_id'] = $user->ID;
} else {
$retval['search'] = $search;
}
} else {
// All other logs are linked to customers.
$customer = edd_get_customer( $search );
if ( ! empty( $customer->id ) ) {
$retval['customer_id'] = $customer->id;
} elseif ( 'file_downloads' === $this->log_type ) {
$retval['product_id'] = $search;
} else {
$retval['search'] = $search;
}
}
} else {
if ( 'file_downloads' === $this->log_type ) {
$this->file_search = true;
} else {
$retval['search'] = $search;
}
}
}
// Start date
$start_date = $this->get_filtered_start_date();
$end_date = $this->get_filtered_end_date();
// Setup original array
if ( ! empty( $start_date ) || ! empty( $end_date ) ) {
$retval['date_created_query']['column'] = 'date_created';
// Start date
if ( ! empty( $start_date ) ) {
$retval['date_created_query'][] = array(
'column' => 'date_created',
'after' => \Carbon\Carbon::parse( date( 'Y-m-d H:i:s', strtotime( "{$start_date} midnight" ) ), edd_get_timezone_id() )->setTimezone( 'UTC' )->toDateTimeString(),
);
}
// End date
if ( ! empty( $end_date ) ) {
$retval['date_created_query'][] = array(
'column' => 'date_created',
'before' => \Carbon\Carbon::parse( date( 'Y-m-d H:i:s', strtotime( "{$end_date} + 1 day" ) ), edd_get_timezone_id() )->setTimezone( 'UTC' )->toDateTimeString(),
);
}
}
$retval = array_filter( $retval );
// Return query arguments
return ( true === $paginate )
? $this->parse_pagination_args( $retval )
: $retval;
}
/**
* Output advanced filters for payments
*
* @since 3.0
*/
public function advanced_filters() {
edd_admin_filter_bar( 'logs' );
}
/**
* Output filter bar items
*
* @since 3.0
*/
public function filter_bar_items() {
// Get values
$start_date = $this->get_filtered_start_date();
$end_date = $this->get_filtered_end_date();
$download = $this->get_filtered_download();
$customer = $this->get_filtered_customer();
$view = $this->get_filtered_view();
$clear_url = edd_get_admin_url( array(
'page' => 'edd-tools',
'tab' => 'logs',
'view' => sanitize_key( $view ),
) ); ?>
<span id="edd-type-filter">
<?php $this->log_views(); ?>
</span>
<span id="edd-date-filters" class="edd-from-to-wrapper">
<?php
echo EDD()->html->date_field( array(
'id' => 'start-date',
'name' => 'start-date',
'placeholder' => _x( 'From', 'date filter', 'easy-digital-downloads' ),
'value' => $start_date
) );
echo EDD()->html->date_field( array(
'id' => 'end-date',
'name' => 'end-date',
'placeholder' => _x( 'To', 'date filter', 'easy-digital-downloads' ),
'value' => $end_date
) );
?></span>
<span id="edd-download-filter">
<?php $this->downloads_filter( $download ); ?>
</span>
<?php if ( ! empty( $customer ) ) : ?>
<span id="edd-customer-filter">
<?php printf( esc_html__( 'Customer ID: %d', 'easy-digital-downloads' ), $customer ); ?>
</span>
<?php endif; ?>
<input type="submit" class="button-secondary" value="<?php esc_attr_e( 'Filter', 'easy-digital-downloads' ); ?>"/>
<?php if ( ! empty( $start_date ) || ! empty( $end_date ) || ! empty( $download ) || ! empty( $customer ) ) : ?>
<a href="<?php echo esc_url( $clear_url ); ?>" class="button-secondary">
<?php esc_html_e( 'Clear', 'easy-digital-downloads' ); ?>
</a>
<?php endif; ?>
<?php
}
/**
* Output the filter bar searchbox
*
* @since 3.0
*/
public function filter_bar_searchbox() {
do_action( 'edd_logs_advanced_filters_row' );
$this->search_box( __( 'Search', 'easy-digital-downloads' ), 'edd-logs' );
}
/**
* Show the search field
*
* @since 3.0
*
* @param string $text Label for the search box
* @param string $input_id ID of the search box
*
* @return void
*/
public function search_box( $text, $input_id ) {
// Bail if no customers and no search
if ( empty( $_REQUEST['s'] ) && ! $this->has_items() ) {
return;
}
$input_id = $input_id . '-search-input';
if ( ! empty( $_REQUEST['orderby'] ) ) {
echo '<input type="hidden" name="orderby" value="' . esc_attr( $_REQUEST['orderby'] ) . '" />';
}
if ( ! empty( $_REQUEST['order'] ) ) {
echo '<input type="hidden" name="order" value="' . esc_attr( $_REQUEST['order'] ) . '" />';
}
?>
<p class="search-form">
<label class="screen-reader-text" for="<?php echo esc_attr( $input_id ); ?>"><?php echo esc_html( $text ); ?>:</label>
<input type="search" id="<?php echo esc_attr( $input_id ); ?>" name="s" value="<?php _admin_search_query(); ?>" placeholder="<?php esc_html_e( 'Search logs...', 'easy-digital-downloads' ); ?>" />
</p>
<?php
}
}

View File

@ -0,0 +1,380 @@
<?php
/**
* Earnings by Category Reports Table Class
*
* @package EDD
* @subpackage Admin/Reports
* @copyright Copyright (c) 2018, Easy Digital Downloads, LLC
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
* @since 2.4
*/
// Exit if accessed directly
defined( 'ABSPATH' ) || exit;
use EDD\Admin\List_Table;
/**
* EDD_Categories_Reports_Table Class
*
* Renders the Download Reports table
*
* @since 2.4
*/
class EDD_Categories_Reports_Table extends List_Table {
/**
* Get things started
*
* @since 2.4
* @see WP_List_Table::__construct()
*/
public function __construct() {
// Set parent defaults
parent::__construct( array(
'singular' => 'report-earning',
'plural' => 'report-earnings',
'ajax' => false
) );
}
/**
* Gets the name of the primary column.
*
* @since 2.5
* @access protected
*
* @return string Name of the primary column.
*/
protected function get_primary_column_name() {
return 'label';
}
/**
* This function renders most of the columns in the list table.
*
* @since 2.4
*
* @param array $item Contains all the data of the downloads
* @param string $column_name The name of the column
*
* @return string Column Name
*/
public function column_default( $item, $column_name ) {
return $item[ $column_name ];
}
/**
* Retrieve the table columns
*
* @since 2.4
* @return array $columns Array of all the list table columns
*/
public function get_columns() {
return array(
'label' => __( 'Category', 'easy-digital-downloads' ),
'total_sales' => __( 'Total Sales', 'easy-digital-downloads' ),
'total_earnings' => __( 'Total Earnings', 'easy-digital-downloads' ),
'avg_sales' => __( 'Monthly Sales Avg', 'easy-digital-downloads' ),
'avg_earnings' => __( 'Monthly Earnings Avg', 'easy-digital-downloads' )
);
}
/**
* Outputs the reporting views
*
* @since 1.5
* @return void
*/
public function display_tablenav( $which = '' ) {
?>
<div class="tablenav <?php echo esc_attr( $which ); ?>">
<div class="alignleft actions bulkactions">
<?php
if ( 'top' === $which ) {
edd_report_views();
}
?>
</div>
</div>
<?php
}
/**
* Builds and retrieves of all the categories reports data.
*
* @since 2.4
* @edeprecated 3.0 Use get_data()
*
* @return array All the data for customer reports.
*/
public function reports_data() {
_edd_deprecated_function( __METHOD__, '3.0', 'EDD_Categories_Reports_Table::get_data()' );
return $this->get_data();
}
/**
* Builds and retrieves all of the categories reports data.
*
* @since 3.0
*
* @return array Categories reports table data.
*/
public function get_data() {
/*
* Date filtering
*/
$dates = edd_get_report_dates();
$include_taxes = empty( $_GET['exclude_taxes'] ) ? true : false;
if ( ! empty( $dates[ 'year' ] ) ) {
$date = new DateTime();
$date->setDate( $dates[ 'year' ], $dates[ 'm_start' ], $dates[ 'day' ] );
$start_date = $date->format( 'Y-m-d' );
$date->setDate( $dates[ 'year_end' ], $dates[ 'm_end' ], $dates[ 'day_end' ] );
$end_date = $date->format( 'Y-m-d' );
$cached_report_key = 'edd_earnings_by_category_data' . $start_date . '_' . $end_date;
} else {
$start_date = false;
$end_date = false;
$cached_report_key = 'edd_earnings_by_category_data';
}
$cached_reports = get_transient( $cached_report_key );
if ( false !== $cached_reports ) {
$reports_data = $cached_reports;
} else {
$reports_data = array();
$categories = get_terms( 'download_category', array(
'parent' => 0,
'hierarchical' => 0,
'hide_empty' => false
) );
foreach ( $categories as $category ) {
$category_slugs = array( $category->slug );
$child_terms = get_terms( 'download_category', array(
'parent' => $category->term_id,
'hierarchical' => 0
) );
if ( ! empty( $child_terms ) ) {
foreach ( $child_terms as $child_term ) {
$category_slugs[] = $child_term->slug;
}
}
$downloads = get_posts( array(
'post_type' => 'download',
'posts_per_page' => -1,
'fields' => 'ids',
'tax_query' => array(
array(
'taxonomy' => 'download_category',
'field' => 'slug',
'terms' => $category_slugs
)
)
) );
$sales = $avg_sales = 0;
$earnings = $avg_earnings = 0.00;
foreach ( $downloads as $download ) {
$current_sales = EDD()->payment_stats->get_sales( $download, $start_date, $end_date );
$current_earnings = EDD()->payment_stats->get_earnings( $download, $start_date, $end_date, $include_taxes );
$current_average_sales = edd_get_average_monthly_download_sales( $download );
$current_average_earnings = edd_get_average_monthly_download_earnings( $download );
$sales += $current_sales;
$earnings += $current_earnings;
$avg_sales += $current_average_sales;
$avg_earnings += $current_average_earnings;
}
$avg_earnings = round( $avg_earnings, edd_currency_decimal_filter() );
if ( ! empty( $avg_earnings ) && $avg_sales < 1 ) {
$avg_sales = __( 'Less than 1', 'easy-digital-downloads' );
} else {
$avg_sales = round( edd_format_amount( $avg_sales, false ) );
}
$reports_data[] = array(
'ID' => $category->term_id,
'label' => $category->name,
'total_sales' => edd_format_amount( $sales, false ),
'total_sales_raw' => $sales,
'total_earnings' => edd_currency_filter( edd_format_amount( $earnings ) ),
'total_earnings_raw' => $earnings,
'avg_sales' => $avg_sales,
'avg_earnings' => edd_currency_filter( edd_format_amount( $avg_earnings ) ),
'is_child' => false,
);
if ( ! empty( $child_terms ) ) {
foreach ( $child_terms as $child_term ) {
$child_downloads = get_posts( array(
'post_type' => 'download',
'posts_per_page' => -1,
'fields' => 'ids',
'tax_query' => array(
array(
'taxonomy' => 'download_category',
'field' => 'slug',
'terms' => $child_term->slug
)
)
) );
$child_sales = $child_avg_sales = 0;
$child_earnings = $child_avg_earnings = 0.00;
foreach ( $child_downloads as $child_download ) {
$current_average_sales = $current_sales = EDD()->payment_stats->get_sales( $child_download, $start_date, $end_date );
$current_average_earnings = $current_earnings = EDD()->payment_stats->get_earnings( $child_download, $start_date, $end_date );
$release_date = get_post_field( 'post_date', $child_download );
$diff = abs( current_time( 'timestamp' ) - strtotime( $release_date ) );
$months = floor( $diff / ( 30 * 60 * 60 * 24 ) ); // Number of months since publication
if ( $months > 0 ) {
$current_average_sales = ( $current_sales / $months );
$current_average_earnings = ( $current_earnings / $months );
}
$child_sales += $current_sales;
$child_earnings += $current_earnings;
$child_avg_sales += $current_average_sales;
$child_avg_earnings += $current_average_earnings;
}
$child_avg_sales = round( $child_avg_sales / count( $child_downloads ) );
$child_avg_earnings = round( $child_avg_earnings / count( $child_downloads ), edd_currency_decimal_filter() );
$reports_data[] = array(
'ID' => $child_term->term_id,
'label' => '&#8212; ' . $child_term->name,
'total_sales' => edd_format_amount( $child_sales, false ),
'total_sales_raw' => $child_sales,
'total_earnings' => edd_currency_filter( edd_format_amount( $child_earnings ) ),
'total_earnings_raw' => $child_earnings,
'avg_sales' => edd_format_amount( $child_avg_sales, false ),
'avg_earnings' => edd_currency_filter( edd_format_amount( $child_avg_earnings ) ),
'is_child' => true
);
}
}
}
}
return $reports_data;
}
/**
* Output the Category Sales Mix Pie Chart
*
* @since 2.4
* @return string The HTML for the outputted graph
*/
public function output_sales_graph() {
if ( empty( $this->items ) ) {
return;
}
$data = array();
$total_sales = 0;
foreach ( $this->items as $item ) {
$total_sales += $item['total_sales_raw'];
if ( ! empty( $item[ 'is_child' ] ) || empty( $item[ 'total_sales_raw' ] ) ) {
continue;
}
$data[ $item[ 'label' ] ] = $item[ 'total_sales_raw' ];
}
if ( empty( $total_sales ) ) {
echo '<p><em>' . __( 'No sales for dates provided.', 'easy-digital-downloads' ) . '</em></p>';
}
// Sort High to Low, prior to filter so people can reorder if they please
arsort( $data );
$data = apply_filters( 'edd_category_sales_graph_data', $data );
$options = apply_filters( 'edd_category_sales_graph_options', array(
'legend_formatter' => 'eddLegendFormatterSales',
), $data );
$pie_graph = new EDD_Pie_Graph( $data, $options );
$pie_graph->display();
}
/**
* Output the Category Earnings Mix Pie Chart
*
* @since 2.4
* @return string The HTML for the outputted graph
*/
public function output_earnings_graph() {
if ( empty( $this->items ) ) {
return;
}
$data = array();
$total_earnings = 0;
foreach ( $this->items as $item ) {
$total_earnings += $item['total_earnings_raw'];
if ( ! empty( $item[ 'is_child' ] ) || empty( $item[ 'total_earnings_raw' ] ) ) {
continue;
}
$data[ $item[ 'label' ] ] = $item[ 'total_earnings_raw' ];
}
if ( empty( $total_earnings ) ) {
echo '<p><em>' . __( 'No earnings for dates provided.', 'easy-digital-downloads' ) . '</em></p>';
}
// Sort High to Low, prior to filter so people can reorder if they please
arsort( $data );
$data = apply_filters( 'edd_category_earnings_graph_data', $data );
$options = apply_filters( 'edd_category_earnings_graph_options', array(
'legend_formatter' => 'eddLegendFormatterEarnings',
), $data );
$pie_graph = new EDD_Pie_Graph( $data, $options );
$pie_graph->display();
}
/**
* Setup the final data for the table
*
* @since 2.4
* @uses EDD_Categories_Reports_Table::get_columns()
* @uses EDD_Categories_Reports_Table::get_sortable_columns()
* @uses EDD_Categories_Reports_Table::reports_data()
* @return void
*/
public function prepare_items() {
$columns = $this->get_columns();
$hidden = array(); // No hidden columns
$sortable = $this->get_sortable_columns();
$this->_column_headers = array( $columns, $hidden, $sortable );
$this->items = $this->get_data();
}
}

View File

@ -0,0 +1,298 @@
<?php
/**
* Download Reports Table Class
*
* @package EDD
* @subpackage Admin/Reports
* @copyright Copyright (c) 2018, Easy Digital Downloads, LLC
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
* @since 1.5
*/
// Exit if accessed directly
defined( 'ABSPATH' ) || exit;
use EDD\Admin\List_Table;
/**
* EDD_Download_Reports_Table Class
*
* Renders the Download Reports table
*
* @since 1.5
*/
class EDD_Download_Reports_Table extends List_Table {
/**
* @var object Query results
* @since 1.5.2
*/
private $products;
/**
* Get things started
*
* @since 1.5
* @see WP_List_Table::__construct()
*/
public function __construct() {
parent::__construct( array(
'singular' => 'report-download',
'plural' => 'report-downloads',
'ajax' => false
) );
add_action( 'edd_report_view_actions', array( $this, 'category_filter' ) );
$this->query();
}
/**
* Gets the name of the primary column.
*
* @since 2.5
* @access protected
*
* @return string Name of the primary column.
*/
protected function get_primary_column_name() {
return 'title';
}
/**
* This function renders most of the columns in the list table.
*
* @since 1.5
*
* @param array $item Contains all the data of the downloads
* @param string $column_name The name of the column
*
* @return string Column Name
*/
public function column_default( $item, $column_name ) {
switch( $column_name ){
case 'earnings' :
return edd_currency_filter( edd_format_amount( $item[ $column_name ] ) );
case 'average_sales' :
return round( $item[ $column_name ] );
case 'average_earnings' :
return edd_currency_filter( edd_format_amount( $item[ $column_name ] ) );
case 'details' :
$url = edd_get_admin_url(
array(
'page' => 'edd-reports',
'view' => 'downloads',
'download-id' => absint( $item['ID'] ),
)
);
return '<a href="' . esc_url( $url ) . '">' . __( 'View Detailed Report', 'easy-digital-downloads' ) . '</a>';
default:
return $item[ $column_name ];
}
}
/**
* Retrieve the table columns
*
* @since 1.5
* @return array $columns Array of all the list table columns
*/
public function get_columns() {
return array(
'title' => edd_get_label_singular(),
'sales' => __( 'Sales', 'easy-digital-downloads' ),
'earnings' => __( 'Earnings', 'easy-digital-downloads' ),
'average_sales' => __( 'Monthly Average Sales', 'easy-digital-downloads' ),
'average_earnings' => __( 'Monthly Average Earnings', 'easy-digital-downloads' ),
'details' => __( 'Detailed Report', 'easy-digital-downloads' )
);
}
/**
* Retrieve the sortable columns
*
* @since 1.4
* @return array Array of all the sortable columns
*/
public function get_sortable_columns() {
return array(
'title' => array( 'title', true ),
'sales' => array( 'sales', false ),
'earnings' => array( 'earnings', false )
);
}
/**
* Retrieve the category being viewed
*
* @since 1.5.2
* @return int Category ID
*/
public function get_category() {
return absint( $this->get_request_var( 'category', 0 ) );
}
/**
* Retrieve the total number of downloads
*
* @since 1.5
* @return int $total Total number of downloads
*/
public function get_total_downloads() {
$total = 0;
$counts = wp_count_posts( 'download', 'readable' );
foreach( $counts as $count ) {
$total += $count;
}
return $total;
}
/**
* Outputs the reporting views
*
* These aren't really bulk actions but this outputs the markup in the
* right place.
*
* @since 1.5
* @return void
*/
public function bulk_actions( $which = '' ) {
edd_report_views();
}
/**
* Attaches the category filter to the log views
*
* @since 1.5.2
* @return void
*/
public function category_filter() {
if ( get_terms( 'download_category' ) ) {
echo EDD()->html->category_dropdown( 'category', $this->get_category() );
}
}
/**
* Performs the products query
*
* @since 1.5.2
* @return void
*/
public function query() {
$orderby = sanitize_text_field( $this->get_request_var( 'orderby', 'title' ) );
$order = sanitize_text_field( $this->get_request_var( 'order', 'DESC' ) );
$category = $this->get_category();
$args = array(
'post_type' => 'download',
'post_status' => 'publish',
'order' => $order,
'fields' => 'ids',
'posts_per_page' => $this->per_page,
'paged' => $this->get_paged(),
'suppress_filters' => true
);
if ( ! empty( $category ) ) {
$args['tax_query'] = array(
array(
'taxonomy' => 'download_category',
'terms' => $category
)
);
}
switch ( $orderby ) {
case 'title' :
$args['orderby'] = 'title';
break;
case 'sales' :
$args['orderby'] = 'meta_value_num';
$args['meta_key'] = '_edd_download_sales';
break;
case 'earnings' :
$args['orderby'] = 'meta_value_num';
$args['meta_key'] = '_edd_download_earnings';
break;
}
$r = apply_filters( 'edd_download_reports_prepare_items_args', $args, $this );
$this->products = new WP_Query( $r );
}
/**
* Build and retrieves all of the download reports data.
*
* @since 1.5
* @deprecated 3.0 Use get_data()
*
* @return array All the data for customer reports.
*/
public function reports_data() {
_edd_deprecated_function( __METHOD__, '3.0', 'EDD_Download_Reports_Table::get_data()' );
return $this->get_data();
}
/**
* Retrieves all of the download reports data.
*
* @since 3.0
*
* @return array Download reports table data.
*/
public function get_data() {
$reports_data = array();
$downloads = $this->products->posts;
if ( $downloads ) {
foreach ( $downloads as $download ) {
$reports_data[] = array(
'ID' => $download,
'title' => get_the_title( $download ),
'sales' => edd_get_download_sales_stats( $download ),
'earnings' => edd_get_download_earnings_stats( $download ),
'average_sales' => edd_get_average_monthly_download_sales( $download ),
'average_earnings' => edd_get_average_monthly_download_earnings( $download ),
);
}
}
return $reports_data;
}
/**
* Setup the final data for the table
*
* @since 1.5
* @uses EDD_Download_Reports_Table::get_columns()
* @uses EDD_Download_Reports_Table::get_sortable_columns()
* @uses EDD_Download_Reports_Table::get_total_downloads()
* @uses EDD_Download_Reports_Table::get_data()
* @uses EDD_Download_Reports_Table::set_pagination_args()
* @return void
*/
public function prepare_items() {
$this->_column_headers = array(
$this->get_columns(),
array(),
$this->get_sortable_columns()
);
$total_items = $this->get_total_downloads();
$this->items = $this->get_data();
$this->set_pagination_args( array(
'total_pages' => ceil( $total_items / $this->per_page ),
'total_items' => $total_items,
'per_page' => $this->per_page,
) );
}
}

View File

@ -0,0 +1,291 @@
<?php
/**
* Graphs
*
* This class handles building pretty report graphs
*
* @package EDD
* @subpackage Admin/Reports
* @copyright Copyright (c) 2018, Easy Digital Downloads, LLC
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
* @since 1.9
*/
// Exit if accessed directly
defined( 'ABSPATH' ) || exit;
/**
* EDD_Graph Class
*
* @since 1.9
*/
class EDD_Graph {
/*
Simple example:
data format for each point: array( location on x, location on y )
$data = array(
'Label' => array(
array( 1, 5 ),
array( 3, 8 ),
array( 10, 2 )
),
'Second Label' => array(
array( 1, 7 ),
array( 4, 5 ),
array( 12, 8 )
)
);
$graph = new EDD_Graph( $data );
$graph->display();
*/
/**
* Data to graph
*
* @var array
* @since 1.9
*/
private $data;
/**
* Unique ID for the graph
*
* @var string
* @since 1.9
*/
private $id = '';
/**
* Graph options
*
* @var array
* @since 1.9
*/
private $options = array();
/**
* Get things started
*
* @since 1.9
*/
public function __construct( $_data ) {
$this->data = $_data;
// Generate unique ID
$this->id = 'a' . md5( rand() );
// Setup default options;
$this->options = array(
'y_mode' => null,
'x_mode' => null,
'y_decimals' => 0,
'x_decimals' => 0,
'y_position' => 'right',
'time_format' => '%d/%b',
'ticksize_unit' => 'day',
'ticksize_num' => 1,
'multiple_y_axes' => false,
'bgcolor' => '#f9f9f9',
'bordercolor' => '#ccc',
'color' => '#bbb',
'borderwidth' => 2,
'bars' => false,
'lines' => true,
'points' => true,
'additional_options' => '',
);
}
/**
* Set an option
*
* @param $key The option key to set
* @param $value The value to assign to the key
* @since 1.9
*/
public function set( $key, $value ) {
$this->options[ $key ] = $value;
}
/**
* Get an option
*
* @param $key The option key to get
* @since 1.9
*/
public function get( $key ) {
return isset( $this->options[ $key ] ) ? $this->options[ $key ] : false;
}
/**
* Get graph data
*
* @since 1.9
*/
public function get_data() {
return apply_filters( 'edd_get_graph_data', $this->data, $this );
}
/**
* Load the graphing library script
*
* @since 1.9
*/
public function load_scripts() {
wp_enqueue_script( 'edd-jquery-flot', EDD_PLUGIN_URL . 'assets/js/vendor/jquery.flot.min.js' );
wp_enqueue_script( 'edd-jquery-flot-time', EDD_PLUGIN_URL . 'assets/js/vendor/jquery.flot.time.min.js' );
/**
* Fires immediately after the legacy Flot JS graphing framework is enqueued.
*
* @since 1.9
*/
do_action( 'edd_graph_load_scripts' );
}
/**
* Build the graph and return it as a string
*
* @var array
* @since 1.9
* @return string
*/
public function build_graph() {
$yaxis_count = 1;
$this->load_scripts();
ob_start();
?>
<script type="text/javascript">
jQuery( document ).ready( function($) {
$.plot(
$("#edd-graph-<?php echo $this->id; ?>"),
[
<?php foreach( $this->get_data() as $label => $data ) : ?>
{
label: "<?php echo esc_attr( $label ); ?>",
id: "<?php echo sanitize_key( $label ); ?>",
// data format is: [ point on x, value on y ]
data: [<?php foreach( $data as $point ) { echo '[' . implode( ',', $point ) . '],'; } ?>],
points: {
show: <?php echo $this->options['points'] ? 'true' : 'false'; ?>,
},
bars: {
show: <?php echo $this->options['bars'] ? 'true' : 'false'; ?>,
barWidth: 12,
aling: 'center'
},
lines: {
show: <?php echo $this->options['lines'] ? 'true' : 'false'; ?>
},
<?php if( $this->options['multiple_y_axes'] ) : ?>
yaxis: <?php echo $yaxis_count; ?>
<?php endif; ?>
},
<?php $yaxis_count++; endforeach; ?>
],
{
// Options
grid: {
show: true,
aboveData: false,
color: "<?php echo $this->options['color']; ?>",
backgroundColor: "<?php echo $this->options['bgcolor']; ?>",
borderColor: "<?php echo $this->options['bordercolor']; ?>",
borderWidth: <?php echo absint( $this->options['borderwidth'] ); ?>,
clickable: false,
hoverable: true
},
xaxis: {
mode: "<?php echo $this->options['x_mode']; ?>",
timeFormat: "<?php echo $this->options['x_mode'] == 'time' ? $this->options['time_format'] : ''; ?>",
tickSize: "<?php echo $this->options['x_mode'] == 'time' ? '' : $this->options['ticksize_num']; ?>",
<?php if( $this->options['x_mode'] != 'time' ) : ?>
tickDecimals: <?php echo $this->options['x_decimals']; ?>
<?php endif; ?>
},
yaxis: {
position: 'right',
min: 0,
mode: "<?php echo $this->options['y_mode']; ?>",
timeFormat: "<?php echo $this->options['y_mode'] == 'time' ? $this->options['time_format'] : ''; ?>",
<?php if( $this->options['y_mode'] != 'time' ) : ?>
tickDecimals: <?php echo $this->options['y_decimals']; ?>
<?php endif; ?>
},
<?php echo $this->options['additional_options']; ?>
}
);
function edd_flot_tooltip(x, y, contents) {
$('<div id="edd-flot-tooltip">' + contents + '</div>').css( {
position: 'absolute',
display: 'none',
top: y + 5,
left: x + 5,
border: '1px solid #fdd',
padding: '2px',
'background-color': '#fee',
opacity: 0.80,
zIndex: 3,
}).appendTo("body").fadeIn(200);
}
var previousPoint = null;
$("#edd-graph-<?php echo $this->id; ?>").bind("plothover", function (event, pos, item) {
$("#x").text(pos.x.toFixed(2));
$("#y").text(pos.y.toFixed(2));
if (item) {
if (previousPoint != item.dataIndex) {
previousPoint = item.dataIndex;
$("#edd-flot-tooltip").remove();
var x = item.datapoint[0].toFixed(2),
y = item.datapoint[1].toFixed(2);
if( item.series.id.includes('earnings') ) {
if( edd_vars.currency_pos == 'before' ) {
edd_flot_tooltip( item.pageX, item.pageY, item.series.label + ' ' + edd_vars.currency_sign + y );
} else {
edd_flot_tooltip( item.pageX, item.pageY, item.series.label + ' ' + y + edd_vars.currency_sign );
}
} else {
edd_flot_tooltip( item.pageX, item.pageY, item.series.label + ' ' + y.replace( '.00', '' ) );
}
}
} else {
$("#edd-flot-tooltip").remove();
previousPoint = null;
}
});
});
</script>
<div id="edd-graph-<?php echo $this->id; ?>" class="edd-graph" style="height: 300px;"></div>
<?php
return ob_get_clean();
}
/**
* Output the final graph
*
* @since 1.9
*/
public function display() {
do_action( 'edd_before_graph', $this );
echo $this->build_graph();
do_action( 'edd_after_graph', $this );
}
}

View File

@ -0,0 +1,199 @@
<?php
/**
* Graphs
*
* This class handles building pretty report graphs
*
* @package EDD
* @subpackage Admin/Reports
* @copyright Copyright (c) 2018, Easy Digital Downloads, LLC
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
* @since 2.4
*/
// Exit if accessed directly
defined( 'ABSPATH' ) || exit;
/**
* EDD_Graph Class
*
* @since 2.4
*/
class EDD_Pie_Graph extends EDD_Graph {
/*
Simple example:
data format for each point: array( location on x, location on y )
$data = array(
array( 'Label' => 'value' ),
array( 'Label 2' => 'value 2' ),
);
$graph = new EDD_Pie_Graph( $data );
$graph->display();
*/
/**
* Data to graph
*
* @var array
* @since 2.4
*/
private $data;
/**
* Unique ID for the graph
*
* @var string
* @since 2.4
*/
private $id = '';
/**
* Graph options
*
* @var array
* @since 2.4
*/
private $options = array();
/**
* Get things started
*
* @since 2.4
*/
public function __construct( $_data, $options = array() ) {
$this->data = $_data;
// Set this so filters recieving $this can quickly know if it's a graph they want to modify
$this->type = 'pie';
// Generate unique ID, add 'a' since md5 can leave a numerical first character
$this->id = 'a' . md5( rand() );
// Setup default options;
$this->options = wp_parse_args( $options, array(
'radius' => 1,
'legend' => true,
'legend_formatter' => false,
'legend_columns' => 3,
'legend_position' => 's',
'show_labels' => false,
'label_threshold' => 0.01,
'label_formatter' => 'eddLabelFormatter',
'label_bg_opacity' => 0.75,
'label_radius' => 1,
'height' => '300',
'hoverable' => true,
'clickable' => false,
'threshold' => false,
) );
add_action( 'edd_graph_load_scripts', array( $this, 'load_additional_scripts' ) );
}
/**
* Load the graphing library script
*
* @since 2.4
*/
public function load_additional_scripts() {
wp_enqueue_script( 'edd-jquery-flot-pie', EDD_PLUGIN_URL . 'assets/js/vendor/jquery.flot.pie.min.js' );
}
/**
* Build the graph and return it as a string
*
* @var array
* @since 2.4
* @return string
*/
public function build_graph() {
if ( count( $this->data ) ) {
$this->load_scripts();
ob_start();
?>
<script type="text/javascript">
var <?php echo $this->id; ?>_data = [
<?php foreach ( $this->data as $label => $value ) : ?>
<?php echo '{ label: "' . esc_attr( $label ) . '", data: "' . $value . '" },' . "\n"; ?>
<?php endforeach; ?>
];
var <?php echo $this->id; ?>_options = {
series: {
pie: {
show: true,
radius: <?php echo $this->options['radius']; ?>,
label: [],
},
edd_vars: {
id: '<?php echo $this->id; ?>',
}
},
legend: {
show: <?php echo $this->options['legend']; ?>,
},
grid: {},
};
<?php if ( true === $this->options['show_labels'] ) : ?>
<?php echo $this->id; ?>_options.series.pie.label.show = true;
<?php echo $this->id; ?>_options.series.pie.label.formatter = <?php echo $this->options['label_formatter']; ?>;
<?php echo $this->id; ?>_options.series.pie.label.threshold = <?php echo $this->options['label_threshold']; ?>;
<?php echo $this->id; ?>_options.series.pie.label.radius = <?php echo $this->options['label_radius']; ?>;
<?php echo $this->id; ?>_options.series.pie.label.background = { opacity: <?php echo $this->options['label_bg_opacity']; ?> };
<?php endif; ?>
<?php if ( true === $this->options['legend'] && ! empty( $this->options['legend_formatter'] ) ) : ?>
<?php echo $this->id; ?>_options.legend.labelFormatter = <?php echo $this->options['legend_formatter']; ?>;
<?php echo $this->id; ?>_options.legend.noColumns = <?php echo $this->options['legend_columns']; ?>;
<?php echo $this->id; ?>_options.legend.position = "<?php echo $this->options['legend_position']; ?>";
<?php endif; ?>
<?php if ( true === $this->options['hoverable'] ) : ?>
<?php echo $this->id; ?>_options.grid.hoverable = true;
<?php endif; ?>
<?php if ( true === $this->options['clickable'] ) : ?>
<?php echo $this->id; ?>_options.grid.clickable = true;
<?php endif; ?>
jQuery( document ).ready( function($) {
var <?php echo $this->id; ?>Chart = $('#edd-pie-graph-<?php echo $this->id; ?>');
$.plot( <?php echo $this->id; ?>Chart, <?php echo $this->id; ?>_data, <?php echo $this->id; ?>_options );
<?php if ( ! wp_is_mobile() ) : ?>
$(<?php echo $this->id; ?>Chart).on('plothover', function (event, pos, item) {
$('.edd-legend-item-wrapper').css('background-color', 'inherit');
if ( item ) {
var label = item.series.label;
var id = item.series.edd_vars.id;
var slug = label.toLowerCase().replace(/\s/g, '-');
var legendTarget = '#' + id + slug;
$('.edd-legend-item-wrapper' + legendTarget).css('background-color', '#f0f0f0');
}
});
<?php endif; ?>
});
</script>
<div class="edd-pie-graph-wrap">
<div id="edd-pie-graph-<?php echo $this->id; ?>" class="edd-pie-graph" style="height: <?php echo $this->options['height']; ?>px;"></div>
<div id="edd-pie-legend-<?php echo $this->id; ?>" class="edd-pie-legend"></div>
</div>
<?php
}
return apply_filters( 'edd_pie_graph_output', ob_get_clean(), $this->id, $this->data, $this->options );
}
}

View File

@ -0,0 +1,165 @@
<?php
/**
* Customers Export Class
*
* This class handles customer export
*
* @package EDD
* @subpackage Admin/Reports
* @copyright Copyright (c) 2018, Easy Digital Downloads, LLC
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
* @since 1.4.4
*/
// Exit if accessed directly
defined( 'ABSPATH' ) || exit;
/**
* EDD_Customers_Export Class
*
* @since 1.4.4
*/
class EDD_Customers_Export extends EDD_Export {
/**
* Our export type. Used for export-type specific filters/actions
*
* @var string
* @since 1.4.4
*/
public $export_type = 'customers';
/**
* Set the export headers
*
* @since 1.4.4
* @return void
*/
public function headers() {
edd_set_time_limit();
$extra = '';
if ( ! empty( $_POST['edd_export_download'] ) ) {
$extra = sanitize_title( get_the_title( absint( $_POST['edd_export_download'] ) ) ) . '-';
}
nocache_headers();
header( 'Content-Type: text/csv; charset=utf-8' );
header( 'Content-Disposition: attachment; filename="' . apply_filters( 'edd_customers_export_filename', 'edd-export-' . $extra . $this->export_type . '-' . date( 'm-d-Y' ) ) . '.csv"' );
header( 'Expires: 0' );
}
/**
* Set the CSV columns
*
* @since 1.4.4
* @return array $cols All the columns
*/
public function csv_cols() {
if ( ! empty( $_POST['edd_export_download'] ) ) {
$cols = array(
'first_name' => __( 'First Name', 'easy-digital-downloads' ),
'last_name' => __( 'Last Name', 'easy-digital-downloads' ),
'email' => __( 'Email', 'easy-digital-downloads' ),
'date' => __( 'Date Purchased', 'easy-digital-downloads' )
);
} else {
$cols = array();
if( 'emails' != $_POST['edd_export_option'] ) {
$cols['name'] = __( 'Name', 'easy-digital-downloads' );
}
$cols['email'] = __( 'Email', 'easy-digital-downloads' );
if( 'full' == $_POST['edd_export_option'] ) {
$cols['purchases'] = __( 'Total Purchases', 'easy-digital-downloads' );
$cols['amount'] = __( 'Total Purchased', 'easy-digital-downloads' ) . ' (' . html_entity_decode( edd_currency_filter( '' ) ) . ')';
}
}
return $cols;
}
/**
* Get the Export Data
*
* @since 1.4.4
* @global object $wpdb Used to query the database using the WordPress
* Database API
* @global object $edd_logs EDD Logs Object
* @return array $data The data for the CSV file
*/
public function get_data() {
$data = array();
if ( ! empty( $_POST['edd_export_download'] ) ) {
$edd_logs = EDD()->debug_log;
$args = array(
'post_parent' => absint( $_POST['edd_export_download'] ),
'log_type' => 'sale',
'nopaging' => true
);
if( isset( $_POST['edd_price_option'] ) ) {
$args['meta_query'] = array(
array(
'key' => '_edd_log_price_id',
'value' => (int) $_POST['edd_price_option']
)
);
}
$logs = $edd_logs->get_connected_logs( $args );
if ( $logs ) {
foreach ( $logs as $log ) {
$payment_id = get_post_meta( $log->ID, '_edd_log_payment_id', true );
$user_info = edd_get_payment_meta_user_info( $payment_id );
$data[] = array(
'first_name' => $user_info['first_name'],
'last_name' => $user_info['last_name'],
'email' => $user_info['email'],
'date' => $log->post_date
);
}
}
} else {
// Export all customers
$customers = edd_get_customers( array(
'limit' => 9999999,
) );
$i = 0;
foreach ( $customers as $customer ) {
if( 'emails' != $_POST['edd_export_option'] ) {
$data[$i]['name'] = $customer->name;
}
$data[$i]['email'] = $customer->email;
if( 'full' == $_POST['edd_export_option'] ) {
$data[$i]['purchases'] = $customer->purchase_count;
$data[$i]['amount'] = edd_format_amount( $customer->purchase_value );
}
$i++;
}
}
$data = apply_filters( 'edd_export_get_data', $data );
$data = apply_filters( 'edd_export_get_data_' . $this->export_type, $data );
return $data;
}
}

View File

@ -0,0 +1,113 @@
<?php
/**
* Customers Export Class
*
* This class handles customer export
*
* @package EDD
* @subpackage Admin/Reports
* @copyright Copyright (c) 2018, Easy Digital Downloads, LLC
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
* @since 1.4.4
*/
// Exit if accessed directly
defined( 'ABSPATH' ) || exit;
/**
* EDD_Download_History_Export Class
*
* @since 1.4.4
*/
class EDD_Download_History_Export extends EDD_Export {
/**
* Our export type. Used for export-type specific filters/actions
*
* @var string
* @since 1.4.4
*/
public $export_type = 'download_history';
/**
* Set the export headers
*
* @since 1.4.4
* @return void
*/
public function headers() {
edd_set_time_limit();
$month = isset( $_POST['month'] ) ? absint( $_POST['month'] ) : date( 'n' );
$year = isset( $_POST['year'] ) ? absint( $_POST['year'] ) : date( 'Y' );
nocache_headers();
header( 'Content-Type: text/csv; charset=utf-8' );
header( 'Content-Disposition: attachment; filename="' . apply_filters( 'edd_download_history_export_filename', 'edd-export-' . $this->export_type . '-' . $month . '-' . $year ) . '.csv"' );
header( 'Expires: 0' );
}
/**
* Set the CSV columns
*
* @since 1.4.4
* @return array $cols All the columns
*/
public function csv_cols() {
$cols = array(
'date' => __( 'Date', 'easy-digital-downloads' ),
'user' => __( 'Downloaded by', 'easy-digital-downloads' ),
'ip' => __( 'IP Address', 'easy-digital-downloads' ),
'download' => __( 'Product', 'easy-digital-downloads' ),
'file' => __( 'File', 'easy-digital-downloads' )
);
return $cols;
}
/**
* Get the Export Data
*
* @since 1.4.4
* @global object $edd_logs EDD Logs Object
* @return array $data The data for the CSV file
*/
public function get_data() {
$edd_logs = EDD()->debug_log;
$data = array();
$args = array(
'nopaging' => true,
'log_type' => 'file_download',
'monthnum' => isset( $_POST['month'] ) ? absint( $_POST['month'] ) : date( 'n' ),
'year' => isset( $_POST['year'] ) ? absint( $_POST['year'] ) : date( 'Y' )
);
$logs = $edd_logs->get_connected_logs( $args );
if ( $logs ) {
foreach ( $logs as $log ) {
$user_info = get_post_meta( $log->ID, '_edd_log_user_info', true );
$files = edd_get_download_files( $log->post_parent );
$file_id = (int) get_post_meta( $log->ID, '_edd_log_file_id', true );
$file_name = isset( $files[ $file_id ]['name'] ) ? $files[ $file_id ]['name'] : null;
$user = get_userdata( $user_info['id'] );
$user = $user ? $user->user_login : $user_info['email'];
$data[] = array(
'date' => $log->post_date,
'user' => $user,
'ip' => get_post_meta( $log->ID, '_edd_log_ip', true ),
'download' => get_the_title( $log->post_parent ),
'file' => $file_name
);
}
}
$data = apply_filters( 'edd_export_get_data', $data );
$data = apply_filters( 'edd_export_get_data_' . $this->export_type, $data );
return $data;
}
}

View File

@ -0,0 +1,201 @@
<?php
/**
* Payments Export Class
*
* This class handles payment export
*
* @package EDD
* @subpackage Admin/Reports
* @copyright Copyright (c) 2018, Easy Digital Downloads, LLC
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
* @since 1.4.4
*/
// Exit if accessed directly
defined( 'ABSPATH' ) || exit;
/**
* EDD_Payments_Export Class
*
* @since 1.4.4
*/
class EDD_Payments_Export extends EDD_Export {
/**
* Our export type. Used for export-type specific filters/actions
* @var string
* @since 1.4.4
*/
public $export_type = 'payments';
/**
* Set the export headers
*
* @since 1.6
* @return void
*/
public function headers() {
edd_set_time_limit();
$month = isset( $_POST['month'] ) ? absint( $_POST['month'] ) : date( 'n' );
$year = isset( $_POST['year'] ) ? absint( $_POST['year'] ) : date( 'Y' );
nocache_headers();
header( 'Content-Type: text/csv; charset=utf-8' );
header( 'Content-Disposition: attachment; filename="' . apply_filters( 'edd_payments_export_filename', 'edd-export-' . $this->export_type . '-' . $month . '-' . $year ) . '.csv"' );
header( 'Expires: 0' );
}
/**
* Set the CSV columns
*
* @since 1.4.4
* @return array $cols All the columns
*/
public function csv_cols() {
$cols = array(
'id' => __( 'ID', 'easy-digital-downloads' ), // unaltered payment ID (use for querying)
'seq_id' => __( 'Payment Number', 'easy-digital-downloads' ), // sequential payment ID
'email' => __( 'Email', 'easy-digital-downloads' ),
'first' => __( 'First Name', 'easy-digital-downloads' ),
'last' => __( 'Last Name', 'easy-digital-downloads' ),
'address1' => __( 'Address', 'easy-digital-downloads' ),
'address2' => __( 'Address (Line 2)', 'easy-digital-downloads' ),
'city' => __( 'City', 'easy-digital-downloads' ),
'state' => __( 'State', 'easy-digital-downloads' ),
'country' => __( 'Country', 'easy-digital-downloads' ),
'zip' => __( 'Zip / Postal Code', 'easy-digital-downloads' ),
'products' => __( 'Products', 'easy-digital-downloads' ),
'skus' => __( 'SKUs', 'easy-digital-downloads' ),
'currency' => __( 'Currency', 'easy-digital-downloads' ),
'amount' => __( 'Amount', 'easy-digital-downloads' ),
'tax' => __( 'Tax', 'easy-digital-downloads' ),
'discount' => __( 'Discount Code', 'easy-digital-downloads' ),
'gateway' => __( 'Payment Method', 'easy-digital-downloads' ),
'trans_id' => __( 'Transaction ID', 'easy-digital-downloads' ),
'key' => __( 'Purchase Key', 'easy-digital-downloads' ),
'date' => __( 'Date', 'easy-digital-downloads' ),
'user' => __( 'User', 'easy-digital-downloads' ),
'status' => __( 'Status', 'easy-digital-downloads' )
);
if( ! edd_use_skus() ){
unset( $cols['skus'] );
}
if ( ! edd_get_option( 'enable_sequential' ) ) {
unset( $cols['seq_id'] );
}
return $cols;
}
/**
* Get the Export Data
*
* @since 1.4.4
* @global object $wpdb Used to query the database using the WordPress
* Database API
* @return array $data The data for the CSV file
*/
public function get_data() {
global $wpdb;
$data = array();
$payments = edd_get_payments( array(
'offset' => 0,
'number' => 9999999,
'mode' => edd_is_test_mode() ? 'test' : 'live',
'status' => isset( $_POST['edd_export_payment_status'] ) ? $_POST['edd_export_payment_status'] : 'any',
'month' => isset( $_POST['month'] ) ? absint( $_POST['month'] ) : date( 'n' ),
'year' => isset( $_POST['year'] ) ? absint( $_POST['year'] ) : date( 'Y' )
) );
foreach ( $payments as $payment ) {
$payment_meta = edd_get_payment_meta( $payment->ID );
$user_info = edd_get_payment_meta_user_info( $payment->ID );
$downloads = edd_get_payment_meta_cart_details( $payment->ID );
$total = edd_get_payment_amount( $payment->ID );
$user_id = isset( $user_info['id'] ) && $user_info['id'] != -1 ? $user_info['id'] : $user_info['email'];
$products = '';
$skus = '';
if ( $downloads ) {
foreach ( $downloads as $key => $download ) {
// Download ID
$id = isset( $payment_meta['cart_details'] ) ? $download['id'] : $download;
// If the download has variable prices, override the default price
$price_override = isset( $payment_meta['cart_details'] ) ? $download['price'] : null;
$price = edd_get_download_final_price( $id, $user_info, $price_override );
// Display the Downoad Name
$products .= get_the_title( $id ) . ' - ';
if ( edd_use_skus() ) {
$sku = edd_get_download_sku( $id );
if ( ! empty( $sku ) )
$skus .= $sku;
}
if ( isset( $downloads[ $key ]['item_number'] ) && isset( $downloads[ $key ]['item_number']['options'] ) ) {
$price_options = $downloads[ $key ]['item_number']['options'];
if ( isset( $price_options['price_id'] ) ) {
$products .= edd_get_price_option_name( $id, $price_options['price_id'], $payment->ID ) . ' - ';
}
}
$products .= html_entity_decode( edd_currency_filter( $price ) );
if ( $key != ( count( $downloads ) -1 ) ) {
$products .= ' / ';
if( edd_use_skus() )
$skus .= ' / ';
}
}
}
if ( is_numeric( $user_id ) ) {
$user = get_userdata( $user_id );
} else {
$user = false;
}
$currency_code = edd_get_payment_currency_code( $payment->ID );
$data[] = array(
'id' => $payment->ID,
'seq_id' => edd_get_payment_number( $payment->ID ),
'email' => $payment_meta['email'],
'first' => $user_info['first_name'],
'last' => $user_info['last_name'],
'address1' => isset( $user_info['address']['line1'] ) ? $user_info['address']['line1'] : '',
'address2' => isset( $user_info['address']['line2'] ) ? $user_info['address']['line2'] : '',
'city' => isset( $user_info['address']['city'] ) ? $user_info['address']['city'] : '',
'state' => isset( $user_info['address']['state'] ) ? $user_info['address']['state'] : '',
'country' => isset( $user_info['address']['country'] ) ? $user_info['address']['country'] : '',
'zip' => isset( $user_info['address']['zip'] ) ? $user_info['address']['zip'] : '',
'products' => $products,
'skus' => $skus,
'currency' => $currency_code,
'amount' => html_entity_decode( edd_format_amount( $total, $currency_code ) ),
'tax' => html_entity_decode( edd_format_amount( edd_get_payment_tax( $payment->ID, $payment_meta ), $currency_code ) ),
'discount' => isset( $user_info['discount'] ) && $user_info['discount'] != 'none' ? $user_info['discount'] : __( 'none', 'easy-digital-downloads' ),
'gateway' => edd_get_gateway_admin_label( edd_get_payment_meta( $payment->ID, '_edd_payment_gateway', true ) ),
'trans_id' => edd_get_payment_transaction_id( $payment->ID ),
'key' => $payment_meta['key'],
'date' => $payment->post_date,
'user' => $user ? $user->display_name : __( 'guest', 'easy-digital-downloads' ),
'status' => edd_get_payment_status( $payment, true )
);
}
$data = apply_filters( 'edd_export_get_data', $data );
$data = apply_filters( 'edd_export_get_data_' . $this->export_type, $data );
return $data;
}
}

View File

@ -0,0 +1,202 @@
<?php
/**
* Base export class.
*
* This is the base class for all export methods. Each data export type (customers, payments, etc) extend this class.
*
* @package EDD
* @subpackage Admin/Reports
* @copyright Copyright (c) 2018, Easy Digital Downloads, LLC
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
* @since 1.4.4
*/
// Exit if accessed directly
defined( 'ABSPATH' ) || exit;
/**
* EDD_Export Class
*
* @since 1.4.4
*/
class EDD_Export {
/**
* Our export type. Used for export-type specific filters/actions
* @var string
* @since 1.4.4
*/
public $export_type = 'default';
/**
* Can we export?
*
* @since 1.4.4
*
* @return bool True if exporting is allowed, false otherwise.
*/
public function can_export() {
return (bool) apply_filters( 'edd_export_capability', current_user_can( 'export_shop_reports' ) );
}
/**
* Set the export headers.
*
* @since 1.4.4
* @since 3.0 Add BOM to the CSV export.
*/
public function headers() {
edd_set_time_limit();
nocache_headers();
header( 'Content-Type: text/csv; charset=utf-8' );
header( 'Content-Disposition: attachment; filename="edd-export-' . $this->export_type . '-' . date( 'm-d-Y' ) . '.csv"' );
header( 'Expires: 0' );
/**
* We need to append a BOM to the export so that Microsoft Excel knows
* that the file is in Unicode.
*
* @see https://github.com/easydigitaldownloads/easy-digital-downloads/issues/4859
*/
echo "\xEF\xBB\xBF";
}
/**
* Set the CSV columns.
*
* @since 1.4.4
*
* @return array $cols CSV columns.
*/
public function csv_cols() {
$cols = array(
'id' => __( 'ID', 'easy-digital-downloads' ),
'date' => __( 'Date', 'easy-digital-downloads' ),
);
return $cols;
}
/**
* Retrieve the CSV columns.
*
* @since 1.4.4
*
* @return array $cols Array of the columns.
*/
public function get_csv_cols() {
$cols = $this->csv_cols();
return apply_filters( 'edd_export_csv_cols_' . $this->export_type, $cols );
}
/**
* Output the CSV columns.
*
* @since 1.4.4
*/
public function csv_cols_out() {
$cols = $this->get_csv_cols();
$i = 1;
// Output each column.
foreach ( $cols as $col_id => $column ) {
echo '"' . addslashes( $column ) . '"';
echo count( $cols ) === $i
? ''
: ',';
$i++;
}
echo "\r\n";
}
/**
* Get the data being exported.
*
* @since 1.4.4
*
* @return array $data Data for export.
*/
public function get_data() {
// Just a sample data array
$data = array(
0 => array(
'id' => '',
'data' => date( 'F j, Y' ),
),
1 => array(
'id' => '',
'data' => date( 'F j, Y' ),
),
);
$data = apply_filters( 'edd_export_get_data', $data );
$data = apply_filters( 'edd_export_get_data_' . $this->export_type, $data );
return $data;
}
/**
* Output the CSV rows.
*
* @since 1.4.4
*/
public function csv_rows_out() {
$data = $this->get_data();
$cols = $this->get_csv_cols();
// Output each row.
foreach ( $data as $row ) {
$i = 1;
foreach ( $row as $col_id => $column ) {
// Make sure the column is valid.
if ( array_key_exists( $col_id, $cols ) ) {
echo '"' . addslashes( $column ) . '"';
echo count( $cols ) === $i
? ''
: ',';
$i++;
}
}
echo "\r\n";
}
}
/**
* Perform the export.
*
* @since 1.4.4
*
*
* @uses EDD_Export::can_export()
* @uses EDD_Export::headers()
* @uses EDD_Export::csv_cols_out()
* @uses EDD_Export::csv_rows_out()
*/
public function export() {
// Bail if user if unauthorized.
if ( ! $this->can_export() ) {
wp_die( __( 'You do not have permission to export data.', 'easy-digital-downloads' ), __( 'Error', 'easy-digital-downloads' ), array( 'response' => 403 ) );
}
// Set headers
$this->headers();
// Output CSV columns (headers)
$this->csv_cols_out();
// Output CSV rows
$this->csv_rows_out();
edd_die();
}
}

View File

@ -0,0 +1,257 @@
<?php
/**
* File Downloads Log List Table.
*
* @package EDD
* @subpackage Admin/Reports
* @copyright Copyright (c) 2018, Easy Digital Downloads, LLC
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
* @since 1.4.4
* @since 3.0 Updated to use the custom tables.
*/
use EDD\Logs\File_Download_Log;
// Exit if accessed directly
defined( 'ABSPATH' ) || exit;
/**
* EDD_File_Downloads_Log_Table Class
*
* @since 1.4
* @since 3.0 Updated to use the custom tables and new query classes.
*/
class EDD_File_Downloads_Log_Table extends EDD_Base_Log_List_Table {
/**
* Log type
*
* @var string
*/
protected $log_type = 'file_downloads';
/**
* Are we searching for files?
*
* @var bool
* @since 1.4
*/
public $file_search = false;
/**
* Store each unique product's files so they only need to be queried once
*
* @var array
* @since 1.9
*/
private $queried_files = array();
/**
* Get things started
*
* @since 1.4
* @see WP_List_Table::__construct()
*/
public function __construct() {
parent::__construct();
}
/**
* This function renders most of the columns in the list table.
*
* @since 1.4
*
* @param array $item Contains all the data of the log item.
* @param string $column_name The name of the column.
*
* @return string Column Name
*/
public function column_default( $item, $column_name ) {
$base_url = remove_query_arg( 'paged' );
switch ( $column_name ) {
case 'download' :
$download = new EDD_Download( $item[ $column_name ] );
$column_value = ! empty( $item['price_id'] )
? edd_get_download_name( $download->ID, $item['price_id'] )
: edd_get_download_name( $download->ID );
return '<a href="' . esc_url( add_query_arg( 'download', absint( $download->ID ), $base_url ) ) . '" >' . esc_html( $column_value ) . '</a>';
case 'customer' :
return ! empty( $item[ 'customer' ]->id )
? '<a href="' . esc_url( add_query_arg( 'customer', absint( $item['customer']->id ), $base_url ) ) . '">' . esc_html( $item['customer']->name ) . '</a>'
: '&mdash;';
case 'payment_id' :
$number = edd_get_payment_number( $item['payment_id'] );
return ! empty( $number )
? '<a href="' . esc_url( edd_get_admin_url( array( 'page' => 'edd-payment-history', 'view' => 'view-order-details', 'id' => absint( $item['payment_id'] ) ) ) ) . '">' . esc_html( $number ) . '</a>'
: '&mdash;';
case 'ip' :
return '<a href="' . esc_url( 'https://ipinfo.io/' . esc_attr( $item['ip'] ) ) . '" target="_blank" rel="noopener noreferrer">' . esc_html( $item['ip'] ) . '</a>';
case 'file':
return ! empty( $item['file'] )
? esc_html( $item['file'] )
: '&mdash;';
default:
return $item[ $column_name ];
}
}
/**
* Set the table columns.
*
* @since 1.4
*
* @return array $columns Array of all the list table columns
*/
public function get_columns() {
return array(
'ID' => __( 'Log ID', 'easy-digital-downloads' ),
'download' => edd_get_label_singular(),
'customer' => __( 'Customer', 'easy-digital-downloads' ),
'payment_id' => __( 'Order Number', 'easy-digital-downloads' ),
'file' => __( 'File', 'easy-digital-downloads' ),
'ip' => __( 'IP Address', 'easy-digital-downloads' ),
'user_agent' => __( 'User Agent', 'easy-digital-downloads' ),
'date' => __( 'Date', 'easy-digital-downloads' )
);
}
/**
* Gets the log entries for the current view
*
* @since 1.4
*
* @param $log_query array Arguments for getting logs.
*
* @return array $logs_data Array of all the logs.
*/
function get_logs( $log_query = array() ) {
$logs_data = array();
$logs = edd_get_file_download_logs( $log_query );
if ( $logs ) {
foreach ( $logs as $log ) {
/** @var $log File_Download_Log */
$customer_id = ! empty( $log->customer_id ) ? (int) $log->customer_id : edd_get_payment_customer_id( $log->order_id );
$files = $this->get_log_files( $log, $customer_id );
$file_id = $log->file_id;
/**
* Filters the ID of the file that was actually downloaded from this log.
*
* @param int $file_id
* @param File_Download_Log $log
*/
$file_id = apply_filters( 'edd_log_file_download_file_id', $file_id, $log );
$file_name = '';
if ( ! empty( $files ) && is_numeric( $file_id ) && isset( $files[ $file_id ] ) ) {
$file_name = ! empty( $files[ $file_id ]['name'] )
? $files[ $file_id ]['name']
: edd_get_file_name( $files[ $file_id ] );
}
if ( empty( $this->file_search ) || ( ! empty( $this->file_search ) && strpos( strtolower( $file_name ), strtolower( $this->get_search() ) ) !== false ) ) {
$logs_data[] = array(
'ID' => $log->id,
'download' => $log->product_id,
'customer' => new EDD_Customer( $customer_id ),
'payment_id' => $log->order_id,
'price_id' => $log->price_id,
'file' => $file_name,
'ip' => $log->ip,
'user_agent' => $log->user_agent,
'date' => $log->date_created,
);
}
}
}
return $logs_data;
}
/**
* Retrieves the array of files associated with the log.
*
* This method contains a lot of logic to ensure backwards compatibility with how
* the `edd_log_file_download_download_files` filter was formatted in EDD 2.x.
*
* @since 3.0
*
* @param File_Download_Log $log
* @param int $customer_id
*
* @return array
*/
protected function get_log_files( File_Download_Log $log, $customer_id ) {
$customer = ! empty( $customer_id ) ? edd_get_customer( $customer_id ) : false;
/*
* Get the files associated with this download and store them in a property to prevent
* multiple queries for the same download.
* This is needed for backwards compatibility in the `edd_log_file_download_download_files` filter.
*/
if ( ! array_key_exists( $log->product_id, $this->queried_files ) ) {
$files = get_post_meta( $log->product_id, 'edd_download_files', true );
$this->queried_files[ $log->product_id ] = $files;
} else {
$files = $this->queried_files[ $log->product_id ];
}
/*
* User info is needed for backwards compatibility in the `edd_log_file_download_download_files` filter.
*/
$user = ! empty( $customer->user_id ) ? get_userdata( $customer->user_id ) : false;
$user_info = ! empty( $user )
? array(
'id' => $user->ID,
'email' => $user->user_email,
'name' => $user->display_name,
)
: array();
/*
* Build up an array of meta.
*/
$meta = edd_get_file_download_log_meta( $log->id );
// These meta keys no longer exist, but we need to create them for use in the filter.
$backwards_compat_meta = array(
'_edd_log_user_info' => $user_info,
'_edd_log_user_id' => ! empty( $customer->user_id ) ? $customer->user_id : false,
'_edd_log_customer_id' => $customer_id,
'_edd_log_file_id' => $log->file_id,
'_edd_log_ip' => $log->ip,
'_edd_log_payment_id' => $log->order_id,
'_edd_log_price_id' => $log->price_id,
);
foreach( $backwards_compat_meta as $meta_key => $meta_value ) {
$meta[ $meta_key ] = array( $meta_value );
}
/**
* Filters the array of all files linked to the product.
*
* @param array $files Files linked to the product.
* @param File_Download_Log $log Log record from the database.
* @param array $meta What used to be the meta array in EDD 2.9 and lower.
*/
return apply_filters( 'edd_log_file_download_download_files', $files, $log, $meta );
}
/**
* Setup the final data for the table.
*
* @since 1.5
*/
public function get_total( $log_query = array() ) {
return edd_count_file_download_logs( $log_query );
}
}

View File

@ -0,0 +1,158 @@
<?php
/**
* Gateway Error Log View Class
*
* @package EDD
* @subpackage Admin/Reports
* @copyright Copyright (c) 2018, Easy Digital Downloads, LLC
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
*/
// Exit if accessed directly
defined( 'ABSPATH' ) || exit;
/**
* EDD_Gateway_Error_Log_Table Class
*
* @since 1.4
* @since 3.0 Updated to use the custom tables and new query classes.
*/
class EDD_Gateway_Error_Log_Table extends EDD_Base_Log_List_Table {
/**
* Get things started
*
* @since 1.4
* @see WP_List_Table::__construct()
*/
public function __construct() {
parent::__construct();
}
/**
* Gets the name of the primary column.
*
* @since 2.5
* @access protected
*
* @return string Name of the primary column.
*/
protected function get_primary_column_name() {
return 'ID';
}
/**
* This function renders most of the columns in the list table.
*
* @since 1.4
*
* @param array $item Contains all the data of the log item
* @param string $column_name The name of the column
*
* @return string Column Name
*/
public function column_default( $item, $column_name ) {
switch ( $column_name ) {
case 'error' :
return $item['error'];
case 'payment_id' :
return ! empty( $item['payment_id'] ) ? $item['payment_id'] : '&ndash;';
default:
return $item[ $column_name ];
}
}
/**
* Output Error Message Column
*
* @since 1.4.4
* @param array $item Contains all the data of the log
* @return void
*/
public function column_message( $item ) {
?>
<a href="#TB_inline?width=640&amp;inlineId=log-message-<?php echo esc_attr( $item['ID'] ); ?>" class="thickbox"><?php esc_html_e( 'View Log Message', 'easy-digital-downloads' ); ?></a>
<div id="log-message-<?php echo esc_attr( $item['ID'] ); ?>" style="display:none;">
<?php
$log_message = $item['content'];
$serialized = strpos( $log_message, '{"' );
// Check to see if the log message contains serialized information
if ( $serialized !== false ) {
$length = strlen( $log_message ) - $serialized;
$intro = substr( $log_message, 0, - $length );
$data = substr( $log_message, $serialized, strlen( $log_message ) - 1 );
echo wpautop( $intro );
echo '<strong>' . wpautop( __( 'Log data:', 'easy-digital-downloads' ) ) . '</strong>';
echo '<div style="word-wrap: break-word;">' . wpautop( $data ) . '</div>';
} else {
// No serialized data found
echo wpautop( $log_message );
}
?>
</div>
<?php
}
/**
* Retrieve the table columns
*
* @since 1.4
* @return array $columns Array of all the list table columns
*/
public function get_columns() {
return array(
'ID' => __( 'Log ID', 'easy-digital-downloads' ),
'payment_id' => __( 'Order Number', 'easy-digital-downloads' ),
'error' => __( 'Error', 'easy-digital-downloads' ),
'message' => __( 'Error Message', 'easy-digital-downloads' ),
'gateway' => __( 'Gateway', 'easy-digital-downloads' ),
'date' => __( 'Date', 'easy-digital-downloads' )
);
}
/**
* Gets the log entries for the current view
*
* @since 1.4
* @param array $log_query Query arguments
* @global object $edd_logs EDD Logs Object
* @return array $logs_data Array of all the Log entries
*/
public function get_logs( $log_query = array() ) {
$logs_data = array();
$log_query['type'] = 'gateway_error';
$logs = edd_get_logs( $log_query );
if ( $logs ) {
foreach ( $logs as $log ) {
/** @var $log EDD\Logs\Log */
$logs_data[] = array(
'ID' => $log->id,
'payment_id' => $log->object_id,
'error' => $log->title ? $log->title : __( 'Payment Error', 'easy-digital-downloads' ),
'gateway' => edd_get_payment_gateway( $log->object_id ),
'date' => $log->date_created,
'content' => $log->content,
);
}
}
return $logs_data;
}
/**
* Setup the final data for the table.
*
* @since 1.5
*/
public function get_total( $log_query = array() ) {
$log_query['type'] = 'gateway_error';
return edd_count_logs( $log_query );
}
}

View File

@ -0,0 +1,159 @@
<?php
/**
* Gateways Reports Table Class
*
* @package EDD
* @subpackage Admin/Reports
* @copyright Copyright (c) 2018, Easy Digital Downloads, LLC
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
* @since 1.5
*/
// Exit if accessed directly
defined( 'ABSPATH' ) || exit;
use EDD\Admin\List_Table;
/**
* EDD_Gateway_Reports_Table Class
*
* Renders the Download Reports table
*
* @since 1.5
*/
class EDD_Gateway_Reports_Table extends List_Table {
/**
* Get things started
*
* @since 1.5
* @see WP_List_Table::__construct()
*/
public function __construct() {
parent::__construct( array(
'singular' => 'report-gateway',
'plural' => 'report-gateways',
'ajax' => false
) );
}
/**
* Gets the name of the primary column.
*
* @since 2.5
* @access protected
*
* @return string Name of the primary column.
*/
protected function get_primary_column_name() {
return 'label';
}
/**
* This function renders most of the columns in the list table.
*
* @since 1.5
*
* @param array $item Contains all the data of the downloads
* @param string $column_name The name of the column
*
* @return string Column Name
*/
public function column_default( $item, $column_name ) {
return $item[ $column_name ];
}
/**
* Retrieve the table columns
*
* @since 1.5
* @return array $columns Array of all the list table columns
*/
public function get_columns() {
return array(
'label' => __( 'Gateway', 'easy-digital-downloads' ),
'complete_sales' => __( 'Complete Sales', 'easy-digital-downloads' ),
'pending_sales' => __( 'Pending / Failed Sales', 'easy-digital-downloads' ),
'total_sales' => __( 'Total Sales', 'easy-digital-downloads' )
);
}
/**
* Outputs the reporting views
*
* @since 1.5
* @return void
*/
public function bulk_actions( $which = '' ) {
// These aren't really bulk actions but this outputs the markup in
// the right place.
edd_report_views();
}
/**
* Builds and retrieves all of the payment gateways reports data.
*
* @since 1.5
* @deprecated 3.0 Use get_data()
*
* @return array All the data for customer reports.
*/
public function reports_data() {
_edd_deprecated_function( __METHOD__, '3.0', 'EDD_Gateway_Reports_Table::get_data()' );
return $this->get_data();
}
/**
* Retrieves all of the payment gateways reports data.
*
* @since 3.0
*
* @return array Payment gateways reports table data.
*/
public function get_data() {
$reports_data = array();
$gateways = edd_get_payment_gateways();
foreach ( $gateways as $gateway_id => $gateway ) {
$complete_count = edd_count_sales_by_gateway( $gateway_id, edd_get_gross_order_statuses() );
$pending_count = edd_count_sales_by_gateway( $gateway_id, edd_get_incomplete_order_statuses() );
$reports_data[] = array(
'ID' => $gateway_id,
'label' => $gateway['admin_label'],
'complete_sales' => edd_format_amount( $complete_count, false ),
'pending_sales' => edd_format_amount( $pending_count, false ),
'total_sales' => edd_format_amount( $complete_count + $pending_count, false ),
);
}
return $reports_data;
}
/**
* Setup the final data for the table
*
* @since 1.5
* @uses EDD_Gateway_Reports_Table::get_columns()
* @uses EDD_Gateway_Reports_Table::get_sortable_columns()
* @uses EDD_Gateway_Reports_Table::reports_data()
* @return void
*/
public function prepare_items() {
$columns = $this->get_columns();
$hidden = array(); // No hidden columns
$sortable = $this->get_sortable_columns();
$this->_column_headers = array( $columns, $hidden, $sortable );
$this->items = $this->get_data();
}
}
/**
* Back-compat for typo
*
* @see https://github.com/easydigitaldownloads/easy-digital-downloads/issues/6549
*/
class_alias( 'EDD_Gateway_Reports_Table', 'EDD_Gateawy_Reports_Table' );

View File

@ -0,0 +1,51 @@
<?php
/**
* Reports Sections Class.
*
* @package EDD
* @subpackage Admin
* @copyright Copyright (c) 2018, Easy Digital Downloads, LLC
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
* @since 3.0
*/
namespace EDD\Admin;
// Exit if accessed directly
defined( 'ABSPATH' ) || exit;
/**
* Class for creating a vertically tabbed UI for reports.
*
* @since 3.0
*/
class Reports_Sections extends Sections {
/**
* Output the contents
*
* @since 3.0
*/
public function display() {
$use_js = ! empty( $this->use_js )
? ' use-js'
: '';
$role = $this->use_js ? 'tablist' : 'menu';
?>
<div class="edd-sections-wrap edd-reports-wrapper">
<div class="edd-vertical-sections<?php echo $use_js; ?>">
<ul class="section-nav" role="<?php echo esc_attr( $role ); ?>">
<?php echo $this->get_all_section_links(); ?>
</ul>
<div class="section-wrap">
<?php echo $this->get_all_section_contents(); ?>
</div>
<br class="clear">
</div>
</div>
<?php
}
}

View File

@ -0,0 +1,263 @@
<?php
/**
* Sales Log Table.
*
* @package EDD
* @subpackage Admin/Reports
* @copyright Copyright (c) 2018, Easy Digital Downloads, LLC
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
*/
// Exit if accessed directly
defined( 'ABSPATH' ) || exit;
/**
* EDD_Sales_Log_Table Class.
*
* @since 1.4
* @since 3.0 Updated to use the custom tables and new query classes.
* Updated table to display order items as sales logs have been deprecated.
*/
class EDD_Sales_Log_Table extends EDD_Base_Log_List_Table {
/**
* Gets the name of the primary column.
*
* @since 2.5
* @access protected
*
* @return string Name of the primary column.
*/
protected function get_primary_column_name() {
return 'ID';
}
/**
* This function renders most of the columns in the list table.
*
* @since 1.4
*
* @param array $item Contains all the data of the log item.
* @param string $column_name The name of the column.
*
* @return string Column data.
*/
public function column_default( $item, $column_name ) {
$return = '';
$currency = $item['currency'];
switch ( $column_name ) {
case 'download':
$download_id = $item[ $column_name ];
$download = edd_get_download( $download_id );
$price_id = isset( $item['price_id'] ) && is_numeric( $item['price_id'] )
? absint( $item['price_id'] )
: null;
$title = $download->get_name( $price_id );
$return = '<a href="' . esc_url( add_query_arg( 'download', urlencode( $item[ $column_name ] ) ) ) . '" >' . esc_html( $title ) . '</a>';
break;
case 'customer':
$name = ! empty( $item['customer']->name )
? $item['customer']->name
: '<em>' . __( 'Unnamed Customer', 'easy-digital-downloads' ) . '</em>';
$return = '<a href="' . esc_url( edd_get_admin_url( array( 'page' => 'edd-customers', 'view' => 'overview', 'id' => absint( $item['customer']->id ) ) ) ) . '">#' . esc_html( $item['customer']->id ) . ' ' . esc_html( $name ) . '</a>';
break;
case 'item_price':
$return = edd_currency_filter( edd_format_amount( $item['item_price'] ), $currency );
break;
case 'amount':
$return = edd_currency_filter( edd_format_amount( $item['amount'] / $item['quantity'] ), $currency );
break;
case 'ID':
$return = '<a href="' . esc_url( edd_get_admin_url( array( 'page' => 'edd-payment-history', 'view' => 'view-order-details', 'id' => absint( $item['order_id'] ) ) ) ) . '">' . absint( $item['ID'] ) . '</a>';
break;
default:
$return = $item[ $column_name ];
break;
}
return $return;
}
/**
* Retrieve the table columns
*
* @since 1.4
* @return array $columns Array of all the list table columns
*/
public function get_columns() {
return array(
'ID' => __( 'Order Number', 'easy-digital-downloads' ),
'customer' => __( 'Customer', 'easy-digital-downloads' ),
'download' => edd_get_label_singular(),
'amount' => __( 'Item Amount', 'easy-digital-downloads' ),
'date' => __( 'Date', 'easy-digital-downloads' ),
);
}
/**
* Return array of query arguments.
*
* @since 3.0
*
* @param boolean $paginate
*
* @return array
*/
protected function get_query_args( $paginate = true ) {
$retval = parent::get_query_args( $paginate );
$user = $this->get_filtered_user();
if ( $user ) {
// Show only logs from a specific user
$retval['user_id'] = $user;
}
$search = $this->get_search();
if ( $search ) {
if ( is_email( $search ) ) {
$field = 'email';
} else {
// Look for a user
$field = 'user_id';
if ( ! is_numeric( $search ) ) {
// Searching for user by username
$user = get_user_by( 'login', $search );
if ( $user ) {
// Found one, set meta value to user's ID
$search = $user->ID;
} else {
// No user found so let's do a real search query
$users = new WP_User_Query( array(
'search' => $search,
'search_columns' => array( 'user_url', 'user_nicename' ),
'number' => 1,
'fields' => 'ids',
) );
$found_user = $users->get_results();
if ( $found_user ) {
$search = $found_user[0];
}
}
}
}
if ( ! $this->file_search ) {
$retval[ $field ] = $search;
}
}
return $retval;
}
/**
* Gets the log entries for the current view.
*
* @since 1.4
* @since 3.0 Refactored to fetch from order items table.
*
* @param array $log_query Query vars.
* @return array $data Array of all the sales.
*/
public function get_logs( $log_query = array() ) {
$data = $order_args = array();
// Customer ID
if ( ! empty( $log_query['customer_id'] ) ) {
$order_args = array(
'customer_id' => $log_query['customer_id'],
'no_found_rows' => true
);
// Customer Email
} elseif ( ! empty( $log_query['email'] ) ) {
$order_args = array(
'email' => $log_query['email'],
'no_found_rows' => true
);
}
// Maybe query for orders first
if ( ! empty( $order_args ) ) {
$orders = edd_get_orders( $order_args );
$log_query['order_id__in'] = wp_list_pluck( $orders, 'id' );
}
// Query order items
$order_items = edd_get_order_items( $log_query );
// Bail if no order items
if ( empty( $order_items ) ) {
return $data;
}
// Maybe prime orders
if ( empty( $orders ) ) {
$order_ids = array_values( array_unique( wp_list_pluck( $order_items, 'order_id' ) ) );
if ( count( $order_ids ) > 2 ) {
$orders = edd_get_orders( array(
'id__in' => $order_ids,
'no_found_rows' => true
) );
}
}
// Maybe prime customers
if ( ! empty( $orders ) ) {
$customer_ids = array_values( array_unique( wp_list_pluck( $orders, 'customer_id' ) ) );
if ( count( $customer_ids ) > 2 ) {
edd_get_customers( array(
'id__in' => $customer_ids,
'no_found_rows' => true
) );
}
}
// Loop through order items
foreach ( $order_items as $order_item ) {
$order = edd_get_order( $order_item->order_id );
$data[] = array(
'ID' => $order->get_number(),
'order_id' => $order->id,
'customer' => edd_get_customer( $order->customer_id ),
'download' => $order_item->product_id,
'price_id' => $order_item->price_id,
'item_price' => $order_item->amount,
'amount' => $order_item->total,
'date' => EDD()->utils->date( $order_item->date_created, null, true )->toDateTimeString(),
'quantity' => $order_item->quantity,
'currency' => $order->currency,
);
}
return $data;
}
/**
* Get the total number of items
*
* @since 3.0
*
* @param array $log_query
*
* @return int
*/
public function get_total( $log_query = array() ) {
return edd_count_order_items( $log_query );
}
}

View File

@ -0,0 +1,92 @@
<?php
/**
* Contextual Help
*
* @package EDD
* @subpackage Admin/Reports
* @copyright Copyright (c) 2018, Easy Digital Downloads, LLC
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
* @since 1.4
*/
use EDD\Admin\Pass_Manager;
// Exit if accessed directly
defined( 'ABSPATH' ) || exit;
/**
* Reports contextual help.
*
* @access private
* @since 1.4
* @return void
*/
function edd_reporting_contextual_help() {
$screen = get_current_screen();
if ( $screen->id != 'download_page_edd-reports' ) {
return;
}
$pass_manager = new Pass_Manager();
if ( $pass_manager->isFree() ) {
$docs_url = edd_link_helper(
'https://easydigitaldownloads.com/docs/',
array(
'utm_medium' => 'reports-contextual-help',
'utm_content' => 'documentation',
)
);
$upgrade_url = edd_link_helper(
'https://easydigitaldownloads.com/lite-upgrade/',
array(
'utm_medium' => 'reports-contextual-help',
'utm_content' => 'lite-upgrade',
)
);
$screen->set_help_sidebar(
'<p><strong>' . __( 'For more information:', 'easy-digital-downloads' ) . '</strong></p>' .
'<p>' . sprintf( __( 'Visit the <a href="%s">documentation</a> on the Easy Digital Downloads website.', 'easy-digital-downloads' ), $docs_url ) . '</p>' .
'<p>' . sprintf(
__( 'Need more from your Easy Digital Downloads store? <a href="%s">Upgrade Now</a>!', 'easy-digital-downloads' ),
$upgrade_url
) . '</p>'
);
}
$screen->add_help_tab( array(
'id' => 'edd-reports',
'title' => __( 'Reports', 'easy-digital-downloads' ),
'content' => '<p>' . __( 'This screen provides you with reports for your earnings, downloads, customers and taxes.', 'easy-digital-downloads' ) . '</p>'
) );
$screen->add_help_tab( array(
'id' => 'edd-reports-export',
'title' => __( 'Export', 'easy-digital-downloads' ),
'content' =>
'<p>' . __( 'This screen allows you to export your reports into a CSV format.', 'easy-digital-downloads' ) . '</p>' .
'<p>' . __( '<strong>Sales and Earnings</strong> - This report exports all of the sales and earnings that you have made in the current year. It includes your sales and earnings for each product as well a graphs of sales and earnings so you can compare them for each month.', 'easy-digital-downloads' ) . '</p>' .
'<p>' . __( '<strong>Payment History</strong> - This report exports all of the payments you have received on your EDD store in a CSV format. It includes the contact details of the customer, the products they have purchased as well as any discount codes they have used and the final price they have paid.', 'easy-digital-downloads' ) . '</p>' .
'<p>' . __( "<strong>Customers</strong> - This report exports all of your customers in a CSV format. It exports the customer's name and email address and the amount of products they have purchased as well as the final price of their total purchases.", 'easy-digital-downloads' ) . '</p>' .
'<p>' . __( '<strong>Download History</strong> - This report exports all of the downloads you have received in the current month into a CSV. It exports the date the file was downloaded, the customer it was downloaded by, their IP address, the name of the product and the file they downloaded.', 'easy-digital-downloads' ) . '</p>'
) );
if( ! empty( $_GET['tab'] ) && 'logs' == $_GET['tab'] ) {
$screen->add_help_tab( array(
'id' => 'edd-reports-log-search',
'title' => __( 'Search File Downloads', 'easy-digital-downloads' ),
'content' =>
'<p>' . __( 'The file download log can be searched in several different ways:', 'easy-digital-downloads' ) . '</p>' .
'<ul>
<li>' . __( 'You can enter the customer\'s email address', 'easy-digital-downloads' ) . '</li>
<li>' . __( 'You can enter the customer\'s IP address', 'easy-digital-downloads' ) . '</li>
<li>' . __( 'You can enter the download file\'s name', 'easy-digital-downloads' ) . '</li>
</ul>'
) );
}
do_action( 'edd_reports_contextual_help', $screen );
}
add_action( 'load-download_page_edd-reports', 'edd_reporting_contextual_help' );

View File

@ -0,0 +1,132 @@
<?php
/**
* Batch API Request Logs Export Class
*
* This class handles API request logs export
*
* @package EDD
* @subpackage Admin/Reporting/Export
* @copyright Copyright (c) 2018, Easy Digital Downloads, LLC
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
* @since 2.7
*/
// Exit if accessed directly
defined( 'ABSPATH' ) || exit;
/**
* EDD_Batch_API_Requests_Export Class
*
* @since 2.7
*/
class EDD_Batch_API_Requests_Export extends EDD_Batch_Export {
/**
* Our export type. Used for export-type specific filters/actions
*
* @var string
* @since 2.7
*/
public $export_type = 'api_requests';
/**
* Set the CSV columns.
*
* @since 2.7
* @return array $cols All the columns
*/
public function csv_cols() {
$cols = array(
'ID' => __( 'Log ID', 'easy-digital-downloads' ),
'request' => __( 'API Request', 'easy-digital-downloads' ),
'ip' => __( 'IP Address', 'easy-digital-downloads' ),
'user' => __( 'API User', 'easy-digital-downloads' ),
'key' => __( 'API Key', 'easy-digital-downloads' ),
'version' => __( 'API Version', 'easy-digital-downloads' ),
'speed' => __( 'Request Speed', 'easy-digital-downloads' ),
'date' => __( 'Date', 'easy-digital-downloads' )
);
return $cols;
}
/**
* Get the export data.
*
* @since 2.7
* @since 3.0 Updated to use new query methods.
*
* @return array $data The data for the CSV file.
*/
public function get_data() {
$data = array();
$args = array(
'number' => 30,
'offset' => ( $this->step * 30 ) - 30
);
if ( ! empty( $this->start ) || ! empty( $this->end ) ) {
$args['date_query'] = $this->get_date_query();
}
$logs = edd_get_api_request_logs( $args );
foreach ( $logs as $log ) {
/** @var EDD\Logs\Api_Request_Log $log */
$data[] = array(
'ID' => $log->id,
'request' => $log->request,
'ip' => $log->ip,
'user' => $log->user_id,
'key' => $log->api_key,
'version' => $log->version,
'speed' => $log->time,
'date' => $log->date_created
);
}
$data = apply_filters( 'edd_export_get_data', $data );
$data = apply_filters( 'edd_export_get_data_' . $this->export_type, $data );
return ! empty( $data )
? $data
: false;
}
/**
* Return the calculated completion percentage.
*
* @since 2.7
* @since 3.0 Updated to use new query methods.
*
* @return int Percentage complete.
*/
public function get_percentage_complete() {
$args = array(
'fields' => 'ids',
);
if ( ! empty( $this->start ) || ! empty( $this->end ) ) {
$args['date_query'] = $this->get_date_query();
}
$total = edd_count_api_request_logs( $args );
$percentage = 100;
if ( $total > 0 ) {
$percentage = ( ( 30 * $this->step ) / $total ) * 100;
}
if ( $percentage > 100 ) {
$percentage = 100;
}
return $percentage;
}
public function set_properties( $request ) {
$this->start = isset( $request['api-requests-export-start'] ) ? sanitize_text_field( $request['api-requests-export-start'] ) : '';
$this->end = isset( $request['api-requests-export-end'] ) ? sanitize_text_field( $request['api-requests-export-end'] ) : '';
}
}

View File

@ -0,0 +1,230 @@
<?php
/**
* Batch Customers Export Class
*
* This class handles customer export
*
* @package EDD
* @subpackage Admin/Reporting/Export
* @copyright Copyright (c) 2018, Easy Digital Downloads, LLC
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
* @since 2.4
*/
// Exit if accessed directly
defined( 'ABSPATH' ) || exit;
/**
* EDD_Batch_Customers_Export Class
*
* @since 2.4
* @since 3.0 Allowed customers to be exported by taxonomy.
*/
class EDD_Batch_Customers_Export extends EDD_Batch_Export {
/**
* Our export type. Used for export-type specific filters/actions.
*
* @var string
* @since 2.4
*/
public $export_type = 'customers';
/**
* Taxonomy.
*
* @since 3.0
* @var int
*/
public $taxonomy = null;
/**
* Set the CSV columns.
*
* @since 2.4
*
* @return array $cols All the columns
*/
public function csv_cols() {
return array(
'id' => __( 'ID', 'easy-digital-downloads' ),
'user_id' => __( 'User ID', 'easy-digital-downloads' ),
'name' => __( 'Name', 'easy-digital-downloads' ),
'email' => __( 'Email', 'easy-digital-downloads' ),
'purchases' => __( 'Number of Purchases', 'easy-digital-downloads' ),
'amount' => __( 'Customer Value', 'easy-digital-downloads' ),
'payment_ids' => __( 'Payment IDs', 'easy-digital-downloads' ),
'date_created' => __( 'Date Created', 'easy-digital-downloads' ),
);
}
/**
* Get the export data.
*
* @since 2.4
* @since 3.0 Updated to use new query methods.
*
* @return array $data The data for the CSV file.
*/
public function get_data() {
global $wpdb;
$data = array();
// Taxonomy.
if ( ! empty( $this->taxonomy ) ) {
$taxonomy = $wpdb->prepare( 't.term_id = %d', $this->taxonomy );
$limit = $wpdb->prepare( '%d, %d', 30 * ( $this->step - 1 ), 30 );
$sql = "SELECT DISTINCT o.customer_id
FROM {$wpdb->terms} t
INNER JOIN {$wpdb->term_taxonomy} tt ON t.term_id = tt.term_id
INNER JOIN {$wpdb->term_relationships} tr ON tr.term_taxonomy_id = tt.term_taxonomy_id
INNER JOIN {$wpdb->edd_order_items} oi ON tr.object_id = oi.product_id
INNER JOIN {$wpdb->edd_orders} o ON oi.order_id = o.id
WHERE {$taxonomy}
LIMIT {$limit}";
$results = $wpdb->get_col( $sql ); // WPCS: unprepared SQL ok.
if ( $results ) {
foreach ( $results as $customer_id ) {
$customer = new EDD_Customer( $customer_id );
$name = ! empty( $customer->name ) ? $customer->name : '';
if ( preg_match( '~^[+\-=@]~m', $name ) ) {
$name = "'{$name}";
}
$data[] = array(
'id' => $customer->id,
'name' => $name,
'email' => $customer->email,
'purchases' => $customer->purchase_count,
'amount' => edd_format_amount( $customer->purchase_value ),
);
}
}
// Download.
} elseif ( ! empty( $this->download ) ) {
// Export customers of a specific product
$args = array(
'product_id' => absint( $this->download ),
'number' => 30,
'offset' => 30 * ( $this->step - 1 ),
);
if ( null !== $this->price_id ) {
$args['price_id'] = (int) $this->price_id;
}
$order_items = edd_get_order_items( $args );
if ( $order_items ) {
foreach ( $order_items as $item ) {
$order = edd_get_order( $item->order_id );
$customer = new EDD_Customer( $order->customer_id );
$name = ! empty( $customer->name ) ? $customer->name : '';
if ( preg_match( '~^[+\-=@]~m', $name ) ) {
$name = "'{$name}";
}
$data[] = array(
'id' => $customer->id,
'user_id' => $customer->user_id,
'name' => $name,
'email' => $customer->email,
'purchases' => $customer->purchase_count,
'amount' => edd_format_amount( $customer->purchase_value ),
'payment_ids' => $customer->payment_ids,
'date_created' => $customer->date_created,
);
}
}
// All customers.
} else {
$customers = edd_get_customers( array(
'number' => 30,
'offset' => 30 * ( $this->step - 1 ),
) );
$i = 0;
foreach ( $customers as $customer ) {
$name = ! empty( $customer->name ) ? $customer->name : '';
if ( preg_match( '~^[+\-=@]~m', $name ) ) {
$name = "'{$name}";
}
$data[ $i ]= array(
'id' => $customer->id,
'user_id' => $customer->user_id,
'name' => $name,
'email' => $customer->email,
'purchases' => $customer->purchase_count,
'amount' => edd_format_amount( $customer->purchase_value ),
'payment_ids' => $customer->payment_ids,
'date_created' => $customer->date_created,
);
$i++;
}
}
$data = apply_filters( 'edd_export_get_data', $data );
$data = apply_filters( 'edd_export_get_data_' . $this->export_type, $data );
return $data;
}
/**
* Return the calculated completion percentage.
*
* @since 2.4
*
* @return float Percentage complete.
*/
public function get_percentage_complete() {
$percentage = 0;
// We can't count the number when getting them for a specific download.
if ( empty( $this->download ) ) {
$total = edd_count_customers();
if ( $total > 0 ) {
$percentage = ( ( 30 * $this->step ) / $total ) * 100;
}
}
if ( $percentage > 100 ) {
$percentage = 100;
}
return $percentage;
}
/**
* Set the properties specific to the Customers export
*
* @since 2.4.2
*
* @param array $request Form data passed into the batch processing.
*/
public function set_properties( $request ) {
$this->taxonomy = isset( $request['taxonomy'] )
? absint( $request['taxonomy'] )
: null;
$this->download = isset( $request['download'] )
? absint( $request['download'] )
: null;
$this->price_id = ! empty( $request['edd_price_option'] ) && 0 !== $request['edd_price_option']
? absint( $request['edd_price_option'] )
: null;
}
}

View File

@ -0,0 +1,234 @@
<?php
/**
* Batch Downloads Export Class
*
* This class handles download products export
*
* @package EDD
* @subpackage Admin/Reporting/Export
* @copyright Copyright (c) 2018, Easy Digital Downloads, LLC
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
* @since 2.5
*/
// Exit if accessed directly
defined( 'ABSPATH' ) || exit;
/**
* EDD_Batch_Downloads_Export Class
*
* @since 2.5
*/
class EDD_Batch_Downloads_Export extends EDD_Batch_Export {
/**
* Our export type. Used for export-type specific filters/actions
*
* @var string
* @since 2.5
*/
public $export_type = 'downloads';
/**
* Set the CSV columns.
*
* @since 2.5
*
* @return array $cols All the columns.
*/
public function csv_cols() {
$cols = array(
'ID' => __( 'ID', 'easy-digital-downloads' ),
'post_name' => __( 'Slug', 'easy-digital-downloads' ),
'post_title' => __( 'Name', 'easy-digital-downloads' ),
'post_date' => __( 'Date Created', 'easy-digital-downloads' ),
'post_author' => __( 'Author', 'easy-digital-downloads' ),
'post_content' => __( 'Description', 'easy-digital-downloads' ),
'post_excerpt' => __( 'Excerpt', 'easy-digital-downloads' ),
'post_status' => __( 'Status', 'easy-digital-downloads' ),
'categories' => __( 'Categories', 'easy-digital-downloads' ),
'tags' => __( 'Tags', 'easy-digital-downloads' ),
'edd_price' => __( 'Price', 'easy-digital-downloads' ),
'_edd_files' => __( 'Files', 'easy-digital-downloads' ),
'_edd_download_limit' => __( 'File Download Limit', 'easy-digital-downloads' ),
'_thumbnail_id' => __( 'Featured Image', 'easy-digital-downloads' ),
'edd_sku' => __( 'SKU', 'easy-digital-downloads' ),
'edd_product_notes' => __( 'Notes', 'easy-digital-downloads' ),
'_edd_download_sales' => __( 'Sales', 'easy-digital-downloads' ),
'_edd_download_earnings' => __( 'Earnings', 'easy-digital-downloads' ),
);
return $cols;
}
/**
* Get the export data.
*
* @since 2.5
*
* @return array $data The data for the CSV file.
*/
public function get_data() {
$data = array();
$meta = array(
'edd_price',
'_edd_files',
'_edd_download_limit',
'_thumbnail_id',
'edd_sku',
'edd_product_notes',
'_edd_download_sales',
'_edd_download_earnings',
);
$args = array(
'post_type' => 'download',
'posts_per_page' => 30,
'paged' => $this->step,
'orderby' => 'ID',
'order' => 'ASC',
);
if ( 0 !== $this->download ) {
$args['post__in'] = array( $this->download );
}
$downloads = new WP_Query( $args );
if ( $downloads->posts ) {
foreach ( $downloads->posts as $download ) {
$row = array();
foreach ( $this->csv_cols() as $key => $value ) {
// Setup default value
$row[ $key ] = '';
if ( in_array( $key, $meta ) ) {
switch ( $key ) {
case '_thumbnail_id' :
$image_id = get_post_thumbnail_id( $download->ID );
$row[ $key ] = wp_get_attachment_url( $image_id );
break;
case 'edd_price' :
if ( edd_has_variable_prices( $download->ID ) ) {
$prices = array();
foreach ( edd_get_variable_prices( $download->ID ) as $price ) {
$prices[] = $price['name'] . ': ' . $price['amount'];
}
$row[ $key ] = implode( ' | ', $prices );
} else {
$row[ $key ] = edd_get_download_price( $download->ID );
}
break;
case '_edd_files' :
$files = array();
foreach ( edd_get_download_files( $download->ID ) as $file ) {
$f = $file['file'];
if ( edd_has_variable_prices( $download->ID ) ) {
$condition = isset( $file['condition'] ) ? $file['condition'] : 'all';
$f .= ';' . $condition;
}
$files[] = $f;
unset( $file );
}
$row[ $key ] = implode( ' | ', $files );
break;
default :
$row[ $key ] = get_post_meta( $download->ID, $key, true );
break;
}
} elseif ( isset( $download->$key ) ) {
switch ( $key ) {
case 'post_author':
$row[ $key ] = get_the_author_meta( 'user_login', $download->post_author );
break;
default:
$row[ $key ] = $download->$key;
break;
}
} elseif ( 'tags' == $key ) {
$terms = get_the_terms( $download->ID, 'download_tag' );
if ( $terms ) {
$terms = wp_list_pluck( $terms, 'name' );
$row[ $key ] = implode( ' | ', $terms );
}
} elseif ( 'categories' == $key ) {
$terms = get_the_terms( $download->ID, 'download_category' );
if ( $terms ) {
$terms = wp_list_pluck( $terms, 'name' );
$row[ $key ] = implode( ' | ', $terms );
}
}
}
$data[] = $row;
}
$data = apply_filters( 'edd_export_get_data', $data );
$data = apply_filters( 'edd_export_get_data_' . $this->export_type, $data );
return $data;
}
return false;
}
/**
* Return the calculated completion percentage.
*
* @since 2.5
*
* @return int Percentage complete.
*/
public function get_percentage_complete() {
$args = array(
'post_type' => 'download',
'posts_per_page' => - 1,
'post_status' => 'any',
'fields' => 'ids',
);
if ( 0 !== $this->download ) {
$args['post__in'] = array( $this->download );
}
$downloads = new WP_Query( $args );
$total = (int) $downloads->post_count;
$percentage = 100;
if ( $total > 0 ) {
$percentage = ( ( 30 * $this->step ) / $total ) * 100;
}
if ( $percentage > 100 ) {
$percentage = 100;
}
return $percentage;
}
/**
* Set the properties specific to the downloads export.
*
* @since 3.0
*
* @param array $request Form data passed into the batch processor.
*/
public function set_properties( $request ) {
$this->download = isset( $request['download_id'] ) ? absint( $request['download_id'] ) : null;
}
}

View File

@ -0,0 +1,349 @@
<?php
/**
* Batch Earnings Report Export Class.
*
* This class handles earnings report export.
*
* @package EDD
* @subpackage Admin/Reporting/Export
* @copyright Copyright (c) 2018, Easy Digital Downloads, LLC
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
* @since 2.7
*/
// Exit if accessed directly
defined( 'ABSPATH' ) || exit;
/**
* EDD_Earnings_Report_Export Class
*
* @since 2.7
*/
class EDD_Batch_Earnings_Report_Export extends EDD_Batch_Export {
/**
* Our export type. Used for export-type specific filters/actions.
*
* @since 2.7
* @var string
*/
public $export_type = 'earnings_report';
/**
* Set the export headers.
*
* @since 2.7
*/
public function headers() {
edd_set_time_limit();
nocache_headers();
header( 'Content-Type: text/csv; charset=utf-8' );
header( 'Content-Disposition: attachment; filename="' . apply_filters( 'edd_earnings_report_export_filename', 'edd-export-' . $this->export_type . '-' . date( 'm' ) . '-' . date( 'Y' ) ) . '.csv"' );
header( 'Expires: 0' );
}
/**
* Get the column headers for the Earnings Report.
*
* @since 2.8.18
*
* @return array CSV columns.
*/
public function get_csv_cols() {
// Always start with the date column.
$pre_status_columns = array(
__( 'Monthly Sales Activity', 'easy-digital-downloads' ),
__( 'Gross Activity', 'easy-digital-downloads' ),
);
$status_cols = $this->get_status_cols();
// Append the arrays together so it starts with the date, then include the status list.
$cols = array_merge( $pre_status_columns, $status_cols );
// Include the 'net' after all other columns.
$cols[] = __( 'Net Activity', 'easy-digital-downloads' );
return $cols;
}
/**
* Specifically retrieve the headers for supported order statuses.
*
* @since 2.8.18
*
* @return array Order status columns.
*/
public function get_status_cols() {
$status_cols = edd_get_payment_statuses();
$supported_statuses = $this->get_supported_statuses();
foreach ( $status_cols as $id => $label ) {
if ( ! in_array( $id, $supported_statuses ) ) {
unset( $status_cols[ $id ] );
}
}
return array_values( $status_cols );
}
/**
* Get a list of the statuses supported in this report.
*
* @since 2.8.18
*
* @return array The status keys supported (not labels).
*/
public function get_supported_statuses() {
$statuses = edd_get_payment_statuses();
// Unset a few statuses we don't need in the report:
unset( $statuses['pending'], $statuses['processing'], $statuses['preapproval'] );
$supported_statuses = array_keys( $statuses );
return apply_filters( 'edd_export_earnings_supported_statuses', $supported_statuses );
}
/**
* Output the CSV columns.
*
* We make use of this function to set up the header of the earnings report.
*
* @since 2.7
*
* @return string $col_data CSV cols.
*/
public function print_csv_cols() {
$cols = $this->get_csv_cols();
$col_data = '';
$column_count = count( $cols );
for ( $i = 0; $i < $column_count; $i++ ) {
$col_data .= $cols[ $i ];
// We don't need an extra space after the first column.
if ( $i == 0 ) {
$col_data .= ',';
continue;
}
if ( $i == ( $column_count - 1 ) ) {
$col_data .= "\r\n";
} else {
$col_data .= ",,";
}
}
$statuses = $this->get_supported_statuses();
$number_cols = count( $statuses ) + 2;
$col_data .= ',';
for ( $i = 1; $i <= $number_cols; $i++ ) {
$col_data .= __( 'Order Count', 'easy-digital-downloads' ) . ',';
$col_data .= __( 'Gross Amount', 'easy-digital-downloads' );
if ( $number_cols !== $i ) {
$col_data .= ',';
}
}
$col_data .= "\r\n";
$this->stash_step_data( $col_data );
return $col_data;
}
/**
* Print the CSV rows for the current step.
*
* @since 2.7
*
* @return mixed string|false
*/
public function print_csv_rows() {
$row_data = '';
$data = $this->get_data();
if ( $data ) {
$start_date = date( 'Y-m-d', strtotime( $this->start ) );
if ( $this->count() == 0 ) {
$end_date = date( 'Y-m-d', strtotime( $this->end ) );
} else {
$end_date = date( 'Y-m-d', strtotime( 'first day of +1 month', strtotime( $start_date ) ) );
}
if ( $this->step == 1 ) {
$row_data .= $start_date . ',';
} elseif ( $this->step > 1 ) {
$start_date = date( 'Y-m-d', strtotime( 'first day of +' . ( $this->step - 1 ) . ' month', strtotime( $start_date ) ) );
if ( date( 'Y-m', strtotime( $start_date ) ) == date( 'Y-m', strtotime( $this->end ) ) ) {
$end_date = date( 'Y-m-d', strtotime( $this->end ) );
$row_data .= $end_date . ',';
} else {
$row_data .= $start_date . ',';
}
}
$supported_statuses = $this->get_supported_statuses();
$gross_count = 0;
$gross_amount = 0;
foreach ( $supported_statuses as $status ) {
$gross_count += absint( $data[ $status ]['count'] );
$gross_amount += $data[ $status ]['amount'];
}
$row_data .= $gross_count . ',';
$row_data .= '"' . edd_format_amount( $gross_amount ) . '",';
foreach ( $data as $status => $status_data ) {
$row_data .= isset( $data[ $status ]['count'] ) ? $data[ $status ]['count'] . ',' : 0 . ',';
$column_amount = isset( $data[ $status ]['amount'] ) ? edd_format_amount( $data[ $status ]['amount'] ) : 0;
if ( ! empty( $column_amount ) && 'refunded' == $status ) {
$column_amount = '-' . $column_amount;
}
$row_data .= isset( $data[ $status ]['amount'] ) ? '"' . $column_amount . '"' . ',' : 0 . ',';
}
// Allows extensions with other 'completed' statuses to alter net earnings, like recurring.
$completed_statuses = apply_filters( 'edd_export_earnings_completed_statuses', edd_get_complete_order_statuses() );
$net_count = 0;
$net_amount = 0;
foreach ( $completed_statuses as $status ) {
if ( ! isset( $data[ $status ] ) ) {
continue;
}
$net_count += absint( $data[ $status ]['count'] );
$net_amount += floatval( $data[ $status ]['amount'] );
}
$row_data .= $net_count . ',';
$row_data .= '"' . edd_format_amount( $net_amount ) . '"';
$row_data .= "\r\n";
$this->stash_step_data( $row_data );
return $row_data;
}
return false;
}
/**
* Get the Export Data.
*
* @since 2.7
*
* @return array $data The data for the CSV file
*/
public function get_data() {
global $wpdb;
$data = array();
$start_date = date( 'Y-m-d 00:00:00', strtotime( $this->start ) );
$end_date = date( 'Y-m-t 23:59:59', strtotime( $this->start ) );
if ( $this->step > 1 ) {
$start_timestamp = strtotime( 'first day of +' . ( $this->step - 1 ) . ' month', strtotime( $start_date ) );
$start_date = date( 'Y-m-d 00:00:00', $start_timestamp );
$end_date = date( 'Y-m-t 23:59:59', $start_timestamp );
}
if ( strtotime( $start_date ) > strtotime( $this->end ) ) {
return false;
}
$statuses = $this->get_supported_statuses();
$totals = $wpdb->get_results( $wpdb->prepare(
"SELECT SUM(total) AS total, COUNT(DISTINCT id) AS count, status
FROM {$wpdb->edd_orders}
WHERE date_created >= %s AND date_created <= %s
GROUP BY YEAR(date_created), MONTH(date_created), status
ORDER by date_created ASC", $start_date, $end_date ), ARRAY_A );
$total_data = array();
foreach ( $totals as $row ) {
$total_data[ $row['status'] ] = array(
'count' => $row['count'],
'amount' => floatval( $row['total'] )
);
}
foreach ( $statuses as $status ) {
if ( ! isset( $total_data[ $status ] ) ) {
$data[ $status ] = array(
'count' => 0,
'amount' => 0,
);
} else {
$data[ $status ] = array(
'count' => $total_data[ $status ]['count'],
'amount' => $total_data[ $status ]['amount'],
);
}
}
$data = apply_filters( 'edd_export_get_data', $data );
$data = apply_filters( 'edd_export_get_data_' . $this->export_type, $data, $start_date, $end_date );
return $data;
}
/**
* Count the number of months we are dealing with.
*
* @since 2.7
* @access private
*
* @return void
*/
private function count() {
return abs( ( date( 'Y', strtotime( $this->end ) ) - date( 'Y', strtotime( $this->start ) ) ) * 12 + ( date( 'm', strtotime( $this->end ) ) - date( 'm', strtotime( $this->start ) ) ) );
}
/**
* Return the calculated completion percentage
*
* @since 2.7
*
* @return int Percentage of batch processing complete.
*/
public function get_percentage_complete() {
$percentage = 100;
$total = $this->count();
if ( $total > 0 ) {
$percentage = ( $this->step / $total ) * 100;
}
if ( $percentage > 100 ) {
$percentage = 100;
}
return $percentage;
}
/**
* Set the properties specific to the earnings report.
*
* @since 2.7
*
* @param array $request The Form Data passed into the batch processing
* @return void
*/
public function set_properties( $request ) {
$this->start = ( isset( $request['start_month'] ) && isset( $request['start_year'] ) ) ? sanitize_text_field( $request['start_year'] ) . '-' . sanitize_text_field( $request['start_month'] ) . '-1' : '';
$this->end = ( isset( $request['end_month'] ) && isset( $request['end_year'] ) ) ? sanitize_text_field( $request['end_year'] ) . '-' . sanitize_text_field( $request['end_month'] ) . '-' . cal_days_in_month( CAL_GREGORIAN, sanitize_text_field( $request['end_month'] ), sanitize_text_field( $request['end_year'] ) ) : '';
}
}

View File

@ -0,0 +1,162 @@
<?php
/**
* Batch File Downloads Export Class
*
* This class handles file downloads export
*
* @package EDD
* @subpackage Admin/Reporting/Export
* @copyright Copyright (c) 2018, Easy Digital Downloads, LLC
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
* @since 2.4
*/
// Exit if accessed directly
defined( 'ABSPATH' ) || exit;
/**
* EDD_Batch_File_Downloads_Export Class
*
* @since 2.4
* @since 3.0 Refactored to use new query methods.
*/
class EDD_Batch_File_Downloads_Export extends EDD_Batch_Export {
/**
* Our export type. Used for export-type specific filters/actions.
*
* @var string
* @since 2.4
*/
public $export_type = 'file_downloads';
/**
* Set the CSV columns.
*
* @since 2.4
* @since 3.0 Updated to add 'User Agent' column.
*
* @return array $cols All the columns.
*/
public function csv_cols() {
$cols = array(
'date' => __( 'Date', 'easy-digital-downloads' ),
'user' => __( 'Downloaded by', 'easy-digital-downloads' ),
'ip' => __( 'IP Address', 'easy-digital-downloads' ),
'user_agent' => __( 'User Agent', 'easy-digital-downloads' ),
'download' => __( 'Product', 'easy-digital-downloads' ),
'file' => __( 'File', 'easy-digital-downloads' ),
);
return $cols;
}
/**
* Get the export data.
*
* @since 2.4
* @since 3.0 Refactored to use new query methods.
*
* @return array $data The data for the CSV file.
*/
public function get_data() {
$data = array();
$args = array(
'number' => 30,
'offset' => ( $this->step * 30 ) - 30,
);
if ( ! empty( $this->start ) || ! empty( $this->end ) ) {
$args['date_created_query'] = $this->get_date_query();
}
if ( 0 !== $this->download_id ) {
$args['product_id'] = $this->download_id;
}
$logs = edd_get_file_download_logs( $args );
foreach ( $logs as $log ) {
/** @var EDD\Logs\File_Download_Log $log */
$files = edd_get_download_files( $log->product_id );
$file_id = $log->file_id;
$file_name = isset( $files[ $file_id ]['name'] ) ? $files[ $file_id ]['name'] : null;
$customer = edd_get_customer( $log->customer_id );
if ( $customer ) {
$customer = $customer->email;
if ( ! empty( $customer->name ) ) {
$customer = $customer->name;
if ( preg_match( '~^[+\-=@]~m', $customer ) ) {
$customer = "'{$customer}";
}
}
} else {
$order = edd_get_order( $log->order_id );
if ( $order ) {
$customer = $order->email;
}
}
$data[] = array(
'date' => $log->date_created,
'user' => $customer,
'ip' => $log->ip,
'user_agent' => $log->user_agent,
'download' => get_the_title( $log->product_id ),
'file' => $file_name,
);
}
$data = apply_filters( 'edd_export_get_data', $data );
$data = apply_filters( 'edd_export_get_data_' . $this->export_type, $data );
return ! empty( $data )
? $data
: false;
}
/**
* Return the calculated completion percentage.
*
* @since 2.4
* @since 3.0 Updated to use new query methods.
*
* @return int Percentage complete.
*/
public function get_percentage_complete() {
$args = array(
'fields' => 'ids',
);
if ( ! empty( $this->start ) || ! empty( $this->end ) ) {
$args['date_created_query'] = $this->get_date_query();
}
if ( 0 !== $this->download_id ) {
$args['download_id'] = $this->download_id;
}
$total = edd_count_file_download_logs( $args );
$percentage = 100;
if ( $total > 0 ) {
$percentage = ( ( 30 * $this->step ) / $total ) * 100;
}
if ( $percentage > 100 ) {
$percentage = 100;
}
return $percentage;
}
public function set_properties( $request ) {
$this->start = isset( $request['file-download-export-start'] ) ? sanitize_text_field( $request['file-download-export-start'] ) : '';
$this->end = isset( $request['file-download-export-end'] ) ? sanitize_text_field( $request['file-download-export-end'] ) : '';
$this->download_id = isset( $request['download_id'] ) ? absint( $request['download_id'] ) : 0;
}
}

View File

@ -0,0 +1,280 @@
<?php
/**
* Payments Export Class
*
* This class handles payment export in batches
*
* @package EDD
* @subpackage Admin/Reporting/Export
* @copyright Copyright (c) 2018, Easy Digital Downloads, LLC
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
* @since 2.4
*/
// Exit if accessed directly
defined( 'ABSPATH' ) || exit;
/**
* EDD_Batch_Payments_Export Class
*
* @since 2.4
*/
class EDD_Batch_Payments_Export extends EDD_Batch_Export {
/**
* Our export type. Used for export-type specific filters/actions.
*
* @var string
* @since 2.4
*/
public $export_type = 'orders';
/**
* Set the CSV columns
*
* @since 2.4
*
* @return array $cols All the columns
*/
public function csv_cols() {
$cols = array(
'id' => __( 'Order ID', 'easy-digital-downloads' ), // unaltered payment ID (use for querying)
'seq_id' => __( 'Order Number', 'easy-digital-downloads' ), // sequential payment ID
'email' => __( 'Email', 'easy-digital-downloads' ),
'customer_id' => __( 'Customer ID', 'easy-digital-downloads' ),
'name' => __( 'Customer Name', 'easy-digital-downloads' ),
'address1' => __( 'Address', 'easy-digital-downloads' ),
'address2' => __( 'Address (Line 2)', 'easy-digital-downloads' ),
'city' => __( 'City', 'easy-digital-downloads' ),
'state' => __( 'State', 'easy-digital-downloads' ),
'country' => __( 'Country', 'easy-digital-downloads' ),
'zip' => __( 'Zip / Postal Code', 'easy-digital-downloads' ),
'products' => __( 'Products (Verbose)', 'easy-digital-downloads' ),
'products_raw' => __( 'Products (Raw)', 'easy-digital-downloads' ),
'skus' => __( 'SKUs', 'easy-digital-downloads' ),
'currency' => __( 'Currency', 'easy-digital-downloads' ),
'amount' => __( 'Amount', 'easy-digital-downloads' ),
'tax' => __( 'Tax', 'easy-digital-downloads' ),
'discount' => __( 'Discount Code', 'easy-digital-downloads' ),
'gateway' => __( 'Payment Method', 'easy-digital-downloads' ),
'trans_id' => __( 'Transaction ID', 'easy-digital-downloads' ),
'key' => __( 'Purchase Key', 'easy-digital-downloads' ),
'date' => __( 'Date', 'easy-digital-downloads' ),
'user' => __( 'User', 'easy-digital-downloads' ),
'ip' => __( 'IP Address', 'easy-digital-downloads' ),
'mode' => __( 'Mode (Live|Test)', 'easy-digital-downloads' ),
'status' => __( 'Status', 'easy-digital-downloads' ),
'country_name' => __( 'Country Name', 'easy-digital-downloads' ),
'state_name' => __( 'State Name', 'easy-digital-downloads' ),
);
if ( ! edd_use_skus() ){
unset( $cols['skus'] );
}
if ( ! edd_get_option( 'enable_sequential' ) ) {
unset( $cols['seq_id'] );
}
return $cols;
}
/**
* Get the export data.
*
* @since 2.4
* @since 3.0 Updated to use new query methods.
*
* @return array $data The data for the CSV file.
*/
public function get_data() {
$data = array();
$args = array(
'number' => 30,
'offset' => ( $this->step * 30 ) - 30,
'status' => $this->status,
'order' => 'ASC',
'orderby' => 'date_created',
'type' => 'sale',
'status__not_in' => array( 'trash' ),
);
if ( ! empty( $this->start ) || ! empty( $this->end ) ) {
$args['date_query'] = $this->get_date_query();
}
if ( 'all' === $args['status'] ) {
unset( $args['status'] );
}
$orders = edd_get_orders( $args );
foreach ( $orders as $order ) {
/** @var EDD\Orders\Order $order */
$items = $order->get_items();
$address = $order->get_address();
$total = $order->total;
$user_id = $order->id && $order->id != - 1 ? $order->id : $order->email;
$customer = edd_get_customer( $order->customer_id );
$products = '';
$products_raw = '';
$skus = '';
$discounts = $order->get_discounts();
$discounts = ! empty( $discounts )
? implode( ', ', $discounts )
: __( 'none', 'easy-digital-downloads' );
foreach ( $items as $key => $item ) {
/** @var EDD\Orders\Order_Item $item */
// Setup item information.
$id = $item->product_id;
$qty = $item->quantity;
$price = $item->amount;
$tax = $item->tax;
$price_id = $item->price_id;
// Set up verbose product column.
$products .= html_entity_decode( get_the_title( $id ) );
if ( $qty > 1 ) {
$products .= html_entity_decode( ' (' . $qty . ')' );
}
$products .= ' - ';
if ( edd_use_skus() ) {
$sku = edd_get_download_sku( $id );
if ( ! empty( $sku ) ) {
$skus .= $sku;
}
}
if ( 0 < $item->price_id ) {
$products .= html_entity_decode( edd_get_price_option_name( $id, $item->price_id, $order->id ) ) . ' - ';
}
$products .= html_entity_decode( edd_currency_filter( edd_format_amount( $price ), $order->currency ) );
if ( $key != ( count( $items ) -1 ) ) {
$products .= ' / ';
if ( edd_use_skus() ) {
$skus .= ' / ';
}
}
// Set up raw products column; nothing but product names.
$products_raw .= html_entity_decode( get_the_title( $id ) ) . '|' . $price . '{' . $tax . '}';
// If we have a price ID, include it.
if ( false !== $price_id ) {
$products_raw .= '{' . $price_id . '}';
}
if ( $key != ( count( $items ) -1 ) ) {
$products_raw .= ' / ';
}
}
$user = is_numeric( $user_id )
? get_userdata( $user_id )
: false;
$name = ! empty( $customer->name ) ? $customer->name : '';
if ( preg_match( '~^[+\-=@]~m', $name ) ) {
$name = "'{$name}";
}
$data[] = array(
'id' => $order->id,
'seq_id' => $order->get_number(),
'email' => $order->email,
'customer_id' => $order->customer_id,
'name' => $name,
'address1' => isset( $address->address ) ? $address->address : '',
'address2' => isset( $address->address2 ) ? $address->address2 : '',
'city' => isset( $address->city ) ? $address->city : '',
'state' => isset( $address->region ) ? $address->region : '',
'country' => isset( $address->country ) ? $address->country : '',
'zip' => isset( $address->postal_code ) ? $address->postal_code : '',
'products' => $products,
'products_raw' => $products_raw,
'skus' => $skus,
'currency' => $order->currency,
'amount' => html_entity_decode( edd_format_amount( $total ) ), // The non-discounted item price
'tax' => html_entity_decode( edd_format_amount( $order->tax ) ),
'discount' => $discounts,
'gateway' => edd_get_gateway_admin_label( $order->gateway ),
'trans_id' => $order->get_transaction_id(),
'key' => $order->payment_key,
'date' => $order->date_created,
'user' => $user ? $user->display_name : __( 'guest', 'easy-digital-downloads' ),
'ip' => $order->ip,
'mode' => $order->mode,
'status' => $order->status,
'country_name' => isset( $address->country ) ? edd_get_country_name( $address->country ) : '',
'state_name' => isset( $address->country ) && isset( $address->region ) ? edd_get_state_name( $address->country, $address->region ) : '',
);
}
$data = apply_filters( 'edd_export_get_data', $data );
$data = apply_filters( 'edd_export_get_data_' . $this->export_type, $data );
return ! empty( $data )
? $data
: false;
}
/**
* Return the calculated completion percentage
*
* @since 2.4
* @since 3.0 Updated to use new query methods.
*
* @return int
*/
public function get_percentage_complete() {
$args = array(
'fields' => 'ids',
);
if ( ! empty( $this->start ) || ! empty( $this->end ) ) {
$args['date_query'] = $this->get_date_query();
}
if ( 'any' !== $this->status ) {
$args['status'] = $this->status;
}
$total = edd_count_orders( $args );
$percentage = 100;
if ( $total > 0 ) {
$percentage = ( ( 30 * $this->step ) / $total ) * 100;
}
if ( $percentage > 100 ) {
$percentage = 100;
}
return $percentage;
}
/**
* Set the properties specific to the payments export
*
* @since 2.4.2
*
* @param array $request The Form Data passed into the batch processing
*/
public function set_properties( $request ) {
$this->start = isset( $request['orders-export-start'] ) ? sanitize_text_field( $request['orders-export-start'] ) : '';
$this->end = isset( $request['orders-export-end'] ) ? sanitize_text_field( $request['orders-export-end'] ) : '';
$this->status = isset( $request['status'] ) ? sanitize_text_field( $request['status'] ) : 'complete';
}
}

View File

@ -0,0 +1,238 @@
<?php
/**
* Sales and Earnings Export Class.
*
* This class handles sales and earnings export on a day-by-day basis.
*
* @package EDD
* @subpackage Admin/Reporting/Export
* @copyright Copyright (c) 2018, Easy Digital Downloads, LLC
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
* @since 3.0
*/
// Exit if accessed directly
defined( 'ABSPATH' ) || exit;
/**
* EDD_Batch_Payments_Export Class
*
* @since 2.4
*/
class EDD_Batch_Sales_And_Earnings_Export extends EDD_Batch_Export {
/**
* Our export type. Used for export-type specific filters/actions.
*
* @since 3.0
* @var string
*/
public $export_type = 'sales_and_earnings';
/**
* Download ID.
*
* @since 3.0
* @access protected
* @var int
*/
protected $download_id = 0;
/**
* Customer ID.
*
* @since 3.0
* @access protected
* @var int
*/
protected $customer_id = 0;
/**
* Set the CSV columns.
*
* @since 3.0
*
* @return array $cols CSV columns.
*/
public function csv_cols() {
$cols = array(
'date' => __( 'Date', 'easy-digital-downloads' ),
'sales' => __( 'Sales', 'easy-digital-downloads' ),
'earnings' => __( 'Earnings', 'easy-digital-downloads' ),
);
return $cols;
}
/**
* Get the export data.
*
* @since 3.0
*
* @return array $data The data for the CSV file.
*/
public function get_data() {
global $wpdb;
$data = array();
$args = array(
'number' => 30,
'offset' => ( $this->step * 30 ) - 30,
);
$status = "AND {$wpdb->edd_orders}.status IN ( '" . implode( "', '", $wpdb->_escape( edd_get_complete_order_statuses() ) ) . "' )";
$date_query_sql = '';
// Customer ID.
$customer_id = ! empty( $this->customer_id )
? $wpdb->prepare( "AND {$wpdb->edd_orders}.customer_id = %d", $this->customer_id )
: '';
// Download ID.
$download_id = ! empty( $this->download_id )
? $wpdb->prepare( "AND {$wpdb->edd_order_items}.product_id = %d", $this->download_id )
: '';
// Generate date query SQL if dates have been set.
if ( ! empty( $this->start ) || ! empty( $this->end ) ) {
// Fetch GMT offset.
$offset = EDD()->utils->get_gmt_offset();
$date_query_sql = 'AND ';
if ( ! empty( $this->start ) ) {
$this->start = date( 'Y-m-d 00:00:00', strtotime( $this->start ) );
$this->start = 0 < $offset
? EDD()->utils->date( $this->start )->subSeconds( $offset )->format( 'mysql' )
: EDD()->utils->date( $this->start )->addSeconds( $offset )->format( 'mysql' );
$date_query_sql .= $wpdb->prepare( "{$wpdb->edd_orders}.date_created >= %s", $this->start );
}
// Join dates with `AND` if start and end date set.
if ( ! empty( $this->start ) && ! empty( $this->end ) ) {
$this->end = date( 'Y-m-d 23:59:59', strtotime( $this->end ) );
$this->end = 0 < $offset
? EDD()->utils->date( $this->end )->addSeconds( $offset )->format( 'mysql' )
: EDD()->utils->date( $this->end )->subSeconds( $offset )->format( 'mysql' );
$date_query_sql .= ' AND ';
}
if ( ! empty( $this->end ) ) {
$date_query_sql .= $wpdb->prepare( "{$wpdb->edd_orders}.date_created <= %s", $this->end );
}
}
// Look in orders table if a product ID was not passed.
if ( 0 === $this->download_id ) {
$sql = "
SELECT COUNT(id) AS sales, SUM(total) AS earnings, date_created
FROM {$wpdb->edd_orders}
WHERE 1=1 {$status} {$customer_id} {$date_query_sql}
GROUP BY YEAR(date_created), MONTH(date_created), DAY(date_created)
ORDER BY YEAR(date_created), MONTH(date_created), DAY(date_created) ASC
LIMIT {$args['offset']}, {$args['number']}
";
// Join orders and order items table.
} else {
$sql = "
SELECT SUM({$wpdb->edd_order_items}.quantity) AS sales, SUM({$wpdb->edd_order_items}.total) AS earnings, {$wpdb->edd_orders}.date_created
FROM {$wpdb->edd_orders}
INNER JOIN {$wpdb->edd_order_items} ON {$wpdb->edd_orders}.id = {$wpdb->edd_order_items}.order_id
WHERE 1=1 {$status} {$download_id} {$date_query_sql}
GROUP BY YEAR({$wpdb->edd_orders}.date_created), MONTH({$wpdb->edd_orders}.date_created), DAY({$wpdb->edd_orders}.date_created)
ORDER BY YEAR({$wpdb->edd_orders}.date_created), MONTH({$wpdb->edd_orders}.date_created), DAY({$wpdb->edd_orders}.date_created) ASC
LIMIT {$args['offset']}, {$args['number']}
";
}
$results = $wpdb->get_results( $sql );
foreach ( $results as $result ) {
// Localize the returned time.
$d = EDD()->utils->date( $result->date_created, null, true )->format( 'date' );
$sales = isset( $result->sales )
? absint( $result->sales )
: 0;
$earnings = isset( $result->earnings )
? edd_format_amount( $result->earnings )
: floatval( 0 );
$data[] = array(
'date' => $d,
'sales' => $sales,
'earnings' => $earnings,
);
}
$data = apply_filters( 'edd_export_get_data', $data );
$data = apply_filters( 'edd_export_get_data_' . $this->export_type, $data );
return $data;
}
/**
* Return the calculated completion percentage
*
* @since 2.4
* @since 3.0 Updated to use new query methods.
*
* @return int
*/
public function get_percentage_complete() {
$args = array(
'fields' => 'ids',
);
if ( ! empty( $this->start ) || ! empty( $this->end ) ) {
$args['date_query'] = $this->get_date_query();
}
$total = edd_count_orders( $args );
$percentage = 100;
if ( $total > 0 ) {
$percentage = ( ( 30 * $this->step ) / $total ) * 100;
}
if ( $percentage > 100 ) {
$percentage = 100;
}
return $percentage;
}
/**
* Set the properties specific to the sales and earnings export.
*
* @since 3.0
*
* @param array $request Form data passed to the batch processor.
*/
public function set_properties( $request ) {
$this->start = isset( $request['order-export-start'] )
? sanitize_text_field( $request['order-export-start'] )
: '';
$this->end = isset( $request['order-export-end'] )
? sanitize_text_field( $request['order-export-end'] )
: '';
$this->download_id = isset( $request['download_id'] )
? absint( $request['download_id'] )
: 0;
$this->customer_id = isset( $request['customer_id'] )
? absint( $request['customer_id'] )
: 0;
}
}

View File

@ -0,0 +1,163 @@
<?php
/**
* Batch Sales Logs Export Class
*
* This class handles Sales logs export
*
* @package EDD
* @subpackage Admin/Reporting/Export
* @copyright Copyright (c) 2018, Easy Digital Downloads, LLC
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
* @since 2.7
*/
// Exit if accessed directly
defined( 'ABSPATH' ) || exit;
/**
* EDD_Batch_Sales_Export Class
*
* @since 2.7
*/
class EDD_Batch_Sales_Export extends EDD_Batch_Export {
/**
* Our export type. Used for export-type specific filters/actions
*
* @var string
* @since 2.7
*/
public $export_type = 'sales';
/**
* Set the CSV columns
*
* @since 2.7
* @return array $cols All the columns
*/
public function csv_cols() {
$cols = array(
'ID' => __( 'Log ID', 'easy-digital-downloads' ),
'user_id' => __( 'User', 'easy-digital-downloads' ),
'customer_id' => __( 'Customer ID', 'easy-digital-downloads' ),
'email' => __( 'Email', 'easy-digital-downloads' ),
'first_name' => __( 'First Name', 'easy-digital-downloads' ),
'last_name' => __( 'Last Name', 'easy-digital-downloads' ),
'download' => edd_get_label_singular(),
'quantity' => __( 'Quantity', 'easy-digital-downloads' ),
'amount' => __( 'Item Amount', 'easy-digital-downloads' ),
'payment_id' => __( 'Payment ID', 'easy-digital-downloads' ),
'price_id' => __( 'Price ID', 'easy-digital-downloads' ),
'date' => __( 'Date', 'easy-digital-downloads' ),
);
return $cols;
}
/**
* Get the Export Data
*
* @since 2.7
* @since 3.0 Updated to use new query methods.
*
* @return array|bool The data for the CSV file, false if no data to return.
*/
public function get_data() {
$data = array();
$args = array(
'number' => 30,
'offset' => ( $this->step * 30 ) - 30,
'order' => 'ASC',
);
if ( ! empty( $this->start ) || ! empty( $this->end ) ) {
$args['date_query'] = $this->get_date_query();
}
if ( 0 !== $this->download_id ) {
$args['product_id'] = $this->download_id;
}
$items = edd_get_order_items( $args );
foreach ( $items as $item ) {
/** @var EDD\Orders\Order_Item $item */
$order = edd_get_order( $item->order_id );
$download = edd_get_download( $item->product_id );
$user_info = $order->get_user_info();
$download_title = $item->product_name;
// Maybe append variable price name.
if ( $download->has_variable_prices() ) {
$price_option = edd_get_price_option_name( $item->product_id, $item->price_id, $order->id );
$download_title .= ! empty( $price_option )
? ' - ' . $price_option
: '';
}
$data[] = array(
'ID' => $item->product_id,
'user_id' => $order->user_id,
'customer_id' => $order->customer_id,
'email' => $order->email,
'first_name' => isset( $user_info['first_name'] ) ? $user_info['first_name'] : '',
'last_name' => isset( $user_info['last_name'] ) ? $user_info['last_name'] : '',
'download' => $download_title,
'quantity' => $item->quantity,
'amount' => $order->total,
'payment_id' => $order->id,
'price_id' => $item->price_id,
'date' => $order->date_created,
);
}
$data = apply_filters( 'edd_export_get_data', $data );
$data = apply_filters( 'edd_export_get_data_' . $this->export_type, $data );
return ! empty( $data )
? $data
: false;
}
/**
* Return the calculated completion percentage.
*
* @since 2.7
* @since 3.0 Updated to use new query methods.
*
* @return int
*/
public function get_percentage_complete() {
$args = array(
'fields' => 'ids',
);
if ( ! empty( $this->start ) || ! empty( $this->end ) ) {
$args['date_query'] = $this->get_date_query();
}
if ( 0 !== $this->download_id ) {
$args['product_id'] = $this->download_id;
}
$total = edd_count_order_items( $args );
$percentage = 100;
if ( $total > 0 ) {
$percentage = ( ( 30 * $this->step ) / $total ) * 100;
}
if ( $percentage > 100 ) {
$percentage = 100;
}
return $percentage;
}
public function set_properties( $request ) {
$this->start = isset( $request['orders-export-start'] ) ? sanitize_text_field( $request['orders-export-start'] ) : '';
$this->end = isset( $request['orders-export-end'] ) ? sanitize_text_field( $request['orders-export-end'] ) . ' 23:59:59' : '';
$this->download_id = isset( $request['download_id'] ) ? absint( $request['download_id'] ) : 0;
}
}

View File

@ -0,0 +1,183 @@
<?php
/**
* Taxed Customers Export Class.
*
* This class handles the taxed orders export in batches.
*
* @package EDD
* @subpackage Admin/Reporting/Export
* @copyright Copyright (c) 2018, Easy Digital Downloads, LLC
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
* @since 3.0
*/
// Exit if accessed directly
defined( 'ABSPATH' ) || exit;
/**
* EDD_Batch_Taxed_Orders_Export Class
*
* @since 3.0
*/
class EDD_Batch_Taxed_Customers_Export extends EDD_Batch_Export {
/**
* Our export type. Used for export-type specific filters/actions.
*
* @var string
* @since 3.0
*/
public $export_type = 'taxed_customers';
/**
* Set the CSV columns
*
* @since 3.0
*
* @return array $cols All the columns
*/
public function csv_cols() {
$cols = array(
'id' => __( 'ID', 'easy-digital-downloads' ),
'name' => __( 'Name', 'easy-digital-downloads' ),
'email' => __( 'Email', 'easy-digital-downloads' ),
'purchases' => __( 'Number of Purchases', 'easy-digital-downloads' ),
'amount' => __( 'Customer Value', 'easy-digital-downloads' ),
);
return $cols;
}
/**
* Get the export data.
*
* @since 3.0
*
* @return array $data The data for the CSV file.
*/
public function get_data() {
$data = array();
$args = array(
'number' => 30,
'offset' => ( $this->step * 30 ) - 30,
'status__in' => edd_get_complete_order_statuses(),
'order' => 'ASC',
'orderby' => 'date_created',
'fields' => 'customer_id',
);
if ( ! empty( $this->start ) || ! empty( $this->end ) ) {
$args['date_query'] = $this->get_date_query();
}
add_filter( 'edd_orders_query_clauses', array( $this, 'query_clauses' ), 10, 2 );
$customer_ids = edd_get_orders( $args );
remove_filter( 'edd_orders_query_clauses', array( $this, 'query_clauses' ), 10 );
$customer_ids = array_unique( $customer_ids );
asort( $customer_ids );
foreach ( $customer_ids as $customer_id ) {
// Bail if a customer ID was not set.
if ( 0 === $customer_id ) {
continue;
}
$customer = edd_get_customer( $customer_id );
// Bail if a customer record does not exist.
if ( ! $customer ) {
continue;
}
$name = ! empty( $customer->name ) ? $customer->name : '';
if ( preg_match( '~^[+\-=@]~m', $name ) ) {
$name = "'{$name}";
}
$data[] = array(
'id' => $customer->id,
'name' => $name,
'email' => $customer->email,
'purchases' => $customer->purchase_count,
'amount' => edd_format_amount( $customer->purchase_value ),
);
}
$data = apply_filters( 'edd_export_get_data', $data );
$data = apply_filters( 'edd_export_get_data_' . $this->export_type, $data );
return $data;
}
/**
* Return the calculated completion percentage.
*
* @since 3.0
*
* @return int
*/
public function get_percentage_complete() {
$args = array(
'fields' => 'ids',
'status__in' => edd_get_complete_order_statuses(),
);
if ( ! empty( $this->start ) || ! empty( $this->end ) ) {
$args['date_query'] = $this->get_date_query();
}
add_filter( 'edd_orders_query_clauses', array( $this, 'query_clauses' ), 10, 2 );
$total = edd_count_orders( $args );
remove_filter( 'edd_orders_query_clauses', array( $this, 'query_clauses' ), 10 );
$percentage = 100;
if ( $total > 0 ) {
$percentage = ( ( 30 * $this->step ) / $total ) * 100;
}
if ( $percentage > 100 ) {
$percentage = 100;
}
return $percentage;
}
/**
* Set the properties specific to the taxed orders export.
*
* @since 3.0
*
* @param array $request The form data passed into the batch processing.
*/
public function set_properties( $request ) {
$this->start = isset( $request['taxed-customers-export-start'] ) ? sanitize_text_field( $request['taxed-customers-export-start'] ) : '';
$this->end = isset( $request['taxed-customers-export-end'] ) ? sanitize_text_field( $request['taxed-customers-export-end'] ) : '';
}
/**
* Filter the database query to only return orders which have tax applied to them.
*
* @since 3.0
*
* @param array $clauses A compacted array of item query clauses.
* @param \EDD\Database\Query $base Instance passed by reference.
*
* @return array
*/
public function query_clauses( $clauses, $base ) {
$clauses['where'] = ! empty( $clauses['where'] )
? $clauses['where'] .= ' AND tax > 0'
: 'tax > 0';
return $clauses;
}
}

View File

@ -0,0 +1,306 @@
<?php
/**
* Taxed Orders Export Class.
*
* This class handles the taxed orders export in batches.
*
* @package EDD
* @subpackage Admin/Reporting/Export
* @copyright Copyright (c) 2018, Easy Digital Downloads, LLC
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
* @since 3.0
*/
// Exit if accessed directly
defined( 'ABSPATH' ) || exit;
/**
* EDD_Batch_Taxed_Orders_Export Class
*
* @since 3.0
*/
class EDD_Batch_Taxed_Orders_Export extends EDD_Batch_Export {
/**
* Our export type. Used for export-type specific filters/actions.
*
* @var string
* @since 3.0
*/
public $export_type = 'taxed_orders';
/**
* Set the CSV columns
*
* @since 3.0
*
* @return array $cols All the columns
*/
public function csv_cols() {
$cols = array(
'id' => __( 'Order ID', 'easy-digital-downloads' ), // unaltered payment ID (use for querying)
'seq_id' => __( 'Order Number', 'easy-digital-downloads' ), // sequential payment ID
'email' => __( 'Email', 'easy-digital-downloads' ),
'customer_id' => __( 'Customer ID', 'easy-digital-downloads' ),
'first' => __( 'First Name', 'easy-digital-downloads' ),
'last' => __( 'Last Name', 'easy-digital-downloads' ),
'address1' => __( 'Address', 'easy-digital-downloads' ),
'address2' => __( 'Address (Line 2)', 'easy-digital-downloads' ),
'city' => __( 'City', 'easy-digital-downloads' ),
'state' => __( 'State', 'easy-digital-downloads' ),
'country' => __( 'Country', 'easy-digital-downloads' ),
'zip' => __( 'Zip / Postal Code', 'easy-digital-downloads' ),
'products' => __( 'Products (Verbose)', 'easy-digital-downloads' ),
'products_raw' => __( 'Products (Raw)', 'easy-digital-downloads' ),
'skus' => __( 'SKUs', 'easy-digital-downloads' ),
'amount' => __( 'Amount', 'easy-digital-downloads' ) . ' (' . html_entity_decode( edd_currency_filter( '' ) ) . ')',
'tax' => __( 'Tax', 'easy-digital-downloads' ) . ' (' . html_entity_decode( edd_currency_filter( '' ) ) . ')',
'discount' => __( 'Discount Code', 'easy-digital-downloads' ),
'gateway' => __( 'Gateway', 'easy-digital-downloads' ),
'trans_id' => __( 'Transaction ID', 'easy-digital-downloads' ),
'key' => __( 'Purchase Key', 'easy-digital-downloads' ),
'date' => __( 'Date', 'easy-digital-downloads' ),
'user' => __( 'User', 'easy-digital-downloads' ),
'currency' => __( 'Currency', 'easy-digital-downloads' ),
'ip' => __( 'IP Address', 'easy-digital-downloads' ),
'mode' => __( 'Mode (Live|Test)', 'easy-digital-downloads' ),
'status' => __( 'Status', 'easy-digital-downloads' ),
'country_name' => __( 'Country Name', 'easy-digital-downloads' ),
);
if ( ! edd_use_skus() ) {
unset( $cols['skus'] );
}
if ( ! edd_get_option( 'enable_sequential' ) ) {
unset( $cols['seq_id'] );
}
return $cols;
}
/**
* Get the export data.
*
* @since 3.0
*
* @return array $data The data for the CSV file.
*/
public function get_data() {
$data = array();
$args = array(
'number' => 30,
'offset' => ( $this->step * 30 ) - 30,
'status' => $this->status,
'order' => 'ASC',
'orderby' => 'date_created',
'status__not_in' => array( 'trash' ),
);
if ( ! empty( $this->start ) || ! empty( $this->end ) ) {
$args['date_created_query'] = $this->get_date_query();
}
if ( 'any' === $args['status'] || 'all' === $args['status'] ) {
unset( $args['status'] );
}
add_filter( 'edd_orders_query_clauses', array( $this, 'query_clauses' ), 10, 2 );
$orders = edd_get_orders( $args );
remove_filter( 'edd_orders_query_clauses', array( $this, 'query_clauses' ), 10 );
foreach ( $orders as $order ) {
/** @var EDD\Orders\Order $order */
$items = $order->get_items();
$address = $order->get_address();
$total = $order->total;
$user_id = $order->user_id;
$products = '';
$products_raw = '';
$skus = '';
$discounts = $order->get_discounts();
$discounts = ! empty( $discounts )
? implode( ', ', $discounts )
: __( 'none', 'easy-digital-downloads' );
foreach ( $items as $key => $item ) {
/** @var EDD\Orders\Order_Item $item */
// Setup item information.
$id = $item->product_id;
$qty = $item->quantity;
$price = $item->amount;
$tax = $item->tax;
$price_id = $item->price_id;
// Set up verbose product column.
$products .= html_entity_decode( get_the_title( $id ) );
if ( $qty > 1 ) {
$products .= html_entity_decode( ' (' . $qty . ')' );
}
$products .= ' - ';
if ( edd_use_skus() ) {
$sku = edd_get_download_sku( $id );
if ( ! empty( $sku ) ) {
$skus .= $sku;
}
}
if ( 0 < $item->price_id ) {
$products .= html_entity_decode( edd_get_price_option_name( $id, $item->price_id, $order->id ) ) . ' - ';
}
$products .= html_entity_decode( edd_currency_filter( edd_format_amount( $price ) ) );
if ( ( count( $items ) - 1 ) !== $key ) {
$products .= ' / ';
if ( edd_use_skus() ) {
$skus .= ' / ';
}
}
// Set up raw products column; nothing but product names.
$products_raw .= html_entity_decode( get_the_title( $id ) ) . '|' . $price . '{' . $tax . '}';
// If we have a price ID, include it.
if ( false !== $price_id ) {
$products_raw .= '{' . $price_id . '}';
}
if ( ( count( $items ) - 1 ) !== $key ) {
$products_raw .= ' / ';
}
}
$user = is_numeric( $user_id )
? get_userdata( $user_id )
: false;
$data[] = array(
'id' => $order->id,
'seq_id' => $order->get_number(),
'email' => $order->email,
'customer_id' => $order->customer_id,
'first' => $address->first_name,
'last' => $address->last_name,
'address1' => $address->address,
'address2' => $address->address2,
'city' => $address->city,
'state' => $address->region,
'country' => $address->country,
'zip' => $address->postal_code,
'products' => $products,
'products_raw' => $products_raw,
'skus' => $skus,
'amount' => html_entity_decode( edd_format_amount( $total ) ), // The non-discounted item price
'tax' => html_entity_decode( edd_format_amount( $order->tax ) ),
'discount' => $discounts,
'gateway' => edd_get_gateway_admin_label( $order->gateway ),
'trans_id' => $order->get_transaction_id(),
'key' => $order->payment_key,
'date' => $order->date_created,
'user' => $user ? $user->display_name : __( 'guest', 'easy-digital-downloads' ),
'currency' => $order->currency,
'ip' => $order->ip,
'mode' => $order->mode,
'status' => $order->status,
'country_name' => isset( $user_info['address']['country'] ) ? edd_get_country_name( $user_info['address']['country'] ) : '',
);
}
$data = apply_filters( 'edd_export_get_data', $data );
$data = apply_filters( 'edd_export_get_data_' . $this->export_type, $data );
return ! empty( $data )
? $data
: false;
}
/**
* Return the calculated completion percentage.
*
* @since 3.0
*
* @return int
*/
public function get_percentage_complete() {
$args = array(
'fields' => 'ids',
);
if ( ! empty( $this->start ) || ! empty( $this->end ) ) {
$args['date_created_query'] = $this->get_date_query();
}
if ( 'any' !== $this->status ) {
$args['status'] = $this->status;
}
$total = edd_count_orders( $args );
$percentage = 100;
if ( $total > 0 ) {
$percentage = ( ( 30 * $this->step ) / $total ) * 100;
}
if ( $percentage > 100 ) {
$percentage = 100;
}
return $percentage;
}
/**
* Set the properties specific to the taxed orders export.
*
* @since 3.0
*
* @param array $request The form data passed into the batch processing.
*/
public function set_properties( $request ) {
$this->start = isset( $request['taxed-orders-export-start'] ) ? sanitize_text_field( $request['taxed-orders-export-start'] ) : '';
$this->end = isset( $request['taxed-orders-export-end'] ) ? sanitize_text_field( $request['taxed-orders-export-end'] ) : '';
$this->status = isset( $request['status'] ) ? sanitize_text_field( $request['status'] ) : 'complete';
$this->country = isset( $request['country'] ) ? sanitize_text_field( $request['country'] ) : '';
$this->region = isset( $request['region'] ) ? sanitize_text_field( $request['region'] ) : '';
}
/**
* Filter the database query to only return orders which have tax applied to them.
*
* @since 3.0
*
* @param array $clauses A compacted array of item query clauses.
* @param \EDD\Database\Query $base Instance passed by reference.
*
* @return array
*/
public function query_clauses( $clauses, $base ) {
global $wpdb;
$clauses['where'] = ! empty( $clauses['where'] )
? $clauses['where'] .= ' AND edd_o.tax > 0'
: 'edd_o.tax > 0';
if ( ! empty( $this->country ) ) {
$clauses['join'] = " INNER JOIN {$wpdb->edd_order_addresses} edd_oa ON edd_o.id = edd_oa.order_id";
$clauses['where'] .= $wpdb->prepare( ' AND edd_oa.country = %s', $this->country );
}
if ( ! empty( $this->region ) ) {
$clauses['where'] .= $wpdb->prepare( ' AND edd_oa.region = %s', $this->region );
}
return $clauses;
}
}

View File

@ -0,0 +1,340 @@
<?php
/**
* Batch Export Class
*
* This is the base class for all batch export methods. Each data export type (customers, payments, etc) extend this class
*
* @package EDD
* @subpackage Admin/Export
* @copyright Copyright (c) 2018, Easy Digital Downloads, LLC
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
* @since 2.4
*/
// Exit if accessed directly
defined( 'ABSPATH' ) || exit;
/**
* EDD_Export Class
*
* @since 2.4
*/
class EDD_Batch_Export extends EDD_Export {
/**
* Whether or not we're done processing.
*
* @var bool
*/
public $done;
/**
* The file the data is stored in
*
* @since 2.4
*/
protected $file;
/**
* The name of the file the data is stored in
*
* @since 2.4
*/
public $filename;
/**
* The file type, typically .csv
*
* @since 2.4
*/
public $filetype;
/**
* The current step being processed
*
* @since 2.4
*/
public $step;
/**
* Start date, Y-m-d H:i:s
*
* @since 2.4
*/
public $start;
/**
* End date, Y-m-d H:i:s
*
* @since 2.4
*/
public $end;
/**
* Status to export
*
* @since 2.4
*/
public $status;
/**
* Download to export data for
*
* @since 2.4
*/
public $download = null;
/**
* Download Price ID to export data for
*
* @since 2.4
*/
public $price_id = null;
/**
* Is the export file writable
*
* @since 2.4.4
*/
public $is_writable = true;
/**
* Is the export file empty
*
* @since 2.4.4
*/
public $is_empty = false;
/**
* The data to return to the script.
*
* @since 3.0
* @var array
*/
public $result_data = array();
/**
* Get things started
*
* @param $_step int The step to process
* @since 2.4
*/
public function __construct( $_step = 1 ) {
$upload_dir = wp_upload_dir();
$this->filetype = '.csv';
$this->filename = 'edd-' . $this->export_type . $this->filetype;
$this->file = trailingslashit( $upload_dir['basedir'] ) . $this->filename;
if ( ! is_writeable( $upload_dir['basedir'] ) ) {
$this->is_writable = false;
}
$this->step = $_step;
$this->done = false;
}
/**
* Process a step
*
* @since 2.4
* @return bool
*/
public function process_step() {
if ( ! $this->can_export() ) {
wp_die( __( 'You do not have permission to export data.', 'easy-digital-downloads' ), __( 'Error', 'easy-digital-downloads' ), array( 'response' => 403 ) );
}
if( $this->step < 2 ) {
// Make sure we start with a fresh file on step 1
if ( file_exists( $this->file ) ) {
unlink( $this->file );
}
$this->print_csv_cols();
}
$rows = $this->print_csv_rows();
if( $rows ) {
return true;
} else {
return false;
}
}
/**
* Output the CSV columns
*
* @since 2.4
* @uses EDD_Export::get_csv_cols()
* @return string
*/
public function print_csv_cols() {
$col_data = '';
$cols = $this->get_csv_cols();
$i = 1;
foreach( $cols as $col_id => $column ) {
$col_data .= '"' . addslashes( $column ) . '"';
$col_data .= $i == count( $cols ) ? '' : ',';
$i++;
}
$col_data .= "\r\n";
$this->stash_step_data( $col_data );
return $col_data;
}
/**
* Print the CSV rows for the current step
*
* @since 2.4
* @return string|false
*/
public function print_csv_rows() {
$row_data = '';
$data = $this->get_data();
$cols = $this->get_csv_cols();
if( $data ) {
// Output each row
foreach ( $data as $row ) {
$i = 1;
foreach ( $row as $col_id => $column ) {
// Make sure the column is valid
if ( array_key_exists( $col_id, $cols ) ) {
$row_data .= '"' . addslashes( preg_replace( "/\"/","'", $column ) ) . '"';
$row_data .= $i == count( $cols ) ? '' : ',';
$i++;
}
}
$row_data .= "\r\n";
}
$this->stash_step_data( $row_data );
return $row_data;
}
return false;
}
/**
* Return the calculated completion percentage
*
* @since 2.4
* @return int
*/
public function get_percentage_complete() {
return 100;
}
/**
* Retrieve the file data is written to
*
* @since 2.4
* @return string
*/
protected function get_file() {
$file = '';
if ( @file_exists( $this->file ) ) {
if ( ! is_writeable( $this->file ) ) {
$this->is_writable = false;
}
$file = @file_get_contents( $this->file );
} else {
@file_put_contents( $this->file, '' );
@chmod( $this->file, 0664 );
}
return $file;
}
/**
* Append data to export file
*
* @since 2.4
* @param $data string The data to add to the file
* @return void
*/
protected function stash_step_data( $data = '' ) {
$file = $this->get_file();
$file .= $data;
@file_put_contents( $this->file, $file );
// If we have no rows after this step, mark it as an empty export
$file_rows = file( $this->file, FILE_SKIP_EMPTY_LINES);
$default_cols = $this->get_csv_cols();
$default_cols = empty( $default_cols ) ? 0 : 1;
$this->is_empty = count( $file_rows ) == $default_cols ? true : false;
}
/**
* Perform the export
*
* @since 2.4
* @return void
*/
public function export() {
// Set headers
$this->headers();
$file = $this->get_file();
@unlink( $this->file );
echo $file;
die();
}
/*
* Set the properties specific to the export
*
* @since 2.4.2
* @param array $request The Form Data passed into the batch processing
*/
public function set_properties( $request ) {}
/**
* Allow for prefetching of data for the remainder of the exporter
*
* @since 2.5
* @return void
*/
public function pre_fetch() {}
/**
* Gets the date query.
*
* @since 3.0
* @return array
*/
protected function get_date_query() {
return array(
array(
'after' => $this->start ? date( 'Y-m-d 00:00:00', strtotime( $this->start ) ) : '',
'before' => $this->end ? date( 'Y-m-d 23:59:59', strtotime( $this->end ) ) : '',
'inclusive' => true,
),
);
}
}

View File

@ -0,0 +1,309 @@
<?php
/**
* Exports Actions
*
* These are actions related to exporting data from Easy Digital Downloads.
*
* @package EDD
* @subpackage Admin/Export
* @copyright Copyright (c) 2018, Easy Digital Downloads, LLC
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
* @since 2.4
*/
// Exit if accessed directly
defined( 'ABSPATH' ) || exit;
/**
* Process the download file generated by a batch export.
*
* @since 2.4
*/
function edd_process_batch_export_download() {
if ( ! wp_verify_nonce( $_REQUEST['nonce'], 'edd-batch-export' ) ) {
wp_die( esc_html__( 'Nonce verification failed', 'easy-digital-downloads' ), esc_html__( 'Error', 'easy-digital-downloads' ), array( 'response' => 403 ) );
}
require_once EDD_PLUGIN_DIR . 'includes/admin/reporting/export/class-batch-export.php';
do_action( 'edd_batch_export_class_include', $_REQUEST['class'] );
if ( class_exists( $_REQUEST['class'] ) && 'EDD_Batch_Export' === get_parent_class( $_REQUEST['class'] ) ) {
$export = new $_REQUEST['class']();
$export->export();
}
}
add_action( 'edd_download_batch_export', 'edd_process_batch_export_download' );
/**
* Export all the customers to a CSV file.
*
* Note: The WordPress Database API is being used directly for performance
* reasons (workaround of calling all posts and fetch data respectively)
*
* @since 1.4.4
* @return void
*/
function edd_export_all_customers() {
require_once EDD_PLUGIN_DIR . 'includes/admin/reporting/class-export-customers.php';
$customer_export = new EDD_Customers_Export();
$customer_export->export();
}
add_action( 'edd_email_export', 'edd_export_all_customers' );
/**
* Exports all the downloads to a CSV file using the EDD_Export class.
*
* @since 1.4.4
* @return void
*/
function edd_export_all_downloads_history() {
require_once EDD_PLUGIN_DIR . 'includes/admin/reporting/class-export-download-history.php';
$file_download_export = new EDD_Download_History_Export();
$file_download_export->export();
}
add_action( 'edd_downloads_history_export', 'edd_export_all_downloads_history' );
/**
* Add a hook allowing extensions to register a hook on the batch export process
*
* @since 2.4.2
* @return void
*/
function edd_register_batch_exporters() {
if ( is_admin() ) {
do_action( 'edd_register_batch_exporter' );
}
}
add_action( 'plugins_loaded', 'edd_register_batch_exporters', 99 );
/**
* Register the payments batch exporter
* @since 2.4.2
*/
function edd_register_payments_batch_export() {
add_action( 'edd_batch_export_class_include', 'edd_include_payments_batch_processor', 10, 1 );
}
add_action( 'edd_register_batch_exporter', 'edd_register_payments_batch_export', 10 );
/**
* Loads the payments batch processor if needed.
*
* @since 2.4.2
*
* @param string $class The class being requested to run for the batch export
*/
function edd_include_payments_batch_processor( $class ) {
if ( 'EDD_Batch_Payments_Export' === $class ) {
require_once EDD_PLUGIN_DIR . 'includes/admin/reporting/export/class-batch-export-payments.php';
}
}
/**
* Register the customers batch exporter.
*
* @since 2.4.2
*/
function edd_register_customers_batch_export() {
add_action( 'edd_batch_export_class_include', 'edd_include_customers_batch_processor', 10, 1 );
}
add_action( 'edd_register_batch_exporter', 'edd_register_customers_batch_export', 10 );
/**
* Loads the customers batch processor if needed.
*
* @since 2.4.2
*
* @param string $class The class being requested to run for the batch export.
*/
function edd_include_customers_batch_processor( $class ) {
if ( 'EDD_Batch_Customers_Export' === $class ) {
require_once EDD_PLUGIN_DIR . 'includes/admin/reporting/export/class-batch-export-customers.php';
}
}
/**
* Register the download products batch exporter
*
* @since 2.5
*/
function edd_register_downloads_batch_export() {
add_action( 'edd_batch_export_class_include', 'edd_include_downloads_batch_processor', 10, 1 );
}
add_action( 'edd_register_batch_exporter', 'edd_register_downloads_batch_export', 10 );
/**
* Loads the file downloads batch process if needed
*
* @since 2.5
* @param string $class The class being requested to run for the batch export
* @return void
*/
function edd_include_downloads_batch_processor( $class ) {
if ( 'EDD_Batch_Downloads_Export' === $class ) {
require_once EDD_PLUGIN_DIR . 'includes/admin/reporting/export/class-batch-export-downloads.php';
}
}
/**
* Register the file downloads batch exporter
* @since 2.4.2
*/
function edd_register_file_downloads_batch_export() {
add_action( 'edd_batch_export_class_include', 'edd_include_file_downloads_batch_processor', 10, 1 );
}
add_action( 'edd_register_batch_exporter', 'edd_register_file_downloads_batch_export', 10 );
/**
* Loads the file downloads batch process if needed
*
* @since 2.4.2
* @param string $class The class being requested to run for the batch export
* @return void
*/
function edd_include_file_downloads_batch_processor( $class ) {
if ( 'EDD_Batch_File_Downloads_Export' === $class ) {
require_once EDD_PLUGIN_DIR . 'includes/admin/reporting/export/class-batch-export-file-downloads.php';
}
}
/**
* Register the sales batch exporter.
*
* @since 2.7
*/
function edd_register_sales_export_batch_export() {
add_action( 'edd_batch_export_class_include', 'edd_include_sales_export_batch_processor', 10, 1 );
}
add_action( 'edd_register_batch_exporter', 'edd_register_sales_export_batch_export', 10 );
/**
* Loads the sales export batch process if needed
*
* @since 2.7
* @param string $class The class being requested to run for the batch export
* @return void
*/
function edd_include_sales_export_batch_processor( $class ) {
if ( 'EDD_Batch_Sales_Export' === $class ) {
require_once EDD_PLUGIN_DIR . 'includes/admin/reporting/export/class-batch-export-sales.php';
}
}
/**
* Register the earnings report batch exporter
*
* @since 2.7
*/
function edd_register_earnings_report_batch_export() {
add_action( 'edd_batch_export_class_include', 'edd_include_earnings_report_batch_processor', 10, 1 );
}
add_action( 'edd_register_batch_exporter', 'edd_register_earnings_report_batch_export', 10 );
/**
* Loads the earnings report batch process if needed
*
* @since 2.7
* @param string $class The class being requested to run for the batch export
* @return void
*/
function edd_include_earnings_report_batch_processor( $class ) {
if ( 'EDD_Batch_Earnings_Report_Export' === $class ) {
require_once EDD_PLUGIN_DIR . 'includes/admin/reporting/export/class-batch-export-earnings-report.php';
}
}
/**
* Register the API requests batch exporter
*
* @since 2.7
*/
function edd_register_api_requests_batch_export() {
add_action( 'edd_batch_export_class_include', 'edd_include_api_requests_batch_processor', 10, 1 );
}
add_action( 'edd_register_batch_exporter', 'edd_register_api_requests_batch_export', 10 );
/**
* Loads the API requests batch process if needed
*
* @since 2.7
* @param string $class The class being requested to run for the batch export
* @return void
*/
function edd_include_api_requests_batch_processor( $class ) {
if ( 'EDD_Batch_API_Requests_Export' === $class ) {
require_once EDD_PLUGIN_DIR . 'includes/admin/reporting/export/class-batch-export-api-requests.php';
}
}
/**
* Register the taxed orders report batch exporter.
*
* @since 3.0
*/
function edd_register_taxed_orders_batch_export() {
add_action( 'edd_batch_export_class_include', 'edd_include_taxed_orders_batch_processor', 10, 1 );
}
add_action( 'edd_register_batch_exporter', 'edd_register_taxed_orders_batch_export', 10 );
/**
* Loads the taxed orders report batch process if needed.
*
* @since 3.0
*
* @param string $class The class being requested to run for the batch export
*/
function edd_include_taxed_orders_batch_processor( $class ) {
if ( 'EDD_Batch_Taxed_Orders_Export' === $class ) {
require_once EDD_PLUGIN_DIR . 'includes/admin/reporting/export/class-batch-export-taxed-orders.php';
}
}
/**
* Register the taxed orders report batch exporter.
*
* @since 3.0
*/
function edd_register_taxed_customers_batch_export() {
add_action( 'edd_batch_export_class_include', 'edd_include_taxed_customers_batch_processor', 10, 1 );
}
add_action( 'edd_register_batch_exporter', 'edd_register_taxed_customers_batch_export', 10 );
/**
* Loads the taxed customers report batch process if needed.
*
* @since 3.0
*
* @param string $class The class being requested to run for the batch export
*/
function edd_include_taxed_customers_batch_processor( $class ) {
if ( 'EDD_Batch_Taxed_Customers_Export' === $class ) {
require_once EDD_PLUGIN_DIR . 'includes/admin/reporting/export/class-batch-export-taxed-customers.php';
}
}
/**
* Register the sales and earnings report batch exporter.
*
* @since 3.0
*/
function edd_register_sales_and_earnings_batch_export() {
add_action( 'edd_batch_export_class_include', 'edd_include_sales_and_earnings_batch_processor', 10, 1 );
}
add_action( 'edd_register_batch_exporter', 'edd_register_sales_and_earnings_batch_export', 10 );
/**
* Loads the sales and earnings batch process if needed.
*
* @since 3.0
*
* @param string $class The class being requested to run for the batch export
*/
function edd_include_sales_and_earnings_batch_processor( $class ) {
if ( 'EDD_Batch_Sales_And_Earnings_Export' === $class ) {
require_once EDD_PLUGIN_DIR . 'includes/admin/reporting/export/class-batch-export-sales-and-earnings.php';
}
}

View File

@ -0,0 +1,112 @@
<?php
/**
* Exports Functions
*
* These are functions are used for exporting data from Easy Digital Downloads.
*
* @package EDD
* @subpackage Admin/Export
* @copyright Copyright (c) 2018, Easy Digital Downloads, LLC
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
*/
// Exit if accessed directly
defined( 'ABSPATH' ) || exit;
require_once EDD_PLUGIN_DIR . 'includes/admin/reporting/class-export.php';
require_once EDD_PLUGIN_DIR . 'includes/admin/reporting/export/export-actions.php';
/**
* Process batch exports via AJAX.
*
* @since 2.4
*/
function edd_do_ajax_export() {
require_once EDD_PLUGIN_DIR . 'includes/admin/reporting/export/class-batch-export.php';
parse_str( $_POST['form'], $form ); // WPCS: CSRF ok.
$_REQUEST = $form;
$form = (array) $form;
if ( ! wp_verify_nonce( $_REQUEST['edd_ajax_export'], 'edd_ajax_export' ) ) {
die( '-2' );
}
do_action( 'edd_batch_export_class_include', $form['edd-export-class'] );
$step = absint( $_POST['step'] );
$class = sanitize_text_field( $form['edd-export-class'] );
/** @var \EDD_Batch_Export $export */
$export = new $class( $step );
if ( ! $export->can_export() ) {
die( '-1' );
}
if ( ! $export->is_writable ) {
echo wp_json_encode( array(
'error' => true,
'message' => __( 'Export location or file not writable', 'easy-digital-downloads' ),
));
exit;
}
$export->set_properties( $_REQUEST );
// Added in 2.5 to allow a bulk processor to pre-fetch some data to speed up the remaining steps and cache data.
$export->pre_fetch();
$ret = $export->process_step();
$percentage = $export->get_percentage_complete();
if ( $ret ) {
$step++;
echo wp_json_encode( array(
'step' => absint( $step ),
'percentage' => esc_attr( $percentage ),
) );
exit;
} elseif ( true === $export->is_empty ) {
echo wp_json_encode( array(
'error' => true,
'message' => __( 'No data found for export parameters', 'easy-digital-downloads' ),
) );
exit;
} elseif ( true === $export->done && true === $export->is_void ) {
$message = ! empty( $export->message )
? $export->message
: __( 'Batch Processing Complete', 'easy-digital-downloads' );
echo wp_json_encode( array(
'success' => true,
'message' => $message,
'data' => $export->result_data,
) );
exit;
} else {
$args = array_merge( $_REQUEST, array(
'step' => absint( $step ),
'class' => urlencode( $class ),
'nonce' => wp_create_nonce( 'edd-batch-export' ),
'edd_action' => 'download_batch_export',
) );
$download_url = add_query_arg( $args, admin_url() );
echo wp_json_encode( array(
'step' => 'done',
'url' => esc_url_raw( $download_url ),
) );
exit;
}
}
add_action( 'wp_ajax_edd_do_ajax_export', 'edd_do_ajax_export' );

View File

@ -0,0 +1,775 @@
<?php
/**
* Graphing Functions
*
* @package EDD
* @subpackage Admin/Reports
* @copyright Copyright (c) 2018, Easy Digital Downloads, LLC
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
* @since 1.0
*/
use EDD\Reports;
// Exit if accessed directly
defined( 'ABSPATH' ) || exit;
/**
* Show report graphs
*
* @since 1.3
* @return void
*/
function edd_reports_graph() {
// Retrieve the queried dates
$dates = Reports\get_dates_filter( 'objects' );
$day_by_day = Reports\get_dates_filter_day_by_day();
$earnings_totals = 0.00; // Total earnings for time period shown
$sales_totals = 0; // Total sales for time period shown
$include_taxes = empty( $_GET['exclude_taxes'] ) ? true : false;
if ( $dates['range'] == 'today' || $dates['range'] == 'yesterday' ) {
// Hour by hour
$hour = 0;
$month = $dates['start']->month;
$i = 0;
$j = 0;
$start = $dates['start']->format( 'Y-m-d' );
$end = $dates['end']->format( 'Y-m-d' );
$sales = EDD()->payment_stats->get_sales_by_range( $dates['range'], true, $start, $end );
$earnings = EDD()->payment_stats->get_earnings_by_range( $dates['range'], true, $start, $end, $include_taxes );
while ( $hour <= 23 ) {
$date = mktime( $hour, 0, 0, $month, $dates['start']->day, $dates['start']->year ) * 1000;
if ( isset( $earnings[ $i ] ) && $earnings[ $i ]['h'] == $hour ) {
$earnings_data[] = array( $date, $earnings[ $i ]['total'] );
$earnings_totals += $earnings[ $i ]['total'];
$i++;
} else {
$earnings_data[] = array( $date, 0 );
}
if ( isset( $sales[ $j ] ) && $sales[ $j ]['h'] == $hour ) {
$sales_data[] = array( $date, $sales[ $j ]['count'] );
$sales_totals += $sales[ $j ]['count'];
$j++;
} else {
$sales_data[] = array( $date, 0 );
}
$hour++;
}
} elseif ( $dates['range'] == 'this_week' || $dates['range'] == 'last_week' ) {
$report_dates = array();
$i = 0;
while ( $i <= 6 ) {
if ( ( $dates['start']->day + $i ) <= $dates['end']->day ) {
$report_dates[ $i ] = array(
'day' => (string) $dates['start']->day + $i,
'month' => $dates['start']->month,
'year' => $dates['start']->year,
);
} else {
$report_dates[ $i ] = array(
'day' => (string) $i,
'month' => $dates['end']->month,
'year' => $dates['end']->year,
);
}
$i++;
}
$start_date = $report_dates[0];
$end_date = end( $report_dates );
$sales = EDD()->payment_stats->get_sales_by_range( $dates['range'], true, $start_date['year'] . '-' . $start_date['month'] . '-' . $start_date['day'], $end_date['year'] . '-' . $end_date['month'] . '-' . $end_date['day'] );
$earnings = EDD()->payment_stats->get_earnings_by_range( $dates['range'], true, $start_date['year'] . '-' . $start_date['month'] . '-' . $start_date['day'], $end_date['year'] . '-' . $end_date['month'] . '-' . $end_date['day'], $include_taxes );
$i = 0;
$j = 0;
foreach ( $report_dates as $report_date ) {
$date = mktime( 0, 0, 0, $report_date['month'], $report_date['day'], $report_date['year'] ) * 1000;
if ( array_key_exists( $i, $sales ) && $report_date['day'] == $sales[ $i ]['d'] && $report_date['month'] == $sales[ $i ]['m'] && $report_date['year'] == $sales[ $i ]['y'] ) {
$sales_data[] = array( $date, $sales[ $i ]['count'] );
$sales_totals += $sales[ $i ]['count'];
$i++;
} else {
$sales_data[] = array( $date, 0 );
}
if ( array_key_exists( $j, $earnings ) && $report_date['day'] == $earnings[ $j ]['d'] && $report_date['month'] == $earnings[ $j ]['m'] && $report_date['year'] == $earnings[ $j ]['y'] ) {
$earnings_data[] = array( $date, $earnings[ $j ]['total'] );
$earnings_totals += $earnings[ $j ]['total'];
$j++;
} else {
$earnings_data[] = array( $date, 0 );
}
}
} else {
$date_start = $dates['start']->format( 'Y-m-d' );
$date_end = $dates['end']->format( 'Y-m-d' );
$sales = EDD()->payment_stats->get_sales_by_range( $dates['range'], $day_by_day, $date_start, $date_end );
$earnings = EDD()->payment_stats->get_earnings_by_range( $dates['range'], $day_by_day, $date_start, $date_end, $include_taxes );
$temp_data = array(
'sales' => array(),
'earnings' => array(),
);
foreach ( $sales as $sale ) {
if ( $day_by_day ) {
$temp_data['sales'][ $sale['y'] ][ $sale['m'] ][ $sale['d'] ] = $sale['count'];
} else {
$temp_data['sales'][ $sale['y'] ][ $sale['m'] ] = $sale['count'];
}
$sales_totals += $sale['count'];
}
foreach ( $earnings as $earning ) {
if ( $day_by_day ) {
$temp_data['earnings'][ $earning['y'] ][ $earning['m'] ][ $earning['d'] ] = $earning['total'];
} else {
$temp_data['earnings'][ $earning['y'] ][ $earning['m'] ] = $earning['total'];
}
$earnings_totals += $earning['total'];
}
while ( $day_by_day && ( strtotime( $date_start ) <= strtotime( $date_end ) ) ) {
$d = $dates['start']->day;
$m = $dates['start']->month;
$y = $dates['start']->year;
if ( ! isset( $temp_data['sales'][ $y ][ $m ][ $d ] ) ) {
$temp_data['sales'][ $y ][ $m ][ $d ] = 0;
}
if ( ! isset( $temp_data['earnings'][ $y ][ $m ][ $d ] ) ) {
$temp_data['earnings'][ $y ][ $m ][ $d ] = 0;
}
$date_start = $dates['start']->addDays( 1 )->format( 'Y-m-d' );
}
while ( ! $day_by_day && ( strtotime( $date_start ) <= strtotime( $date_end ) ) ) {
$m = $dates['start']->month;
$y = $dates['start']->year;
if ( ! isset( $temp_data['sales'][ $y ][ $m ] ) ) {
$temp_data['sales'][ $y ][ $m ] = 0;
}
if ( ! isset( $temp_data['earnings'][ $y ][ $m ] ) ) {
$temp_data['earnings'][ $y ][ $m ] = 0;
}
$date_start = $dates['start']->addMonths( 1 )->format( 'Y-m' );
}
$sales_data = array();
$earnings_data = array();
// When using 3 months or smaller as the custom range, show each day individually on the graph
if ( $day_by_day ) {
foreach ( $temp_data['sales'] as $year => $months ) {
foreach ( $months as $month => $days ) {
foreach ( $days as $day => $count ) {
$date = mktime( 0, 0, 0, $month, $day, $year ) * 1000;
$sales_data[] = array( $date, $count );
}
}
}
foreach ( $temp_data['earnings'] as $year => $months ) {
foreach ( $months as $month => $days ) {
foreach ( $days as $day => $total ) {
$date = mktime( 0, 0, 0, $month, $day, $year ) * 1000;
$earnings_data[] = array( $date, $total );
}
}
}
// Sort dates in ascending order
foreach ( $sales_data as $key => $value ) {
$timestamps[ $key ] = $value[0];
}
if ( ! empty( $timestamps ) ) {
array_multisort( $timestamps, SORT_ASC, $sales_data );
}
foreach ( $earnings_data as $key => $value ) {
$earnings_timestamps[ $key ] = $value[0];
}
if ( ! empty( $earnings_timestamps ) ) {
array_multisort( $earnings_timestamps, SORT_ASC, $earnings_data );
}
// When showing more than 3 months of results, group them by month, by the first (except for the last month, group on the last day of the month selected)
} else {
foreach ( $temp_data['sales'] as $year => $months ) {
$month_keys = array_keys( $months );
$last_month = end( $month_keys );
if ( $day_by_day ) {
foreach ( $months as $month => $days ) {
$day_keys = array_keys( $days );
$last_day = end( $day_keys );
$month_keys = array_keys( $months );
$consolidated_date = $month === end( $month_keys ) ? cal_days_in_month( CAL_GREGORIAN, $month, $year ) : 1;
$sales = array_sum( $days );
$date = mktime( 0, 0, 0, $month, $consolidated_date, $year ) * 1000;
$sales_data[] = array( $date, $sales );
}
} else {
foreach ( $months as $month => $count ) {
$month_keys = array_keys( $months );
$consolidated_date = $month === end( $month_keys ) ? cal_days_in_month( CAL_GREGORIAN, $month, $year ) : 1;
$date = mktime( 0, 0, 0, $month, $consolidated_date, $year ) * 1000;
$sales_data[] = array( $date, $count );
}
}
}
// Sort dates in ascending order
foreach ( $sales_data as $key => $value ) {
$timestamps[ $key ] = $value[0];
}
if ( ! empty( $timestamps ) ) {
array_multisort( $timestamps, SORT_ASC, $sales_data );
}
foreach ( $temp_data['earnings'] as $year => $months ) {
$month_keys = array_keys( $months );
$last_month = end( $month_keys );
if ( $day_by_day ) {
foreach ( $months as $month => $days ) {
$day_keys = array_keys( $days );
$last_day = end( $day_keys );
$month_keys = array_keys( $months );
$consolidated_date = $month === end( $month_keys )
? cal_days_in_month( CAL_GREGORIAN, $month, $year )
: 1;
$earnings = array_sum( $days );
$date = mktime( 0, 0, 0, $month, $consolidated_date, $year ) * 1000;
$earnings_data[] = array( $date, $earnings );
}
} else {
foreach ( $months as $month => $count ) {
$month_keys = array_keys( $months );
$consolidated_date = $month === end( $month_keys )
? cal_days_in_month( CAL_GREGORIAN, $month, $year )
: 1;
$date = mktime( 0, 0, 0, $month, $consolidated_date, $year ) * 1000;
$earnings_data[] = array( $date, $count );
}
}
}
// Sort dates in ascending order
foreach ( $earnings_data as $key => $value ) {
$earnings_timestamps[ $key ] = $value[0];
}
if ( ! empty( $earnings_timestamps ) ) {
array_multisort( $earnings_timestamps, SORT_ASC, $earnings_data );
}
}
}
$data = array(
__( 'Earnings', 'easy-digital-downloads' ) => $earnings_data,
__( 'Sales', 'easy-digital-downloads' ) => $sales_data
);
// start our own output buffer
ob_start();
do_action( 'edd_reports_graph_before' ); ?>
<div id="edd-dashboard-widgets-wrap">
<div class="metabox-holder" style="padding-top: 0;">
<div class="postbox">
<h3><span><?php _e('Earnings Over Time','easy-digital-downloads' ); ?></span></h3>
<div class="inside">
<?php
$graph = new EDD_Graph( $data );
$graph->set( 'x_mode', 'time' );
$graph->set( 'multiple_y_axes', true );
$graph->display();
if( ! empty( $dates['range'] ) && 'this_month' == $dates['range'] ) {
$estimated = edd_estimated_monthly_stats( $include_taxes );
}
?>
<p class="edd_graph_totals">
<strong>
<?php
_e( 'Total earnings for period shown: ', 'easy-digital-downloads' );
echo edd_currency_filter( edd_format_amount( $earnings_totals ) );
?>
</strong>
<?php if ( ! $include_taxes ) : ?>
<sup>&dagger;</sup>
<?php endif; ?>
</p>
<p class="edd_graph_totals"><strong><?php _e( 'Total sales for period shown: ', 'easy-digital-downloads' ); echo edd_format_amount( $sales_totals, false ); ?></strong></p>
<?php if( ! empty( $dates['range'] ) && 'this_month' == $dates['range'] ) : ?>
<p class="edd_graph_totals">
<strong>
<?php
_e( 'Estimated monthly earnings: ', 'easy-digital-downloads' );
echo edd_currency_filter( edd_format_amount( $estimated['earnings'] ) );
?>
</strong>
<?php if ( ! $include_taxes ) : ?>
<sup>&dagger;</sup>
<?php endif; ?>
</p>
<p class="edd_graph_totals"><strong><?php _e( 'Estimated monthly sales: ', 'easy-digital-downloads' ); echo edd_format_amount( $estimated['sales'], false ); ?></strong></p>
<?php endif; ?>
<?php do_action( 'edd_reports_graph_additional_stats' ); ?>
<p class="edd_graph_notes">
<?php if ( false === $include_taxes ) : ?>
<em><sup>&dagger;</sup> <?php _e( 'Excludes sales tax.', 'easy-digital-downloads' ); ?></em>
<?php endif; ?>
</p>
</div>
</div>
</div>
</div>
<?php do_action( 'edd_reports_graph_after' );
// Output the buffer
echo ob_get_clean();
}
/**
* Show report graphs of a specific product
*
* @since 1.9
* @return void
*/
function edd_reports_graph_of_download( $download_id = 0 ) {
// Retrieve the queried dates
$dates = edd_get_report_dates();
// Determine graph options
switch ( $dates['range'] ) {
case 'today' :
case 'yesterday' :
$day_by_day = true;
break;
case 'last_year' :
case 'this_year' :
$day_by_day = false;
break;
case 'last_quarter' :
case 'this_quarter' :
$day_by_day = false;
break;
case 'other' :
if ( $dates['m_start'] == 12 && $dates['m_end'] == 1 ) {
$day_by_day = true;
} elseif ( $dates['m_end'] - $dates['m_start'] >= 3 || ( $dates['year_end'] > $dates['year'] && ( $dates['m_start'] - $dates['m_end'] ) != 10 ) ) {
$day_by_day = false;
} else {
$day_by_day = true;
}
break;
default:
$day_by_day = true;
break;
}
$earnings_totals = (float) 0.00; // Total earnings for time period shown
$sales_totals = 0; // Total sales for time period shown
$include_taxes = empty( $_GET['exclude_taxes'] ) ? true : false;
$earnings_data = array();
$sales_data = array();
if ( $dates['range'] == 'today' || $dates['range'] == 'yesterday' ) {
// Hour by hour
$month = $dates['m_start'];
$hour = 0;
$minute = 0;
$second = 0;
while ( $hour <= 23 ) :
if ( $hour == 23 ) {
$minute = $second = 59;
}
$date = mktime( $hour, $minute, $second, $month, $dates['day'], $dates['year'] );
$date_end = mktime( $hour + 1, $minute, $second, $month, $dates['day'], $dates['year'] );
$sales = EDD()->payment_stats->get_sales( $download_id, $date, $date_end );
$sales_totals += $sales;
$earnings = EDD()->payment_stats->get_earnings( $download_id, $date, $date_end, $include_taxes );
$earnings_totals += $earnings;
$sales_data[] = array( $date * 1000, $sales );
$earnings_data[] = array( $date * 1000, $earnings );
$hour++;
endwhile;
} elseif( $dates['range'] == 'this_week' || $dates['range'] == 'last_week' ) {
$num_of_days = cal_days_in_month( CAL_GREGORIAN, $dates['m_start'], $dates['year'] );
$report_dates = array();
$i = 0;
while ( $i <= 6 ) {
if ( ( $dates['day'] + $i ) <= $num_of_days ) {
$report_dates[ $i ] = array(
'day' => (string) $dates['day'] + $i,
'month' => $dates['m_start'],
'year' => $dates['year'],
);
} else {
$report_dates[ $i ] = array(
'day' => (string) $i,
'month' => $dates['m_end'],
'year' => $dates['year_end'],
);
}
$i++;
}
foreach ( $report_dates as $report_date ) {
$date = mktime( 0, 0, 0, $report_date['month'], $report_date['day'], $report_date['year'] );
$date_end = mktime( 23, 59, 59, $report_date['month'], $report_date['day'], $report_date['year'] );
$sales = EDD()->payment_stats->get_sales( $download_id, $date, $date_end );
$sales_totals += $sales;
$earnings = EDD()->payment_stats->get_earnings( $download_id, $date, $date_end, $include_taxes );
$earnings_totals += $earnings;
$sales_data[] = array( $date * 1000, $sales );
$earnings_data[] = array( $date * 1000, $earnings );
}
} else {
$y = $dates['year'];
$temp_data = array();
while( $y <= $dates['year_end'] ) {
$last_year = false;
if( $dates['year'] == $dates['year_end'] ) {
$month_start = $dates['m_start'];
$month_end = $dates['m_end'];
$last_year = true;
} elseif( $y == $dates['year'] ) {
$month_start = $dates['m_start'];
$month_end = 12;
} elseif ( $y == $dates['year_end'] ) {
$month_start = 1;
$month_end = $dates['m_end'];
} else {
$month_start = 1;
$month_end = 12;
}
$i = $month_start;
while ( $i <= $month_end ) {
$d = $dates['day'];
if ( $i == $month_end ) {
$num_of_days = $dates['day_end'];
if ( $month_start < $month_end ) {
$d = 1;
}
} elseif ( $i > $month_start && $i < $month_end ) {
$num_of_days = cal_days_in_month( CAL_GREGORIAN, $i, $y );
$d = 1;
} else {
$num_of_days = cal_days_in_month( CAL_GREGORIAN, $i, $y );
}
while ( $d <= $num_of_days ) {
$date = mktime( 0, 0, 0, $i, $d, $y );
$end_date = mktime( 23, 59, 59, $i, $d, $y );
$earnings = EDD()->payment_stats->get_earnings( $download_id, $date, $end_date, $include_taxes );
$earnings_totals += $earnings;
$sales = EDD()->payment_stats->get_sales( $download_id, $date, $end_date );
$sales_totals += $sales;
$temp_data['earnings'][ $y ][ $i ][ $d ] = $earnings;
$temp_data['sales'][ $y ][ $i ][ $d ] = $sales;
$d++;
}
$i++;
}
$y++;
}
$sales_data = array();
$earnings_data = array();
// When using 2 months or smaller as the custom range, show each day individually on the graph
if ( $day_by_day ) {
foreach ( $temp_data[ 'sales' ] as $year => $months ) {
foreach( $months as $month => $dates ) {
foreach ( $dates as $day => $sales ) {
$date = mktime( 0, 0, 0, $month, $day, $year ) * 1000;
$sales_data[] = array( $date, $sales );
}
}
}
foreach ( $temp_data[ 'earnings' ] as $year => $months ) {
foreach( $months as $month => $dates ) {
foreach ( $dates as $day => $earnings ) {
$date = mktime( 0, 0, 0, $month, $day, $year ) * 1000;
$earnings_data[] = array( $date, $earnings );
}
}
}
// When showing more than 2 months of results, group them by month, by the first (except for the last month, group on the last day of the month selected)
} else {
foreach ( $temp_data[ 'sales' ] as $year => $months ) {
$month_keys = array_keys( $months );
$last_month = end( $month_keys );
foreach ( $months as $month => $days ) {
$day_keys = array_keys( $days );
$last_day = end( $day_keys );
$consolidated_date = $month === $last_month ? $last_day : 1;
$sales = array_sum( $days );
$date = mktime( 0, 0, 0, $month, $consolidated_date, $year ) * 1000;
$sales_data[] = array( $date, $sales );
}
}
foreach ( $temp_data[ 'earnings' ] as $year => $months ) {
$month_keys = array_keys( $months );
$last_month = end( $month_keys );
foreach ( $months as $month => $days ) {
$day_keys = array_keys( $days );
$last_day = end( $day_keys );
$consolidated_date = $month === $last_month ? $last_day : 1;
$earnings = array_sum( $days );
$date = mktime( 0, 0, 0, $month, $consolidated_date, $year ) * 1000;
$earnings_data[] = array( $date, $earnings );
}
}
}
}
$data = array(
__( 'Earnings', 'easy-digital-downloads' ) => $earnings_data,
__( 'Sales', 'easy-digital-downloads' ) => $sales_data
);
?>
<div class="metabox-holder" style="padding-top: 0;">
<div class="postbox">
<h3><span><?php printf( __('Earnings Over Time for %s', 'easy-digital-downloads' ), get_the_title( $download_id ) ); ?></span></h3>
<div class="inside">
<?php
$graph = new EDD_Graph( $data );
$graph->set( 'x_mode', 'time' );
$graph->set( 'multiple_y_axes', true );
$graph->display();
?>
<p class="edd_graph_totals"><strong><?php _e( 'Total earnings for period shown: ', 'easy-digital-downloads' ); echo edd_currency_filter( edd_format_amount( $earnings_totals ) ); ?></strong></p>
<p class="edd_graph_totals"><strong><?php _e( 'Total sales for period shown: ', 'easy-digital-downloads' ); echo $sales_totals; ?></strong></p>
<p class="edd_graph_totals"><strong><?php printf( __( 'Average monthly earnings: %s', 'easy-digital-downloads' ), edd_currency_filter( edd_format_amount( edd_get_average_monthly_download_earnings( $download_id ) ) ) ); ?>
<p class="edd_graph_totals"><strong><?php printf( __( 'Average monthly sales: %s', 'easy-digital-downloads' ), number_format( edd_get_average_monthly_download_sales( $download_id ), 0 ) ); ?>
</div>
</div>
</div>
<?php
echo ob_get_clean();
}
/**
* Grabs all of the selected date info and then redirects appropriately
*
* @since 1.3
*
* @param array $form_data POSTed data from the filters form.
*/
function edd_parse_report_dates( $form_data ) {
// Load the Reports API dependencies.
Reports\Init::bootstrap();
$filters = Reports\get_filters();
$redirect = ! empty( $form_data['edd_redirect'] )
? $form_data['edd_redirect']
: edd_get_admin_url( array(
'page' => 'edd-reports',
) );
$filter_args = array();
// Parse and validate filters.
foreach ( $filters as $filter => $attributes ) {
switch ( $filter ) {
case 'dates':
if ( ! empty( $form_data['range'] ) ) {
$range = sanitize_key( $form_data['range'] );
$relative_range = sanitize_key( $form_data['relative_range'] );
} else {
$range = Reports\get_dates_filter_range();
$relative_range = Reports\get_relative_dates_filter_range();
}
if ( 'other' === $range ) {
try {
/*
* This validates the input dates before saving. If they're not valid, an exception
* will be thrown.
*/
EDD()->utils->date( $form_data['filter_from'] );
EDD()->utils->date( $form_data['filter_to'] );
} catch ( \Exception $e ) {
wp_die(
esc_html__( 'Invalid date format. Please enter a date in the format: YYYY-mm-dd.', 'easy-digital-downloads' ),
esc_html__( 'Invalid Date Error', 'easy-digital-downloads' ),
array( 'response' => 400, 'back_link' => true )
);
}
$filter_args = array_merge(
array(
'filter_from' => ! empty( $form_data['filter_from'] )
? sanitize_text_field( $form_data['filter_from'] )
: '',
'filter_to' => ! empty( $form_data['filter_to'] )
? sanitize_text_field( $form_data['filter_to'] )
: '',
'range' => 'other',
'relative_range' => 'previous_period',
),
$filter_args
);
} else {
$dates = Reports\parse_dates_for_range( $range );
$filter_args = array_merge(
array(
'filter_from' => $dates['start']->format( 'date-mysql' ),
'filter_to' => $dates['end']->format( 'date-mysql' ),
'range' => $range,
'relative_range' => $relative_range,
),
$filter_args
);
}
break;
case 'taxes':
$filter_args = array_merge(
array(
'exclude_taxes' => isset( $form_data['exclude_taxes'] ),
),
$filter_args
);
break;
default:
$filter_arg = isset( $form_data[ $filter ] )
? $form_data[ $filter ]
: array();
if ( ! empty( $filter_arg ) ) {
$filter_args[ $filter ] = $filter_arg;
}
break;
}
}
// Redirect back to report.
$redirect = add_query_arg( $filter_args, $redirect );
edd_redirect( $redirect );
}
add_action( 'edd_filter_reports', 'edd_parse_report_dates' );
/**
* EDD Reports Refresh Button
* @since 2.7
* @description: Outputs a "Refresh Reports" button for graphs
*/
function edd_reports_refresh_button() {
$url = wp_nonce_url( add_query_arg( array(
'edd_action' => 'refresh_reports_transients',
'edd-message' => 'refreshed-reports'
) ), 'edd-refresh-reports' );
echo '<a href="' . esc_url( $url ) . '" title="' . esc_html__( 'Clicking this will clear the reports cache', 'easy-digital-downloads' ) . '" class="button edd-refresh-reports-button">' . esc_html__( 'Refresh Reports', 'easy-digital-downloads' ) . '</a>';
}
add_action( 'edd_reports_graph_after', 'edd_reports_refresh_button' );
/**
* EDD trigger the refresh of reports transients
*
* @since 2.7
*
* @param array $data Parameters sent from Settings page
* @return void
*/
function edd_run_refresh_reports_transients( $data ) {
if ( ! wp_verify_nonce( $data['_wpnonce'], 'edd-refresh-reports' ) ) {
return;
}
// Delete transients
delete_transient( 'edd_stats_earnings' );
delete_transient( 'edd_stats_sales' );
delete_transient( 'edd_estimated_monthly_stats' );
delete_transient( 'edd_earnings_total' );
delete_transient( md5( 'edd_earnings_this_monththis_month' ) );
delete_transient( md5( 'edd_earnings_todaytoday' ) );
}
add_action( 'edd_refresh_reports_transients', 'edd_run_refresh_reports_transients' );

View File

@ -0,0 +1,23 @@
<?php
/**
* Logs UI (moved)
*
* @package EDD
* @subpackage Admin/Reports
* @copyright Copyright (c) 2018, Easy Digital Downloads, LLC
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
* @since 1.4
* @deprecated 3.0
*/
// Exit if accessed directly
defined( 'ABSPATH' ) || exit;
_edd_deprecated_file(
__FILE__,
'3.0',
'includes/admin/tools/logs.php',
__( 'The logs tab has been moved to the Tools screen.', 'easy-digital-downloads' )
);
require_once EDD_PLUGIN_DIR . 'includes/admin/tools/logs.php';

View File

@ -0,0 +1,298 @@
<?php
/**
* Reports functions.
*
* @package EDD
* @subpackage Admin/Reports
* @copyright Copyright (c) 2018, Easy Digital Downloads, LLC
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
* @since 1.0
* @since 3.0 Full refactor of Reports.
*/
use EDD\Reports;
// Exit if accessed directly.
defined( 'ABSPATH' ) || exit;
/**
* The callback function which fetches the data for the overview_sales_earnings_chart reports endpoint.
*
* @since 3.0
*/
function edd_overview_sales_earnings_chart() {
global $wpdb;
$dates = Reports\get_dates_filter( 'objects' );
$chart_dates = Reports\parse_dates_for_range( null, 'now', false );
$day_by_day = Reports\get_dates_filter_day_by_day();
$hour_by_hour = Reports\get_dates_filter_hour_by_hour();
$column = Reports\get_taxes_excluded_filter() ? '(total - tax)' : 'total';
$currency = Reports\get_filter_value( 'currencies' );
if ( empty( $currency ) || 'convert' === $currency ) {
$column .= ' / rate';
}
$sql_clauses = array(
'select' => 'date_created AS date',
'where' => '',
'groupby' => '',
);
// Default to 'monthly'.
$sql_clauses['groupby'] = Reports\get_groupby_date_string( 'MONTH', 'date_created' );
$sql_clauses['orderby'] = 'MONTH(date_created)';
// Now drill down to the smallest unit.
if ( $hour_by_hour ) {
$sql_clauses['groupby'] = Reports\get_groupby_date_string( 'HOUR', 'date_created' );
$sql_clauses['orderby'] = 'HOUR(date_created)';
} elseif ( $day_by_day ) {
$sql_clauses['groupby'] = Reports\get_groupby_date_string( 'DATE', 'date_created' );
$sql_clauses['orderby'] = 'DATE(date_created)';
}
if ( ! empty( $currency ) && array_key_exists( strtoupper( $currency ), edd_get_currencies() ) ) {
$sql_clauses['where'] = $wpdb->prepare( " AND currency = %s ", strtoupper( $currency ) );
}
// Revenue calculations should include gross statuses to negate refunds properly.
$statuses = edd_get_gross_order_statuses();
$statuses = apply_filters( 'edd_payment_stats_post_statuses', $statuses );
$statuses = "'" . implode( "', '", $statuses ) . "'";
$earnings_results = $wpdb->get_results(
$wpdb->prepare(
"SELECT SUM({$column}) AS earnings, {$sql_clauses['select']}
FROM {$wpdb->edd_orders} edd_o
WHERE date_created >= %s AND date_created <= %s
AND status IN( {$statuses} )
AND type IN ( 'sale', 'refund' )
{$sql_clauses['where']}
GROUP BY {$sql_clauses['groupby']}
ORDER BY {$sql_clauses['orderby']} ASC",
$dates['start']->copy()->format( 'mysql' ),
$dates['end']->copy()->format( 'mysql' )
)
);
// Sales counts should count by 'net' statuses, which excludes refunds.
$statuses = edd_get_net_order_statuses();
$statuses = apply_filters( 'edd_payment_stats_post_statuses', $statuses );
$statuses = "'" . implode( "', '", $statuses ) . "'";
$sales_results = $wpdb->get_results(
$wpdb->prepare(
"SELECT COUNT(id) AS sales, {$sql_clauses['select']}
FROM {$wpdb->edd_orders} edd_o
WHERE date_created >= %s AND date_created <= %s
AND status IN( {$statuses} )
AND type = 'sale'
{$sql_clauses['where']}
GROUP BY {$sql_clauses['groupby']}
ORDER BY {$sql_clauses['orderby']} ASC",
$dates['start']->copy()->format( 'mysql' ),
$dates['end']->copy()->format( 'mysql' )
)
);
$sales = array();
$earnings = array();
/**
* Initialise all arrays with timestamps and set values to 0.
*
* We use the Chart based dates for this loop, so the graph shows in the proper date ranges while the actual DB queries are all UTC based.
*/
while ( strtotime( $chart_dates['start']->copy()->format( 'mysql' ) ) <= strtotime( $chart_dates['end']->copy()->format( 'mysql' ) ) ) {
$timestamp = $chart_dates['start']->copy()->format( 'U' );
$date_on_chart = $chart_dates['start'];
$sales[ $timestamp ][0] = $date_on_chart->format( 'Y-m-d H:i:s' );
$sales[ $timestamp ][1] = 0;
$earnings[ $timestamp ][0] = $date_on_chart->format( 'Y-m-d H:i:s' );
$earnings[ $timestamp ][1] = 0.00;
// Loop through each date there were sales/earnings, which we queried from the database.
foreach ( $earnings_results as $earnings_result ) {
$date_of_db_value = edd_get_edd_timezone_equivalent_date_from_utc( EDD()->utils->date( $earnings_result->date ) );
// Add any sales/earnings that happened during this hour.
if ( $hour_by_hour ) {
// If the date of this db value matches the date on this line graph/chart, set the y axis value for the chart to the number in the DB result.
if ( $date_of_db_value->format( 'Y-m-d H' ) === $date_on_chart->format( 'Y-m-d H' ) ) {
$earnings[ $timestamp ][1] += $earnings_result->earnings;
}
// Add any sales/earnings that happened during this day.
} elseif ( $day_by_day ) {
// If the date of this db value matches the date on this line graph/chart, set the y axis value for the chart to the number in the DB result.
if ( $date_of_db_value->format( 'Y-m-d' ) === $date_on_chart->format( 'Y-m-d' ) ) {
$earnings[ $timestamp ][1] += $earnings_result->earnings;
}
// Add any sales/earnings that happened during this month.
} else {
// If the date of this db value matches the date on this line graph/chart, set the y axis value for the chart to the number in the DB result.
if ( $date_of_db_value->format( 'Y-m' ) === $date_on_chart->format( 'Y-m' ) ) {
$earnings[ $timestamp ][1] += $earnings_result->earnings;
}
}
}
// Loop through each date there were sales/earnings, which we queried from the database.
foreach ( $sales_results as $sales_result ) {
$date_of_db_value = edd_get_edd_timezone_equivalent_date_from_utc( EDD()->utils->date( $sales_result->date ) );
// Add any sales/earnings that happened during this hour.
if ( $hour_by_hour ) {
// If the date of this db value matches the date on this line graph/chart, set the y axis value for the chart to the number in the DB result.
if ( $date_of_db_value->format( 'Y-m-d H' ) === $date_on_chart->format( 'Y-m-d H' ) ) {
$sales[ $timestamp ][1] += $sales_result->sales;
}
// Add any sales/earnings that happened during this day.
} elseif ( $day_by_day ) {
// If the date of this db value matches the date on this line graph/chart, set the y axis value for the chart to the number in the DB result.
if ( $date_of_db_value->format( 'Y-m-d' ) === $date_on_chart->format( 'Y-m-d' ) ) {
$sales[ $timestamp ][1] += $sales_result->sales;
}
// Add any sales/earnings that happened during this month.
} else {
// If the date of this db value matches the date on this line graph/chart, set the y axis value for the chart to the number in the DB result.
if ( $date_of_db_value->format( 'Y-m' ) === $date_on_chart->format( 'Y-m' ) ) {
$sales[ $timestamp ][1] += $sales_result->sales;
}
}
}
// Move the chart along to the next hour/day/month to get ready for the next loop.
if ( $hour_by_hour ) {
$chart_dates['start']->addHour( 1 );
} elseif ( $day_by_day ) {
$chart_dates['start']->addDays( 1 );
} else {
$chart_dates['start']->addMonth( 1 );
}
}
return array(
'sales' => array_values( $sales ),
'earnings' => array_values( $earnings ),
);
}
/**
* The callback function which fetches the data for the edd_overview_refunds_chart reports endpoint.
*
* @since 3.0
*/
function edd_overview_refunds_chart() {
global $wpdb;
$dates = Reports\get_dates_filter( 'objects' );
$chart_dates = Reports\parse_dates_for_range( null, 'now', false );
$day_by_day = Reports\get_dates_filter_day_by_day();
$hour_by_hour = Reports\get_dates_filter_hour_by_hour();
$column = Reports\get_taxes_excluded_filter() ? 'total - tax' : 'total';
$currency = Reports\get_filter_value( 'currencies' );
$sql_clauses = array(
'select' => 'date_created AS date',
'where' => '',
);
// Default to 'monthly'.
$sql_clauses['groupby'] = Reports\get_groupby_date_string( 'MONTH', 'date_created' );
$sql_clauses['orderby'] = 'MONTH(date_created)';
// Now drill down to the smallest unit.
if ( $hour_by_hour ) {
$sql_clauses['groupby'] = Reports\get_groupby_date_string( 'HOUR', 'date_created' );
$sql_clauses['orderby'] = 'HOUR(date_created)';
} elseif ( $day_by_day ) {
$sql_clauses['groupby'] = Reports\get_groupby_date_string( 'DATE', 'date_created' );
$sql_clauses['orderby'] = 'DATE(date_created)';
}
if ( empty( $currency ) || 'convert' === $currency ) {
$column = sprintf( '(%s) / rate', $column );
} else {
$sql_clauses['where'] = $wpdb->prepare( " AND currency = %s ", strtoupper( $currency ) );
}
$results = $wpdb->get_results(
$wpdb->prepare(
"SELECT COUNT(id) AS number, SUM({$column}) AS amount, {$sql_clauses['select']}
FROM {$wpdb->edd_orders} edd_o
WHERE status IN (%s, %s) AND date_created >= %s AND date_created <= %s AND type = 'refund'
{$sql_clauses['where']}
GROUP BY {$sql_clauses['groupby']}
ORDER BY {$sql_clauses['orderby']} ASC",
esc_sql( 'complete' ),
esc_sql( 'partially_refunded' ),
$dates['start']->copy()->format( 'mysql' ),
$dates['end']->copy()->format( 'mysql' )
)
);
$number = array();
$amount = array();
// Initialise all arrays with timestamps and set values to 0.
while ( strtotime( $chart_dates['start']->copy()->format( 'mysql' ) ) <= strtotime( $chart_dates['end']->copy()->format( 'mysql' ) ) ) {
$timestamp = $chart_dates['start']->copy()->format( 'U' );
$date_on_chart = $chart_dates['start'];
$number[ $timestamp ][0] = $date_on_chart->format( 'Y-m-d H:i:s' );
$number[ $timestamp ][1] = 0;
$amount[ $timestamp ][0] = $date_on_chart->format( 'Y-m-d H:i:s' );
$amount[ $timestamp ][1] = 0.00;
// Loop through each date there were refunds, which we queried from the database.
foreach ( $results as $result ) {
$date_of_db_value = edd_get_edd_timezone_equivalent_date_from_utc( EDD()->utils->date( $result->date ) );
// Add any refunds that happened during this hour.
if ( $hour_by_hour ) {
// If the date of this db value matches the date on this line graph/chart, set the y axis value for the chart to the number in the DB result.
if ( $date_of_db_value->format( 'Y-m-d H' ) === $date_on_chart->format( 'Y-m-d H' ) ) {
$number[ $timestamp ][1] += $result->number;
$amount[ $timestamp ][1] += abs( $result->amount );
}
// Add any refunds that happened during this day.
} elseif ( $day_by_day ) {
// If the date of this db value matches the date on this line graph/chart, set the y axis value for the chart to the number in the DB result.
if ( $date_of_db_value->format( 'Y-m-d' ) === $date_on_chart->format( 'Y-m-d' ) ) {
$number[ $timestamp ][1] += $result->number;
$amount[ $timestamp ][1] += abs( $result->amount );
}
// Add any refunds that happened during this month.
} else {
// If the date of this db value matches the date on this line graph/chart, set the y axis value for the chart to the number in the DB result.
if ( $date_of_db_value->format( 'Y-m' ) === $date_on_chart->format( 'Y-m' ) ) {
$number[ $timestamp ][1] += $result->number;
$amount[ $timestamp ][1] += abs( $result->amount );
}
}
}
// Move the chart along to the next hour/day/month to get ready for the next loop.
if ( $hour_by_hour ) {
$chart_dates['start']->addHour( 1 );
} elseif ( $day_by_day ) {
$chart_dates['start']->addDays( 1 );
} else {
$chart_dates['start']->addMonth( 1 );
}
}
return array(
'number' => array_values( $number ),
'amount' => array_values( $amount ),
);
}

File diff suppressed because it is too large Load Diff