Merge branch 'master' into fix/1035

# Conflicts:
#	includes/class-wc-admin-reports-interval.php
#	includes/data-stores/class-wc-admin-reports-data-store.php
#	includes/data-stores/class-wc-admin-reports-products-data-store.php
This commit is contained in:
Peter Fabian 2019-01-16 12:51:23 +01:00
commit 05c7670090
21 changed files with 206 additions and 220 deletions

View File

@ -5,6 +5,7 @@ const fs = require( 'fs' );
const { execSync } = require( 'child_process' );
const path = require( 'path' );
const chalk = require( 'chalk' );
const watch = require( 'node-watch' );
/**
* Internal dependencies
@ -33,14 +34,14 @@ getPackages().forEach( ( p ) => {
const srcDir = path.resolve( p, 'src' );
try {
fs.accessSync( srcDir, fs.F_OK );
fs.watch( path.resolve( p, 'src' ), { recursive: true }, ( event, filename ) => {
watch( path.resolve( p, 'src' ), { recursive: true }, ( event, filename ) => {
const filePath = path.resolve( srcDir, filename );
if ( ! isSourceFile( filename ) ) {
return;
}
if ( ( event === 'change' || event === 'rename' ) && exists( filePath ) ) {
if ( ( [ 'update', 'change', 'rename' ].includes( event ) ) && exists( filePath ) ) {
// eslint-disable-next-line no-console
console.log( chalk.green( '->' ), `${ event }: ${ filename }` );
rebuild( filePath );

View File

@ -385,6 +385,7 @@ class WC_Admin_REST_Reports_Orders_Stats_Controller extends WC_Admin_REST_Report
'type' => 'array',
'sanitize_callback' => 'wp_parse_slug_list',
'validate_callback' => 'rest_validate_request_arg',
'default' => null,
'items' => array(
'enum' => $this->get_order_statuses(),
'type' => 'string',

View File

@ -30,7 +30,7 @@ class WC_Admin_Reports_Interval {
* Returns date format to be used as grouping clause in SQL.
*
* @param string $time_interval Time interval.
* @param string $table_name Name of db table.
* @param string $table_name Name of the db table relevant for the date constraint.
* @return mixed
*/
public static function db_datetime_format( $time_interval, $table_name ) {
@ -38,21 +38,21 @@ class WC_Admin_Reports_Interval {
if ( 1 === $first_day_of_week ) {
// Week begins on Monday, ISO 8601.
$week_format = "DATE_FORMAT($table_name.date_created, '%x-%v')";
$week_format = "DATE_FORMAT({$table_name}.date_created, '%x-%v')";
} else {
// Week begins on day other than specified by ISO 8601, needs to be in sync with function simple_week_number.
$week_format = "CONCAT(YEAR($table_name.date_created), '-', LPAD( FLOOR( ( DAYOFYEAR($table_name.date_created) + ( ( DATE_FORMAT(MAKEDATE(YEAR($table_name.date_created),1), '%w') - $first_day_of_week + 7 ) % 7 ) - 1 ) / 7 ) + 1 , 2, '0'))";
$week_format = "CONCAT(YEAR({$table_name}.date_created), '-', LPAD( FLOOR( ( DAYOFYEAR({$table_name}.date_created) + ( ( DATE_FORMAT(MAKEDATE(YEAR({$table_name}.date_created),1), '%w') - $first_day_of_week + 7 ) % 7 ) - 1 ) / 7 ) + 1 , 2, '0'))";
}
// Whenever this is changed, double check method time_interval_id to make sure they are in sync.
$mysql_date_format_mapping = array(
'hour' => "DATE_FORMAT($table_name.date_created, '%Y-%m-%d %H')",
'day' => "DATE_FORMAT($table_name.date_created, '%Y-%m-%d')",
'hour' => "DATE_FORMAT({$table_name}.date_created, '%Y-%m-%d %H')",
'day' => "DATE_FORMAT({$table_name}.date_created, '%Y-%m-%d')",
'week' => $week_format,
'month' => "DATE_FORMAT($table_name.date_created, '%Y-%m')",
'quarter' => "CONCAT(YEAR($table_name.date_created), '-', QUARTER($table_name.date_created))",
'year' => "YEAR($table_name.date_created)",
'month' => "DATE_FORMAT({$table_name}.date_created, '%Y-%m')",
'quarter' => "CONCAT(YEAR({$table_name}.date_created), '-', QUARTER({$table_name}.date_created))",
'year' => "YEAR({$table_name}.date_created)",
);

View File

@ -9,7 +9,7 @@
* 'interval' => 'week',
* 'categories' => array(15, 18),
* 'coupons' => array(138),
* 'order_status' => array('completed'),
* 'status_in' => array('completed'),
* );
* $report = new WC_Admin_Reports_Orders_Stats_Query( $args );
* $mydata = $report->get_data();

View File

@ -59,6 +59,16 @@ class WC_Admin_Reports_Categories_Data_Store extends WC_Admin_Reports_Data_Store
'products_count' => 'COUNT(DISTINCT product_id) as products_count',
);
/**
* Constructor
*/
public function __construct() {
global $wpdb;
$table_name = $wpdb->prefix . self::TABLE_NAME;
// Avoid ambigious column order_id in SQL query.
$this->report_columns['orders_count'] = str_replace( 'order_id', $table_name . '.order_id', $this->report_columns['orders_count'] );
}
/**
* Return the database query with parameters used for Categories report: time span and order status.
*
@ -93,7 +103,7 @@ class WC_Admin_Reports_Categories_Data_Store extends WC_Admin_Reports_Data_Store
$order_status_filter = $this->get_status_subquery( $query_args );
if ( $order_status_filter ) {
$sql_query_params['from_clause'] .= " JOIN {$wpdb->prefix}posts ON {$order_product_lookup_table}.order_id = {$wpdb->prefix}posts.ID";
$sql_query_params['from_clause'] .= " JOIN {$wpdb->prefix}wc_order_stats ON {$order_product_lookup_table}.order_id = {$wpdb->prefix}wc_order_stats.order_id";
$sql_query_params['where_clause'] .= " AND ( {$order_status_filter} )";
}
@ -216,9 +226,6 @@ class WC_Admin_Reports_Categories_Data_Store extends WC_Admin_Reports_Data_Store
'fields' => '*',
'categories' => array(),
'extended_info' => false,
// This is not a parameter for products reports per se, but maybe we should restricts order statuses here, too?
'order_status' => parent::get_report_order_statuses(),
);
$query_args = wp_parse_args( $query_args, $defaults );

View File

@ -41,6 +41,16 @@ class WC_Admin_Reports_Coupons_Data_Store extends WC_Admin_Reports_Data_Store im
'orders_count' => 'COUNT(DISTINCT order_id) as orders_count',
);
/**
* Constructor
*/
public function __construct() {
global $wpdb;
$table_name = $wpdb->prefix . self::TABLE_NAME;
// Avoid ambigious column order_id in SQL query.
$this->report_columns['orders_count'] = str_replace( 'order_id', $table_name . '.order_id', $this->report_columns['orders_count'] );
}
/**
* Set up all the hooks for maintaining and populating table data.
*/
@ -84,10 +94,9 @@ class WC_Admin_Reports_Coupons_Data_Store extends WC_Admin_Reports_Data_Store im
$sql_query_params['where_clause'] .= " AND {$order_coupon_lookup_table}.coupon_id IN ({$included_coupons})";
}
// TODO: questionable, I think we need order status filters, even though it's not specified.
$order_status_filter = $this->get_status_subquery( $query_args );
if ( $order_status_filter ) {
$sql_query_params['from_clause'] .= " JOIN {$wpdb->prefix}posts ON {$order_coupon_lookup_table}.order_id = {$wpdb->prefix}posts.ID";
$sql_query_params['from_clause'] .= " JOIN {$wpdb->prefix}wc_order_stats ON {$order_coupon_lookup_table}.order_id = {$wpdb->prefix}wc_order_stats.order_id";
$sql_query_params['where_clause'] .= " AND ( {$order_status_filter} )";
}
@ -214,9 +223,6 @@ class WC_Admin_Reports_Coupons_Data_Store extends WC_Admin_Reports_Data_Store im
'fields' => '*',
'coupons' => array(),
'extended_info' => false,
// This is not a parameter for coupons reports per se, but we want to only take into account selected order types.
'order_status' => parent::get_report_order_statuses(),
);
$query_args = wp_parse_args( $query_args, $defaults );
@ -319,15 +325,6 @@ class WC_Admin_Reports_Coupons_Data_Store extends WC_Admin_Reports_Data_Store im
return;
}
if ( ! in_array( $order->get_status(), parent::get_report_order_statuses(), true ) ) {
$wpdb->delete(
$wpdb->prefix . self::TABLE_NAME,
array( 'order_id' => $order->get_id() ),
array( '%d' )
);
return;
}
$coupon_items = $order->get_items( 'coupon' );
foreach ( $coupon_items as $coupon_item ) {
$wpdb->replace(

View File

@ -39,6 +39,16 @@ class WC_Admin_Reports_Coupons_Stats_Data_Store extends WC_Admin_Reports_Coupons
'orders_count' => 'COUNT(DISTINCT order_id) as orders_count',
);
/**
* Constructor
*/
public function __construct() {
global $wpdb;
$table_name = $wpdb->prefix . self::TABLE_NAME;
// Avoid ambigious column order_id in SQL query.
$this->report_columns['orders_count'] = str_replace( 'order_id', $table_name . '.order_id', $this->report_columns['orders_count'] );
}
/**
* Updates the database query with parameters used for Products Stats report: categories and order status.
*
@ -61,7 +71,7 @@ class WC_Admin_Reports_Coupons_Stats_Data_Store extends WC_Admin_Reports_Coupons
$order_status_filter = $this->get_status_subquery( $query_args );
if ( $order_status_filter ) {
$coupons_from_clause .= " JOIN {$wpdb->prefix}posts ON {$order_coupon_lookup_table}.order_id = {$wpdb->prefix}posts.ID";
$coupons_from_clause .= " JOIN {$wpdb->prefix}wc_order_stats ON {$order_coupon_lookup_table}.order_id = {$wpdb->prefix}wc_order_stats.order_id";
$coupons_where_clause .= " AND ( {$order_status_filter} )";
}
@ -99,8 +109,6 @@ class WC_Admin_Reports_Coupons_Stats_Data_Store extends WC_Admin_Reports_Coupons
'fields' => '*',
'interval' => 'week',
'coupons' => array(),
// This is not a parameter for products reports per se, but we should probably restricts order statuses here, too.
'order_status' => parent::get_report_order_statuses(),
);
$query_args = wp_parse_args( $query_args, $defaults );
@ -168,7 +176,7 @@ class WC_Admin_Reports_Coupons_Stats_Data_Store extends WC_Admin_Reports_Coupons
$intervals = $wpdb->get_results(
"SELECT
MAX(date_created) AS datetime_anchor,
MAX({$table_name}.date_created) AS datetime_anchor,
{$intervals_query['select_clause']} AS time_interval
{$selections}
FROM

View File

@ -203,11 +203,13 @@ class WC_Admin_Reports_Customers_Data_Store extends WC_Admin_Reports_Data_Store
*/
protected function get_sql_query_params( $query_args ) {
global $wpdb;
$customer_lookup_table = $wpdb->prefix . self::TABLE_NAME;
$customer_lookup_table = $wpdb->prefix . self::TABLE_NAME;
$order_stats_table_name = $wpdb->prefix . 'wc_order_stats';
$sql_query_params = $this->get_time_period_sql_params( $query_args, $customer_lookup_table );
$sql_query_params = array_merge( $sql_query_params, $this->get_limit_sql_params( $query_args ) );
$sql_query_params = array_merge( $sql_query_params, $this->get_order_by_sql_params( $query_args ) );
$sql_query_params = $this->get_time_period_sql_params( $query_args, $customer_lookup_table );
$sql_query_params = array_merge( $sql_query_params, $this->get_limit_sql_params( $query_args ) );
$sql_query_params = array_merge( $sql_query_params, $this->get_order_by_sql_params( $query_args ) );
$sql_query_params['from_clause'] = " LEFT JOIN {$order_stats_table_name} ON {$customer_lookup_table}.customer_id = {$order_stats_table_name}.customer_id";
$match_operator = $this->get_match_operator( $query_args );
$where_clauses = array();
@ -276,6 +278,11 @@ class WC_Admin_Reports_Customers_Data_Store extends WC_Admin_Reports_Data_Store
$sql_query_params['where_clause'] = $preceding_match . implode( " {$match_operator} ", $where_clauses );
}
$order_status_filter = $this->get_status_subquery( $query_args );
if ( $order_status_filter ) {
$sql_query_params['from_clause'] .= " AND ( {$order_status_filter} )";
}
if ( $having_clauses ) {
$preceding_match = empty( $sql_query_params['having_clause'] ) ? ' AND ' : " {$match_operator} ";
$sql_query_params['having_clause'] .= $preceding_match . implode( " {$match_operator} ", $having_clauses );
@ -293,7 +300,7 @@ class WC_Admin_Reports_Customers_Data_Store extends WC_Admin_Reports_Data_Store
public function get_data( $query_args ) {
global $wpdb;
$customers_table_name = $wpdb->prefix . self::TABLE_NAME;
$customers_table_name = $wpdb->prefix . self::TABLE_NAME;
$order_stats_table_name = $wpdb->prefix . 'wc_order_stats';
// These defaults are only partially applied when used via REST API, as that has its own defaults.
@ -325,10 +332,7 @@ class WC_Admin_Reports_Customers_Data_Store extends WC_Admin_Reports_Data_Store
SELECT {$customers_table_name}.customer_id
FROM
{$customers_table_name}
LEFT JOIN
{$order_stats_table_name}
ON
{$customers_table_name}.customer_id = {$order_stats_table_name}.customer_id
{$sql_query_params['from_clause']}
WHERE
1=1
{$sql_query_params['where_time_clause']}
@ -352,10 +356,7 @@ class WC_Admin_Reports_Customers_Data_Store extends WC_Admin_Reports_Data_Store
{$selections}
FROM
{$customers_table_name}
LEFT JOIN
{$order_stats_table_name}
ON
{$customers_table_name}.customer_id = {$order_stats_table_name}.customer_id
{$sql_query_params['from_clause']}
WHERE
1=1
{$sql_query_params['where_time_clause']}

View File

@ -266,7 +266,7 @@ class WC_Admin_Reports_Data_Store {
* @param array $query_args Query arguements.
* @param int $db_interval_count Database interval count.
* @param int $expected_interval_count Expected interval count on the output.
* @param string $table_name Name of SQL table where the date_created column (used for time filtering) exists.
* @param string $table_name Name of the db table relevant for the date constraint.
*/
protected function update_intervals_sql_params( &$intervals_query, &$query_args, $db_interval_count, $expected_interval_count, $table_name ) {
if ( $db_interval_count === $expected_interval_count ) {
@ -340,8 +340,8 @@ class WC_Admin_Reports_Data_Store {
$query_args['adj_after'] = $new_start_date->format( WC_Admin_Reports_Interval::$iso_datetime_format );
$query_args['adj_before'] = $new_end_date->format( WC_Admin_Reports_Interval::$iso_datetime_format );
$intervals_query['where_time_clause'] = '';
$intervals_query['where_time_clause'] .= " AND $table_name.date_created <= '{$query_args['adj_before']}'";
$intervals_query['where_time_clause'] .= " AND $table_name.date_created >= '{$query_args['adj_after']}'";
$intervals_query['where_time_clause'] .= " AND {$table_name}.date_created <= '{$query_args['adj_before']}'";
$intervals_query['where_time_clause'] .= " AND {$table_name}.date_created >= '{$query_args['adj_after']}'";
$intervals_query['limit'] = 'LIMIT 0,' . $intervals_query['per_page'];
} else {
if ( 'asc' === $query_args['order'] ) {
@ -408,12 +408,12 @@ class WC_Admin_Reports_Data_Store {
}
/**
* Get the order statuses used when calculating reports.
* Get the excluded order statuses used when calculating reports.
*
* @return array
*/
protected static function get_report_order_statuses() {
return apply_filters( 'woocommerce_reports_order_statuses', array( 'completed', 'processing', 'on-hold' ) );
protected static function get_excluded_report_order_statuses() {
return apply_filters( 'woocommerce_reports_excluded_order_statuses', array( 'refunded', 'pending', 'failed', 'cancelled' ) );
}
/**
@ -781,7 +781,8 @@ class WC_Admin_Reports_Data_Store {
protected function get_status_subquery( $query_args, $operator = 'AND' ) {
global $wpdb;
$subqueries = array();
$subqueries = array();
$excluded_statuses = array();
if ( isset( $query_args['status_is'] ) && is_array( $query_args['status_is'] ) && count( $query_args['status_is'] ) > 0 ) {
$allowed_statuses = array_map( array( $this, 'normalize_order_status' ), $query_args['status_is'] );
if ( $allowed_statuses ) {
@ -790,10 +791,17 @@ class WC_Admin_Reports_Data_Store {
}
if ( isset( $query_args['status_is_not'] ) && is_array( $query_args['status_is_not'] ) && count( $query_args['status_is_not'] ) > 0 ) {
$forbidden_statuses = array_map( array( $this, 'normalize_order_status' ), $query_args['status_is_not'] );
if ( $forbidden_statuses ) {
$subqueries[] = "{$wpdb->prefix}wc_order_stats.status NOT IN ( '" . implode( "','", $forbidden_statuses ) . "' )";
}
$excluded_statuses = array_map( array( $this, 'normalize_order_status' ), $query_args['status_is_not'] );
}
if ( ( ! isset( $query_args['status_is'] ) || empty( $query_args['status_is'] ) )
&& ( ! isset( $query_args['status_is_not'] ) || empty( $query_args['status_is_not'] ) )
) {
$excluded_statuses = array_map( array( $this, 'normalize_order_status' ), $this->get_excluded_report_order_statuses() );
}
if ( $excluded_statuses ) {
$subqueries[] = "{$wpdb->prefix}wc_order_stats.status NOT IN ( '" . implode( "','", $excluded_statuses ) . "' )";
}
return implode( " $operator ", $subqueries );

View File

@ -141,7 +141,7 @@ class WC_Admin_Reports_Orders_Data_Store extends WC_Admin_Reports_Data_Store imp
'coupon_includes' => array(),
'coupon_excludes' => array(),
'customer_type' => null,
'status_is' => parent::get_report_order_statuses(),
'status_is' => array(),
'extended_info' => false,
);
$query_args = wp_parse_args( $query_args, $defaults );
@ -228,34 +228,6 @@ class WC_Admin_Reports_Orders_Data_Store extends WC_Admin_Reports_Data_Store imp
if ( 'date' === $order_by ) {
return 'date_created';
}
return $order_by;
}
/**
* Returns order status subquery to be used in WHERE SQL query, based on query arguments from the user.
*
* @param array $query_args Parameters supplied by the user.
* @param string $operator AND or OR, based on match query argument.
* @return string
*/
protected function get_status_subquery( $query_args, $operator = 'AND' ) {
$subqueries = array();
if ( isset( $query_args['status_is'] ) && is_array( $query_args['status_is'] ) && count( $query_args['status_is'] ) > 0 ) {
$allowed_statuses = array_map( array( $this, 'normalize_order_status' ), $query_args['status_is'] );
if ( $allowed_statuses ) {
$subqueries[] = "status IN ( '" . implode( "','", $allowed_statuses ) . "' )";
}
}
if ( isset( $query_args['status_is_not'] ) && is_array( $query_args['status_is_not'] ) && count( $query_args['status_is_not'] ) > 0 ) {
$forbidden_statuses = array_map( array( $this, 'normalize_order_status' ), $query_args['status_is_not'] );
if ( $forbidden_statuses ) {
$subqueries[] = "status NOT IN ( '" . implode( "','", $forbidden_statuses ) . "' )";
}
}
return implode( " $operator ", $subqueries );
}
/**

View File

@ -171,11 +171,6 @@ class WC_Admin_Reports_Orders_Stats_Data_Store extends WC_Admin_Reports_Data_Sto
)";
}
$order_status_filter = $this->get_status_subquery( $query_args, $operator );
if ( $order_status_filter ) {
$where_filters[] = $order_status_filter;
}
$customer_filter = $this->get_customer_subquery( $query_args );
if ( $customer_filter ) {
$where_filters[] = $customer_filter;
@ -183,6 +178,15 @@ class WC_Admin_Reports_Orders_Stats_Data_Store extends WC_Admin_Reports_Data_Sto
$where_subclause = implode( " $operator ", $where_filters );
// Append status filter after to avoid matching ANY on default statuses.
$order_status_filter = $this->get_status_subquery( $query_args, $operator );
if ( $order_status_filter ) {
if ( empty( $query_args['status_is'] ) && empty( $query_args['status_is_not'] ) ) {
$operator = 'AND';
}
$where_subclause = implode( " $operator ", array_filter( array( $where_subclause, $order_status_filter ) ) );
}
// To avoid requesting the subqueries twice, the result is applied to all queries passed to the method.
if ( $where_subclause ) {
$totals_query['where_clause'] .= " AND ( $where_subclause )";
@ -1209,7 +1213,6 @@ class WC_Admin_Reports_Orders_Stats_Data_Store extends WC_Admin_Reports_Data_Sto
$order_ids = wc_get_orders(
array(
'limit' => -1,
'status' => parent::get_report_order_statuses(),
'type' => 'shop_order',
'return' => 'ids',
)
@ -1265,16 +1268,6 @@ class WC_Admin_Reports_Orders_Stats_Data_Store extends WC_Admin_Reports_Data_Sto
return false;
}
if ( ! in_array( $order->get_status(), parent::get_report_order_statuses(), true ) ) {
$wpdb->delete(
$table_name,
array(
'order_id' => $order->get_id(),
)
);
return;
}
$data = array(
'order_id' => $order->get_id(),
'date_created' => $order->get_date_created()->date( 'Y-m-d H:i:s' ),

View File

@ -72,6 +72,16 @@ class WC_Admin_Reports_Products_Data_Store extends WC_Admin_Reports_Data_Store i
'sku',
);
/**
* Constructor
*/
public function __construct() {
global $wpdb;
$table_name = $wpdb->prefix . self::TABLE_NAME;
// Avoid ambigious column order_id in SQL query.
$this->report_columns['orders_count'] = str_replace( 'order_id', $table_name . '.order_id', $this->report_columns['orders_count'] );
}
/**
* Set up all the hooks for maintaining and populating table data.
*/
@ -134,7 +144,7 @@ class WC_Admin_Reports_Products_Data_Store extends WC_Admin_Reports_Data_Store i
$order_status_filter = $this->get_status_subquery( $query_args );
if ( $order_status_filter ) {
$sql_query_params['from_clause'] .= " JOIN {$wpdb->prefix}posts ON {$order_product_lookup_table}.order_id = {$wpdb->prefix}posts.ID";
$sql_query_params['from_clause'] .= " JOIN {$wpdb->prefix}wc_order_stats ON {$order_product_lookup_table}.order_id = {$wpdb->prefix}wc_order_stats.order_id";
$sql_query_params['where_clause'] .= " AND ( {$order_status_filter} )";
}
@ -148,8 +158,11 @@ class WC_Admin_Reports_Products_Data_Store extends WC_Admin_Reports_Data_Store i
* @return string
*/
protected function normalize_order_by( $order_by ) {
global $wpdb;
$order_product_lookup_table = $wpdb->prefix . self::TABLE_NAME;
if ( 'date' === $order_by ) {
return 'date_created';
return $order_product_lookup_table . '.date_created';
}
if ( 'product_name' === $order_by ) {
return '_products.post_title';
@ -214,9 +227,6 @@ class WC_Admin_Reports_Products_Data_Store extends WC_Admin_Reports_Data_Store i
'categories' => array(),
'product_includes' => array(),
'extended_info' => false,
// This is not a parameter for products reports per se, but we want to only take into account selected order types.
'order_status' => parent::get_report_order_statuses(),
);
$query_args = wp_parse_args( $query_args, $defaults );
@ -321,15 +331,6 @@ class WC_Admin_Reports_Products_Data_Store extends WC_Admin_Reports_Data_Store i
return;
}
if ( ! in_array( $order->get_status(), parent::get_report_order_statuses(), true ) ) {
$wpdb->delete(
$wpdb->prefix . self::TABLE_NAME,
array( 'order_id' => $order->get_id() ),
array( '%d' )
); // WPCS: cache ok, DB call ok.
return;
}
$refunds = self::get_order_refund_items( $order );
foreach ( $order->get_items() as $order_item ) {

View File

@ -40,6 +40,16 @@ class WC_Admin_Reports_Products_Stats_Data_Store extends WC_Admin_Reports_Produc
'products_count' => 'COUNT(DISTINCT product_id) as products_count',
);
/**
* Constructor
*/
public function __construct() {
global $wpdb;
$table_name = $wpdb->prefix . self::TABLE_NAME;
// Avoid ambigious column order_id in SQL query.
$this->report_columns['orders_count'] = str_replace( 'order_id', $table_name . '.order_id', $this->report_columns['orders_count'] );
}
/**
* Updates the database query with parameters used for Products Stats report: categories and order status.
*
@ -62,7 +72,7 @@ class WC_Admin_Reports_Products_Stats_Data_Store extends WC_Admin_Reports_Produc
$order_status_filter = $this->get_status_subquery( $query_args );
if ( $order_status_filter ) {
$products_from_clause .= " JOIN {$wpdb->prefix}posts ON {$order_product_lookup_table}.order_id = {$wpdb->prefix}posts.ID";
$products_from_clause .= " JOIN {$wpdb->prefix}wc_order_stats ON {$order_product_lookup_table}.order_id = {$wpdb->prefix}wc_order_stats.order_id";
$products_where_clause .= " AND ( {$order_status_filter} )";
}
@ -101,8 +111,6 @@ class WC_Admin_Reports_Products_Stats_Data_Store extends WC_Admin_Reports_Produc
'categories' => array(),
'interval' => 'week',
'product_includes' => array(),
// This is not a parameter for products reports per se, but we should probably restricts order statuses here, too.
'order_status' => parent::get_report_order_statuses(),
);
$query_args = wp_parse_args( $query_args, $defaults );
@ -161,7 +169,7 @@ class WC_Admin_Reports_Products_Stats_Data_Store extends WC_Admin_Reports_Produc
$intervals = $wpdb->get_results(
"SELECT
MAX(date_created) AS datetime_anchor,
MAX(${table_name}.date_created) AS datetime_anchor,
{$intervals_query['select_clause']} AS time_interval
{$selections}
FROM

View File

@ -61,8 +61,9 @@ class WC_Admin_Reports_Taxes_Data_Store extends WC_Admin_Reports_Data_Store impl
public function __construct() {
global $wpdb;
$table_name = $wpdb->prefix . self::TABLE_NAME;
// Avoid ambigious column tax_rate_id in SQL query.
$this->report_columns['tax_rate_id'] = $table_name . '.' . $this->report_columns['tax_rate_id'];
// Avoid ambigious columns in SQL query.
$this->report_columns['tax_rate_id'] = $table_name . '.' . $this->report_columns['tax_rate_id'];
$this->report_columns['orders_count'] = str_replace( 'order_id', $table_name . '.order_id', $this->report_columns['orders_count'] );
}
/**
@ -94,6 +95,12 @@ class WC_Admin_Reports_Taxes_Data_Store extends WC_Admin_Reports_Data_Store impl
$sql_query_params['where_clause'] .= " AND {$order_tax_lookup_table}.tax_rate_id IN ({$allowed_taxes})";
}
$order_status_filter = $this->get_status_subquery( $query_args );
if ( $order_status_filter ) {
$sql_query_params['from_clause'] .= " JOIN {$wpdb->prefix}wc_order_stats ON {$order_tax_lookup_table}.order_id = {$wpdb->prefix}wc_order_stats.order_id";
$sql_query_params['where_clause'] .= " AND ( {$order_status_filter} )";
}
$sql_query_params['from_clause'] .= " JOIN {$wpdb->prefix}woocommerce_tax_rates ON {$order_tax_lookup_table}.tax_rate_id = {$wpdb->prefix}woocommerce_tax_rates.tax_rate_id";
return $sql_query_params;
@ -257,15 +264,6 @@ class WC_Admin_Reports_Taxes_Data_Store extends WC_Admin_Reports_Data_Store impl
return;
}
if ( ! in_array( $order->get_status(), parent::get_report_order_statuses(), true ) ) {
$wpdb->delete(
$wpdb->prefix . self::TABLE_NAME,
array( 'order_id' => $order->get_id() ),
array( '%d' )
);
return;
}
foreach ( $order->get_items( 'tax' ) as $tax_item ) {
$wpdb->replace(
$wpdb->prefix . self::TABLE_NAME,

View File

@ -66,6 +66,12 @@ class WC_Admin_Reports_Taxes_Stats_Data_Store extends WC_Admin_Reports_Data_Stor
$sql_query_params['where_clause'] .= " AND {$order_tax_lookup_table}.tax_rate_id IN ({$allowed_taxes})";
}
$order_status_filter = $this->get_status_subquery( $query_args );
if ( $order_status_filter ) {
$sql_query_params['from_clause'] .= " JOIN {$wpdb->prefix}wc_order_stats ON {$order_product_lookup_table}.order_id = {$wpdb->prefix}wc_order_stats.order_id";
$sql_query_params['where_clause'] .= " AND ( {$order_status_filter} )";
}
return $sql_query_params;
}

View File

@ -66,6 +66,15 @@ class WC_Admin_Reports_Variations_Data_Store extends WC_Admin_Reports_Data_Store
'low_stock_amount',
);
/**
* Constructor
*/
public function __construct() {
global $wpdb;
$table_name = $wpdb->prefix . self::TABLE_NAME;
// Avoid ambigious column order_id in SQL query.
$this->report_columns['orders_count'] = str_replace( 'order_id', $table_name . '.order_id', $this->report_columns['orders_count'] );
}
/**
* Updates the database query with parameters used for Products report: categories and order status.
@ -91,11 +100,10 @@ class WC_Admin_Reports_Variations_Data_Store extends WC_Admin_Reports_Data_Store
$sql_query_params['where_clause'] .= " AND {$order_product_lookup_table}.variation_id IN ({$allowed_variations_str})";
}
if ( is_array( $query_args['order_status'] ) && count( $query_args['order_status'] ) > 0 ) {
$statuses = array_map( array( $this, 'normalize_order_status' ), $query_args['order_status'] );
$sql_query_params['from_clause'] .= " JOIN {$wpdb->prefix}posts ON {$order_product_lookup_table}.order_id = {$wpdb->prefix}posts.ID";
$sql_query_params['where_clause'] .= " AND {$wpdb->prefix}posts.post_status IN ( '" . implode( "','", $statuses ) . "' ) ";
$order_status_filter = $this->get_status_subquery( $query_args );
if ( $order_status_filter ) {
$sql_query_params['from_clause'] .= " JOIN {$wpdb->prefix}wc_order_stats ON {$order_product_lookup_table}.order_id = {$wpdb->prefix}wc_order_stats.order_id";
$sql_query_params['where_clause'] .= " AND ( {$order_status_filter} )";
$sql_query_params['where_clause'] .= ' AND variation_id > 0';
}
@ -109,8 +117,11 @@ class WC_Admin_Reports_Variations_Data_Store extends WC_Admin_Reports_Data_Store
* @return string
*/
protected function normalize_order_by( $order_by ) {
global $wpdb;
$table_name = $wpdb->prefix . self::TABLE_NAME;
if ( 'date' === $order_by ) {
return 'date_created';
return $table_name . '.date_created';
}
return $order_by;
@ -190,9 +201,6 @@ class WC_Admin_Reports_Variations_Data_Store extends WC_Admin_Reports_Data_Store
'products' => array(),
'variations' => array(),
'extended_info' => false,
// This is not a parameter for products reports per se, but we want to only take into account selected order types.
'order_status' => parent::get_report_order_statuses(),
);
$query_args = wp_parse_args( $query_args, $defaults );

View File

@ -8074,36 +8074,6 @@
"is-extglob": "^1.0.0"
}
},
"extract-text-webpack-plugin": {
"version": "4.0.0-beta.0",
"resolved": "https://registry.npmjs.org/extract-text-webpack-plugin/-/extract-text-webpack-plugin-4.0.0-beta.0.tgz",
"integrity": "sha512-Hypkn9jUTnFr0DpekNam53X47tXn3ucY08BQumv7kdGgeVUBLq3DJHJTi6HNxv4jl9W+Skxjz9+RnK0sJyqqjA==",
"dev": true,
"requires": {
"async": "^2.4.1",
"loader-utils": "^1.1.0",
"schema-utils": "^0.4.5",
"webpack-sources": "^1.1.0"
},
"dependencies": {
"ajv-keywords": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.2.0.tgz",
"integrity": "sha1-6GuBnGAs+IIa1jdBNpjx3sAhhHo=",
"dev": true
},
"schema-utils": {
"version": "0.4.7",
"resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.4.7.tgz",
"integrity": "sha512-v/iwU6wvwGK8HbU9yi3/nhGzP0yGSuhQMzL6ySiec1FSrZZDkhm4noOSWzrNFo/jEc+SJY6jRTwuwbSXJPDUnQ==",
"dev": true,
"requires": {
"ajv": "^6.1.0",
"ajv-keywords": "^3.1.0"
}
}
}
},
"extsprintf": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
@ -8977,7 +8947,8 @@
},
"ansi-regex": {
"version": "2.1.1",
"bundled": true
"bundled": true,
"optional": true
},
"aproba": {
"version": "1.2.0",
@ -9342,7 +9313,8 @@
},
"safe-buffer": {
"version": "5.1.1",
"bundled": true
"bundled": true,
"optional": true
},
"safer-buffer": {
"version": "2.1.2",
@ -9390,6 +9362,7 @@
"strip-ansi": {
"version": "3.0.1",
"bundled": true,
"optional": true,
"requires": {
"ansi-regex": "^2.0.0"
}
@ -9428,11 +9401,13 @@
},
"wrappy": {
"version": "1.0.2",
"bundled": true
"bundled": true,
"optional": true
},
"yallist": {
"version": "3.0.2",
"bundled": true
"bundled": true,
"optional": true
}
}
},
@ -13572,6 +13547,17 @@
"resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz",
"integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ=="
},
"mini-css-extract-plugin": {
"version": "0.5.0",
"resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-0.5.0.tgz",
"integrity": "sha512-IuaLjruM0vMKhUUT51fQdQzBYTX49dLj8w68ALEAe2A4iYNpIC4eMac67mt3NzycvjOlf07/kYxJDc0RTl1Wqw==",
"dev": true,
"requires": {
"loader-utils": "^1.1.0",
"schema-utils": "^1.0.0",
"webpack-sources": "^1.1.0"
}
},
"minimalistic-assert": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz",

View File

@ -80,13 +80,14 @@
"eslint-plugin-jsx-a11y": "6.1.2",
"eslint-plugin-react": "7.12.3",
"eslint-plugin-wpcalypso": "4.0.2",
"extract-text-webpack-plugin": "4.0.0-beta.0",
"grunt": "1.0.3",
"grunt-checktextdomain": "1.0.1",
"grunt-wp-i18n": "1.0.3",
"husky": "1.3.1",
"lerna": "3.10.5",
"mini-css-extract-plugin": "0.5.0",
"node-sass": "4.11.0",
"node-watch": "^0.6.0",
"postcss-color-function": "4.0.1",
"postcss-loader": "3.0.0",
"prettier": "github:automattic/calypso-prettier#c56b4251",

View File

@ -46,7 +46,16 @@ export const drawBars = ( node, data, params ) => {
.attr( 'y', 0 )
.attr( 'width', params.xGroupScale.range()[ 1 ] )
.attr( 'height', params.height )
.attr( 'opacity', '0' );
.attr( 'opacity', '0' )
.on( 'mouseover', ( d, i, nodes ) => {
const position = calculateTooltipPosition(
d3Event.target,
node.node(),
params.tooltipPosition
);
handleMouseOverBarChart( d.date, nodes[ i ].parentNode, node, data, params, position );
} )
.on( 'mouseout', ( d, i, nodes ) => hideTooltip( nodes[ i ].parentNode, params.tooltip ) );
barGroup
.selectAll( '.bar' )
@ -68,6 +77,7 @@ export const drawBars = ( node, data, params ) => {
.attr( 'width', params.xGroupScale.bandwidth() )
.attr( 'height', d => params.height - params.yScale( d.value ) )
.attr( 'fill', d => getColor( d.key, params.orderedKeys, params.colorScheme ) )
.attr( 'pointer-events', 'none' )
.attr( 'tabindex', '0' )
.attr( 'aria-label', d => {
const label = params.mode === 'time-comparison' && d.label ? d.label : d.key;
@ -83,22 +93,4 @@ export const drawBars = ( node, data, params ) => {
handleMouseOverBarChart( d.date, nodes[ i ].parentNode, node, data, params, position );
} )
.on( 'blur', ( d, i, nodes ) => hideTooltip( nodes[ i ].parentNode, params.tooltip ) );
barGroup
.append( 'rect' )
.attr( 'class', 'barmouse' )
.attr( 'x', 0 )
.attr( 'y', 0 )
.attr( 'width', params.xGroupScale.range()[ 1 ] )
.attr( 'height', params.height )
.attr( 'opacity', '0' )
.on( 'mouseover', ( d, i, nodes ) => {
const position = calculateTooltipPosition(
d3Event.target,
node.node(),
params.tooltipPosition
);
handleMouseOverBarChart( d.date, nodes[ i ].parentNode, node, data, params, position );
} )
.on( 'mouseout', ( d, i, nodes ) => hideTooltip( nodes[ i ].parentNode, params.tooltip ) );
};

View File

@ -82,7 +82,7 @@ class WC_Tests_API_Reports_Taxes extends WC_REST_Unit_Test_Case {
$wpdb->insert(
$wpdb->prefix . 'wc_order_tax_lookup',
array(
'order_id' => 1,
'order_id' => $order->get_id(),
'tax_rate_id' => 1,
'date_created' => date( 'Y-m-d H:i:s' ),
'shipping_tax' => 2,

View File

@ -2,7 +2,7 @@
/**
* External dependencies
*/
const ExtractTextPlugin = require( 'extract-text-webpack-plugin' );
const MiniCssExtractPlugin = require( 'mini-css-extract-plugin' );
const { get } = require( 'lodash' );
const path = require( 'path' );
const CopyWebpackPlugin = require( 'copy-webpack-plugin' );
@ -96,32 +96,30 @@ const webpackConfig = {
{ test: /\.md$/, use: 'raw-loader' },
{
test: /\.s?css$/,
use: ExtractTextPlugin.extract( {
fallback: 'style-loader',
use: [
'css-loader',
{
// postcss loader so we can use autoprefixer and theme Gutenberg components
loader: 'postcss-loader',
options: {
config: {
path: 'postcss.config.js',
},
use: [
MiniCssExtractPlugin.loader,
'css-loader',
{
// postcss loader so we can use autoprefixer and theme Gutenberg components
loader: 'postcss-loader',
options: {
config: {
path: 'postcss.config.js',
},
},
{
loader: 'sass-loader',
query: {
includePaths: [ 'client/stylesheets/abstracts' ],
data:
'@import "_colors"; ' +
'@import "_variables"; ' +
'@import "_breakpoints"; ' +
'@import "_mixins"; ',
},
},
{
loader: 'sass-loader',
query: {
includePaths: [ 'client/stylesheets/abstracts' ],
data:
'@import "_colors"; ' +
'@import "_variables"; ' +
'@import "_breakpoints"; ' +
'@import "_mixins"; ',
},
],
} ),
},
],
},
],
},
@ -146,7 +144,7 @@ const webpackConfig = {
return outputPath;
},
} ),
new ExtractTextPlugin( {
new MiniCssExtractPlugin( {
filename: './dist/[name]/style.css',
} ),
new CopyWebpackPlugin(