WC_Admin_Report

Admin Report.

Defined (1)

The class is defined in the following location(s).

/includes/admin/reports/class-wc-admin-report.php  
  1. class WC_Admin_Report { 
  2.  
  3. /** 
  4. * The chart interval. 
  5. * @var int 
  6. */ 
  7. public $chart_interval; 
  8.  
  9. /** 
  10. * Group by SQL query. 
  11. * @var string 
  12. */ 
  13. public $group_by_query; 
  14.  
  15. /** 
  16. * The bar width. 
  17. * @var int 
  18. */ 
  19. public $barwidth; 
  20.  
  21. /** 
  22. * Group chart item by day or month. 
  23. * @var string 
  24. */ 
  25. public $chart_groupby; 
  26.  
  27. /** 
  28. * The start date of the report. 
  29. * @var int timestamp 
  30. */ 
  31. public $start_date; 
  32.  
  33. /** 
  34. * The end date of the report. 
  35. * @var int timestamp 
  36. */ 
  37. public $end_date; 
  38.  
  39. /** 
  40. * Get report totals such as order totals and discount amounts. 
  41. * Data example: 
  42. * '_order_total' => array( 
  43. * 'type' => 'meta',  
  44. * 'function' => 'SUM',  
  45. * 'name' => 'total_sales' 
  46. * ) 
  47. * @param array $args 
  48. * @return mixed depending on query_type 
  49. */ 
  50. public function get_order_report_data( $args = array() ) { 
  51. global $wpdb; 
  52.  
  53. $default_args = array( 
  54. 'data' => array(),  
  55. 'where' => array(),  
  56. 'where_meta' => array(),  
  57. 'query_type' => 'get_row',  
  58. 'group_by' => '',  
  59. 'order_by' => '',  
  60. 'limit' => '',  
  61. 'filter_range' => false,  
  62. 'nocache' => false,  
  63. 'debug' => false,  
  64. 'order_types' => wc_get_order_types( 'reports' ),  
  65. 'order_status' => array( 'completed', 'processing', 'on-hold' ),  
  66. 'parent_order_status' => false,  
  67. ); 
  68. $args = apply_filters( 'woocommerce_reports_get_order_report_data_args', $args ); 
  69. $args = wp_parse_args( $args, $default_args ); 
  70.  
  71. extract( $args ); 
  72.  
  73. if ( empty( $data ) ) { 
  74. return ''; 
  75.  
  76. $order_status = apply_filters( 'woocommerce_reports_order_statuses', $order_status ); 
  77.  
  78. $query = array(); 
  79. $select = array(); 
  80.  
  81. foreach ( $data as $key => $value ) { 
  82. $distinct = ''; 
  83.  
  84. if ( isset( $value['distinct'] ) ) { 
  85. $distinct = 'DISTINCT'; 
  86.  
  87. switch ( $value['type'] ) { 
  88. case 'meta' : 
  89. $get_key = "meta_{$key}.meta_value"; 
  90. break; 
  91. case 'parent_meta' : 
  92. $get_key = "parent_meta_{$key}.meta_value"; 
  93. break; 
  94. case 'post_data' : 
  95. $get_key = "posts.{$key}"; 
  96. break; 
  97. case 'order_item_meta' : 
  98. $get_key = "order_item_meta_{$key}.meta_value"; 
  99. break; 
  100. case 'order_item' : 
  101. $get_key = "order_items.{$key}"; 
  102. break; 
  103. default : 
  104. continue; 
  105.  
  106. if ( $value['function'] ) { 
  107. $get = "{$value['function']}({$distinct} {$get_key})"; 
  108. } else { 
  109. $get = "{$distinct} {$get_key}"; 
  110.  
  111. $select[] = "{$get} as {$value['name']}"; 
  112.  
  113. $query['select'] = "SELECT " . implode( ', ', $select ); 
  114. $query['from'] = "FROM {$wpdb->posts} AS posts"; 
  115.  
  116. // Joins 
  117. $joins = array(); 
  118.  
  119. foreach ( ( $data + $where ) as $key => $value ) { 
  120. $join_type = isset( $value['join_type'] ) ? $value['join_type'] : 'INNER'; 
  121. $type = isset( $value['type'] ) ? $value['type'] : false; 
  122.  
  123. switch ( $type ) { 
  124. case 'meta' : 
  125. $joins[ "meta_{$key}" ] = "{$join_type} JOIN {$wpdb->postmeta} AS meta_{$key} ON ( posts.ID = meta_{$key}.post_id AND meta_{$key}.meta_key = '{$key}' )"; 
  126. break; 
  127. case 'parent_meta' : 
  128. $joins[ "parent_meta_{$key}" ] = "{$join_type} JOIN {$wpdb->postmeta} AS parent_meta_{$key} ON (posts.post_parent = parent_meta_{$key}.post_id) AND (parent_meta_{$key}.meta_key = '{$key}')"; 
  129. break; 
  130. case 'order_item_meta' : 
  131. $joins["order_items"] = "{$join_type} JOIN {$wpdb->prefix}woocommerce_order_items AS order_items ON (posts.ID = order_items.order_id)"; 
  132.  
  133. if ( ! empty( $value['order_item_type'] ) ) { 
  134. $joins["order_items"] .= " AND (order_items.order_item_type = '{$value['order_item_type']}')"; 
  135.  
  136. $joins[ "order_item_meta_{$key}" ] = "{$join_type} JOIN {$wpdb->prefix}woocommerce_order_itemmeta AS order_item_meta_{$key} ON " . 
  137. "(order_items.order_item_id = order_item_meta_{$key}.order_item_id) " . 
  138. " AND (order_item_meta_{$key}.meta_key = '{$key}')"; 
  139. break; 
  140. case 'order_item' : 
  141. $joins["order_items"] = "{$join_type} JOIN {$wpdb->prefix}woocommerce_order_items AS order_items ON posts.ID = order_items.order_id"; 
  142. break; 
  143.  
  144. if ( ! empty( $where_meta ) ) { 
  145. foreach ( $where_meta as $value ) { 
  146. if ( ! is_array( $value ) ) { 
  147. continue; 
  148. $join_type = isset( $value['join_type'] ) ? $value['join_type'] : 'INNER'; 
  149. $type = isset( $value['type'] ) ? $value['type'] : false; 
  150. $key = is_array( $value['meta_key'] ) ? $value['meta_key'][0] . '_array' : $value['meta_key']; 
  151.  
  152. if ( 'order_item_meta' === $type ) { 
  153.  
  154. $joins["order_items"] = "{$join_type} JOIN {$wpdb->prefix}woocommerce_order_items AS order_items ON posts.ID = order_items.order_id"; 
  155. $joins[ "order_item_meta_{$key}" ] = "{$join_type} JOIN {$wpdb->prefix}woocommerce_order_itemmeta AS order_item_meta_{$key} ON order_items.order_item_id = order_item_meta_{$key}.order_item_id"; 
  156.  
  157. } else { 
  158. // If we have a where clause for meta, join the postmeta table 
  159. $joins[ "meta_{$key}" ] = "{$join_type} JOIN {$wpdb->postmeta} AS meta_{$key} ON posts.ID = meta_{$key}.post_id"; 
  160.  
  161. if ( ! empty( $parent_order_status ) ) { 
  162. $joins["parent"] = "LEFT JOIN {$wpdb->posts} AS parent ON posts.post_parent = parent.ID"; 
  163.  
  164. $query['join'] = implode( ' ', $joins ); 
  165.  
  166. $query['where'] = " 
  167. WHERE posts.post_type IN ( '" . implode( "', '", $order_types ) . "' ) 
  168. "; 
  169.  
  170. if ( ! empty( $order_status ) ) { 
  171. $query['where'] .= " 
  172. AND posts.post_status IN ( 'wc-" . implode( "', 'wc-", $order_status ) . "') 
  173. "; 
  174.  
  175. if ( ! empty( $parent_order_status ) ) { 
  176. if ( ! empty( $order_status ) ) { 
  177. $query['where'] .= " AND ( parent.post_status IN ( 'wc-" . implode( "', 'wc-", $parent_order_status ) . "') OR parent.ID IS NULL ) "; 
  178. } else { 
  179. $query['where'] .= " AND parent.post_status IN ( 'wc-" . implode( "', 'wc-", $parent_order_status ) . "') "; 
  180.  
  181. if ( $filter_range ) { 
  182. $query['where'] .= " 
  183. AND posts.post_date >= '" . date( 'Y-m-d H:i:s', $this->start_date ) . "' 
  184. AND posts.post_date < '" . date( 'Y-m-d H:i:s', strtotime( '+1 DAY', $this->end_date ) ) . "' 
  185. "; 
  186.  
  187. if ( ! empty( $where_meta ) ) { 
  188.  
  189. $relation = isset( $where_meta['relation'] ) ? $where_meta['relation'] : 'AND'; 
  190.  
  191. $query['where'] .= " AND ("; 
  192.  
  193. foreach ( $where_meta as $index => $value ) { 
  194.  
  195. if ( ! is_array( $value ) ) { 
  196. continue; 
  197.  
  198. $key = is_array( $value['meta_key'] ) ? $value['meta_key'][0] . '_array' : $value['meta_key']; 
  199.  
  200. if ( strtolower( $value['operator'] ) == 'in' || strtolower( $value['operator'] ) == 'not in' ) { 
  201.  
  202. if ( is_array( $value['meta_value'] ) ) { 
  203. $value['meta_value'] = implode( "', '", $value['meta_value'] ); 
  204.  
  205. if ( ! empty( $value['meta_value'] ) ) { 
  206. $where_value = "{$value['operator']} ('{$value['meta_value']}')"; 
  207. } else { 
  208. $where_value = "{$value['operator']} '{$value['meta_value']}'"; 
  209.  
  210. if ( ! empty( $where_value ) ) { 
  211. if ( $index > 0 ) { 
  212. $query['where'] .= ' ' . $relation; 
  213.  
  214. if ( isset( $value['type'] ) && 'order_item_meta' === $value['type'] ) { 
  215.  
  216. if ( is_array( $value['meta_key'] ) ) { 
  217. $query['where'] .= " ( order_item_meta_{$key}.meta_key IN ('" . implode( "', '", $value['meta_key'] ) . "')"; 
  218. } else { 
  219. $query['where'] .= " ( order_item_meta_{$key}.meta_key = '{$value['meta_key']}'"; 
  220.  
  221. $query['where'] .= " AND order_item_meta_{$key}.meta_value {$where_value} )"; 
  222. } else { 
  223.  
  224. if ( is_array( $value['meta_key'] ) ) { 
  225. $query['where'] .= " ( meta_{$key}.meta_key IN ('" . implode( "', '", $value['meta_key'] ) . "')"; 
  226. } else { 
  227. $query['where'] .= " ( meta_{$key}.meta_key = '{$value['meta_key']}'"; 
  228.  
  229. $query['where'] .= " AND meta_{$key}.meta_value {$where_value} )"; 
  230.  
  231. $query['where'] .= ")"; 
  232.  
  233. if ( ! empty( $where ) ) { 
  234.  
  235. foreach ( $where as $value ) { 
  236.  
  237. if ( strtolower( $value['operator'] ) == 'in' || strtolower( $value['operator'] ) == 'not in' ) { 
  238.  
  239. if ( is_array( $value['value'] ) ) { 
  240. $value['value'] = implode( "', '", $value['value'] ); 
  241.  
  242. if ( ! empty( $value['value'] ) ) { 
  243. $where_value = "{$value['operator']} ('{$value['value']}')"; 
  244. } else { 
  245. $where_value = "{$value['operator']} '{$value['value']}'"; 
  246.  
  247. if ( ! empty( $where_value ) ) 
  248. $query['where'] .= " AND {$value['key']} {$where_value}"; 
  249.  
  250. if ( $group_by ) { 
  251. $query['group_by'] = "GROUP BY {$group_by}"; 
  252.  
  253. if ( $order_by ) { 
  254. $query['order_by'] = "ORDER BY {$order_by}"; 
  255.  
  256. if ( $limit ) { 
  257. $query['limit'] = "LIMIT {$limit}"; 
  258.  
  259. $query = apply_filters( 'woocommerce_reports_get_order_report_query', $query ); 
  260. $query = implode( ' ', $query ); 
  261. $query_hash = md5( $query_type . $query ); 
  262. $cached_results = get_transient( strtolower( get_class( $this ) ) ); 
  263.  
  264. if ( $debug ) { 
  265. echo '<pre>'; 
  266. wc_print_r( $query ); 
  267. echo '</pre>'; 
  268.  
  269. if ( $debug || $nocache || false === $cached_results || ! isset( $cached_results[ $query_hash ] ) ) { 
  270. // Enable big selects for reports 
  271. $wpdb->query( 'SET SESSION SQL_BIG_SELECTS=1' ); 
  272. $cached_results[ $query_hash ] = apply_filters( 'woocommerce_reports_get_order_report_data', $wpdb->$query_type( $query ), $data ); 
  273. set_transient( strtolower( get_class( $this ) ), $cached_results, DAY_IN_SECONDS ); 
  274.  
  275. $result = $cached_results[ $query_hash ]; 
  276.  
  277. return $result; 
  278.  
  279. /** 
  280. * Put data with post_date's into an array of times. 
  281. * @param array $data array of your data 
  282. * @param string $date_key key for the 'date' field. e.g. 'post_date' 
  283. * @param string $data_key key for the data you are charting 
  284. * @param int $interval 
  285. * @param string $start_date 
  286. * @param string $group_by 
  287. * @return array 
  288. */ 
  289. public function prepare_chart_data( $data, $date_key, $data_key, $interval, $start_date, $group_by ) { 
  290. $prepared_data = array(); 
  291.  
  292. // Ensure all days (or months) have values in this range. 
  293. if ( 'day' === $group_by ) { 
  294. for ( $i = 0; $i <= $interval; $i ++ ) { 
  295. $time = strtotime( date( 'Ymd', strtotime( "+{$i} DAY", $start_date ) ) ) . '000'; 
  296.  
  297. if ( ! isset( $prepared_data[ $time ] ) ) { 
  298. $prepared_data[ $time ] = array( esc_js( $time ), 0 ); 
  299. } else { 
  300. $current_yearnum = date( 'Y', $start_date ); 
  301. $current_monthnum = date( 'm', $start_date ); 
  302.  
  303. for ( $i = 0; $i <= $interval; $i ++ ) { 
  304. $time = strtotime( $current_yearnum . str_pad( $current_monthnum, 2, '0', STR_PAD_LEFT ) . '01' ) . '000'; 
  305.  
  306. if ( ! isset( $prepared_data[ $time ] ) ) { 
  307. $prepared_data[ $time ] = array( esc_js( $time ), 0 ); 
  308.  
  309. $current_monthnum ++; 
  310.  
  311. if ( $current_monthnum > 12 ) { 
  312. $current_monthnum = 1; 
  313. $current_yearnum ++; 
  314.  
  315. foreach ( $data as $d ) { 
  316. switch ( $group_by ) { 
  317. case 'day' : 
  318. $time = strtotime( date( 'Ymd', strtotime( $d->$date_key ) ) ) . '000'; 
  319. break; 
  320. case 'month' : 
  321. default : 
  322. $time = strtotime( date( 'Ym', strtotime( $d->$date_key ) ) . '01' ) . '000'; 
  323. break; 
  324.  
  325. if ( ! isset( $prepared_data[ $time ] ) ) { 
  326. continue; 
  327.  
  328. if ( $data_key ) { 
  329. $prepared_data[ $time ][1] += $d->$data_key; 
  330. } else { 
  331. $prepared_data[ $time ][1] ++; 
  332.  
  333. return $prepared_data; 
  334.  
  335. /** 
  336. * Prepares a sparkline to show sales in the last X days. 
  337. * @param int $id ID of the product to show. Blank to get all orders. 
  338. * @param int $days Days of stats to get. 
  339. * @param string $type Type of sparkline to get. Ignored if ID is not set. 
  340. * @return string 
  341. */ 
  342. public function sales_sparkline( $id = '', $days = 7, $type = 'sales' ) { 
  343.  
  344. if ( $id ) { 
  345. $meta_key = ( 'sales' === $type ) ? '_line_total' : '_qty'; 
  346.  
  347. $data = $this->get_order_report_data( array( 
  348. 'data' => array( 
  349. '_product_id' => array( 
  350. 'type' => 'order_item_meta',  
  351. 'order_item_type' => 'line_item',  
  352. 'function' => '',  
  353. 'name' => 'product_id',  
  354. ),  
  355. $meta_key => array( 
  356. 'type' => 'order_item_meta',  
  357. 'order_item_type' => 'line_item',  
  358. 'function' => 'SUM',  
  359. 'name' => 'sparkline_value',  
  360. ),  
  361. 'post_date' => array( 
  362. 'type' => 'post_data',  
  363. 'function' => '',  
  364. 'name' => 'post_date',  
  365. ),  
  366. ),  
  367. 'where' => array( 
  368. array( 
  369. 'key' => 'post_date',  
  370. 'value' => date( 'Y-m-d', strtotime( 'midnight -' . ( $days - 1 ) . ' days', current_time( 'timestamp' ) ) ),  
  371. 'operator' => '>',  
  372. ),  
  373. array( 
  374. 'key' => 'order_item_meta__product_id.meta_value',  
  375. 'value' => $id,  
  376. 'operator' => '=',  
  377. ),  
  378. ),  
  379. 'group_by' => 'YEAR(posts.post_date), MONTH(posts.post_date), DAY(posts.post_date)',  
  380. 'query_type' => 'get_results',  
  381. 'filter_range' => false,  
  382. ) ); 
  383. } else { 
  384.  
  385. $data = $this->get_order_report_data( array( 
  386. 'data' => array( 
  387. '_order_total' => array( 
  388. 'type' => 'meta',  
  389. 'function' => 'SUM',  
  390. 'name' => 'sparkline_value',  
  391. ),  
  392. 'post_date' => array( 
  393. 'type' => 'post_data',  
  394. 'function' => '',  
  395. 'name' => 'post_date',  
  396. ),  
  397. ),  
  398. 'where' => array( 
  399. array( 
  400. 'key' => 'post_date',  
  401. 'value' => date( 'Y-m-d', strtotime( 'midnight -' . ( $days - 1 ) . ' days', current_time( 'timestamp' ) ) ),  
  402. 'operator' => '>',  
  403. ),  
  404. ),  
  405. 'group_by' => 'YEAR(posts.post_date), MONTH(posts.post_date), DAY(posts.post_date)',  
  406. 'query_type' => 'get_results',  
  407. 'filter_range' => false,  
  408. ) ); 
  409.  
  410. $total = 0; 
  411. foreach ( $data as $d ) { 
  412. $total += $d->sparkline_value; 
  413.  
  414. if ( 'sales' === $type ) { 
  415. /** translators: 1: total income 2: days */ 
  416. $tooltip = sprintf( __( 'Sold %1$s worth in the last %2$d days', 'woocommerce' ), strip_tags( wc_price( $total ) ), $days ); 
  417. } else { 
  418. /** translators: 1: total items sold 2: days */ 
  419. $tooltip = sprintf( _n( 'Sold 1 item in the last %2$d days', 'Sold %1$d items in the last %2$d days', $total, 'woocommerce' ), $total, $days ); 
  420.  
  421. $sparkline_data = array_values( $this->prepare_chart_data( $data, 'post_date', 'sparkline_value', $days - 1, strtotime( 'midnight -' . ( $days - 1 ) . ' days', current_time( 'timestamp' ) ), 'day' ) ); 
  422.  
  423. 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="' . esc_attr( json_encode( $sparkline_data ) ) . '"></span>'; 
  424.  
  425. /** 
  426. * Get the current range and calculate the start and end dates. 
  427. * @param string $current_range 
  428. */ 
  429. public function calculate_current_range( $current_range ) { 
  430.  
  431. switch ( $current_range ) { 
  432.  
  433. case 'custom' : 
  434.  
  435. $this->start_date = max( strtotime( '-20 years' ), strtotime( sanitize_text_field( $_GET['start_date'] ) ) ); 
  436.  
  437. if ( empty( $_GET['end_date'] ) ) { 
  438. $this->end_date = strtotime( 'midnight', current_time( 'timestamp' ) ); 
  439. } else { 
  440. $this->end_date = strtotime( 'midnight', strtotime( sanitize_text_field( $_GET['end_date'] ) ) ); 
  441.  
  442. $interval = 0; 
  443. $min_date = $this->start_date; 
  444.  
  445. while ( ( $min_date = strtotime( "+1 MONTH", $min_date ) ) <= $this->end_date ) { 
  446. $interval ++; 
  447.  
  448. // 3 months max for day view 
  449. if ( $interval > 3 ) { 
  450. $this->chart_groupby = 'month'; 
  451. } else { 
  452. $this->chart_groupby = 'day'; 
  453. break; 
  454.  
  455. case 'year' : 
  456. $this->start_date = strtotime( date( 'Y-01-01', current_time( 'timestamp' ) ) ); 
  457. $this->end_date = strtotime( 'midnight', current_time( 'timestamp' ) ); 
  458. $this->chart_groupby = 'month'; 
  459. break; 
  460.  
  461. case 'last_month' : 
  462. $first_day_current_month = strtotime( date( 'Y-m-01', current_time( 'timestamp' ) ) ); 
  463. $this->start_date = strtotime( date( 'Y-m-01', strtotime( '-1 DAY', $first_day_current_month ) ) ); 
  464. $this->end_date = strtotime( date( 'Y-m-t', strtotime( '-1 DAY', $first_day_current_month ) ) ); 
  465. $this->chart_groupby = 'day'; 
  466. break; 
  467.  
  468. case 'month' : 
  469. $this->start_date = strtotime( date( 'Y-m-01', current_time( 'timestamp' ) ) ); 
  470. $this->end_date = strtotime( 'midnight', current_time( 'timestamp' ) ); 
  471. $this->chart_groupby = 'day'; 
  472. break; 
  473.  
  474. case '7day' : 
  475. $this->start_date = strtotime( '-6 days', current_time( 'timestamp' ) ); 
  476. $this->end_date = strtotime( 'midnight', current_time( 'timestamp' ) ); 
  477. $this->chart_groupby = 'day'; 
  478. break; 
  479.  
  480. // Group by 
  481. switch ( $this->chart_groupby ) { 
  482.  
  483. case 'day' : 
  484. $this->group_by_query = 'YEAR(posts.post_date), MONTH(posts.post_date), DAY(posts.post_date)'; 
  485. $this->chart_interval = absint( ceil( max( 0, ( $this->end_date - $this->start_date ) / ( 60 * 60 * 24 ) ) ) ); 
  486. $this->barwidth = 60 * 60 * 24 * 1000; 
  487. break; 
  488.  
  489. case 'month' : 
  490. $this->group_by_query = 'YEAR(posts.post_date), MONTH(posts.post_date)'; 
  491. $this->chart_interval = 0; 
  492. $min_date = strtotime( date( 'Y-m-01', $this->start_date ) ); 
  493.  
  494. while ( ( $min_date = strtotime( "+1 MONTH", $min_date ) ) <= $this->end_date ) { 
  495. $this->chart_interval ++; 
  496.  
  497. $this->barwidth = 60 * 60 * 24 * 7 * 4 * 1000; 
  498. break; 
  499.  
  500. /** 
  501. * Return currency tooltip JS based on WooCommerce currency position settings. 
  502. * @return string 
  503. */ 
  504. public function get_currency_tooltip() { 
  505. switch ( get_option( 'woocommerce_currency_pos' ) ) { 
  506. case 'right': 
  507. $currency_tooltip = 'append_tooltip: "' . get_woocommerce_currency_symbol() . '"'; 
  508. break; 
  509. case 'right_space': 
  510. $currency_tooltip = 'append_tooltip: " ' . get_woocommerce_currency_symbol() . '"'; 
  511. break; 
  512. case 'left': 
  513. $currency_tooltip = 'prepend_tooltip: "' . get_woocommerce_currency_symbol() . '"'; 
  514. break; 
  515. case 'left_space': 
  516. default: 
  517. $currency_tooltip = 'prepend_tooltip: "' . get_woocommerce_currency_symbol() . ' "'; 
  518. break; 
  519.  
  520. return $currency_tooltip; 
  521.  
  522. /** 
  523. * Get the main chart. 
  524. * @return string 
  525. */ 
  526. public function get_main_chart() {} 
  527.  
  528. /** 
  529. * Get the legend for the main chart sidebar. 
  530. * @return array 
  531. */ 
  532. public function get_chart_legend() { 
  533. return array(); 
  534.  
  535. /** 
  536. * Get chart widgets. 
  537. * @return array 
  538. */ 
  539. public function get_chart_widgets() { 
  540. return array(); 
  541.  
  542. /** 
  543. * Get an export link if needed. 
  544. */ 
  545. public function get_export_button() {} 
  546.  
  547. /** 
  548. * Output the report. 
  549. */ 
  550. public function output_report() {} 
  551.  
  552. /** 
  553. * Check nonce for current range. 
  554. * @since 3.0.4 
  555. * @param string $current_range Current range. 
  556. */ 
  557. public function check_current_range_nonce( $current_range ) { 
  558. if ( 'custom' !== $current_range ) { 
  559. return; 
  560.  
  561. if ( ! isset( $_GET['wc_reports_nonce'] ) || ! wp_verify_nonce( $_GET['wc_reports_nonce'], 'custom_range' ) ) { 
  562. wp_safe_redirect( remove_query_arg( array( 'start_date', 'end_date', 'range', 'wc_reports_nonce' ) ) ); 
  563. exit;