1 <?php
2 3 4 5 6 7 8 9
10
11 if ( ! defined( 'ABSPATH' ) ) exit;
12
13 if ( ! class_exists( 'WC_Admin_Dashboard' ) ) :
14
15 16 17
18 class WC_Admin_Dashboard {
19
20 21 22
23 public function __construct() {
24
25 if ( current_user_can( 'view_woocommerce_reports' ) || current_user_can( 'manage_woocommerce' ) || current_user_can( 'publish_shop_orders' ) ) {
26 add_action( 'wp_dashboard_setup', array( $this, 'init' ) );
27 }
28 }
29
30 31 32
33 public function init() {
34 if ( current_user_can( 'publish_shop_orders' ) ) {
35 wp_add_dashboard_widget( 'woocommerce_dashboard_recent_reviews', __( 'WooCommerce Recent Reviews', 'woocommerce' ), array( $this, 'recent_reviews' ) );
36 }
37
38 wp_add_dashboard_widget( 'woocommerce_dashboard_status', __( 'WooCommerce Status', 'woocommerce' ), array( $this, 'status_widget' ) );
39 }
40
41 42 43
44 public function status_widget() {
45 global $wpdb;
46
47 include_once( 'reports/class-wc-admin-report.php' );
48
49 $reports = new WC_Admin_Report();
50
51
52 $sales = $wpdb->get_var( "SELECT SUM( postmeta.meta_value ) FROM {$wpdb->posts} as posts
53 LEFT JOIN {$wpdb->term_relationships} AS rel ON posts.ID=rel.object_ID
54 LEFT JOIN {$wpdb->term_taxonomy} AS tax USING( term_taxonomy_id )
55 LEFT JOIN {$wpdb->terms} AS term USING( term_id )
56 LEFT JOIN {$wpdb->postmeta} AS postmeta ON posts.ID = postmeta.post_id
57 WHERE posts.post_type = 'shop_order'
58 AND posts.post_status = 'publish'
59 AND tax.taxonomy = 'shop_order_status'
60 AND term.slug IN ( '" . implode( "','", apply_filters( 'woocommerce_reports_order_statuses', array( 'completed', 'processing', 'on-hold' ) ) ) . "' )
61 AND postmeta.meta_key = '_order_total'
62 AND posts.post_date >= '" . date( 'Y-m-01', current_time( 'timestamp' ) ) . "'
63 AND posts.post_date <= '" . date( 'Y-m-d H:i:s', current_time( 'timestamp' ) ) . "'
64 " );
65
66
67 $top_seller = $wpdb->get_row( "SELECT SUM( order_item_meta.meta_value ) as qty, order_item_meta_2.meta_value as product_id
68 FROM {$wpdb->posts} as posts
69 LEFT JOIN {$wpdb->term_relationships} AS rel ON posts.ID=rel.object_ID
70 LEFT JOIN {$wpdb->term_taxonomy} AS tax USING( term_taxonomy_id )
71 LEFT JOIN {$wpdb->terms} AS term USING( term_id )
72 LEFT JOIN {$wpdb->prefix}woocommerce_order_items AS order_items ON posts.ID = order_id
73 LEFT JOIN {$wpdb->prefix}woocommerce_order_itemmeta AS order_item_meta ON order_items.order_item_id = order_item_meta.order_item_id
74 LEFT JOIN {$wpdb->prefix}woocommerce_order_itemmeta AS order_item_meta_2 ON order_items.order_item_id = order_item_meta_2.order_item_id
75 WHERE posts.post_type = 'shop_order'
76 AND posts.post_status = 'publish'
77 AND tax.taxonomy = 'shop_order_status'
78 AND term.slug IN ( '" . implode( "','", apply_filters( 'woocommerce_reports_order_statuses', array( 'completed', 'processing', 'on-hold' ) ) ) . "' )
79 AND order_item_meta.meta_key = '_qty'
80 AND order_item_meta_2.meta_key = '_product_id'
81 AND posts.post_date >= '" . date( 'Y-m-01', current_time( 'timestamp' ) ) . "'
82 AND posts.post_date <= '" . date( 'Y-m-d H:i:s', current_time( 'timestamp' ) ) . "'
83 GROUP BY product_id
84 ORDER BY qty DESC
85 LIMIT 1
86 " );
87
88
89 $on_hold_count = get_term_by( 'slug', 'on-hold', 'shop_order_status' )->count;
90 $processing_count = get_term_by( 'slug', 'processing', 'shop_order_status' )->count;
91
92
93 $stock = absint( max( get_option( 'woocommerce_notify_low_stock_amount' ), 1 ) );
94 $nostock = absint( max( get_option( 'woocommerce_notify_no_stock_amount' ), 0 ) );
95
96 $query_from = "FROM {$wpdb->posts} as posts
97 INNER JOIN {$wpdb->postmeta} AS postmeta ON posts.ID = postmeta.post_id
98 INNER JOIN {$wpdb->postmeta} AS postmeta2 ON posts.ID = postmeta2.post_id
99 WHERE 1=1
100 AND posts.post_type IN ('product', 'product_variation')
101 AND posts.post_status = 'publish'
102 AND (
103 postmeta.meta_key = '_stock' AND CAST(postmeta.meta_value AS SIGNED) <= '{$stock}' AND CAST(postmeta.meta_value AS SIGNED) > '{$nostock}' AND postmeta.meta_value != ''
104 )
105 AND (
106 ( postmeta2.meta_key = '_manage_stock' AND postmeta2.meta_value = 'yes' ) OR ( posts.post_type = 'product_variation' )
107 )
108 ";
109
110 $lowinstock_count = absint( $wpdb->get_var( "SELECT COUNT( DISTINCT posts.ID ) {$query_from};" ) );
111
112 $query_from = "FROM {$wpdb->posts} as posts
113 INNER JOIN {$wpdb->postmeta} AS postmeta ON posts.ID = postmeta.post_id
114 INNER JOIN {$wpdb->postmeta} AS postmeta2 ON posts.ID = postmeta2.post_id
115 WHERE 1=1
116 AND posts.post_type IN ('product', 'product_variation')
117 AND posts.post_status = 'publish'
118 AND (
119 postmeta.meta_key = '_stock' AND CAST(postmeta.meta_value AS SIGNED) <= '{$nostock}' AND postmeta.meta_value != ''
120 )
121 AND (
122 ( postmeta2.meta_key = '_manage_stock' AND postmeta2.meta_value = 'yes' ) OR ( posts.post_type = 'product_variation' )
123 )
124 ";
125
126 $outofstock_count = absint( $wpdb->get_var( "SELECT COUNT( DISTINCT posts.ID ) {$query_from};" ) );
127 ?>
128 <ul class="wc_status_list">
129 <li class="sales-this-month">
130 <a href="<?php echo admin_url( 'admin.php?page=wc-reports&tab=orders&range=month' ); ?>">
131 <?php echo $reports->sales_sparkline( '', max( 7, date( 'd', current_time( 'timestamp' ) ) ) ); ?>
132 <?php printf( __( "<strong>%s</strong> sales this month", 'woocommerce' ), wc_price( $sales ) ); ?>
133 </a>
134 </li>
135 <?php if ( $top_seller && $top_seller->qty ) : ?>
136 <li class="best-seller-this-month">
137 <a href="<?php echo admin_url( 'admin.php?page=wc-reports&tab=orders&report=sales_by_product&range=month&product_ids=' . $top_seller->product_id ); ?>">
138 <?php echo $reports->sales_sparkline( $top_seller->product_id, max( 7, date( 'd', current_time( 'timestamp' ) ) ), 'count' ); ?>
139 <?php printf( __( "%s top seller this month (sold %d)", 'woocommerce' ), "<strong>" . get_the_title( $top_seller->product_id ) . "</strong>", $top_seller->qty ); ?>
140 </a>
141 </li>
142 <?php endif; ?>
143 <li class="processing-orders">
144 <a href="<?php echo admin_url( 'edit.php?s&post_status=all&post_type=shop_order&shop_order_status=processing' ); ?>">
145 <?php printf( _n( "<strong>%s order</strong> awaiting processing", "<strong>%s orders</strong> awaiting processing", $processing_count, 'woocommerce' ), $processing_count ); ?>
146 </a>
147 </li>
148 <li class="on-hold-orders">
149 <a href="<?php echo admin_url( 'edit.php?s&post_status=all&post_type=shop_order&shop_order_status=on-hold' ); ?>">
150 <?php printf( _n( "<strong>%s order</strong> on-hold", "<strong>%s orders</strong> on-hold", $on_hold_count, 'woocommerce' ), $on_hold_count ); ?>
151 </a>
152 </li>
153 <li class="low-in-stock">
154 <a href="<?php echo admin_url( 'admin.php?page=wc-reports&tab=stock&report=low_in_stock' ); ?>">
155 <?php printf( _n( "<strong>%s product</strong> low in stock", "<strong>%s products</strong> low in stock", $lowinstock_count, 'woocommerce' ), $lowinstock_count ); ?>
156 </a>
157 </li>
158 <li class="out-of-stock">
159 <a href="<?php echo admin_url( 'admin.php?page=wc-reports&tab=stock&report=out_of_stock' ); ?>">
160 <?php printf( _n( "<strong>%s product</strong> out of stock", "<strong>%s products</strong> out of stock", $outofstock_count, 'woocommerce' ), $outofstock_count ); ?>
161 </a>
162 </li>
163 </ul>
164 <?php
165 }
166
167 168 169
170 public function recent_reviews() {
171 global $wpdb;
172 $comments = $wpdb->get_results( "SELECT *, SUBSTRING(comment_content,1,100) AS comment_excerpt
173 FROM $wpdb->comments
174 LEFT JOIN $wpdb->posts ON ($wpdb->comments.comment_post_ID = $wpdb->posts.ID)
175 WHERE comment_approved = '1'
176 AND comment_type = ''
177 AND post_password = ''
178 AND post_type = 'product'
179 ORDER BY comment_date_gmt DESC
180 LIMIT 8" );
181
182 if ( $comments ) {
183 echo '<ul>';
184 foreach ( $comments as $comment ) {
185
186 echo '<li>';
187
188 echo get_avatar( $comment->comment_author, '32' );
189
190 $rating = get_comment_meta( $comment->comment_ID, 'rating', true );
191
192 echo '<div class="star-rating" title="' . esc_attr( $rating ) . '">
193 <span style="width:'. ( $rating * 20 ) . '%">' . $rating . ' ' . __( 'out of 5', 'woocommerce' ) . '</span></div>';
194
195 echo '<h4 class="meta"><a href="' . get_permalink( $comment->ID ) . '#comment-' . absint( $comment->comment_ID ) .'">' . esc_html__( $comment->post_title ) . '</a> ' . __( 'reviewed by', 'woocommerce' ) . ' ' . esc_html( $comment->comment_author ) .'</h4>';
196 echo '<blockquote>' . wp_kses_data( $comment->comment_excerpt ) . ' [...]</blockquote></li>';
197
198 }
199 echo '</ul>';
200 } else {
201 echo '<p>' . __( 'There are no product reviews yet.', 'woocommerce' ) . '</p>';
202 }
203 }
204
205 }
206
207 endif;
208
209 return new WC_Admin_Dashboard();
210