updated plugin Easy Digital Downloads
version 3.1.0.4
This commit is contained in:
@ -450,4 +450,33 @@ class EDD_Customer_Addresses_Table extends List_Table {
|
||||
'per_page' => $this->per_page
|
||||
) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the table navigation above or below the table.
|
||||
* We're overriding this to turn off the referer param in `wp_nonce_field()`.
|
||||
*
|
||||
* @param string $which
|
||||
* @since 3.1.0.4
|
||||
*/
|
||||
protected function display_tablenav( $which ) {
|
||||
if ( 'top' === $which ) {
|
||||
wp_nonce_field( 'bulk-' . $this->_args['plural'], '_wpnonce', false );
|
||||
}
|
||||
?>
|
||||
<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
|
||||
}
|
||||
}
|
||||
|
@ -437,4 +437,33 @@ class EDD_Customer_Email_Addresses_Table extends List_Table {
|
||||
'per_page' => $this->per_page
|
||||
) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the table navigation above or below the table.
|
||||
* We're overriding this to turn off the referer param in `wp_nonce_field()`.
|
||||
*
|
||||
* @param string $which
|
||||
* @since 3.1.0.4
|
||||
*/
|
||||
protected function display_tablenav( $which ) {
|
||||
if ( 'top' === $which ) {
|
||||
wp_nonce_field( 'bulk-' . $this->_args['plural'], '_wpnonce', false );
|
||||
}
|
||||
?>
|
||||
<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
|
||||
}
|
||||
}
|
||||
|
@ -430,4 +430,33 @@ class EDD_Customer_Reports_Table extends List_Table {
|
||||
'per_page' => $this->per_page,
|
||||
) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the table navigation above or below the table.
|
||||
* We're overriding this to turn off the referer param in `wp_nonce_field()`.
|
||||
*
|
||||
* @param string $which
|
||||
* @since 3.1.0.4
|
||||
*/
|
||||
protected function display_tablenav( $which ) {
|
||||
if ( 'top' === $which ) {
|
||||
wp_nonce_field( 'bulk-' . $this->_args['plural'], '_wpnonce', false );
|
||||
}
|
||||
?>
|
||||
<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
|
||||
}
|
||||
}
|
||||
|
@ -427,4 +427,33 @@ class EDD_Discount_Codes_Table extends List_Table {
|
||||
'per_page' => $this->per_page,
|
||||
) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the table navigation above or below the table.
|
||||
* We're overriding this to turn off the referer param in `wp_nonce_field()`.
|
||||
*
|
||||
* @param string $which
|
||||
* @since 3.1.0.4
|
||||
*/
|
||||
protected function display_tablenav( $which ) {
|
||||
if ( 'top' === $which ) {
|
||||
wp_nonce_field( 'bulk-' . $this->_args['plural'], '_wpnonce', false );
|
||||
}
|
||||
?>
|
||||
<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
|
||||
}
|
||||
}
|
||||
|
@ -226,33 +226,52 @@ add_action( 'load-edit.php', 'edd_download_load', 9999 );
|
||||
function edd_add_download_filters() {
|
||||
global $typenow;
|
||||
|
||||
// Checks if the current post type is 'download'
|
||||
if ( $typenow !== 'download') {
|
||||
// Checks if the current post type is 'download'.
|
||||
if ( 'download' !== $typenow ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$terms = get_terms( 'download_category' );
|
||||
if ( count( $terms ) > 0 ) {
|
||||
echo "<select name='download_category' id='download_category' class='postform'>";
|
||||
$category_labels = edd_get_taxonomy_labels( 'download_category' );
|
||||
echo "<option value=''>" . sprintf( __( 'All %s', 'easy-digital-downloads' ), strtolower( $category_labels['name'] ) ) . "</option>";
|
||||
foreach ( $terms as $term ) {
|
||||
$selected = isset( $_GET['download_category'] ) && $_GET['download_category'] === $term->slug ? ' selected="selected"' : '';
|
||||
echo '<option value="' . esc_attr( $term->slug ) . '"' . $selected . '>' . esc_html( $term->name ) .' (' . $term->count .')</option>';
|
||||
}
|
||||
echo "</select>";
|
||||
}
|
||||
$category_args = array(
|
||||
'taxonomy' => 'download_category',
|
||||
'number' => 30,
|
||||
);
|
||||
|
||||
$terms = get_terms( 'download_tag' );
|
||||
if ( count( $terms ) > 0 ) {
|
||||
echo "<select name='download_tag' id='download_tag' class='postform'>";
|
||||
$tag_labels = edd_get_taxonomy_labels( 'download_tag' );
|
||||
echo "<option value=''>" . sprintf( __( 'All %s', 'easy-digital-downloads' ), strtolower( $tag_labels['name'] ) ) . "</option>";
|
||||
foreach ( $terms as $term ) {
|
||||
$selected = isset( $_GET['download_tag']) && $_GET['download_tag'] === $term->slug ? ' selected="selected"' : '';
|
||||
echo '<option value="' . esc_attr( $term->slug ) . '"' . $selected . '>' . esc_html( $term->name ) .' (' . $term->count .')</option>';
|
||||
}
|
||||
echo "</select>";
|
||||
$categories = get_terms( $category_args );
|
||||
if ( ! empty( $categories ) ) {
|
||||
$category_labels = edd_get_taxonomy_labels( 'download_category' );
|
||||
|
||||
$options = array();
|
||||
$options[''] = sprintf( _x( 'All %s', 'plural: Example: "All Categories"', 'easy-digital-downloads' ), $category_labels['name'] );
|
||||
|
||||
// Ensure we include the selected value in the pre-populated list.
|
||||
$selected = ! empty( $_GET['download_category'] ) ? $_GET['download_category'] : '';
|
||||
if ( ! empty( $selected ) ) {
|
||||
$selected_term = get_term_by( 'slug', $selected, 'download_category' );
|
||||
|
||||
$options[ $selected_term->slug ] = $selected_term->name . ' (' . $selected_term->count . ')';
|
||||
}
|
||||
|
||||
foreach ( $categories as $category ) {
|
||||
$options[ $category->slug ] = $category->name . ' (' . $category->count . ')';
|
||||
}
|
||||
|
||||
echo EDD()->html->select(
|
||||
array(
|
||||
'name' => 'download_category',
|
||||
'id' => 'download_category',
|
||||
'class' => 'postform',
|
||||
'chosen' => true,
|
||||
'show_option_all' => false,
|
||||
'show_option_none' => false,
|
||||
'options' => $options,
|
||||
'selected' => $selected,
|
||||
'data' => array(
|
||||
'placeholder' => sprintf( _x( 'Search %s', 'plural: Example: "Search Download Categories"', 'easy-digital-downloads' ), $category_labels['name'] ),
|
||||
'search-type' => 'download_category',
|
||||
'search-placeholder' => sprintf( _x( 'Search %s', 'plural: Example: "Search Download Categories"', 'easy-digital-downloads' ), $category_labels['name'] ),
|
||||
),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
if ( isset( $_REQUEST['all_posts'] ) && '1' === $_REQUEST['all_posts'] ) {
|
||||
|
@ -1057,4 +1057,33 @@ class EDD_Payment_History_Table extends List_Table {
|
||||
'per_page' => $this->per_page,
|
||||
) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the table navigation above or below the table.
|
||||
* We're overriding this to turn off the referer param in `wp_nonce_field()`.
|
||||
*
|
||||
* @param string $which
|
||||
* @since 3.1.0.4
|
||||
*/
|
||||
protected function display_tablenav( $which ) {
|
||||
if ( 'top' === $which ) {
|
||||
wp_nonce_field( 'bulk-' . $this->_args['plural'], '_wpnonce', false );
|
||||
}
|
||||
?>
|
||||
<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
|
||||
}
|
||||
}
|
||||
|
@ -745,39 +745,85 @@ function edd_register_downloads_report( $reports ) {
|
||||
'groupby' => '',
|
||||
);
|
||||
|
||||
$union_clauses = array(
|
||||
'select' => 'date',
|
||||
'where' => '',
|
||||
'groupby' => '',
|
||||
);
|
||||
|
||||
// Default to 'monthly'.
|
||||
$sql_clauses['groupby'] = Reports\get_groupby_date_string( 'MONTH', 'edd_oi.date_created' );
|
||||
$sql_clauses['orderby'] = 'MONTH(edd_oi.date_created)';
|
||||
|
||||
$union_clauses['groupby'] = Reports\get_groupby_date_string( 'MONTH', 'date' );
|
||||
$union_clauses['orderby'] = 'MONTH(date)';
|
||||
|
||||
// Now drill down to the smallest unit.
|
||||
if ( $hour_by_hour ) {
|
||||
$sql_clauses['groupby'] = Reports\get_groupby_date_string( 'HOUR', 'edd_oi.date_created' );
|
||||
$sql_clauses['orderby'] = 'HOUR(edd_oi.date_created)';
|
||||
|
||||
$union_clauses['groupby'] = Reports\get_groupby_date_string( 'HOUR', 'date' );
|
||||
$union_clauses['orderby'] = 'HOUR(date)';
|
||||
} elseif ( $day_by_day ) {
|
||||
$sql_clauses['groupby'] = Reports\get_groupby_date_string( 'DATE', 'edd_oi.date_created' );
|
||||
$sql_clauses['orderby'] = 'DATE(edd_oi.date_created)';
|
||||
}
|
||||
|
||||
$union_clauses['groupby'] = Reports\get_groupby_date_string( 'DATE', 'date' );
|
||||
$union_clauses['orderby'] = 'DATE(date)';
|
||||
}
|
||||
|
||||
$price_id = isset( $download_data['price_id'] ) && is_numeric( $download_data['price_id'] )
|
||||
? sprintf( 'AND price_id = %d', absint( $download_data['price_id'] ) )
|
||||
: '';
|
||||
|
||||
$earnings_results = $wpdb->get_results(
|
||||
$wpdb->prepare(
|
||||
"SELECT SUM(edd_oi.total / edd_oi.rate) AS earnings, %1s
|
||||
FROM {$wpdb->edd_order_items} edd_oi
|
||||
WHERE edd_oi.product_id = %d %1s AND edd_oi.date_created >= %s AND edd_oi.date_created <= %s AND edd_oi.status IN ( 'complete', 'refunded', 'partially_refunded' )
|
||||
GROUP BY {$sql_clauses['groupby']}
|
||||
ORDER BY {$sql_clauses['orderby']} ASC",
|
||||
$sql_clauses['select'],
|
||||
$download_data['download_id'],
|
||||
$price_id,
|
||||
$dates['start']->copy()->format( 'mysql' ),
|
||||
$dates['end']->copy()->format( 'mysql' )
|
||||
)
|
||||
$earnings_statuses = edd_get_gross_order_statuses();
|
||||
$earnings_status_string = implode( ', ', array_fill( 0, count( $earnings_statuses ), '%s' ) );
|
||||
|
||||
$order_item_earnings = $wpdb->prepare(
|
||||
"SELECT SUM(edd_oi.total / edd_oi.rate) AS earnings, %1s
|
||||
FROM {$wpdb->edd_order_items} edd_oi
|
||||
INNER JOIN {$wpdb->edd_orders} edd_o ON edd_oi.order_id = edd_o.id
|
||||
WHERE edd_oi.product_id = %d %1s AND edd_oi.date_created >= %s AND edd_oi.date_created <= %s AND edd_o.status IN ({$earnings_status_string})
|
||||
GROUP BY {$sql_clauses['groupby']}",
|
||||
$sql_clauses['select'],
|
||||
$download_data['download_id'],
|
||||
$price_id,
|
||||
$dates['start']->copy()->format( 'mysql' ),
|
||||
$dates['end']->copy()->format( 'mysql' ),
|
||||
...$earnings_statuses
|
||||
);
|
||||
|
||||
/**
|
||||
* The adjustments query needs a different order status check than the order items. This is due to the fact that
|
||||
* adjustments refunded would end up being double counted, and therefore create an inaccurate revenue report.
|
||||
*/
|
||||
$adjustments_statuses = edd_get_net_order_statuses();
|
||||
$adjustments_status_string = implode( ', ', array_fill( 0, count( $adjustments_statuses ), '%s' ) );
|
||||
|
||||
$order_adjustments = $wpdb->prepare(
|
||||
"SELECT SUM(edd_oa.total / edd_oa.rate) AS earnings, %1s
|
||||
FROM {$wpdb->edd_order_adjustments} edd_oa
|
||||
INNER JOIN {$wpdb->edd_order_items} edd_oi ON
|
||||
edd_oi.id = edd_oa.object_id
|
||||
AND edd_oi.product_id = %d
|
||||
%1s
|
||||
AND edd_oi.date_created >= %s AND edd_oi.date_created <= %s
|
||||
INNER JOIN {$wpdb->edd_orders} edd_o ON edd_oi.order_id = edd_o.id AND edd_o.type = 'sale' AND edd_o.status IN ({$adjustments_status_string})
|
||||
WHERE edd_oa.object_type = 'order_item'
|
||||
AND edd_oa.type != 'discount'
|
||||
GROUP BY {$sql_clauses['groupby']}",
|
||||
$sql_clauses['select'],
|
||||
$download_data['download_id'],
|
||||
$price_id,
|
||||
$dates['start']->copy()->format( 'mysql' ),
|
||||
$dates['end']->copy()->format( 'mysql' ),
|
||||
...$adjustments_statuses
|
||||
);
|
||||
|
||||
$earnings_sql = "SELECT SUM(earnings) as earnings, {$union_clauses['select']} FROM ({$order_item_earnings} UNION {$order_adjustments})a GROUP BY {$union_clauses['groupby']} ORDER BY {$union_clauses['orderby']}";
|
||||
$earnings_results = $wpdb->get_results( $earnings_sql );
|
||||
|
||||
$statuses = edd_get_net_order_statuses();
|
||||
$status_string = implode( ', ', array_fill( 0, count( $statuses ), '%s' ) );
|
||||
|
||||
@ -786,22 +832,22 @@ function edd_register_downloads_report( $reports ) {
|
||||
...$statuses
|
||||
);
|
||||
|
||||
$sales_results = $wpdb->get_results(
|
||||
$wpdb->prepare(
|
||||
"SELECT COUNT(edd_oi.total) AS sales, %1s
|
||||
FROM {$wpdb->edd_order_items} edd_oi
|
||||
{$join}
|
||||
WHERE edd_oi.product_id = %d %1s AND edd_oi.date_created >= %s AND edd_oi.date_created <= %s AND edd_oi.status IN ( 'complete', 'refunded', 'partially_refunded' )
|
||||
GROUP BY {$sql_clauses['groupby']}
|
||||
ORDER BY {$sql_clauses['orderby']} ASC",
|
||||
$sql_clauses['select'],
|
||||
$download_data['download_id'],
|
||||
$price_id,
|
||||
$dates['start']->copy()->format( 'mysql' ),
|
||||
$dates['end']->copy()->format( 'mysql' )
|
||||
)
|
||||
$sales_sql = $wpdb->prepare(
|
||||
"SELECT COUNT(edd_oi.total) AS sales, {$sql_clauses['select']}
|
||||
FROM {$wpdb->edd_order_items} edd_oi
|
||||
{$join}
|
||||
WHERE edd_oi.product_id = %d %1s AND edd_oi.date_created >= %s AND edd_oi.date_created <= %s AND edd_oi.status IN ({$status_string})
|
||||
GROUP BY {$sql_clauses['groupby']}
|
||||
ORDER BY {$sql_clauses['orderby']} ASC",
|
||||
$download_data['download_id'],
|
||||
$price_id,
|
||||
$dates['start']->copy()->format( 'mysql' ),
|
||||
$dates['end']->copy()->format( 'mysql' ),
|
||||
...$statuses
|
||||
);
|
||||
|
||||
$sales_results = $wpdb->get_results( $sales_sql );
|
||||
|
||||
$sales = array();
|
||||
$earnings = array();
|
||||
|
||||
|
@ -598,24 +598,30 @@ function edd_ajax_download_search() {
|
||||
// but we'll worry about that later if that situation ever happens.
|
||||
$args = get_transient( 'edd_download_search' );
|
||||
|
||||
// Parse args
|
||||
$search = wp_parse_args( (array) $args, array(
|
||||
'text' => '',
|
||||
'results' => array()
|
||||
) );
|
||||
// Parse args.
|
||||
$search = wp_parse_args(
|
||||
(array) $args,
|
||||
array(
|
||||
'text' => '',
|
||||
'results' => array(),
|
||||
)
|
||||
);
|
||||
|
||||
// Get the search string
|
||||
// Get the search string.
|
||||
$new_search = isset( $_GET['s'] )
|
||||
? sanitize_text_field( $_GET['s'] )
|
||||
: '';
|
||||
|
||||
// Bail early if the search text has not changed
|
||||
// Limit to only alphanumeric characters, including unicode and spaces.
|
||||
$new_search = preg_replace( '/[^\pL^\pN\pZ]/', ' ', $new_search );
|
||||
|
||||
// Bail early if the search text has not changed.
|
||||
if ( $search['text'] === $new_search ) {
|
||||
echo json_encode( $search['results'] );
|
||||
echo wp_json_encode( $search['results'] );
|
||||
edd_die();
|
||||
}
|
||||
|
||||
// Set the local static search variable
|
||||
// Set the local static search variable.
|
||||
$search['text'] = $new_search;
|
||||
|
||||
// Are we excluding the current ID?
|
||||
@ -640,17 +646,17 @@ function edd_ajax_download_search() {
|
||||
// Are we including all statuses, or only public ones?
|
||||
$status = ! current_user_can( 'edit_products' )
|
||||
? apply_filters( 'edd_product_dropdown_status_nopriv', array( 'publish' ) )
|
||||
: apply_filters( 'edd_product_dropdown_status', array( 'publish', 'draft', 'private', 'future' ) );
|
||||
: apply_filters( 'edd_product_dropdown_status', array( 'publish', 'draft', 'private', 'future' ) );
|
||||
|
||||
// Default query arguments
|
||||
// Default query arguments.
|
||||
$args = array(
|
||||
'orderby' => 'title',
|
||||
'order' => 'ASC',
|
||||
'post_type' => 'download',
|
||||
'posts_per_page' => 50,
|
||||
'post_status' => implode( ',', $status ), // String
|
||||
'post__not_in' => $excludes, // Array
|
||||
'edd_search' => $new_search, // String
|
||||
'post_status' => implode( ',', $status ), // String.
|
||||
'post__not_in' => $excludes, // Array.
|
||||
'edd_search' => $new_search, // String.
|
||||
'suppress_filters' => false,
|
||||
);
|
||||
|
||||
@ -672,11 +678,11 @@ function edd_ajax_download_search() {
|
||||
}
|
||||
|
||||
add_filter( 'posts_where', 'edd_ajax_filter_download_where', 10, 2 );
|
||||
// Get downloads
|
||||
// Get downloads.
|
||||
$items = get_posts( $args );
|
||||
remove_filter( 'posts_where', 'edd_ajax_filter_download_where', 10, 2 );
|
||||
|
||||
// Pluck title & ID
|
||||
// Pluck title & ID.
|
||||
if ( ! empty( $items ) ) {
|
||||
$items = wp_list_pluck( $items, 'post_title', 'ID' );
|
||||
|
||||
@ -684,25 +690,25 @@ function edd_ajax_download_search() {
|
||||
foreach ( $items as $post_id => $title ) {
|
||||
$product_title = $title;
|
||||
|
||||
// Look for variable pricing
|
||||
// Look for variable pricing.
|
||||
$prices = edd_get_variable_prices( $post_id );
|
||||
|
||||
if ( ! empty( $prices ) && ( false === $variations|| ! $variations_only ) ) {
|
||||
if ( ! empty( $prices ) && ( false === $variations || ! $variations_only ) ) {
|
||||
$title .= ' (' . __( 'All Price Options', 'easy-digital-downloads' ) . ')';
|
||||
}
|
||||
|
||||
if ( empty( $prices ) || ! $variations_only ) {
|
||||
// Add item to results array
|
||||
// Add item to results array.
|
||||
$search['results'][] = array(
|
||||
'id' => $post_id,
|
||||
'name' => $title,
|
||||
);
|
||||
}
|
||||
|
||||
// Maybe include variable pricing
|
||||
// Maybe include variable pricing.
|
||||
if ( ! empty( $variations ) && ! empty( $prices ) ) {
|
||||
foreach ( $prices as $key => $value ) {
|
||||
$name = ! empty( $value['name'] ) ? $value['name'] : '';
|
||||
$name = ! empty( $value['name'] ) ? $value['name'] : '';
|
||||
|
||||
if ( ! empty( $name ) ) {
|
||||
$search['results'][] = array(
|
||||
@ -713,17 +719,16 @@ function edd_ajax_download_search() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Empty the results array
|
||||
} else {
|
||||
// Empty the results array.
|
||||
$search['results'] = array();
|
||||
}
|
||||
|
||||
// Update the transient
|
||||
// Update the transient.
|
||||
set_transient( 'edd_download_search', $search, 30 );
|
||||
|
||||
// Output the results
|
||||
echo json_encode( $search['results'] );
|
||||
// Output the results.
|
||||
echo wp_json_encode( $search['results'] );
|
||||
|
||||
// Done!
|
||||
edd_die();
|
||||
@ -802,6 +807,45 @@ function edd_ajax_customer_search() {
|
||||
}
|
||||
add_action( 'wp_ajax_edd_customer_search', 'edd_ajax_customer_search' );
|
||||
|
||||
/**
|
||||
* Search the download categories via AJAX
|
||||
*
|
||||
* @since 3.1.0.4
|
||||
* @return void
|
||||
*/
|
||||
function edd_ajax_download_category_search() {
|
||||
$search = esc_sql( sanitize_text_field( $_GET['s'] ) );
|
||||
$results = array();
|
||||
|
||||
$category_args = array(
|
||||
'taxonomy' => array( 'download_category' ),
|
||||
'orderby' => 'id',
|
||||
'order' => 'ASC',
|
||||
'hide_empty' => true,
|
||||
'fields' => 'all',
|
||||
'name__like' => $search,
|
||||
);
|
||||
|
||||
$categories_found = get_terms( $category_args );
|
||||
|
||||
if ( ! empty( $categories_found ) ) {
|
||||
foreach ( $categories_found as $category ) {
|
||||
$results[] = array(
|
||||
'id' => $category->slug,
|
||||
'name' => $category->name . ' (' . $category->count . ')',
|
||||
);
|
||||
}
|
||||
} else {
|
||||
$results[] = array(
|
||||
'id' => 0,
|
||||
'name' => __( 'No categories found', 'easy-digital-downloads' ),
|
||||
);
|
||||
}
|
||||
|
||||
echo wp_send_json( $results );
|
||||
}
|
||||
add_action( 'wp_ajax_edd_download_category_search', 'edd_ajax_download_category_search' );
|
||||
|
||||
/**
|
||||
* Search the users database via AJAX
|
||||
*
|
||||
|
@ -370,102 +370,118 @@ class EDD_API_V2 extends EDD_API_V1 {
|
||||
|
||||
$sales = array();
|
||||
|
||||
if( ! user_can( $this->user_id, 'view_shop_reports' ) && ! $this->override ) {
|
||||
if ( ! user_can( $this->user_id, 'view_shop_reports' ) && ! $this->override ) {
|
||||
return $sales;
|
||||
}
|
||||
|
||||
if( isset( $wp_query->query_vars['id'] ) ) {
|
||||
if ( isset( $wp_query->query_vars['id'] ) ) {
|
||||
$query = array();
|
||||
$query[] = new EDD_Payment( $wp_query->query_vars['id'] );
|
||||
} elseif( isset( $wp_query->query_vars['purchasekey'] ) ) {
|
||||
$query[] = edd_get_order( $wp_query->query_vars['id'] );
|
||||
} elseif ( isset( $wp_query->query_vars['purchasekey'] ) ) {
|
||||
$query = array();
|
||||
$query[] = edd_get_payment_by( 'key', $wp_query->query_vars['purchasekey'] );
|
||||
} elseif( isset( $wp_query->query_vars['email'] ) ) {
|
||||
$query = edd_get_payments( array( 'fields' => 'ids', 'meta_key' => '_edd_payment_user_email', 'meta_value' => $wp_query->query_vars['email'], 'number' => $this->per_page(), 'page' => $this->get_paged(), 'status' => 'complete' ) );
|
||||
$query[] = edd_get_order_by( 'payment_key', $wp_query->query_vars['purchasekey'] );
|
||||
} elseif ( isset( $wp_query->query_vars['email'] ) ) {
|
||||
$query = edd_get_orders(
|
||||
array(
|
||||
'type' => 'sale',
|
||||
'email' => $wp_query->query_vars['email'],
|
||||
'number' => $this->per_page(),
|
||||
'offset' => ( $this->get_paged() - 1 ) * $this->per_page(),
|
||||
'status__in' => edd_get_net_order_statuses(),
|
||||
)
|
||||
);
|
||||
} else {
|
||||
$query = edd_get_payments( array( 'fields' => 'ids', 'number' => $this->per_page(), 'page' => $this->get_paged(), 'status' => 'complete' ) );
|
||||
$query = edd_get_orders(
|
||||
array(
|
||||
'type' => 'sale',
|
||||
'number' => $this->per_page(),
|
||||
'offset' => ( $this->get_paged() - 1 ) * $this->per_page(),
|
||||
'status__in' => edd_get_net_order_statuses(),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
if ( $query ) {
|
||||
$i = 0;
|
||||
foreach ( $query as $payment ) {
|
||||
if ( is_numeric( $payment ) ) {
|
||||
$payment = new EDD_Payment( $payment );
|
||||
foreach ( $query as $order ) {
|
||||
/** @var EDD\Orders\Order $order An Order object. */
|
||||
|
||||
$localized_time = edd_get_edd_timezone_equivalent_date_from_utc( EDD()->utils->date( $order->date_created ) );
|
||||
|
||||
$sales['sales'][ $i ]['ID'] = $order->get_number();
|
||||
$sales['sales'][ $i ]['mode'] = $order->mode;
|
||||
$sales['sales'][ $i ]['status'] = $order->status;
|
||||
$sales['sales'][ $i ]['transaction_id'] = $order->get_transaction_id();
|
||||
$sales['sales'][ $i ]['key'] = $order->payment_key;
|
||||
$sales['sales'][ $i ]['subtotal'] = $order->subtotal;
|
||||
$sales['sales'][ $i ]['tax'] = $order->tax;
|
||||
$sales['sales'][ $i ]['total'] = $order->total;
|
||||
$sales['sales'][ $i ]['gateway'] = $order->gateway;
|
||||
$sales['sales'][ $i ]['customer_id'] = $order->customer_id;
|
||||
$sales['sales'][ $i ]['user_id'] = $order->user_id;
|
||||
$sales['sales'][ $i ]['email'] = $order->email;
|
||||
$sales['sales'][ $i ]['date'] = $localized_time->copy()->format( 'Y-m-d H:i:s' );
|
||||
$sales['sales'][ $i ]['date_utc'] = $order->date_created;
|
||||
|
||||
$fees = array();
|
||||
$discounts = array();
|
||||
|
||||
foreach ( $order->adjustments as $adjustment ) {
|
||||
switch ( $adjustment->type ) {
|
||||
case 'fee':
|
||||
$fees[] = array(
|
||||
'amount' => $adjustment->total,
|
||||
'label' => $adjustment->description,
|
||||
'no_tax' => empty( $adjustment->tax ),
|
||||
'type' => $adjustment->type,
|
||||
'price_id' => null,
|
||||
'download_id' => null,
|
||||
'id' => $adjustment->type_key,
|
||||
);
|
||||
break;
|
||||
|
||||
case 'discount':
|
||||
$discounts[ $adjustment->description ] = $adjustment->total;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$payment_meta = $payment->get_meta();
|
||||
$user_info = $payment->user_info;
|
||||
|
||||
$sales['sales'][ $i ]['ID'] = $payment->number;
|
||||
$sales['sales'][ $i ]['mode'] = $payment->mode;
|
||||
$sales['sales'][ $i ]['status'] = $payment->status;
|
||||
$sales['sales'][ $i ]['transaction_id'] = ( ! empty( $payment->transaction_id ) ) ? $payment->transaction_id : null;
|
||||
$sales['sales'][ $i ]['key'] = $payment->key;
|
||||
$sales['sales'][ $i ]['subtotal'] = $payment->subtotal;
|
||||
$sales['sales'][ $i ]['tax'] = $payment->tax;
|
||||
$sales['sales'][ $i ]['fees'] = ( ! empty( $payment->fees ) ? $payment->fees : null );
|
||||
$sales['sales'][ $i ]['total'] = $payment->total;
|
||||
$sales['sales'][ $i ]['gateway'] = $payment->gateway;
|
||||
$sales['sales'][ $i ]['customer_id'] = $payment->customer_id;
|
||||
$sales['sales'][ $i ]['user_id'] = $payment->user_id;
|
||||
$sales['sales'][ $i ]['email'] = $payment->email;
|
||||
$sales['sales'][ $i ]['date'] = $payment->date;
|
||||
|
||||
$c = 0;
|
||||
|
||||
$discounts = ! empty( $payment->discounts ) ? explode( ',', $payment->discounts ) : array();
|
||||
$discounts = array_map( 'trim', $discounts );
|
||||
$discount_values = array();
|
||||
|
||||
foreach ( $discounts as $discount ) {
|
||||
if ( 'none' === $discount ) { continue; }
|
||||
|
||||
$discount_values[ $discount ] = 0;
|
||||
}
|
||||
|
||||
$cart_items = array();
|
||||
|
||||
foreach ( $payment->cart_details as $key => $item ) {
|
||||
foreach ( $order->items as $item ) {
|
||||
$cart_items[ $c ]['object_id'] = $item->id;
|
||||
$cart_items[ $c ]['id'] = $item->product_id;
|
||||
$cart_items[ $c ]['quantity'] = $item->quantity;
|
||||
$cart_items[ $c ]['name'] = $item->product_name;
|
||||
$cart_items[ $c ]['price'] = $item->total;
|
||||
|
||||
$item_id = isset( $item['id'] ) ? $item['id'] : $item;
|
||||
$price = isset( $item['price'] ) ? $item['price'] : false; // The final price for the item
|
||||
$item_price = isset( $item['item_price'] ) ? $item['item_price'] : false; // The price before discounts
|
||||
// Keeping this here for backwards compatibility.
|
||||
$cart_items[ $c ]['price_name'] = null === $item->price_id
|
||||
? ''
|
||||
: edd_get_price_name( $item->product_id, array( 'price_id' => $item->price_id ) );
|
||||
|
||||
$price_id = isset( $item['item_number']['options']['price_id'] ) ? $item['item_number']['options']['price_id'] : null;
|
||||
$quantity = isset( $item['quantity'] ) && $item['quantity'] > 0 ? $item['quantity'] : 1;
|
||||
|
||||
if( ! $price ) {
|
||||
// This function is only used on payments with near 1.0 cart data structure
|
||||
$price = edd_get_download_final_price( $item_id, $user_info, null );
|
||||
}
|
||||
|
||||
$price_name = '';
|
||||
if ( isset( $item['item_number'] ) && isset( $item['item_number']['options'] ) ) {
|
||||
$price_options = $item['item_number']['options'];
|
||||
if ( isset( $price_options['price_id'] ) ) {
|
||||
$price_name = edd_get_price_option_name( $item_id, $price_options['price_id'], $payment->ID );
|
||||
// Check for any item level fees to include in the fees array.
|
||||
foreach ( $item->adjustments as $adjustment ) {
|
||||
if ( 'fee' === $adjustment->type ) {
|
||||
$fees[] = array(
|
||||
'amount' => $adjustment->total,
|
||||
'label' => $adjustment->description,
|
||||
'no_tax' => empty( $adjustment->tax ),
|
||||
'type' => $adjustment->type,
|
||||
'price_id' => $item->price_id,
|
||||
'download_id' => $item->product_id,
|
||||
'id' => $adjustment->type_key,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
$cart_items[ $c ]['id'] = $item_id;
|
||||
$cart_items[ $c ]['quantity'] = $quantity;
|
||||
$cart_items[ $c ]['name'] = get_the_title( $item_id );
|
||||
$cart_items[ $c ]['price'] = $price;
|
||||
$cart_items[ $c ]['price_name'] = $price_name;
|
||||
|
||||
// Determine the discount amount for the item, if there is one
|
||||
foreach ( $discount_values as $discount => $amount ) {
|
||||
|
||||
$item_discount = edd_get_cart_item_discount_amount( $item, $discount );
|
||||
$discount_values[ $discount ] += $item_discount;
|
||||
|
||||
}
|
||||
|
||||
$c++;
|
||||
}
|
||||
|
||||
$sales['sales'][ $i ]['discounts'] = ( ! empty( $discount_values ) ? $discount_values : null );
|
||||
$sales['sales'][ $i ]['products'] = $cart_items;
|
||||
$sales['sales'][ $i ]['fees'] = ! empty( $fees ) ? $fees : null;
|
||||
$sales['sales'][ $i ]['discounts'] = ! empty( $discounts ) ? $discounts : null;
|
||||
|
||||
$i++;
|
||||
}
|
||||
|
@ -6,7 +6,7 @@
|
||||
"title": "EDD Checkout",
|
||||
"category": "easy-digital-downloads",
|
||||
"icon": "products",
|
||||
"description": "Beta: Full checkout block for Easy Digital Downloads.",
|
||||
"description": "Full checkout block for Easy Digital Downloads.",
|
||||
"keywords": [
|
||||
"easy digital downloads",
|
||||
"edd",
|
||||
|
@ -4,7 +4,7 @@
|
||||
* Description: Core blocks for Easy Digital Downloads.
|
||||
* Requires at least: 5.8
|
||||
* Requires PHP: 7.0
|
||||
* Version: 2.0.2
|
||||
* Version: 2.0.3
|
||||
* Author: Easy Digital Downloads
|
||||
* License: GPL-2.0-or-later
|
||||
* License URI: https://www.gnu.org/licenses/gpl-2.0.html
|
||||
|
@ -181,6 +181,7 @@ function checkout( $block_attributes = array() ) {
|
||||
}
|
||||
do_action( 'edd_before_checkout_cart' );
|
||||
include EDD_BLOCKS_DIR . 'views/checkout/cart/cart.php';
|
||||
do_action( 'edd_after_checkout_cart' );
|
||||
Forms\do_purchase_form( $block_attributes );
|
||||
?>
|
||||
</div>
|
||||
|
@ -160,7 +160,7 @@ class EDD_Cart {
|
||||
*/
|
||||
private function get_tax_rate() {
|
||||
if ( null === $this->tax_rate ) {
|
||||
$this->tax_rate = edd_get_tax_rate();
|
||||
$this->tax_rate = edd_use_taxes() ? edd_get_tax_rate() : 0;
|
||||
}
|
||||
|
||||
return $this->tax_rate;
|
||||
|
@ -325,7 +325,7 @@ final class Easy_Digital_Downloads {
|
||||
|
||||
// Plugin version.
|
||||
if ( ! defined( 'EDD_VERSION' ) ) {
|
||||
define( 'EDD_VERSION', '3.1.0.3' );
|
||||
define( 'EDD_VERSION', '3.1.0.4' );
|
||||
}
|
||||
|
||||
// Plugin Root File.
|
||||
|
@ -147,7 +147,8 @@ class Stats {
|
||||
$args = wp_parse_args( $args, array(
|
||||
'column_prefix' => '',
|
||||
'accepted_functions' => array(),
|
||||
'rate' => true
|
||||
'requested_function' => false,
|
||||
'rate' => true,
|
||||
) );
|
||||
|
||||
$column = $this->query_vars['column'];
|
||||
@ -165,11 +166,16 @@ class Stats {
|
||||
|
||||
$default_function = is_array( $args['accepted_functions'] ) && isset( $args['accepted_functions'][0] ) ? $args['accepted_functions'][0] : false;
|
||||
$function = ! empty( $this->query_vars['function'] ) ? $this->query_vars['function'] : $default_function;
|
||||
|
||||
if ( ! empty( $args['requested_function'] ) ) {
|
||||
$function = $args['requested_function'];
|
||||
}
|
||||
|
||||
if ( empty( $function ) ) {
|
||||
throw new \InvalidArgumentException( 'Missing select function.' );
|
||||
}
|
||||
|
||||
if ( ! empty( $args['accepted_functions'] ) && ! in_array( strtoupper( $this->query_vars['function'] ), $args['accepted_functions'], true ) ) {
|
||||
if ( ! empty( $args['accepted_functions'] ) && ! in_array( strtoupper( $function ), $args['accepted_functions'], true ) ) {
|
||||
if ( ! empty( $default_function ) ) {
|
||||
$function = $default_function;
|
||||
} else {
|
||||
@ -177,7 +183,7 @@ class Stats {
|
||||
}
|
||||
}
|
||||
|
||||
$function = $this->query_vars['function'] = strtoupper( $function );
|
||||
$function = strtoupper( $function );
|
||||
|
||||
// Multiply by rate if currency conversion is enabled.
|
||||
if (
|
||||
@ -930,18 +936,13 @@ class Stats {
|
||||
$this->query_vars['table'] = $this->get_db()->edd_order_items;
|
||||
$this->query_vars['column'] = true === $this->query_vars['exclude_taxes'] ? 'total - tax' : 'total';
|
||||
$this->query_vars['date_query_column'] = 'date_created';
|
||||
$this->query_vars['status'] = array( 'complete', 'refunded', 'partially_refunded' );
|
||||
$this->query_vars['status'] = edd_get_gross_order_statuses();
|
||||
|
||||
// Run pre-query checks and maybe generate SQL.
|
||||
$this->pre_query( $query );
|
||||
|
||||
$function = $this->get_amount_column_and_function( array(
|
||||
'column_prefix' => $this->query_vars['table'],
|
||||
'accepted_functions' => array( 'SUM', 'AVG' )
|
||||
) );
|
||||
|
||||
$product_id = ! empty( $this->query_vars['product_id'] )
|
||||
? $this->get_db()->prepare( 'AND product_id = %d', absint( $this->query_vars['product_id'] ) )
|
||||
? $this->get_db()->prepare( "AND {$this->query_vars['table']}.product_id = %d", absint( $this->query_vars['product_id'] ) )
|
||||
: '';
|
||||
|
||||
$price_id = $this->generate_price_id_query_sql();
|
||||
@ -954,28 +955,119 @@ class Stats {
|
||||
? $this->get_db()->prepare( 'AND edd_oa.country = %s', esc_sql( $this->query_vars['country'] ) )
|
||||
: '';
|
||||
|
||||
$status = ! empty( $this->query_vars['status'] )
|
||||
? " AND {$this->query_vars['table']}.status IN ('" . implode( "', '", $this->query_vars['status'] ) . "')"
|
||||
: '';
|
||||
|
||||
$join = $currency = '';
|
||||
if ( ! empty( $country ) || ! empty( $region ) ) {
|
||||
$join .= " INNER JOIN {$this->get_db()->edd_order_addresses} edd_oa ON {$this->query_vars['table']}.order_id = edd_oa.order_id ";
|
||||
}
|
||||
|
||||
$join .= " INNER JOIN {$this->get_db()->edd_orders} edd_o ON ({$this->query_vars['table']}.order_id = edd_o.id) AND edd_o.status IN ('" . implode( "', '", $this->query_vars['status'] ) . "') ";
|
||||
|
||||
if ( ! empty( $this->query_vars['currency'] ) && array_key_exists( strtoupper( $this->query_vars['currency'] ), edd_get_currencies() ) ) {
|
||||
$join .= " INNER JOIN {$this->get_db()->edd_orders} edd_o ON ({$this->query_vars['table']}.order_id = edd_o.id) ";
|
||||
$currency = $this->get_db()->prepare( "AND edd_o.currency = %s", strtoupper( $this->query_vars['currency'] ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* The adjustments query needs a different order status check than the order items. This is due to the fact that
|
||||
* adjustments refunded would end up being double counted, and therefore create an inaccurate revenue report.
|
||||
*/
|
||||
$adjustments_join = " INNER JOIN {$this->get_db()->edd_orders} edd_o ON ({$this->query_vars['table']}.order_id = edd_o.id) AND edd_o.type = 'sale' AND edd_o.status IN ('" . implode( "', '", edd_get_net_order_statuses() ) . "') ";
|
||||
|
||||
/**
|
||||
* With the addition of including fees into the calcualtion, the order_items
|
||||
* and order_adjustments for the order items needs to be a SUM and then the final function
|
||||
* (SUM or AVG) needs to be run on the final UNION Query.
|
||||
*/
|
||||
$order_item_function = $this->get_amount_column_and_function( array(
|
||||
'column_prefix' => $this->query_vars['table'],
|
||||
'accepted_functions' => array( 'SUM', 'AVG' ),
|
||||
'requested_function' => 'SUM',
|
||||
) );
|
||||
|
||||
$order_adjustment_function = $this->get_amount_column_and_function( array(
|
||||
'column_prefix' => 'oadj',
|
||||
'accepted_functions' => array( 'SUM', 'AVG' ),
|
||||
'requested_function' => 'SUM',
|
||||
) );
|
||||
|
||||
$union_function = $this->get_amount_column_and_function( array(
|
||||
'column_prefix' => '',
|
||||
'accepted_functions' => array( 'SUM', 'AVG' ),
|
||||
'rate' => false,
|
||||
) );
|
||||
|
||||
if ( true === $this->query_vars['grouped'] ) {
|
||||
$sql = "SELECT product_id, price_id, {$function} AS total
|
||||
FROM {$this->query_vars['table']}
|
||||
{$join}
|
||||
WHERE 1=1 {$product_id} {$price_id} {$region} {$country} {$currency} {$this->query_vars['where_sql']} {$this->query_vars['date_query_sql']}
|
||||
GROUP BY product_id, price_id
|
||||
ORDER BY total DESC";
|
||||
$order_items = "SELECT
|
||||
{$this->query_vars['table']}.product_id,
|
||||
{$this->query_vars['table']}.price_id,
|
||||
{$order_item_function} AS total
|
||||
FROM {$this->query_vars['table']}
|
||||
{$join}
|
||||
WHERE 1=1
|
||||
{$product_id}
|
||||
{$price_id}
|
||||
{$region}
|
||||
{$country}
|
||||
{$currency}
|
||||
{$this->query_vars['where_sql']}
|
||||
{$this->query_vars['date_query_sql']}
|
||||
GROUP BY {$this->query_vars['table']}.product_id, {$this->query_vars['table']}.price_id";
|
||||
|
||||
$order_adjustments = "SELECT
|
||||
{$this->query_vars['table']}.product_id as product_id,
|
||||
{$this->query_vars['table']}.price_id as price_id,
|
||||
{$order_adjustment_function} as total
|
||||
FROM {$this->get_db()->edd_order_adjustments} oadj
|
||||
INNER JOIN {$this->query_vars['table']} ON
|
||||
({$this->query_vars['table']}.id = oadj.object_id)
|
||||
{$product_id}
|
||||
{$price_id}
|
||||
{$region}
|
||||
{$country}
|
||||
{$currency}
|
||||
{$adjustments_join}
|
||||
WHERE oadj.object_type = 'order_item'
|
||||
AND oadj.type != 'discount'
|
||||
{$this->query_vars['date_query_sql']}
|
||||
GROUP BY {$this->query_vars['table']}.product_id, {$this->query_vars['table']}.price_id";
|
||||
|
||||
$sql = "SELECT product_id, price_id, {$union_function} AS total
|
||||
FROM ({$order_items} UNION {$order_adjustments})a
|
||||
GROUP BY product_id, price_id
|
||||
ORDER BY total DESC";
|
||||
} else {
|
||||
$sql = "SELECT {$function} AS total
|
||||
FROM {$this->query_vars['table']}
|
||||
{$join}
|
||||
WHERE 1=1 {$product_id} {$price_id} {$region} {$country} {$currency} {$this->query_vars['where_sql']} {$this->query_vars['date_query_sql']}";
|
||||
$order_items = "SELECT
|
||||
{$order_item_function} AS total
|
||||
FROM {$this->query_vars['table']}
|
||||
{$join}
|
||||
WHERE 1=1
|
||||
{$product_id}
|
||||
{$price_id}
|
||||
{$region}
|
||||
{$country}
|
||||
{$currency}
|
||||
{$this->query_vars['where_sql']}
|
||||
{$this->query_vars['date_query_sql']}";
|
||||
|
||||
$order_adjustments = "SELECT
|
||||
{$order_adjustment_function} as total
|
||||
FROM {$this->get_db()->edd_order_adjustments} oadj
|
||||
INNER JOIN {$this->query_vars['table']} ON
|
||||
({$this->query_vars['table']}.id = oadj.object_id)
|
||||
{$product_id}
|
||||
{$price_id}
|
||||
{$region}
|
||||
{$country}
|
||||
{$currency}
|
||||
{$adjustments_join}
|
||||
WHERE oadj.object_type = 'order_item'
|
||||
AND oadj.type != 'discount'
|
||||
{$this->query_vars['date_query_sql']}";
|
||||
|
||||
$sql = "SELECT {$union_function} AS total FROM ({$order_items} UNION {$order_adjustments})a";
|
||||
}
|
||||
|
||||
$result = $this->get_db()->get_results( $sql );
|
||||
@ -2788,8 +2880,9 @@ class Stats {
|
||||
$date_query_sql = ' AND ';
|
||||
|
||||
if ( ! empty( $this->query_vars['start'] ) ) {
|
||||
$start_date = EDD()->utils->date( $this->query_vars['start'], edd_get_timezone_id(), false )->format( 'mysql' );
|
||||
$date_query_sql .= "{$this->query_vars['table']}.{$this->query_vars['date_query_column']} ";
|
||||
$date_query_sql .= $this->get_db()->prepare( '>= %s', $this->query_vars['start'] );
|
||||
$date_query_sql .= $this->get_db()->prepare( '>= %s', $start_date );
|
||||
}
|
||||
|
||||
// Join dates with `AND` if start and end date set.
|
||||
@ -2798,7 +2891,8 @@ class Stats {
|
||||
}
|
||||
|
||||
if ( ! empty( $this->query_vars['end'] ) ) {
|
||||
$date_query_sql .= $this->get_db()->prepare( "{$this->query_vars['table']}.{$this->query_vars['date_query_column']} <= %s", $this->query_vars['end'] );
|
||||
$end_date = EDD()->utils->date( $this->query_vars['end'], edd_get_timezone_id(), false )->format( 'mysql' );
|
||||
$date_query_sql .= $this->get_db()->prepare( "{$this->query_vars['table']}.{$this->query_vars['date_query_column']} <= %s", $end_date );
|
||||
}
|
||||
|
||||
$this->query_vars['date_query_sql'] = $date_query_sql;
|
||||
@ -2957,7 +3051,7 @@ class Stats {
|
||||
*/
|
||||
private function generate_price_id_query_sql() {
|
||||
return ! is_null( $this->query_vars['price_id'] ) && is_numeric( $this->query_vars['price_id'] )
|
||||
? $this->get_db()->prepare( 'AND price_id = %d', absint( $this->query_vars['price_id'] ) )
|
||||
? $this->get_db()->prepare( "AND {$this->query_vars['table']}.price_id = %d", absint( $this->query_vars['price_id'] ) )
|
||||
: '';
|
||||
}
|
||||
|
||||
|
@ -8,9 +8,10 @@
|
||||
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
|
||||
* @since 3.0
|
||||
*/
|
||||
|
||||
namespace EDD\Database\Schemas;
|
||||
|
||||
// Exit if accessed directly
|
||||
// Exit if accessed directly.
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
use EDD\Database\Schema;
|
||||
@ -30,18 +31,18 @@ final class Adjustments extends Schema {
|
||||
*/
|
||||
public $columns = array(
|
||||
|
||||
// id
|
||||
// id.
|
||||
array(
|
||||
'name' => 'id',
|
||||
'type' => 'bigint',
|
||||
'length' => '20',
|
||||
'unsigned' => true,
|
||||
'extra' => 'auto_increment',
|
||||
'primary' => true,
|
||||
'sortable' => true
|
||||
'name' => 'id',
|
||||
'type' => 'bigint',
|
||||
'length' => '20',
|
||||
'unsigned' => true,
|
||||
'extra' => 'auto_increment',
|
||||
'primary' => true,
|
||||
'sortable' => true,
|
||||
),
|
||||
|
||||
// parent
|
||||
// parent.
|
||||
array(
|
||||
'name' => 'parent',
|
||||
'type' => 'bigint',
|
||||
@ -49,35 +50,36 @@ final class Adjustments extends Schema {
|
||||
'unsigned' => true,
|
||||
'default' => '0',
|
||||
'sortable' => true,
|
||||
'transition' => true
|
||||
'transition' => true,
|
||||
),
|
||||
|
||||
// name
|
||||
// name.
|
||||
array(
|
||||
'name' => 'name',
|
||||
'type' => 'varchar',
|
||||
'length' => '200',
|
||||
'searchable' => true,
|
||||
'sortable' => true
|
||||
'sortable' => true,
|
||||
),
|
||||
|
||||
// code
|
||||
// code.
|
||||
array(
|
||||
'name' => 'code',
|
||||
'type' => 'varchar',
|
||||
'length' => '50',
|
||||
'searchable' => true,
|
||||
'sortable' => true
|
||||
'sortable' => true,
|
||||
'cache_key' => true,
|
||||
),
|
||||
|
||||
// status
|
||||
// status.
|
||||
array(
|
||||
'name' => 'status',
|
||||
'type' => 'varchar',
|
||||
'length' => '20',
|
||||
'default' => 'draft',
|
||||
'sortable' => true,
|
||||
'transition' => true
|
||||
'transition' => true,
|
||||
),
|
||||
|
||||
// type
|
||||
@ -87,124 +89,124 @@ final class Adjustments extends Schema {
|
||||
'length' => '20',
|
||||
'default' => '',
|
||||
'sortable' => true,
|
||||
'transition' => true
|
||||
'transition' => true,
|
||||
),
|
||||
|
||||
// scope
|
||||
// scope.
|
||||
array(
|
||||
'name' => 'scope',
|
||||
'type' => 'varchar',
|
||||
'length' => '20',
|
||||
'default' => '',
|
||||
'sortable' => true,
|
||||
'transition' => true
|
||||
'transition' => true,
|
||||
),
|
||||
|
||||
// amount_type
|
||||
// amount_type.
|
||||
array(
|
||||
'name' => 'amount_type',
|
||||
'type' => 'varchar',
|
||||
'length' => '20',
|
||||
'default' => '',
|
||||
'sortable' => true,
|
||||
'transition' => true
|
||||
'transition' => true,
|
||||
),
|
||||
|
||||
// amount
|
||||
// amount.
|
||||
array(
|
||||
'name' => 'amount',
|
||||
'type' => 'decimal',
|
||||
'length' => '18,9',
|
||||
'default' => '0',
|
||||
'sortable' => true
|
||||
'name' => 'amount',
|
||||
'type' => 'decimal',
|
||||
'length' => '18,9',
|
||||
'default' => '0',
|
||||
'sortable' => true,
|
||||
),
|
||||
|
||||
// description
|
||||
// description.
|
||||
array(
|
||||
'name' => 'description',
|
||||
'type' => 'longtext',
|
||||
'default' => '',
|
||||
'searchable' => true
|
||||
'searchable' => true,
|
||||
),
|
||||
|
||||
// max_uses
|
||||
// max_uses.
|
||||
array(
|
||||
'name' => 'max_uses',
|
||||
'type' => 'bigint',
|
||||
'length' => '20',
|
||||
'unsigned' => true,
|
||||
'default' => '0'
|
||||
),
|
||||
|
||||
// use_count
|
||||
array(
|
||||
'name' => 'use_count',
|
||||
'type' => 'bigint',
|
||||
'length' => '20',
|
||||
'unsigned' => true,
|
||||
'default' => '0',
|
||||
'sortable' => true,
|
||||
),
|
||||
|
||||
// once_per_customer
|
||||
// use_count.
|
||||
array(
|
||||
'name' => 'once_per_customer',
|
||||
'type' => 'int',
|
||||
'length' => '1',
|
||||
'default' => '0'
|
||||
'name' => 'use_count',
|
||||
'type' => 'bigint',
|
||||
'length' => '20',
|
||||
'unsigned' => true,
|
||||
'default' => '0',
|
||||
'sortable' => true,
|
||||
),
|
||||
|
||||
// min_charge_amount
|
||||
// once_per_customer.
|
||||
array(
|
||||
'name' => 'min_charge_amount',
|
||||
'type' => 'decimal',
|
||||
'length' => '18,9',
|
||||
'default' => '0'
|
||||
'name' => 'once_per_customer',
|
||||
'type' => 'int',
|
||||
'length' => '1',
|
||||
'default' => '0',
|
||||
),
|
||||
|
||||
// start_date
|
||||
// min_charge_amount.
|
||||
array(
|
||||
'name' => 'min_charge_amount',
|
||||
'type' => 'decimal',
|
||||
'length' => '18,9',
|
||||
'default' => '0',
|
||||
),
|
||||
|
||||
// start_date.
|
||||
array(
|
||||
'name' => 'start_date',
|
||||
'type' => 'datetime',
|
||||
'default' => null,
|
||||
'allow_null' => true,
|
||||
'date_query' => true,
|
||||
'sortable' => true
|
||||
'sortable' => true,
|
||||
),
|
||||
|
||||
// end_date
|
||||
// end_date.
|
||||
array(
|
||||
'name' => 'end_date',
|
||||
'type' => 'datetime',
|
||||
'default' => null,
|
||||
'allow_null' => true,
|
||||
'date_query' => true,
|
||||
'sortable' => true
|
||||
'sortable' => true,
|
||||
),
|
||||
|
||||
// date_created
|
||||
// date_created.
|
||||
array(
|
||||
'name' => 'date_created',
|
||||
'type' => 'datetime',
|
||||
'default' => '', // Defaults to current time in query class
|
||||
'default' => '', // Defaults to current time in query class.
|
||||
'created' => true,
|
||||
'date_query' => true,
|
||||
'sortable' => true
|
||||
'sortable' => true,
|
||||
),
|
||||
|
||||
// date_modified
|
||||
// date_modified.
|
||||
array(
|
||||
'name' => 'date_modified',
|
||||
'type' => 'datetime',
|
||||
'default' => '', // Defaults to current time in query class
|
||||
'default' => '', // Defaults to current time in query class.
|
||||
'modified' => true,
|
||||
'date_query' => true,
|
||||
'sortable' => true
|
||||
'sortable' => true,
|
||||
),
|
||||
|
||||
// uuid
|
||||
// uuid.
|
||||
array(
|
||||
'uuid' => true,
|
||||
)
|
||||
'uuid' => true,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
@ -280,8 +280,12 @@ function get_order_items( $purchase_data ) {
|
||||
if ( $item_amount <= 0 ) {
|
||||
$item_amount = 0;
|
||||
}
|
||||
|
||||
$substr_func = function_exists( 'mb_substr' ) ? 'mb_substr' : 'substr';
|
||||
$name = $substr_func( edd_get_cart_item_name( $item ), 0, 127 );
|
||||
|
||||
$items[ $i ] = array(
|
||||
'name' => stripslashes_deep( html_entity_decode( substr( edd_get_cart_item_name( $item ), 0, 127 ), ENT_COMPAT, 'UTF-8' ) ),
|
||||
'name' => stripslashes_deep( html_entity_decode( $name, ENT_COMPAT, 'UTF-8' ) ),
|
||||
'quantity' => $item['quantity'],
|
||||
'unit_amount' => array(
|
||||
'currency_code' => edd_get_currency(),
|
||||
|
@ -13,6 +13,7 @@
|
||||
|
||||
namespace EDD\Gateways\PayPal\IPN;
|
||||
|
||||
use EDD\Gateways\PayPal;
|
||||
/**
|
||||
* Listens for an IPN call from PayPal
|
||||
*
|
||||
@ -25,6 +26,11 @@ function listen_for_ipn() {
|
||||
return;
|
||||
}
|
||||
|
||||
// If PayPal is not connected, we don't need to run here.
|
||||
if ( ! PayPal\has_rest_api_connection() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
ipn_debug_log( 'IPN Backup Loaded' );
|
||||
|
||||
// Moving this up in the load order so we can check some things before even getting to verification.
|
||||
@ -174,7 +180,7 @@ function listen_for_ipn() {
|
||||
|
||||
|
||||
// Bail if this is the very first payment.
|
||||
if ( date( 'Y-n-d', strtotime( $subscription->created ) ) == date( 'Y-n-d', strtotime( $posted['payment_date'] ) ) ) {
|
||||
if ( ! empty( $posted['payment_date'] ) && date( 'Y-n-d', strtotime( $subscription->created ) ) == date( 'Y-n-d', strtotime( $posted['payment_date'] ) ) ) {
|
||||
ipn_debug_log( 'IPN for subscription ' . $subscription->id . ': processing stopped because this is the initial payment.' );
|
||||
return;
|
||||
}
|
||||
|
File diff suppressed because one or more lines are too long
@ -8,10 +8,19 @@ domReady( () => {
|
||||
const containerEl = document.getElementById( 'edds-stripe-connect-account' );
|
||||
const actionsEl = document.getElementById( 'edds-stripe-disconnect-reconnect' );
|
||||
|
||||
|
||||
if ( ! containerEl ) {
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Do not make a request, if we are inside Onboarding Wizard.
|
||||
* Onboarding Wizard will make it's own call.
|
||||
*/
|
||||
if ( containerEl.hasAttribute('data-onboarding-wizard') ) {
|
||||
return;
|
||||
}
|
||||
|
||||
return apiRequest( 'edds_stripe_connect_account_info', {
|
||||
...containerEl.dataset,
|
||||
} )
|
||||
|
@ -3,8 +3,8 @@
|
||||
* Plugin Name: Easy Digital Downloads - Stripe Pro Payment Gateway
|
||||
* Plugin URI: https://easydigitaldownloads.com/downloads/stripe-gateway/
|
||||
* Description: Adds a payment gateway for Stripe.com
|
||||
* Version: 2.8.13
|
||||
* Requires at least: 4.4
|
||||
* Version: 2.8.13.1
|
||||
* Requires at least: 4.9
|
||||
* Requires PHP: 5.6
|
||||
* Author: Easy Digital Downloads
|
||||
* Author URI: https://easydigitaldownloads.com
|
||||
@ -44,7 +44,7 @@ function edd_stripe_core_bootstrap() {
|
||||
}
|
||||
|
||||
if ( ! defined( 'EDD_STRIPE_VERSION' ) ) {
|
||||
define( 'EDD_STRIPE_VERSION', '2.8.13' );
|
||||
define( 'EDD_STRIPE_VERSION', '2.8.13.1' );
|
||||
}
|
||||
|
||||
if ( ! defined( 'EDD_STRIPE_API_VERSION' ) ) {
|
||||
|
@ -83,27 +83,57 @@ function edds_stripe_connect_url() {
|
||||
*/
|
||||
function edds_process_gateway_connect_completion() {
|
||||
|
||||
if( ! isset( $_GET['edd_gateway_connect_completion'] ) || 'stripe_connect' !== $_GET['edd_gateway_connect_completion'] || ! isset( $_GET['state'] ) ) {
|
||||
$redirect_screen = ! empty( $_GET['redirect_screen'] ) ? sanitize_text_field( $_GET['redirect_screen'] ) : '';
|
||||
|
||||
// A cancelled connection doesn't contain the completion or state values, but we do need to listen for the redirect_screen for the wizard.
|
||||
if (
|
||||
isset( $_GET['edd_gateway_connect_error'] ) &&
|
||||
filter_var( $_GET['edd_gateway_connect_error'], FILTER_VALIDATE_BOOLEAN ) &&
|
||||
! empty( $redirect_screen )
|
||||
) {
|
||||
$error_redirect = '';
|
||||
|
||||
switch ( $redirect_screen ) {
|
||||
case 'onboarding-wizard':
|
||||
$error_redirect = admin_url( 'edit.php?post_type=download&page=edd-onboarding-wizard¤t_step=payment_methods' );
|
||||
break;
|
||||
}
|
||||
|
||||
if ( ! empty( $error_redirect ) ) {
|
||||
wp_safe_redirect( esc_url_raw( $error_redirect ) );
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! isset( $_GET['edd_gateway_connect_completion'] ) || 'stripe_connect' !== $_GET['edd_gateway_connect_completion'] || ! isset( $_GET['state'] ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if( ! current_user_can( 'manage_shop_settings' ) ) {
|
||||
if ( ! current_user_can( 'manage_shop_settings' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if( headers_sent() ) {
|
||||
if ( headers_sent() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$edd_credentials_url = add_query_arg( array(
|
||||
'live_mode' => (int) ! edd_is_test_mode(),
|
||||
'state' => sanitize_text_field( $_GET['state'] ),
|
||||
'customer_site_url' => admin_url( 'edit.php?post_type=download' ),
|
||||
), 'https://easydigitaldownloads.com/?edd_gateway_connect_credentials=stripe_connect' );
|
||||
$customer_site_url = admin_url( 'edit.php?post_type=download' );
|
||||
if ( ! empty( $redirect_screen ) ) {
|
||||
$customer_site_url = add_query_arg( 'redirect_screen', $redirect_screen, $customer_site_url );
|
||||
}
|
||||
|
||||
$edd_credentials_url = add_query_arg(
|
||||
array(
|
||||
'live_mode' => (int) ! edd_is_test_mode(),
|
||||
'state' => sanitize_text_field( $_GET['state'] ),
|
||||
'customer_site_url' => urlencode( $customer_site_url ),
|
||||
),
|
||||
'https://easydigitaldownloads.com/?edd_gateway_connect_credentials=stripe_connect'
|
||||
);
|
||||
|
||||
$response = wp_remote_get( esc_url_raw( $edd_credentials_url ) );
|
||||
|
||||
if( is_wp_error( $response ) || 200 !== wp_remote_retrieve_response_code( $response ) ) {
|
||||
if ( is_wp_error( $response ) || 200 !== wp_remote_retrieve_response_code( $response ) ) {
|
||||
$message = '<p>' . sprintf(
|
||||
/* translators: %1$s Opening anchor tag, do not translate. %2$s Closing anchor tag, do not translate. */
|
||||
__( 'There was an error getting your Stripe credentials. Please %1$stry again%2$s. If you continue to have this problem, please contact support.', 'easy-digital-downloads' ),
|
||||
@ -116,7 +146,7 @@ function edds_process_gateway_connect_completion() {
|
||||
$data = json_decode( $response['body'], true );
|
||||
$data = $data['data'];
|
||||
|
||||
if( edd_is_test_mode() ) {
|
||||
if ( edd_is_test_mode() ) {
|
||||
edd_update_option( 'test_publishable_key', sanitize_text_field( $data['publishable_key'] ) );
|
||||
edd_update_option( 'test_secret_key', sanitize_text_field( $data['secret_key'] ) );
|
||||
} else {
|
||||
@ -125,7 +155,18 @@ function edds_process_gateway_connect_completion() {
|
||||
}
|
||||
|
||||
edd_update_option( 'stripe_connect_account_id', sanitize_text_field( $data['stripe_user_id'] ) );
|
||||
wp_redirect( esc_url_raw( admin_url( 'edit.php?post_type=download&page=edd-settings&tab=gateways§ion=edd-stripe' ) ) );
|
||||
|
||||
$redirect_url = admin_url( 'edit.php?post_type=download&page=edd-settings&tab=gateways§ion=edd-stripe' );
|
||||
|
||||
if ( ! empty( $redirect_screen ) ) {
|
||||
switch ( $redirect_screen ) {
|
||||
case 'onboarding-wizard':
|
||||
$redirect_url = admin_url( 'edit.php?post_type=download&page=edd-onboarding-wizard¤t_step=payment_methods' );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
wp_safe_redirect( esc_url_raw( $redirect_url ) );
|
||||
exit;
|
||||
|
||||
}
|
||||
@ -178,7 +219,7 @@ function edds_stripe_connect_disconnect_url() {
|
||||
function edds_stripe_connect_process_disconnect() {
|
||||
// Do not need to handle this request, bail.
|
||||
if (
|
||||
! ( isset( $_GET['page'] ) && 'edd-settings' === $_GET['page'] ) ||
|
||||
! ( isset( $_GET['page'] ) && ( 'edd-settings' === $_GET['page'] || 'edd-onboarding-wizard' === $_GET['page'] ) ) ||
|
||||
! isset( $_GET['edds-stripe-disconnect'] )
|
||||
) {
|
||||
return;
|
||||
@ -337,7 +378,7 @@ function edds_stripe_connect_setting_field() {
|
||||
class="edds-stripe-connect-acount-info notice inline"
|
||||
data-account-id="<?php echo esc_attr( $stripe_connect_account_id ); ?>"
|
||||
data-nonce="<?php echo wp_create_nonce( 'edds-stripe-connect-account-information' ); ?>"
|
||||
>
|
||||
<?php echo ( ! empty( $_GET['page'] ) && 'edd-onboarding-wizard' === $_GET['page'] ) ? ' data-onboarding-wizard="true"' : ''; ?>>
|
||||
<p><span class="spinner is-active"></span>
|
||||
<em><?php esc_html_e( 'Retrieving account information...', 'easy-digital-downloads' ); ?></em>
|
||||
</div>
|
||||
|
@ -357,13 +357,21 @@ function edds_add_payment_method() {
|
||||
}
|
||||
|
||||
$stripe_customer_id = edds_get_stripe_customer_id( get_current_user_id() );
|
||||
$stripe_customer = edds_get_stripe_customer(
|
||||
|
||||
$customer_name = '';
|
||||
if ( ! empty( $edd_customer->name ) ) {
|
||||
$customer_name = $edd_customer->name;
|
||||
}
|
||||
|
||||
$stripe_customer = edds_get_stripe_customer(
|
||||
$stripe_customer_id,
|
||||
array(
|
||||
'email' => $edd_customer->email,
|
||||
'description' => $edd_customer->email,
|
||||
'name' => $customer_name,
|
||||
)
|
||||
);
|
||||
|
||||
if ( false === $stripe_customer ) {
|
||||
wp_send_json_error(
|
||||
array(
|
||||
|
@ -88,7 +88,7 @@ function edds_has_met_requirements( $requirement = false ) {
|
||||
: true
|
||||
),
|
||||
'wp' => (
|
||||
version_compare( get_bloginfo( 'version' ), '4.4', '>=' )
|
||||
version_compare( get_bloginfo( 'version' ), '4.9', '>=' )
|
||||
),
|
||||
);
|
||||
|
||||
|
@ -1175,10 +1175,22 @@ function edds_checkout_setup_customer( $purchase_data ) {
|
||||
// No customer ID found, let's look one up based on the email.
|
||||
$stripe_customer_id = edds_get_stripe_customer_id( $purchase_data['user_email'], false );
|
||||
}
|
||||
|
||||
$customer_name = '';
|
||||
if ( ! empty( $purchase_data['user_info']['first_name'] ) ) {
|
||||
$customer_name .= sanitize_text_field( $purchase_data['user_info']['first_name'] );
|
||||
}
|
||||
|
||||
if ( ! empty( $purchase_data['user_info']['last_name'] ) ) {
|
||||
$customer_name .= ' ' . sanitize_text_field( $purchase_data['user_info']['last_name'] );
|
||||
}
|
||||
|
||||
$customer_args = array(
|
||||
'email' => $purchase_data['user_email'],
|
||||
'description' => $purchase_data['user_email'],
|
||||
'name' => $customer_name,
|
||||
);
|
||||
|
||||
/**
|
||||
* Filters the arguments used to create a Customer in Stripe.
|
||||
*
|
||||
|
@ -32,10 +32,9 @@ function edds_buy_now_modal() {
|
||||
edd_localize_scripts();
|
||||
} else {
|
||||
edd_load_scripts();
|
||||
edd_agree_to_terms_js();
|
||||
}
|
||||
|
||||
edd_agree_to_terms_js();
|
||||
|
||||
remove_filter( 'edd_is_checkout', '__return_true' );
|
||||
|
||||
// Enqueue scripts.
|
||||
|
@ -42,6 +42,9 @@ namespace Composer\Autoload;
|
||||
*/
|
||||
class ClassLoader
|
||||
{
|
||||
/** @var \Closure(string):void */
|
||||
private static $includeFile;
|
||||
|
||||
/** @var ?string */
|
||||
private $vendorDir;
|
||||
|
||||
@ -106,6 +109,7 @@ class ClassLoader
|
||||
public function __construct($vendorDir = null)
|
||||
{
|
||||
$this->vendorDir = $vendorDir;
|
||||
self::initializeIncludeClosure();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -425,7 +429,7 @@ class ClassLoader
|
||||
public function loadClass($class)
|
||||
{
|
||||
if ($file = $this->findFile($class)) {
|
||||
includeFile($file);
|
||||
(self::$includeFile)($file);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -555,18 +559,23 @@ class ClassLoader
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Scope isolated include.
|
||||
*
|
||||
* Prevents access to $this/self from included files.
|
||||
*
|
||||
* @param string $file
|
||||
* @return void
|
||||
* @private
|
||||
*/
|
||||
function includeFile($file)
|
||||
{
|
||||
include $file;
|
||||
private static function initializeIncludeClosure(): void
|
||||
{
|
||||
if (self::$includeFile !== null) {
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Scope isolated include.
|
||||
*
|
||||
* Prevents access to $this/self from included files.
|
||||
*
|
||||
* @param string $file
|
||||
* @return void
|
||||
*/
|
||||
self::$includeFile = static function($file) {
|
||||
include $file;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,7 @@
|
||||
'name' => 'easy-digital-downloads/edd-stripe',
|
||||
'pretty_version' => 'dev-master',
|
||||
'version' => 'dev-master',
|
||||
'reference' => '829e436e3e0b91ab69528aebcee3344aa2e91eca',
|
||||
'reference' => '24964d034941e0d3d07390ecc39570bfc64e7369',
|
||||
'type' => 'wordpress-plugin',
|
||||
'install_path' => __DIR__ . '/../../',
|
||||
'aliases' => array(),
|
||||
@ -13,7 +13,7 @@
|
||||
'easy-digital-downloads/edd-stripe' => array(
|
||||
'pretty_version' => 'dev-master',
|
||||
'version' => 'dev-master',
|
||||
'reference' => '829e436e3e0b91ab69528aebcee3344aa2e91eca',
|
||||
'reference' => '24964d034941e0d3d07390ecc39570bfc64e7369',
|
||||
'type' => 'wordpress-plugin',
|
||||
'install_path' => __DIR__ . '/../../',
|
||||
'aliases' => array(),
|
||||
|
@ -187,6 +187,7 @@ class Download {
|
||||
"SELECT SUM((oa.total - oa.tax)/ oa.rate) as revenue
|
||||
FROM {$wpdb->edd_order_adjustments} oa
|
||||
INNER JOIN {$wpdb->edd_order_items} oi ON(oi.id = oa.object_id)
|
||||
INNER JOIN {$wpdb->edd_orders} o ON oi.order_id = o.id AND o.type = 'sale' {$order_status_sql}
|
||||
WHERE {$product_id_sql}
|
||||
{$price_id_sql}
|
||||
AND oa.object_type = 'order_item'
|
||||
@ -194,7 +195,9 @@ class Download {
|
||||
AND oi.status IN('complete','partially_refunded')
|
||||
{$date_query_sql}";
|
||||
|
||||
$results = $wpdb->get_row( "SELECT SUM(revenue) AS revenue FROM ({$order_items} UNION {$order_adjustments})a" );
|
||||
$sql = "SELECT SUM(revenue) AS revenue FROM ({$order_items} UNION {$order_adjustments})a";
|
||||
|
||||
$results = $wpdb->get_row( $sql );
|
||||
|
||||
return ! empty( $results->revenue ) ? $results->revenue : 0.00;
|
||||
}
|
||||
|
@ -164,4 +164,13 @@ class Order_Adjustment extends \EDD\Database\Rows\Order_Adjustment {
|
||||
'parent' => $this->id
|
||||
) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Backwards compatibility for the `amount` property, which is now the `total`.
|
||||
*
|
||||
* @since 3.1.0.4
|
||||
*/
|
||||
public function get_amount() {
|
||||
return $this->total;
|
||||
}
|
||||
}
|
||||
|
@ -234,6 +234,7 @@ add_action( 'edd_complete_purchase', 'edd_schedule_after_payment_action', 10, 1
|
||||
* Executes the one time event used for after purchase actions.
|
||||
*
|
||||
* @since 2.8
|
||||
* @since 3.1.0.4 This also verifies that all order items have the synced status as the order.
|
||||
* @param $payment_id
|
||||
* @param $force
|
||||
*/
|
||||
@ -248,6 +249,31 @@ function edd_process_after_payment_actions( $payment_id = 0, $force = false ) {
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* In the event that during the order completion process, a timeout happens,
|
||||
* ensure that all the order items have the correct status, to match the order itself.
|
||||
*
|
||||
* @see https://github.com/awesomemotive/easy-digital-downloads-pro/issues/77
|
||||
*/
|
||||
$order_items = edd_get_order_items(
|
||||
array(
|
||||
'order_id' => $payment_id,
|
||||
'status__not_in' => edd_get_deliverable_order_item_statuses(),
|
||||
'number' => 200,
|
||||
)
|
||||
);
|
||||
|
||||
if ( ! empty( $order_items ) ) {
|
||||
foreach ( $order_items as $order_item ) {
|
||||
edd_update_order_item(
|
||||
$order_item->id,
|
||||
array(
|
||||
'status' => $payment->status,
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
$payment->add_note( __( 'After payment actions processed.', 'easy-digital-downloads' ) );
|
||||
$payment->update_meta( '_edd_complete_actions_run', time() ); // This is in GMT
|
||||
|
||||
|
@ -3098,7 +3098,7 @@ class EDD_Payment {
|
||||
}
|
||||
|
||||
$item_fees[ $id ] = array(
|
||||
'amount' => $item_fee->amount,
|
||||
'amount' => $item_fee->total,
|
||||
'label' => $item_fee->description,
|
||||
'no_tax' => $no_tax ? $no_tax : false,
|
||||
'type' => 'fee',
|
||||
|
@ -527,22 +527,22 @@ class EDD_Payments_Query extends EDD_Stats {
|
||||
$order_ids = array();
|
||||
|
||||
if ( is_array( $this->args['download'] ) ) {
|
||||
$orders = edd_get_order_items( array(
|
||||
$order_items = edd_get_order_items( array(
|
||||
'product_id__in' => (array) $this->args['download'],
|
||||
) );
|
||||
|
||||
foreach ( $orders as $order ) {
|
||||
/** @var $order EDD\Orders\Order_Item */
|
||||
$order_ids[] = $order->order_id;
|
||||
foreach ( $order_items as $order_item ) {
|
||||
/** @var $order_item EDD\Orders\Order_Item */
|
||||
$order_ids[] = $order_item->order_id;
|
||||
}
|
||||
} else {
|
||||
$orders = edd_get_order_items( array(
|
||||
$order_items = edd_get_order_items( array(
|
||||
'product_id' => $this->args['download'],
|
||||
) );
|
||||
|
||||
foreach ( $orders as $order ) {
|
||||
/** @var $order EDD\Orders\Order_Item */
|
||||
$order_ids[] = $order->id;
|
||||
foreach ( $order_items as $order_item ) {
|
||||
/** @var $order_item EDD\Orders\Order_Item */
|
||||
$order_ids[] = $order_item->order_id;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1249,7 +1249,7 @@ function edd_get_payment_amount( $order_id = 0 ) {
|
||||
|
||||
// Bail if nothing was passed.
|
||||
if ( empty( $order_id ) ) {
|
||||
return '';
|
||||
return 0.00;
|
||||
}
|
||||
|
||||
$order = edd_get_order( $order_id );
|
||||
|
@ -15,6 +15,7 @@ defined( 'ABSPATH' ) || exit;
|
||||
|
||||
use EDD\Reports as Reports;
|
||||
use EDD\Admin\List_Table;
|
||||
use EDD\Stats as Stats;
|
||||
|
||||
/**
|
||||
* Earnings_By_Taxonomy_List_Table class.
|
||||
@ -34,27 +35,8 @@ class Earnings_By_Taxonomy_List_Table extends List_Table {
|
||||
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 );
|
||||
|
||||
@ -78,64 +60,56 @@ class Earnings_By_Taxonomy_List_Table extends List_Table {
|
||||
$taxonomies[ absint( $r->term_id ) ]['parent'] = absint( $r->parent );
|
||||
}
|
||||
|
||||
$data = array();
|
||||
$parent_ids = array();
|
||||
// Setup an empty array for the final returned data.
|
||||
$data = 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
|
||||
);
|
||||
// Store each download's stats during the loop to avoid double queries.
|
||||
$download_stats = array();
|
||||
|
||||
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'] );
|
||||
$earnings = 0.00;
|
||||
$sales = 0;
|
||||
|
||||
$sql = "SELECT SUM({$column}) as total
|
||||
FROM {$wpdb->edd_order_items} oi
|
||||
{$join}
|
||||
WHERE {$product_id__in} {$currency_clause} {$date_query_sql} {$status_sql}";
|
||||
$average_earnings = 0.00;
|
||||
$average_sales = 0;
|
||||
|
||||
$result = $wpdb->get_row( $sql ); // WPCS: unprepared SQL ok.
|
||||
foreach ( $taxonomies[ $k ]['object_ids'] as $download_id ) {
|
||||
if ( ! isset( $download_stats[ $download_id ] ) ) {
|
||||
$stats = new Stats(
|
||||
array(
|
||||
'product_id' => absint( $download_id ),
|
||||
'currency' => $currency,
|
||||
'range' => $dates['range'],
|
||||
'output' => 'typed',
|
||||
)
|
||||
);
|
||||
|
||||
$earnings = null === $result && null === $result->total
|
||||
? 0.00
|
||||
: floatval( $result->total );
|
||||
$download_stats[ $download_id ]['earnings'] = $stats->get_order_item_earnings(
|
||||
array(
|
||||
'function' => 'SUM',
|
||||
)
|
||||
);
|
||||
|
||||
$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" );
|
||||
$download_stats[ $download_id ]['sales'] = $stats->get_order_item_count(
|
||||
array(
|
||||
'function' => 'COUNT',
|
||||
)
|
||||
);
|
||||
|
||||
$sales = ! empty( $sql_sales->sales ) ? $sql_sales->sales : 0;
|
||||
$download_stats[ $download_id ]['average_earnings'] = edd_get_average_monthly_download_earnings( $download_id );
|
||||
$download_stats[ $download_id ]['average_sales'] = edd_get_average_monthly_download_sales( $download_id );
|
||||
}
|
||||
|
||||
$earnings += $download_stats[ $download_id ]['earnings'];
|
||||
$sales += $download_stats[ $download_id ]['sales'];
|
||||
|
||||
$average_earnings += $download_stats[ $download_id ]['average_earnings'];
|
||||
$average_sales += $download_stats[ $download_id ]['average_sales'];
|
||||
}
|
||||
|
||||
$c->sales = $sales;
|
||||
$c->earnings = $earnings;
|
||||
@ -143,14 +117,6 @@ class Earnings_By_Taxonomy_List_Table extends List_Table {
|
||||
? 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;
|
||||
|
||||
@ -161,7 +127,7 @@ class Earnings_By_Taxonomy_List_Table extends List_Table {
|
||||
|
||||
foreach ( $data as $d ) {
|
||||
|
||||
// Get parent level elements
|
||||
// Get parent level elements.
|
||||
if ( null === $d->parent ) {
|
||||
$sorted_data[] = $d;
|
||||
|
||||
@ -173,7 +139,7 @@ class Earnings_By_Taxonomy_List_Table extends List_Table {
|
||||
}
|
||||
}
|
||||
|
||||
// Sort by total earnings
|
||||
// Sort by total earnings.
|
||||
usort( $sorted_data, function( $a, $b ) {
|
||||
return ( $a->earnings < $b->earnings ) ? -1 : 1;
|
||||
} );
|
||||
|
@ -229,7 +229,7 @@ function edd_get_purchase_link( $args = array() ) {
|
||||
<?php } ?>
|
||||
|
||||
<?php if( apply_filters( 'edd_download_redirect_to_checkout', edd_straight_to_checkout(), $download->ID, $args ) ) : ?>
|
||||
<input type="hidden" name="edd_redirect_to_checkout" id="edd_redirect_to_checkout" value="1">
|
||||
<input type="hidden" name="edd_redirect_to_checkout" value="1">
|
||||
<?php endif; ?>
|
||||
|
||||
<?php do_action( 'edd_purchase_link_end', $download->ID, $args ); ?>
|
||||
|
@ -30,13 +30,24 @@ class NotificationImporter {
|
||||
* @since 2.11.4
|
||||
*/
|
||||
public function run() {
|
||||
$request_timeout = get_option( 'edd_notification_req_timeout', false );
|
||||
if ( false !== $request_timeout && current_time( 'timestamp' ) < $request_timeout ) {
|
||||
edd_debug_log( 'Skipping notifications API request, timeout not reached' );
|
||||
return;
|
||||
}
|
||||
|
||||
edd_debug_log( 'Fetching notifications via ' . $this->getApiEndpoint() );
|
||||
|
||||
try {
|
||||
$notifications = $this->fetchNotifications();
|
||||
|
||||
// If successful, make it so we don't request for another 23 hours.
|
||||
update_option( 'edd_notification_req_timeout', current_time( 'timestamp' ) + ( HOUR_IN_SECONDS * 23 ), false );
|
||||
} catch ( \Exception $e ) {
|
||||
edd_debug_log( sprintf( 'Notification fetch exception: %s', $e->getMessage() ) );
|
||||
|
||||
// If for some reason our request failed, delay for 4 hours.
|
||||
update_option( 'edd_notification_req_timeout', current_time( 'timestamp' ) + ( HOUR_IN_SECONDS * 4 ), false );
|
||||
return;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user