installed plugin Easy Digital Downloads
version 3.1.0.3
This commit is contained in:
@ -0,0 +1,341 @@
|
||||
<?php
|
||||
/**
|
||||
* Earnings by Taxonomy list table.
|
||||
*
|
||||
* @package EDD
|
||||
* @subpackage Reports/Data/File_Downloads
|
||||
* @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\Reports\Data\Downloads;
|
||||
|
||||
// Exit if accessed directly
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
use EDD\Reports as Reports;
|
||||
use EDD\Admin\List_Table;
|
||||
|
||||
/**
|
||||
* Earnings_By_Taxonomy_List_Table class.
|
||||
*
|
||||
* @since 3.0
|
||||
*/
|
||||
class Earnings_By_Taxonomy_List_Table extends List_Table {
|
||||
|
||||
/**
|
||||
* Query the database and fetch the top five most downloaded products.
|
||||
*
|
||||
* @since 3.0
|
||||
*
|
||||
* @return array Taxonomies.
|
||||
*/
|
||||
public function get_data() {
|
||||
global $wpdb;
|
||||
|
||||
$dates = Reports\get_filter_value( 'dates' );
|
||||
$date_range = Reports\parse_dates_for_range( $dates['range'] );
|
||||
$currency = Reports\get_filter_value( 'currencies' );
|
||||
|
||||
// Generate date query SQL if dates have been set.
|
||||
$date_query_sql = '';
|
||||
|
||||
if ( ! empty( $date_range['start'] ) || ! empty( $date_range['end'] ) ) {
|
||||
if ( ! empty( $date_range['start'] ) ) {
|
||||
$date_query_sql .= $wpdb->prepare( 'AND oi.date_created >= %s', $date_range['start']->format( 'mysql' ) );
|
||||
}
|
||||
|
||||
// Join dates with `AND` if start and end date set.
|
||||
if ( ! empty( $date_range['start'] ) && ! empty( $date_range['end'] ) ) {
|
||||
$date_query_sql .= ' AND ';
|
||||
}
|
||||
|
||||
if ( ! empty( $date_range['end'] ) ) {
|
||||
$date_query_sql .= $wpdb->prepare( 'oi.date_created <= %s', $date_range['end']->format( 'mysql' ) );
|
||||
}
|
||||
}
|
||||
|
||||
$taxonomies = edd_get_download_taxonomies();
|
||||
$taxonomies = array_map( 'sanitize_text_field', $taxonomies );
|
||||
|
||||
$placeholders = implode( ', ', array_fill( 0, count( $taxonomies ), '%s' ) );
|
||||
|
||||
$taxonomy__in = $wpdb->prepare( "tt.taxonomy IN ({$placeholders})", $taxonomies );
|
||||
|
||||
$sql = "SELECT t.*, tt.*, tr.object_id
|
||||
FROM {$wpdb->terms} AS t
|
||||
INNER JOIN {$wpdb->term_taxonomy} AS tt ON t.term_id = tt.term_id
|
||||
INNER JOIN {$wpdb->term_relationships} AS tr ON tr.term_taxonomy_id = tt.term_taxonomy_id
|
||||
WHERE {$taxonomy__in}";
|
||||
|
||||
$results = $wpdb->get_results( $sql );
|
||||
|
||||
// Build intermediate array to allow for better data processing.
|
||||
$taxonomies = array();
|
||||
foreach ( $results as $r ) {
|
||||
$taxonomies[ absint( $r->term_id ) ]['name'] = esc_html( $r->name );
|
||||
$taxonomies[ absint( $r->term_id ) ]['object_ids'][] = absint( $r->object_id );
|
||||
$taxonomies[ absint( $r->term_id ) ]['parent'] = absint( $r->parent );
|
||||
}
|
||||
|
||||
$data = array();
|
||||
$parent_ids = array();
|
||||
|
||||
$column = Reports\get_taxes_excluded_filter() ? 'oi.total - oi.tax' : 'oi.total';
|
||||
$join = " INNER JOIN {$wpdb->edd_orders} o ON o.id = oi.order_id ";
|
||||
$currency_clause = '';
|
||||
|
||||
if ( empty( $currency ) || 'convert' === $currency ) {
|
||||
$column = sprintf( '(%s) / oi.rate', $column );
|
||||
} elseif ( array_key_exists( strtoupper( $currency ), edd_get_currencies() ) ) {
|
||||
$currency_clause = $wpdb->prepare(
|
||||
" AND o.currency = %s ",
|
||||
strtoupper( $currency )
|
||||
);
|
||||
}
|
||||
|
||||
$statuses = edd_get_net_order_statuses();
|
||||
$status_string = implode( ', ', array_fill( 0, count( $statuses ), '%s' ) );
|
||||
$status_sql = $wpdb->prepare(
|
||||
" AND oi.status IN('complete','partially_refunded')
|
||||
AND o.status IN({$status_string})",
|
||||
...$statuses
|
||||
);
|
||||
|
||||
foreach ( $taxonomies as $k => $t ) {
|
||||
$c = new \stdClass();
|
||||
$c->id = $k;
|
||||
$c->name = $taxonomies[ $k ]['name'];
|
||||
|
||||
$placeholders = implode( ', ', array_fill( 0, count( $taxonomies[ $k ]['object_ids'] ), '%d' ) );
|
||||
$product_id__in = $wpdb->prepare( "oi.product_id IN({$placeholders})", $taxonomies[ $k ]['object_ids'] );
|
||||
|
||||
$sql = "SELECT SUM({$column}) as total
|
||||
FROM {$wpdb->edd_order_items} oi
|
||||
{$join}
|
||||
WHERE {$product_id__in} {$currency_clause} {$date_query_sql} {$status_sql}";
|
||||
|
||||
$result = $wpdb->get_row( $sql ); // WPCS: unprepared SQL ok.
|
||||
|
||||
$earnings = null === $result && null === $result->total
|
||||
? 0.00
|
||||
: floatval( $result->total );
|
||||
|
||||
$complete_orders = "SELECT SUM(oi.quantity) as sales
|
||||
FROM {$wpdb->edd_order_items} oi
|
||||
{$join}
|
||||
WHERE {$product_id__in} {$currency_clause} {$date_query_sql} {$status_sql}";
|
||||
$partial_orders = "SELECT SUM(oi.quantity) as sales
|
||||
FROM {$wpdb->edd_order_items} oi
|
||||
LEFT JOIN {$wpdb->edd_order_items} ri
|
||||
ON ri.parent = oi.id
|
||||
{$join}
|
||||
WHERE {$product_id__in} {$currency_clause} {$date_query_sql}
|
||||
AND oi.status ='partially_refunded'
|
||||
AND oi.quantity = - ri.quantity";
|
||||
$sql_sales = $wpdb->get_row( "SELECT SUM(sales) AS sales FROM ({$complete_orders} UNION {$partial_orders})a" );
|
||||
|
||||
$sales = ! empty( $sql_sales->sales ) ? $sql_sales->sales : 0;
|
||||
|
||||
$c->sales = $sales;
|
||||
$c->earnings = $earnings;
|
||||
$c->parent = 0 === $t['parent']
|
||||
? null
|
||||
: $t['parent'];
|
||||
|
||||
$average_sales = 0;
|
||||
$average_earnings = 0.00;
|
||||
|
||||
foreach ( $taxonomies[ $k ]['object_ids'] as $download ) {
|
||||
$average_sales += edd_get_average_monthly_download_sales( $download );
|
||||
$average_earnings += edd_get_average_monthly_download_earnings( $download );
|
||||
}
|
||||
|
||||
$c->average_sales = $average_sales;
|
||||
$c->average_earnings = $average_earnings;
|
||||
|
||||
$data[] = $c;
|
||||
}
|
||||
|
||||
$sorted_data = array();
|
||||
|
||||
foreach ( $data as $d ) {
|
||||
|
||||
// Get parent level elements
|
||||
if ( null === $d->parent ) {
|
||||
$sorted_data[] = $d;
|
||||
|
||||
$objects = array_values( wp_filter_object_list( $data, array( 'parent' => $d->id ) ) );
|
||||
|
||||
foreach ( $objects as $o ) {
|
||||
$sorted_data[] = $o;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Sort by total earnings
|
||||
usort( $sorted_data, function( $a, $b ) {
|
||||
return ( $a->earnings < $b->earnings ) ? -1 : 1;
|
||||
} );
|
||||
|
||||
return $sorted_data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the table columns.
|
||||
*
|
||||
* @since 3.0
|
||||
*
|
||||
* @return array $columns Array of all the list table columns
|
||||
*/
|
||||
public function get_columns() {
|
||||
return array(
|
||||
'name' => __( 'Name', 'easy-digital-downloads' ),
|
||||
'sales' => __( 'Total Sales', 'easy-digital-downloads' ),
|
||||
'earnings' => __( 'Total Earnings', 'easy-digital-downloads' ),
|
||||
'average_sales' => __( 'Monthly Sales Average', 'easy-digital-downloads' ),
|
||||
'average_earnings' => __( 'Monthly Earnings Average', 'easy-digital-downloads' )
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the Name Column.
|
||||
*
|
||||
* @since 3.0
|
||||
*
|
||||
* @param \stdClass $taxonomy Taxonomy object.
|
||||
* @return string Data shown in the Name column.
|
||||
*/
|
||||
public function column_name( $taxonomy ) {
|
||||
return 0 < $taxonomy->parent
|
||||
? '— ' . $taxonomy->name
|
||||
: $taxonomy->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the Sales Column.
|
||||
*
|
||||
* @since 3.0
|
||||
*
|
||||
* @param \stdClass $taxonomy Taxonomy object.
|
||||
* @return string Data shown in the Sales column.
|
||||
*/
|
||||
public function column_sales( $taxonomy ) {
|
||||
return $taxonomy->sales;
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the Earnings Column.
|
||||
*
|
||||
* @since 3.0
|
||||
*
|
||||
* @param \stdClass $taxonomy Taxonomy object.
|
||||
* @return string Data shown in the Earnings column.
|
||||
*/
|
||||
public function column_earnings( $taxonomy ) {
|
||||
return edd_currency_filter( edd_format_amount( $taxonomy->earnings ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the Average Sales Column.
|
||||
*
|
||||
* @since 3.0
|
||||
*
|
||||
* @param \stdClass $taxonomy Taxonomy object.
|
||||
* @return int Data shown in the Average Sales column.
|
||||
*/
|
||||
public function column_average_sales( $taxonomy ) {
|
||||
return (int) round( $taxonomy->average_sales );
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the Average Earnings Column.
|
||||
*
|
||||
* @since 3.0
|
||||
*
|
||||
* @param \stdClass $taxonomy Taxonomy object.
|
||||
* @return string Data shown in the Average Earnings column.
|
||||
*/
|
||||
public function column_average_earnings( $taxonomy ) {
|
||||
return edd_currency_filter( edd_format_amount( $taxonomy->average_earnings ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup the final data for the table.
|
||||
*
|
||||
* @since 3.0
|
||||
*/
|
||||
public function prepare_items() {
|
||||
$columns = $this->get_columns();
|
||||
$hidden = array();
|
||||
$sortable = $this->get_sortable_columns();
|
||||
|
||||
$this->_column_headers = array( $columns, $hidden, $sortable );
|
||||
$this->items = $this->get_data();
|
||||
}
|
||||
|
||||
/**
|
||||
* Message to be displayed when there are no items
|
||||
*
|
||||
* @since 3.0
|
||||
*/
|
||||
public function no_items() {
|
||||
esc_html_e( 'No taxonomies found.', 'easy-digital-downloads' );
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 'name';
|
||||
}
|
||||
|
||||
/**
|
||||
* Return empty array to disable sorting.
|
||||
*
|
||||
* @since 3.0
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_sortable_columns() {
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return empty array to remove bulk actions.
|
||||
*
|
||||
* @since 3.0
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_bulk_actions() {
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Hide pagination.
|
||||
*
|
||||
* @since 3.0
|
||||
*
|
||||
* @param string $which
|
||||
*/
|
||||
protected function pagination( $which ) {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Hide table navigation.
|
||||
*
|
||||
* @since 3.0
|
||||
*
|
||||
* @param string $which
|
||||
*/
|
||||
protected function display_tablenav( $which ) {
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,213 @@
|
||||
<?php
|
||||
/**
|
||||
* Top Selling Downloads list table.
|
||||
*
|
||||
* @package EDD
|
||||
* @subpackage Reports/Data/File_Downloads
|
||||
* @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\Reports\Data\Downloads;
|
||||
|
||||
// Exit if accessed directly
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
use EDD\Stats as Stats;
|
||||
use EDD\Reports as Reports;
|
||||
use EDD\Admin\List_Table;
|
||||
|
||||
/**
|
||||
* Top_Selling_Downloads_List_Table class.
|
||||
*
|
||||
* @since 3.0
|
||||
*/
|
||||
class Top_Selling_Downloads_List_Table extends List_Table {
|
||||
|
||||
/**
|
||||
* Query the database and fetch the top five most downloaded products.
|
||||
*
|
||||
* @since 3.0
|
||||
*
|
||||
* @return array Downloads.
|
||||
*/
|
||||
public function get_data() {
|
||||
$filter = Reports\get_filter_value( 'dates' );
|
||||
|
||||
$stats = new Stats();
|
||||
|
||||
return $stats->get_most_valuable_order_items( array(
|
||||
'number' => 10,
|
||||
'range' => $filter['range'],
|
||||
'currency' => '',
|
||||
) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the table columns.
|
||||
*
|
||||
* @since 3.0
|
||||
*
|
||||
* @return array $columns Array of all the list table columns
|
||||
*/
|
||||
public function get_columns() {
|
||||
return array(
|
||||
'name' => __( 'Name', 'easy-digital-downloads' ),
|
||||
'price' => __( 'Price', 'easy-digital-downloads' ),
|
||||
'sales' => __( 'Sales', 'easy-digital-downloads' ),
|
||||
'earnings' => __( 'Net Earnings', 'easy-digital-downloads' ),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the Name Column.
|
||||
*
|
||||
* @since 3.0
|
||||
*
|
||||
* @param \stdClass $download Download object.
|
||||
* @return string Data shown in the Name column.
|
||||
*/
|
||||
public function column_name( $download ) {
|
||||
if ( ! $download->object instanceof \EDD_Download ) {
|
||||
return '—';
|
||||
}
|
||||
|
||||
// Check for variable pricing
|
||||
$retval = ! is_null( $download->price_id ) && is_numeric( $download->price_id )
|
||||
? edd_get_download_name( $download->object->ID, $download->price_id )
|
||||
: edd_get_download_name( $download->object->ID );
|
||||
|
||||
return $retval;
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the Price Column.
|
||||
*
|
||||
* @since 3.0
|
||||
*
|
||||
* @param \stdClass $download Download object.
|
||||
* @return string Data shown in the Price column.
|
||||
*/
|
||||
public function column_price( $download ) {
|
||||
if ( ! $download->object instanceof \EDD_Download ) {
|
||||
return '—';
|
||||
}
|
||||
|
||||
// Check for variable pricing
|
||||
$retval = ! is_null( $download->price_id ) && is_numeric( $download->price_id )
|
||||
? edd_price( $download->object->ID, false, $download->price_id )
|
||||
: edd_price( $download->object->ID, false );
|
||||
|
||||
return $retval;
|
||||
}
|
||||
|
||||
public function column_sales( $download ) {
|
||||
if ( ! $download->object instanceof \EDD_Download ) {
|
||||
return '—';
|
||||
}
|
||||
|
||||
return current_user_can( 'view_product_stats', $download->object->ID )
|
||||
? $download->sales
|
||||
: '—';
|
||||
}
|
||||
|
||||
public function column_earnings( $download ) {
|
||||
if ( ! $download->object instanceof \EDD_Download ) {
|
||||
return '—';
|
||||
}
|
||||
|
||||
return current_user_can( 'view_product_stats', $download->object->ID )
|
||||
? edd_currency_filter( edd_format_amount( $download->total ) )
|
||||
: '—';
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup the final data for the table.
|
||||
*
|
||||
* @since 3.0
|
||||
*/
|
||||
public function prepare_items() {
|
||||
$columns = $this->get_columns();
|
||||
$hidden = array();
|
||||
$sortable = $this->get_sortable_columns();
|
||||
|
||||
$this->_column_headers = array( $columns, $hidden, $sortable );
|
||||
$this->items = $this->get_data();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the base URL for the discount list table
|
||||
*
|
||||
* @since 3.0
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_base_url() {
|
||||
return remove_query_arg( edd_admin_removable_query_args(), edd_get_admin_base_url() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Message to be displayed when there are no items
|
||||
*
|
||||
* @since 3.0
|
||||
*/
|
||||
public function no_items() {
|
||||
esc_html_e( 'No downloads found.', 'easy-digital-downloads' );
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 'name';
|
||||
}
|
||||
|
||||
/**
|
||||
* Return empty array to disable sorting.
|
||||
*
|
||||
* @since 3.0
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_sortable_columns() {
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return empty array to remove bulk actions.
|
||||
*
|
||||
* @since 3.0
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_bulk_actions() {
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Hide pagination.
|
||||
*
|
||||
* @since 3.0
|
||||
*
|
||||
* @param string $which
|
||||
*/
|
||||
protected function pagination( $which ) {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Hide table navigation.
|
||||
*
|
||||
* @since 3.0
|
||||
*
|
||||
* @param string $which
|
||||
*/
|
||||
protected function display_tablenav( $which ) {
|
||||
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user