You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

298 lines
12 KiB

<?php
use WCML\Utilities\DB;
/**
* This class is responsible for handling legacy WC reports. Legacy WC reports are being phased out in favor of newer WC analytics.
* Legacy WC reports are not HPOS-compatible: https://github.com/woocommerce/woocommerce/issues/40671
*
* @deprecated This class is deprecated and should no longer be used because it's incompatible with HPOS.
* @link https://onthegosystems.myjetbrains.com/youtrack/issue/wcml-4489
*/
class WCML_Reports{
public $tab;
public $report;
public function __construct(){
add_action('init', array($this, 'init'));
}
public function init(){
if( isset($_GET['page']) && $_GET['page']==='wc-reports' ) {
$this->tab = isset( $_GET['tab'] ) ? $_GET['tab'] : 'orders';
$this->report = isset( $_GET['report'] ) ? $_GET['report'] : '';
add_filter( 'woocommerce_reports_get_order_report_query', array( $this, 'filter_reports_query' ), 0 );
if ( $this->tab==='orders' && $this->report==='sales_by_product' ) {
add_filter( 'woocommerce_reports_get_order_report_data', array( $this, 'combine_report_by_languages' ) );
}
if ( $this->tab==='orders' && $this->report==='sales_by_category' ) {
add_filter( 'woocommerce_report_sales_by_category_get_products_in_category', array(
$this,
'use_categories_in_all_languages'
), 10, 2 );
}
}
add_filter( 'woocommerce_report_most_stocked_query_from', array( $this, 'filter_reports_stock_query' ) );
add_filter( 'woocommerce_report_out_of_stock_query_from', array( $this, 'filter_reports_stock_query' ) );
add_filter( 'woocommerce_report_low_in_stock_query_from', array( $this, 'filter_reports_stock_query' ) );
}
public function filter_reports_query($query){
global $wpdb, $sitepress;
$current_language = $sitepress->get_current_language();
$active_languages = $sitepress->get_active_languages();
if($this->tab==='orders' && $this->report==='sales_by_product'){
$sparkline_query = strpos( $query[ 'select'], 'sparkline_value' ) !== false;
if(
$sparkline_query ||
isset( $query[ 'order_by' ] ) && ( $query[ 'order_by' ]==='ORDER BY order_item_qty DESC' || $query[ 'order_by' ]==='ORDER BY order_item_total DESC' )
){
$query[ 'select' ] .= " , order_language.meta_value AS order_language , translations.trid";
$query[ 'join' ] .= " LEFT JOIN {$wpdb->postmeta} order_language ON posts.ID = order_language.post_id";
$query[ 'where' ] .= " AND order_language.meta_key = 'wpml_language' ";
$query[ 'join' ] .= " LEFT JOIN {$wpdb->prefix}icl_translations translations ON translations.element_id = order_item_meta__product_id.meta_value";
$query[ 'where' ] .= " AND translations.element_type IN ('post_product','post_product_variation') ";
if(!$sparkline_query){
$limit = (int) trim( str_replace( 'LIMIT ', '', $query['limit'] ) );
$query['limit'] = sprintf( ' LIMIT %d ', $limit * count( $active_languages ) );
}
if($sparkline_query){
preg_match("#order_item_meta__product_id\.meta_value = '([0-9]+)'#", $query[ 'where' ], $matches);
$product_id = $matches[1];
$post_type = get_post_type($product_id);
$trid = $sitepress->get_element_trid($product_id, 'post_'.$post_type);
$translations = $sitepress->get_element_translations($trid, 'post_'.$post_type, true);
$product_ids = array();
foreach($translations as $translation){
$product_ids[] = $translation->element_id;
}
$query[ 'where' ] = str_replace( "order_item_meta__product_id.meta_value = '{$product_id}'", "order_item_meta__product_id.meta_value IN (" . DB::prepareIn( array_filter( $product_ids ), '%d' ) . ")", $query[ 'where' ] );
}
$query[ 'select' ] .= ', translations.language_code AS language_code_' . esc_sql( str_replace('-', '_', $current_language) ); // user for per-language caching.
}elseif(
$query[ 'select' ]==='SELECT SUM( order_item_meta__line_total.meta_value) as order_item_amount' || //sales for the selected items
$query[ 'select' ]==='SELECT SUM( order_item_meta__qty.meta_value) as order_item_count' || //purchases for the selected items
$query[ 'select' ]==='SELECT SUM( order_item_meta__qty.meta_value) as order_item_count, posts.post_date as post_date, order_item_meta__product_id.meta_value as product_id' || //Get orders and dates in range - main chart: order_item_counts
$query[ 'select' ]==='SELECT SUM( order_item_meta__line_total.meta_value) as order_item_amount, posts.post_date as post_date, order_item_meta__product_id.meta_value as product_id' //Get orders and dates in range - main chart: order_item_amounts
){
preg_match("#order_item_meta__product_id_array\.meta_value IN \(([^\)]+)\)#", $query[ 'where' ], $matches);
$product_ids = array();
$exp = array_map('trim', explode(',', $matches[1]));
foreach($exp as $e){
$product_ids[] = trim($e, "'");
}
$all_product_ids = array();
foreach($product_ids as $product_id){
$post_type = get_post_type($product_id);
$trid = $sitepress->get_element_trid($product_id, 'post_'.$post_type);
$translations = $sitepress->get_element_translations($trid, 'post_'.$post_type, true);
foreach($translations as $translation){
$all_product_ids[] = $translation->element_id;
}
}
$query[ 'where' ] = preg_replace( "#order_item_meta__product_id_array\.meta_value IN \(([^\)]+)\)#", "order_item_meta__product_id_array.meta_value IN (" . DB::prepareIn( array_filter( $all_product_ids ), '%d' ) . ')', $query[ 'where' ] );
}
}
return $query;
}
public function combine_report_by_languages($results){
global $sitepress, $wpdb;
if(is_array($results) && isset($results['0']->order_item_qty)){
$mode = 'top_sellers';
}elseif(is_array($results) && isset($results['0']->order_item_total)){
$mode = 'top_earners';
}elseif(isset($results['0']->sparkline_value)){
$mode = 'top_sellers_spark';
}else{
return $results;
}
if(!isset($results['0']->trid)) return $results;
$current_language = $sitepress->get_current_language();
$combined_results = array();
foreach($results as $k => $row){
switch($mode){
case 'top_sellers':
case 'top_earners':
$key = $row->trid;
break;
case 'top_sellers_spark':
$key = $row->trid . '#' . substr($row->post_date, 0, 10);
break;
default:
$key = null;
}
if($key && $row->order_language===$current_language){
$combined_results[$key] = $row;
}
}
foreach($results as $k => $row){
if($row->order_language != $current_language){
switch($mode){
case 'top_sellers':
case 'top_earners':
$key = $row->trid;
break;
case 'top_sellers_spark':
$key = $row->trid . '#' . substr($row->post_date, 0, 10);
break;
default:
$key = null;
}
if($key && isset($combined_results[$key])){
switch($mode){
case 'top_sellers':
$combined_results[$key]->order_item_qty += $row->order_item_qty;
break;
case 'top_earners':
$combined_results[$key]->order_item_total += $row->order_item_total;
break;
case 'top_sellers_spark':
$combined_results[$key]->sparkline_value += $row->sparkline_value;
break;
}
}else{
$default_product_id = apply_filters( 'translate_object_id',$row->product_id, 'product', false, $current_language);
if($default_product_id){
$combined_results[$key] = new stdClass();
$combined_results[$key]->product_id = $default_product_id;
switch($mode){
case 'top_sellers':
$combined_results[$key]->order_item_qty = $row->order_item_qty;
break;
case 'top_earners':
$combined_results[$key]->order_item_total = $row->order_item_total;
break;
case 'top_sellers_spark':
$combined_results[$key]->sparkline_value = $row->sparkline_value;
$combined_results[$key]->post_date = $row->post_date;
break;
}
}
}
}
}
switch($mode){
case 'top_sellers':
usort($combined_results, array(__CLASS__, 'order_by_quantity'));
array_slice($combined_results, 0, 12);
break;
case 'top_earners':
usort($combined_results, array(__CLASS__, 'order_by_total'));
array_slice($combined_results, 0, 12);
break;
case 'top_sellers_spark':
break;
}
foreach($combined_results as $k => $row){
unset($combined_results[$k]->trid, $combined_results[$k]->order_language);
}
return $combined_results;
}
private static function order_by_quantity( $a, $b ) {
return $b->order_item_qty - $a->order_item_qty;
}
private static function order_by_total( $a, $b ) {
return $b->order_item_total - $a->order_item_total;
}
public function filter_reports_stock_query( $query_from ){
global $wpdb, $sitepress;
$current_language = $sitepress->get_current_language();
if( $current_language !== 'all' ){
$query_from = preg_replace("/WHERE/",
"LEFT JOIN {$wpdb->prefix}icl_translations AS t
ON posts.ID = t.element_id
WHERE", $query_from);
$query_from .= " AND t.element_type IN ( 'post_product', 'post_product_variation' ) AND t.language_code = '".$current_language."'";
}
return $query_from;
}
public function use_categories_in_all_languages( $product_ids, $category_id ) {
global $woocommerce_wpml, $sitepress;
$category_term = $woocommerce_wpml->terms->wcml_get_term_by_id( $category_id, 'product_cat' );
if ( ! is_wp_error( $category_term ) ) {
$trid = $sitepress->get_element_trid( $category_term->term_taxonomy_id, 'tax_product_cat' );
$translations = $sitepress->get_element_translations( $trid, 'tax_product_cat', true );
foreach ( $translations as $translation ) {
if ( $translation->term_id != $category_id ) {
$term_ids = get_term_children( $translation->term_id, 'product_cat' );
$term_ids[] = $translation->term_id;
$product_ids = array_merge( array_unique( $product_ids ), get_objects_in_term( $term_ids, 'product_cat' ) );
}
}
}
return $product_ids;
}
}