2013-07-25 14:00:23 +00:00
< ? php
/**
2015-11-03 13:53:50 +00:00
* Admin Dashboard
2013-07-25 14:00:23 +00:00
*
2020-08-05 16:36:24 +00:00
* @ package WooCommerce\Admin
2013-07-25 14:00:23 +00:00
* @ version 2.1 . 0
*/
2020-01-29 05:21:29 +00:00
use Automattic\Jetpack\Constants ;
2014-09-20 19:52:30 +00:00
if ( ! defined ( 'ABSPATH' ) ) {
2019-01-01 20:14:02 +00:00
exit ; // Exit if accessed directly.
2014-09-20 19:52:30 +00:00
}
2013-07-25 14:00:23 +00:00
2017-02-16 11:46:01 +00:00
if ( ! class_exists ( 'WC_Admin_Dashboard' , false ) ) :
2013-07-25 14:00:23 +00:00
/**
2018-03-05 18:59:17 +00:00
* WC_Admin_Dashboard Class .
2013-07-25 14:00:23 +00:00
*/
2018-03-05 18:59:17 +00:00
class WC_Admin_Dashboard {
/**
* Hook in tabs .
*/
public function __construct () {
2019-01-01 20:14:02 +00:00
// Only hook in admin parts if the user has admin access.
2021-03-03 00:06:10 +00:00
if ( $this -> should_display_widget () ) {
2018-03-05 18:59:17 +00:00
// If on network admin, only load the widget that works in that context and skip the rest.
if ( is_multisite () && is_network_admin () ) {
add_action ( 'wp_network_dashboard_setup' , array ( $this , 'register_network_order_widget' ) );
} else {
add_action ( 'wp_dashboard_setup' , array ( $this , 'init' ) );
}
2017-11-18 00:00:48 +00:00
}
2014-01-11 00:18:28 +00:00
}
2013-07-25 14:00:23 +00:00
2018-03-05 18:59:17 +00:00
/**
* Init dashboard widgets .
*/
public function init () {
2019-06-26 17:09:20 +00:00
// Reviews Widget.
2018-03-05 18:59:17 +00:00
if ( current_user_can ( 'publish_shop_orders' ) && post_type_supports ( 'product' , 'comments' ) ) {
2018-11-14 17:34:15 +00:00
wp_add_dashboard_widget ( 'woocommerce_dashboard_recent_reviews' , __ ( 'WooCommerce Recent Reviews' , 'woocommerce' ), array ( $this , 'recent_reviews' ) );
2018-03-05 18:59:17 +00:00
}
2018-11-14 17:34:15 +00:00
wp_add_dashboard_widget ( 'woocommerce_dashboard_status' , __ ( 'WooCommerce Status' , 'woocommerce' ), array ( $this , 'status_widget' ) );
2017-10-24 19:08:34 +00:00
2018-03-05 18:59:17 +00:00
// Network Order Widget.
2019-01-01 20:15:28 +00:00
if ( is_multisite () && is_main_site () ) {
2018-03-05 18:59:17 +00:00
$this -> register_network_order_widget ();
}
2017-11-06 16:30:44 +00:00
}
2013-07-25 14:00:23 +00:00
2018-03-05 18:59:17 +00:00
/**
* Register the network order dashboard widget .
*/
public function register_network_order_widget () {
2018-11-14 17:34:15 +00:00
wp_add_dashboard_widget ( 'woocommerce_network_orders' , __ ( 'WooCommerce Network Orders' , 'woocommerce' ), array ( $this , 'network_orders' ) );
2018-03-05 18:59:17 +00:00
}
2017-11-18 00:00:48 +00:00
2021-02-18 00:10:55 +00:00
/**
* Check to see if we should display the widget .
*
* @ return bool
*/
private function should_display_widget () {
2021-04-08 07:31:51 +00:00
if ( ! WC () -> is_wc_admin_active () ) {
return false ;
}
2021-03-03 00:06:10 +00:00
$has_permission = current_user_can ( 'view_woocommerce_reports' ) || current_user_can ( 'manage_woocommerce' ) || current_user_can ( 'publish_shop_orders' );
$task_completed_or_hidden = 'yes' === get_option ( 'woocommerce_task_list_complete' ) || 'yes' === get_option ( 'woocommerce_task_list_hidden' );
return $task_completed_or_hidden && $has_permission ;
2021-02-18 00:10:55 +00:00
}
2018-03-05 18:59:17 +00:00
/**
* Get top seller from DB .
*
* @ return object
*/
private function get_top_seller () {
global $wpdb ;
2013-07-25 14:00:23 +00:00
2018-03-05 18:59:17 +00:00
$query = array ();
$query [ 'fields' ] = " SELECT SUM( order_item_meta.meta_value ) as qty, order_item_meta_2.meta_value as product_id
2014-05-28 14:19:16 +00:00
FROM { $wpdb -> posts } as posts " ;
2018-03-05 18:59:17 +00:00
$query [ 'join' ] = " INNER JOIN { $wpdb -> prefix } woocommerce_order_items AS order_items ON posts.ID = order_id " ;
$query [ 'join' ] .= " INNER JOIN { $wpdb -> prefix } woocommerce_order_itemmeta AS order_item_meta ON order_items.order_item_id = order_item_meta.order_item_id " ;
$query [ 'join' ] .= " INNER JOIN { $wpdb -> prefix } woocommerce_order_itemmeta AS order_item_meta_2 ON order_items.order_item_id = order_item_meta_2.order_item_id " ;
$query [ 'where' ] = " WHERE posts.post_type IN ( ' " . implode ( " ',' " , wc_get_order_types ( 'order-count' ) ) . " ' ) " ;
$query [ 'where' ] .= " AND posts.post_status IN ( 'wc- " . implode ( " ','wc- " , apply_filters ( 'woocommerce_reports_order_statuses' , array ( 'completed' , 'processing' , 'on-hold' ) ) ) . " ' ) " ;
$query [ 'where' ] .= " AND order_item_meta.meta_key = '_qty' " ;
$query [ 'where' ] .= " AND order_item_meta_2.meta_key = '_product_id' " ;
2020-10-22 20:34:47 +00:00
$query [ 'where' ] .= " AND posts.post_date >= ' " . gmdate ( 'Y-m-01' , current_time ( 'timestamp' ) ) . " ' " ;
$query [ 'where' ] .= " AND posts.post_date <= ' " . gmdate ( 'Y-m-d H:i:s' , current_time ( 'timestamp' ) ) . " ' " ;
2018-03-05 18:59:17 +00:00
$query [ 'groupby' ] = 'GROUP BY product_id' ;
$query [ 'orderby' ] = 'ORDER BY qty DESC' ;
$query [ 'limits' ] = 'LIMIT 1' ;
2019-02-27 15:33:51 +00:00
return $wpdb -> get_row ( implode ( ' ' , apply_filters ( 'woocommerce_dashboard_status_widget_top_seller_query' , $query ) ) ); //phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
2018-03-05 18:59:17 +00:00
}
2016-10-25 10:43:44 +00:00
2018-03-05 18:59:17 +00:00
/**
* Get sales report data .
*
* @ return object
*/
private function get_sales_report_data () {
include_once dirname ( __FILE__ ) . '/reports/class-wc-report-sales-by-date.php' ;
$sales_by_date = new WC_Report_Sales_By_Date ();
2020-10-22 20:34:47 +00:00
$sales_by_date -> start_date = strtotime ( gmdate ( 'Y-m-01' , current_time ( 'timestamp' ) ) );
$sales_by_date -> end_date = strtotime ( gmdate ( 'Y-m-d' , current_time ( 'timestamp' ) ) );
2018-03-05 18:59:17 +00:00
$sales_by_date -> chart_groupby = 'day' ;
$sales_by_date -> group_by_query = 'YEAR(posts.post_date), MONTH(posts.post_date), DAY(posts.post_date)' ;
return $sales_by_date -> get_report_data ();
}
2016-10-25 10:43:44 +00:00
2018-03-05 18:59:17 +00:00
/**
* Show status widget .
*/
public function status_widget () {
2021-02-11 21:47:26 +00:00
$suffix = Constants :: is_true ( 'SCRIPT_DEBUG' ) ? '' : '.min' ;
$version = Constants :: get_constant ( 'WC_VERSION' );
wp_enqueue_script ( 'wc-status-widget' , WC () -> plugin_url () . '/assets/js/admin/wc-status-widget' . $suffix . '.js' , array ( 'jquery' ), $version , true );
2018-03-05 18:59:17 +00:00
include_once dirname ( __FILE__ ) . '/reports/class-wc-admin-report.php' ;
2016-10-25 10:43:44 +00:00
2021-02-10 19:04:04 +00:00
$is_wc_admin_disabled = apply_filters ( 'woocommerce_admin_disabled' , false );
2018-03-05 18:59:17 +00:00
$reports = new WC_Admin_Report ();
2016-10-25 10:43:44 +00:00
2021-04-08 07:31:51 +00:00
$net_sales_link = 'admin.php?page=wc-reports&tab=orders&range=month' ;
2021-02-18 20:05:00 +00:00
$top_seller_link = 'admin.php?page=wc-reports&tab=orders&report=sales_by_product&range=month&product_ids=' ;
2021-04-08 07:31:51 +00:00
$report_data = $is_wc_admin_disabled ? $this -> get_sales_report_data () : $this -> get_wc_admin_performance_data ();
2021-02-16 16:17:08 +00:00
if ( ! $is_wc_admin_disabled ) {
2021-04-08 07:31:51 +00:00
$net_sales_link = 'admin.php?page=wc-admin&path=%2Fanalytics%2Frevenue&chart=net_revenue&orderby=net_revenue&period=month&compare=previous_period' ;
2021-02-18 20:05:00 +00:00
$top_seller_link = 'admin.php?page=wc-admin&filter=single_product&path=%2Fanalytics%2Fproducts&products=' ;
2021-02-16 16:17:08 +00:00
}
2016-10-25 10:43:44 +00:00
2018-03-05 18:59:17 +00:00
echo '<ul class="wc_status_list">' ;
2016-10-25 10:43:44 +00:00
2019-01-01 20:14:02 +00:00
if ( current_user_can ( 'view_woocommerce_reports' ) ) {
2021-02-18 20:05:00 +00:00
2019-01-01 20:14:02 +00:00
if ( $report_data ) {
?>
2018-03-05 18:59:17 +00:00
< li class = " sales-this-month " >
2021-02-16 16:17:08 +00:00
< a href = " <?php echo esc_url( admin_url( $net_sales_link ) ); ?> " >
2021-02-18 20:05:00 +00:00
< ? php echo $this -> sales_sparkline ( $reports , $is_wc_admin_disabled , '' ); // phpcs:ignore WordPress.XSS.EscapeOutput.OutputNotEscaped ?>
2016-10-29 10:16:03 +00:00
< ? php
printf (
2019-01-01 20:14:02 +00:00
/* translators: %s: net sales */
esc_html__ ( '%s net sales this month' , 'woocommerce' ),
2016-10-29 10:16:03 +00:00
'<strong>' . wc_price ( $report_data -> net_sales ) . '</strong>'
2019-01-01 20:14:02 +00:00
); // phpcs:ignore WordPress.XSS.EscapeOutput.OutputNotEscaped
?>
2018-03-05 18:59:17 +00:00
</ a >
</ li >
2019-01-01 20:14:02 +00:00
< ? php
}
2016-10-25 10:43:44 +00:00
2019-01-01 20:14:02 +00:00
$top_seller = $this -> get_top_seller ();
if ( $top_seller && $top_seller -> qty ) {
?>
2018-03-05 18:59:17 +00:00
< li class = " best-seller-this-month " >
2021-02-18 20:05:00 +00:00
< a href = " <?php echo esc_url( admin_url( $top_seller_link . $top_seller->product_id ) ); ?> " >
< ? php echo $this -> sales_sparkline ( $reports , $is_wc_admin_disabled , $top_seller -> product_id , 'count' ); // phpcs:ignore WordPress.XSS.EscapeOutput.OutputNotEscaped ?>
2016-10-29 10:16:03 +00:00
< ? php
printf (
2019-01-01 20:14:02 +00:00
/* translators: 1: top seller product title 2: top seller quantity */
esc_html__ ( '%1$s top seller this month (sold %2$d)' , 'woocommerce' ),
2016-10-29 10:16:03 +00:00
'<strong>' . get_the_title ( $top_seller -> product_id ) . '</strong>' ,
$top_seller -> qty
2019-01-01 20:14:02 +00:00
); // phpcs:ignore WordPress.XSS.EscapeOutput.OutputNotEscaped
?>
2018-03-05 18:59:17 +00:00
</ a >
</ li >
2019-01-01 20:14:02 +00:00
< ? php
}
2018-03-05 18:59:17 +00:00
}
2016-10-25 10:43:44 +00:00
2018-03-05 18:59:17 +00:00
$this -> status_widget_order_rows ();
2021-02-10 19:04:04 +00:00
$this -> status_widget_stock_rows ( $is_wc_admin_disabled );
2016-10-25 10:43:44 +00:00
2018-03-05 18:59:17 +00:00
do_action ( 'woocommerce_after_dashboard_status_widget' , $reports );
echo '</ul>' ;
2016-10-25 10:43:44 +00:00
}
2014-07-11 11:43:42 +00:00
2018-03-05 18:59:17 +00:00
/**
* Show order data is status widget .
*/
private function status_widget_order_rows () {
if ( ! current_user_can ( 'edit_shop_orders' ) ) {
return ;
}
$on_hold_count = 0 ;
$processing_count = 0 ;
foreach ( wc_get_order_types ( 'order-count' ) as $type ) {
$counts = ( array ) wp_count_posts ( $type );
$on_hold_count += isset ( $counts [ 'wc-on-hold' ] ) ? $counts [ 'wc-on-hold' ] : 0 ;
$processing_count += isset ( $counts [ 'wc-processing' ] ) ? $counts [ 'wc-processing' ] : 0 ;
}
?>
< li class = " processing-orders " >
2019-01-01 20:14:02 +00:00
< a href = " <?php echo esc_url( admin_url( 'edit.php?post_status=wc-processing&post_type=shop_order' ) ); ?> " >
2016-10-29 10:16:03 +00:00
< ? php
printf (
2019-01-01 20:14:02 +00:00
/* translators: %s: order count */
2016-10-29 10:16:03 +00:00
_n ( '<strong>%s order</strong> awaiting processing' , '<strong>%s orders</strong> awaiting processing' , $processing_count , 'woocommerce' ),
$processing_count
2019-01-01 20:14:02 +00:00
); // phpcs:ignore WordPress.XSS.EscapeOutput.OutputNotEscaped
2016-10-29 10:16:03 +00:00
?>
2018-03-05 18:59:17 +00:00
</ a >
</ li >
< li class = " on-hold-orders " >
2019-01-01 20:14:02 +00:00
< a href = " <?php echo esc_url( admin_url( 'edit.php?post_status=wc-on-hold&post_type=shop_order' ) ); ?> " >
2016-10-29 10:16:03 +00:00
< ? php
printf (
2019-01-01 20:14:02 +00:00
/* translators: %s: order count */
2016-10-29 10:16:03 +00:00
_n ( '<strong>%s order</strong> on-hold' , '<strong>%s orders</strong> on-hold' , $on_hold_count , 'woocommerce' ),
$on_hold_count
2019-01-01 20:14:02 +00:00
); // phpcs:ignore WordPress.XSS.EscapeOutput.OutputNotEscaped
2016-10-29 10:16:03 +00:00
?>
2018-03-05 18:59:17 +00:00
</ a >
</ li >
< ? php
2015-03-09 11:07:49 +00:00
}
2018-03-05 18:59:17 +00:00
/**
* Show stock data is status widget .
2021-02-10 19:04:04 +00:00
*
* @ param bool $is_wc_admin_disabled if woocommerce admin is disabled .
2018-03-05 18:59:17 +00:00
*/
2021-02-10 19:04:04 +00:00
private function status_widget_stock_rows ( $is_wc_admin_disabled ) {
2018-03-05 18:59:17 +00:00
global $wpdb ;
2019-02-28 14:24:05 +00:00
// Requires lookup table added in 3.6.
if ( version_compare ( get_option ( 'woocommerce_db_version' , null ), '3.6' , '<' ) ) {
return ;
}
2019-02-15 13:37:51 +00:00
$stock = absint ( max ( get_option ( 'woocommerce_notify_low_stock_amount' ), 1 ) );
$nostock = absint ( max ( get_option ( 'woocommerce_notify_no_stock_amount' ), 0 ) );
2018-03-05 18:59:17 +00:00
2019-02-15 13:37:51 +00:00
$transient_name = 'wc_low_stock_count' ;
2019-01-01 20:14:02 +00:00
$lowinstock_count = get_transient ( $transient_name );
2019-02-15 13:37:51 +00:00
2019-01-01 20:14:02 +00:00
if ( false === $lowinstock_count ) {
2019-12-26 10:02:47 +00:00
/**
* Status widget low in stock count pre query .
*
2020-06-02 15:16:54 +00:00
* @ since 4.3 . 0
2019-12-26 10:02:47 +00:00
* @ param null | string $low_in_stock_count Low in stock count , by default null .
* @ param int $stock Low stock amount .
* @ param int $nostock No stock amount
*/
$lowinstock_count = apply_filters ( 'woocommerce_status_widget_low_in_stock_count_pre_query' , null , $stock , $nostock );
2020-06-02 12:05:44 +00:00
if ( is_null ( $lowinstock_count ) ) {
2019-12-26 10:02:47 +00:00
$lowinstock_count = $wpdb -> get_var (
$wpdb -> prepare (
" SELECT COUNT( product_id )
FROM { $wpdb -> wc_product_meta_lookup } AS lookup
INNER JOIN { $wpdb -> posts } as posts ON lookup . product_id = posts . ID
WHERE stock_quantity <= % d
AND stock_quantity > % d
AND posts . post_status = 'publish' " ,
$stock ,
$nostock
)
);
}
set_transient ( $transient_name , ( int ) $lowinstock_count , DAY_IN_SECONDS * 30 );
2018-03-05 18:59:17 +00:00
}
2019-02-15 13:37:51 +00:00
$transient_name = 'wc_outofstock_count' ;
2019-01-01 20:14:02 +00:00
$outofstock_count = get_transient ( $transient_name );
2021-02-10 19:04:04 +00:00
$lowstock_link = 'admin.php?page=wc-reports&tab=stock&report=low_in_stock' ;
$outofstock_link = 'admin.php?page=wc-reports&tab=stock&report=out_of_stock' ;
if ( false === $is_wc_admin_disabled ) {
2021-02-10 20:42:04 +00:00
$lowstock_link = 'admin.php?page=wc-admin&type=lowstock&path=%2Fanalytics%2Fstock' ;
$outofstock_link = 'admin.php?page=wc-admin&type=outofstock&path=%2Fanalytics%2Fstock' ;
2021-02-10 19:04:04 +00:00
}
2019-02-15 13:37:51 +00:00
2019-01-01 20:14:02 +00:00
if ( false === $outofstock_count ) {
2019-12-26 10:02:47 +00:00
/**
* Status widget out of stock count pre query .
*
2020-06-02 15:16:54 +00:00
* @ since 4.3 . 0
2019-12-26 10:02:47 +00:00
* @ param null | string $outofstock_count Out of stock count , by default null .
2020-06-02 15:17:59 +00:00
* @ param int $nostock No stock amount
2019-12-26 10:02:47 +00:00
*/
$outofstock_count = apply_filters ( 'woocommerce_status_widget_out_of_stock_count_pre_query' , null , $nostock );
2020-06-02 12:05:44 +00:00
if ( is_null ( $outofstock_count ) ) {
2019-12-26 10:02:47 +00:00
$outofstock_count = ( int ) $wpdb -> get_var (
$wpdb -> prepare (
" SELECT COUNT( product_id )
FROM { $wpdb -> wc_product_meta_lookup } AS lookup
INNER JOIN { $wpdb -> posts } as posts ON lookup . product_id = posts . ID
WHERE stock_quantity <= % d
AND posts . post_status = 'publish' " ,
$nostock
)
);
}
set_transient ( $transient_name , ( int ) $outofstock_count , DAY_IN_SECONDS * 30 );
2018-03-05 18:59:17 +00:00
}
?>
< li class = " low-in-stock " >
2021-02-10 19:04:04 +00:00
< a href = " <?php echo esc_url( admin_url( $lowstock_link ) ); ?> " >
2016-10-29 10:16:03 +00:00
< ? php
printf (
2019-01-01 20:14:02 +00:00
/* translators: %s: order count */
2016-10-29 10:16:03 +00:00
_n ( '<strong>%s product</strong> low in stock' , '<strong>%s products</strong> low in stock' , $lowinstock_count , 'woocommerce' ),
$lowinstock_count
2019-01-01 20:14:02 +00:00
); // phpcs:ignore WordPress.XSS.EscapeOutput.OutputNotEscaped
2016-10-29 10:16:03 +00:00
?>
2018-03-05 18:59:17 +00:00
</ a >
</ li >
< li class = " out-of-stock " >
2021-02-10 19:04:04 +00:00
< a href = " <?php echo esc_url( admin_url( $outofstock_link ) ); ?> " >
2016-10-29 10:16:03 +00:00
< ? php
printf (
2019-01-01 20:14:02 +00:00
/* translators: %s: order count */
2016-10-29 10:16:03 +00:00
_n ( '<strong>%s product</strong> out of stock' , '<strong>%s products</strong> out of stock' , $outofstock_count , 'woocommerce' ),
$outofstock_count
2019-01-01 20:14:02 +00:00
); // phpcs:ignore WordPress.XSS.EscapeOutput.OutputNotEscaped
2016-10-29 10:16:03 +00:00
?>
2018-03-05 18:59:17 +00:00
</ a >
</ li >
< ? php
}
2013-07-25 14:00:23 +00:00
2018-03-05 18:59:17 +00:00
/**
* Recent reviews widget .
*/
public function recent_reviews () {
global $wpdb ;
2017-06-08 11:21:55 +00:00
2018-03-05 18:59:17 +00:00
$query_from = apply_filters (
'woocommerce_report_recent_reviews_query_from' ,
" FROM { $wpdb -> comments } comments
LEFT JOIN { $wpdb -> posts } posts ON ( comments . comment_post_ID = posts . ID )
WHERE comments . comment_approved = '1'
2018-10-26 11:16:16 +00:00
AND comments . comment_type = 'review'
2018-03-05 18:59:17 +00:00
AND posts . post_password = ''
AND posts . post_type = 'product'
AND comments . comment_parent = 0
ORDER BY comments . comment_date_gmt DESC
LIMIT 5 "
);
2017-06-08 11:21:55 +00:00
2018-03-05 18:59:17 +00:00
$comments = $wpdb -> get_results (
2020-10-22 20:36:17 +00:00
" SELECT posts.ID, posts.post_title, comments.comment_author, comments.comment_author_email, comments.comment_ID, comments.comment_content { $query_from } ; " // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
2018-03-05 18:59:17 +00:00
);
2013-07-25 14:00:23 +00:00
2018-03-05 18:59:17 +00:00
if ( $comments ) {
echo '<ul>' ;
foreach ( $comments as $comment ) {
2013-07-25 14:00:23 +00:00
2018-03-05 18:59:17 +00:00
echo '<li>' ;
2013-07-25 14:00:23 +00:00
2020-10-22 20:36:17 +00:00
echo get_avatar ( $comment -> comment_author_email , '32' );
2013-07-25 14:00:23 +00:00
2018-03-05 18:59:17 +00:00
$rating = intval ( get_comment_meta ( $comment -> comment_ID , 'rating' , true ) );
2013-07-25 14:00:23 +00:00
2018-03-05 18:59:17 +00:00
/* translators: %s: rating */
2019-09-11 09:32:10 +00:00
echo '<div class="star-rating"><span style="width:' . esc_attr ( $rating * 20 ) . '%">' . sprintf ( esc_html__ ( '%s out of 5' , 'woocommerce' ), esc_html ( $rating ) ) . '</span></div>' ;
2013-07-25 14:00:23 +00:00
2018-03-05 18:59:17 +00:00
/* translators: %s: review author */
2019-09-11 09:32:10 +00:00
echo '<h4 class="meta"><a href="' . esc_url ( get_permalink ( $comment -> ID ) ) . '#comment-' . esc_attr ( absint ( $comment -> comment_ID ) ) . '">' . esc_html ( apply_filters ( 'woocommerce_admin_dashboard_recent_reviews' , $comment -> post_title , $comment ) ) . '</a> ' . sprintf ( esc_html__ ( 'reviewed by %s' , 'woocommerce' ), esc_html ( $comment -> comment_author ) ) . '</h4>' ;
2018-03-05 18:59:17 +00:00
echo '<blockquote>' . wp_kses_data ( $comment -> comment_content ) . '</blockquote></li>' ;
2013-07-25 14:00:23 +00:00
2018-03-05 18:59:17 +00:00
}
echo '</ul>' ;
} else {
2019-01-01 20:14:02 +00:00
echo '<p>' . esc_html__ ( 'There are no product reviews yet.' , 'woocommerce' ) . '</p>' ;
2013-07-25 14:00:23 +00:00
}
}
2017-10-24 19:08:34 +00:00
2018-03-05 18:59:17 +00:00
/**
* Network orders widget .
*/
public function network_orders () {
2020-02-04 22:02:57 +00:00
$suffix = Constants :: is_true ( 'SCRIPT_DEBUG' ) ? '' : '.min' ;
$version = Constants :: get_constant ( 'WC_VERSION' );
2017-11-06 17:08:07 +00:00
2020-02-04 22:02:57 +00:00
wp_enqueue_style ( 'wc-network-orders' , WC () -> plugin_url () . '/assets/css/network-order-widget.css' , array (), $version );
2017-11-17 23:44:17 +00:00
2020-02-04 22:02:57 +00:00
wp_enqueue_script ( 'wc-network-orders' , WC () -> plugin_url () . '/assets/js/admin/network-orders' . $suffix . '.js' , array ( 'jquery' , 'underscore' ), $version , true );
2017-10-25 03:45:34 +00:00
2018-03-05 18:59:17 +00:00
$user = wp_get_current_user ();
$blogs = get_blogs_of_user ( $user -> ID );
$blog_ids = wp_list_pluck ( $blogs , 'userblog_id' );
2017-10-25 03:45:34 +00:00
2018-03-05 18:59:17 +00:00
wp_localize_script (
2019-01-01 20:14:02 +00:00
'wc-network-orders' ,
'woocommerce_network_orders' ,
array (
2018-03-05 18:59:17 +00:00
'nonce' => wp_create_nonce ( 'wp_rest' ),
'sites' => array_values ( $blog_ids ),
2019-01-14 07:15:20 +00:00
'order_endpoint' => get_rest_url ( null , 'wc/v3/orders/network' ),
2018-03-05 18:59:17 +00:00
)
);
?>
< div class = " post-type-shop_order " >
2017-11-06 17:44:55 +00:00
< div id = " woocommerce-network-order-table-loading " class = " woocommerce-network-order-table-loading is-active " >
2017-11-06 17:30:32 +00:00
< p >
2019-09-26 04:42:34 +00:00
< span class = " spinner is-active " ></ span > < ? php esc_html_e ( 'Loading network orders' , 'woocommerce' ); ?>
2017-11-06 17:30:32 +00:00
</ p >
</ div >
2017-11-18 00:06:24 +00:00
< table id = " woocommerce-network-order-table " class = " woocommerce-network-order-table " >
2017-10-24 19:08:34 +00:00
< thead >
< tr >
2017-11-15 02:05:44 +00:00
< td >< ? php esc_html_e ( 'Order' , 'woocommerce' ); ?> </td>
< td >< ? php esc_html_e ( 'Status' , 'woocommerce' ); ?> </td>
< td >< ? php esc_html_e ( 'Total' , 'woocommerce' ); ?> </td>
2017-10-24 19:08:34 +00:00
</ tr >
</ thead >
< tbody id = " network-orders-tbody " >
</ tbody >
</ table >
2017-11-06 17:44:55 +00:00
< div id = " woocommerce-network-orders-no-orders " class = " woocommerce-network-orders-no-orders " >
< p >
2017-11-15 01:59:20 +00:00
< ? php esc_html_e ( 'No orders found' , 'woocommerce' ); ?>
2017-11-06 17:44:55 +00:00
</ p >
</ div >
2019-01-01 20:14:02 +00:00
< ? php // @codingStandardsIgnoreStart ?>
2017-10-24 19:08:34 +00:00
< script type = " text/template " id = " network-orders-row-template " >
< tr >
< td >
2018-06-08 15:59:27 +00:00
< a href = " <%- edit_url %> " class = " order-view " >< strong > #<%- number %> <%- customer %></strong></a>
2017-10-24 19:08:34 +00:00
< br >
< em >
<%- blog . blogname %>
</ em >
</ td >
< td >
< mark class = " order-status status-<%- status %> " >< span ><%- status_name %></ span ></ mark >
</ td >
< td >
<%= formatted_total %>
</ td >
</ tr >
</ script >
2019-01-01 20:14:02 +00:00
< ? php // @codingStandardsIgnoreEnd ?>
2017-10-24 19:08:34 +00:00
</ div >
2019-01-01 20:14:02 +00:00
< ? php
2018-03-05 18:59:17 +00:00
}
2021-02-18 20:05:00 +00:00
/**
* Gets the sales performance data from the new WooAdmin store .
*
* @ return stdClass | WP_Error | WP_REST_Response
*/
private function get_wc_admin_performance_data () {
$request = new \WP_REST_Request ( 'GET' , '/wc-analytics/reports/performance-indicators' );
$start_date = gmdate ( 'Y-m-01 00:00:00' , current_time ( 'timestamp' ) );
$end_date = gmdate ( 'Y-m-d 23:59:59' , current_time ( 'timestamp' ) );
$request -> set_query_params (
array (
'before' => $end_date ,
'after' => $start_date ,
'stats' => 'revenue/total_sales,revenue/net_revenue,orders/orders_count,products/items_sold,variations/items_sold' ,
)
);
$response = rest_do_request ( $request );
if ( is_wp_error ( $response ) ) {
return $response ;
}
if ( 200 !== $response -> get_status () ) {
return new \WP_Error ( 'woocommerce_analytics_performance_indicators_result_failed' , __ ( 'Sorry, fetching performance indicators failed.' , 'woocommerce' ) );
}
$report_keys = array (
'net_revenue' => 'net_sales' ,
);
$performance_data = new stdClass ();
foreach ( $response -> get_data () as $indicator ) {
if ( isset ( $indicator [ 'chart' ] ) && isset ( $indicator [ 'value' ] ) ) {
$key = isset ( $report_keys [ $indicator [ 'chart' ] ] ) ? $report_keys [ $indicator [ 'chart' ] ] : $indicator [ 'chart' ];
$performance_data -> $key = $indicator [ 'value' ];
}
}
return $performance_data ;
}
/**
* Overwrites the original sparkline to use the new reports data if WooAdmin is enabled .
* Prepares a sparkline to show sales in the last X days .
*
* @ param WC_Admin_Report $reports old class for getting reports .
* @ param bool $is_wc_admin_disabled If WC Admin is disabled or not .
* @ param int $id ID of the product to show . Blank to get all orders .
* @ param string $type Type of sparkline to get . Ignored if ID is not set .
* @ return string
*/
private function sales_sparkline ( $reports , $is_wc_admin_disabled = false , $id = '' , $type = 'sales' ) {
$days = max ( 7 , gmdate ( 'd' , current_time ( 'timestamp' ) ) );
if ( $is_wc_admin_disabled ) {
return $reports -> sales_sparkline ( $id , $days , $type );
}
$sales_endpoint = '/wc-analytics/reports/revenue/stats' ;
$start_date = gmdate ( 'Y-m-d 00:00:00' , current_time ( 'timestamp' ) - ( ( $days - 1 ) * DAY_IN_SECONDS ) );
$end_date = gmdate ( 'Y-m-d 23:59:59' , current_time ( 'timestamp' ) );
$meta_key = 'net_revenue' ;
$params = array (
'order' => 'asc' ,
'interval' => 'day' ,
'per_page' => 100 ,
'before' => $end_date ,
'after' => $start_date ,
);
if ( $id ) {
$sales_endpoint = '/wc-analytics/reports/products/stats' ;
$meta_key = ( 'sales' === $type ) ? 'net_revenue' : 'items_sold' ;
$params [ 'products' ] = $id ;
}
$request = new \WP_REST_Request ( 'GET' , $sales_endpoint );
$params [ 'fields' ] = array ( $meta_key );
$request -> set_query_params ( $params );
$response = rest_do_request ( $request );
if ( is_wp_error ( $response ) ) {
return $response ;
}
$resp_data = $response -> get_data ();
$data = $resp_data [ 'intervals' ];
$sparkline_data = array ();
$total = 0 ;
foreach ( $data as $d ) {
$total += $d [ 'subtotals' ] -> $meta_key ;
array_push ( $sparkline_data , array ( strval ( strtotime ( $d [ 'interval' ] ) * 1000 ), $d [ 'subtotals' ] -> $meta_key ) );
}
if ( 'sales' === $type ) {
/* translators: 1: total income 2: days */
$tooltip = sprintf ( __ ( 'Sold %1$s worth in the last %2$d days' , 'woocommerce' ), strip_tags ( wc_price ( $total ) ), $days );
} else {
/* translators: 1: total items sold 2: days */
$tooltip = sprintf ( _n ( 'Sold %1$d item in the last %2$d days' , 'Sold %1$d items in the last %2$d days' , $total , 'woocommerce' ), $total , $days );
}
return '<span class="wc_sparkline ' . ( ( 'sales' === $type ) ? 'lines' : 'bars' ) . ' tips" data-color="#777" data-tip="' . esc_attr ( $tooltip ) . '" data-barwidth="' . 60 * 60 * 16 * 1000 . '" data-sparkline="' . wc_esc_json ( wp_json_encode ( $sparkline_data ) ) . '"></span>' ;
}
2018-03-05 18:59:17 +00:00
}
2013-07-25 14:00:23 +00:00
endif ;
2014-01-11 00:14:27 +00:00
return new WC_Admin_Dashboard ();