1 <?php
  2 /**
  3  * Admin Dashboard
  4  *
  5  * @author      WooThemes
  6  * @category    Admin
  7  * @package     WooCommerce/Admin
  8  * @version     2.1.0
  9  */
 10 
 11 if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
 12 
 13 if ( ! class_exists( 'WC_Admin_Dashboard' ) ) :
 14 
 15 /**
 16  * WC_Admin_Dashboard Class
 17  */
 18 class WC_Admin_Dashboard {
 19 
 20     /**
 21      * Hook in tabs.
 22      */
 23     public function __construct() {
 24         // Only hook in admin parts if the user has admin access
 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      * Init dashboard widgets
 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      * Show status widget
 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         // Get sales
 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         // Get top seller
 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         // Counts
 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         // Get products using a query - this is too advanced for get_posts :(
 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      * Recent reviews widget
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 
WooCommerce API documentation generated by ApiGen 2.8.0