File "class-wc-admin-report.php"

Full path: /home/kosmetik/public_html/wp-content/plugins/woocommerce/includes/admin/reports/class-wc-admin-report.php
File size: 20.96 B
MIME-type: text/x-php
Charset: utf-8

Download   Open   Edit   Advanced Editor   Back

<?php

if (!defined('ABSPATH')) {
    exit;
}
class WC_Admin_Report
{
    protected static $transients_to_update = array();
    protected static $cached_results = array();
    public $chart_interval;
    public $group_by_query;
    public $barwidth;
    public $chart_groupby;
    public $start_date;
    public $end_date;
    public function get_order_report_data($args = array())
    {
        global $wpdb;
        $default_args = array('data' => array(), 'where' => array(), 'where_meta' => array(), 'query_type' => 'get_row', 'group_by' => '', 'order_by' => '', 'limit' => '', 'filter_range' => false, 'nocache' => false, 'debug' => false, 'order_types' => wc_get_order_types('reports'), 'order_status' => array('completed', 'processing', 'on-hold'), 'parent_order_status' => false);
        $args = apply_filters('woocommerce_reports_get_order_report_data_args', $args);
        $args = wp_parse_args($args, $default_args);
        extract($args);
        if (empty($data)) {
            return '';
        }
        $order_status = apply_filters('woocommerce_reports_order_statuses', $order_status);
        $query = array();
        $select = array();
        foreach ($data as $raw_key => $value) {
            $key = sanitize_key($raw_key);
            $distinct = '';
            if (isset($value['distinct'])) {
                $distinct = 'DISTINCT';
            }
            switch ($value['type']) {
                case 'meta':
                    $get_key = "meta_{$key}.meta_value";
                    break;
                case 'parent_meta':
                    $get_key = "parent_meta_{$key}.meta_value";
                    break;
                case 'post_data':
                    $get_key = "posts.{$key}";
                    break;
                case 'order_item_meta':
                    $get_key = "order_item_meta_{$key}.meta_value";
                    break;
                case 'order_item':
                    $get_key = "order_items.{$key}";
                    break;
            }
            if (empty($get_key)) {
                continue;
            }
            if ($value['function']) {
                $get = "{$value['function']}({$distinct} {$get_key})";
            } else {
                $get = "{$distinct} {$get_key}";
            }
            $select[] = "{$get} as {$value['name']}";
        }
        $query['select'] = 'SELECT ' . implode(',', $select);
        $query['from'] = "FROM {$wpdb->posts} AS posts";
        $joins = array();
        foreach ($data + $where as $raw_key => $value) {
            $join_type = isset($value['join_type']) ? $value['join_type'] : 'INNER';
            $type = isset($value['type']) ? $value['type'] : false;
            $key = sanitize_key($raw_key);
            switch ($type) {
                case 'meta':
                    $joins["meta_{$key}"] = "{$join_type} JOIN {$wpdb->postmeta} AS meta_{$key} ON ( posts.ID = meta_{$key}.post_id AND meta_{$key}.meta_key = '{$raw_key}' )";
                    break;
                case 'parent_meta':
                    $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 = '{$raw_key}')";
                    break;
                case 'order_item_meta':
                    $joins['order_items'] = "{$join_type} JOIN {$wpdb->prefix}woocommerce_order_items AS order_items ON (posts.ID = order_items.order_id)";
                    if (!empty($value['order_item_type'])) {
                        $joins['order_items'] .= " AND (order_items.order_item_type = '{$value['order_item_type']}')";
                    }
                    $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) " . " AND (order_item_meta_{$key}.meta_key = '{$raw_key}')";
                    break;
                case 'order_item':
                    $joins['order_items'] = "{$join_type} JOIN {$wpdb->prefix}woocommerce_order_items AS order_items ON posts.ID = order_items.order_id";
                    break;
            }
        }
        if (!empty($where_meta)) {
            foreach ($where_meta as $value) {
                if (!is_array($value)) {
                    continue;
                }
                $join_type = isset($value['join_type']) ? $value['join_type'] : 'INNER';
                $type = isset($value['type']) ? $value['type'] : false;
                $key = sanitize_key(is_array($value['meta_key']) ? $value['meta_key'][0] . '_array' : $value['meta_key']);
                if ('order_item_meta' === $type) {
                    $joins['order_items'] = "{$join_type} JOIN {$wpdb->prefix}woocommerce_order_items AS order_items ON posts.ID = order_items.order_id";
                    $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";
                } else {
                    $joins["meta_{$key}"] = "{$join_type} JOIN {$wpdb->postmeta} AS meta_{$key} ON posts.ID = meta_{$key}.post_id";
                }
            }
        }
        if (!empty($parent_order_status)) {
            $joins['parent'] = "LEFT JOIN {$wpdb->posts} AS parent ON posts.post_parent = parent.ID";
        }
        $query['join'] = implode(' ', $joins);
        $query['where'] = "\n\t\t\tWHERE \tposts.post_type \tIN ( '" . implode("','", $order_types) . "' )\n\t\t\t";
        if (!empty($order_status)) {
            $query['where'] .= "\n\t\t\t\tAND \tposts.post_status \tIN ( 'wc-" . implode("','wc-", $order_status) . "')\n\t\t\t";
        }
        if (!empty($parent_order_status)) {
            if (!empty($order_status)) {
                $query['where'] .= " AND ( parent.post_status IN ( 'wc-" . implode("','wc-", $parent_order_status) . "') OR parent.ID IS NULL ) ";
            } else {
                $query['where'] .= " AND parent.post_status IN ( 'wc-" . implode("','wc-", $parent_order_status) . "') ";
            }
        }
        if ($filter_range) {
            $query['where'] .= "\n\t\t\t\tAND \tposts.post_date >= '" . date('Y-m-d H:i:s', $this->start_date) . "'\n\t\t\t\tAND \tposts.post_date < '" . date('Y-m-d H:i:s', strtotime('+1 DAY', $this->end_date)) . "'\n\t\t\t";
        }
        if (!empty($where_meta)) {
            $relation = isset($where_meta['relation']) ? $where_meta['relation'] : 'AND';
            $query['where'] .= ' AND (';
            foreach ($where_meta as $index => $value) {
                if (!is_array($value)) {
                    continue;
                }
                $key = sanitize_key(is_array($value['meta_key']) ? $value['meta_key'][0] . '_array' : $value['meta_key']);
                if (strtolower($value['operator']) == 'in' || strtolower($value['operator']) == 'not in') {
                    if (is_array($value['meta_value'])) {
                        $value['meta_value'] = implode("','", $value['meta_value']);
                    }
                    if (!empty($value['meta_value'])) {
                        $where_value = "{$value['operator']} ('{$value['meta_value']}')";
                    }
                } else {
                    $where_value = "{$value['operator']} '{$value['meta_value']}'";
                }
                if (!empty($where_value)) {
                    if ($index > 0) {
                        $query['where'] .= ' ' . $relation;
                    }
                    if (isset($value['type']) && 'order_item_meta' === $value['type']) {
                        if (is_array($value['meta_key'])) {
                            $query['where'] .= " ( order_item_meta_{$key}.meta_key   IN ('" . implode("','", $value['meta_key']) . "')";
                        } else {
                            $query['where'] .= " ( order_item_meta_{$key}.meta_key   = '{$value['meta_key']}'";
                        }
                        $query['where'] .= " AND order_item_meta_{$key}.meta_value {$where_value} )";
                    } else {
                        if (is_array($value['meta_key'])) {
                            $query['where'] .= " ( meta_{$key}.meta_key   IN ('" . implode("','", $value['meta_key']) . "')";
                        } else {
                            $query['where'] .= " ( meta_{$key}.meta_key   = '{$value['meta_key']}'";
                        }
                        $query['where'] .= " AND meta_{$key}.meta_value {$where_value} )";
                    }
                }
            }
            $query['where'] .= ')';
        }
        if (!empty($where)) {
            foreach ($where as $value) {
                if (strtolower($value['operator']) == 'in' || strtolower($value['operator']) == 'not in') {
                    if (is_array($value['value'])) {
                        $value['value'] = implode("','", $value['value']);
                    }
                    if (!empty($value['value'])) {
                        $where_value = "{$value['operator']} ('{$value['value']}')";
                    }
                } else {
                    $where_value = "{$value['operator']} '{$value['value']}'";
                }
                if (!empty($where_value)) {
                    $query['where'] .= " AND {$value['key']} {$where_value}";
                }
            }
        }
        if ($group_by) {
            $query['group_by'] = "GROUP BY {$group_by}";
        }
        if ($order_by) {
            $query['order_by'] = "ORDER BY {$order_by}";
        }
        if ($limit) {
            $query['limit'] = "LIMIT {$limit}";
        }
        $query = apply_filters('woocommerce_reports_get_order_report_query', $query);
        $query = implode(' ', $query);
        if ($debug) {
            echo '<pre>';
            wc_print_r($query);
            echo '</pre>';
        }
        if ($debug || $nocache) {
            self::enable_big_selects();
            $result = apply_filters('woocommerce_reports_get_order_report_data', $wpdb->{$query_type}($query), $data);
        } else {
            $query_hash = md5($query_type . $query);
            $result = $this->get_cached_query($query_hash);
            if ($result === null) {
                self::enable_big_selects();
                $result = apply_filters('woocommerce_reports_get_order_report_data', $wpdb->{$query_type}($query), $data);
            }
            $this->set_cached_query($query_hash, $result);
        }
        return $result;
    }
    protected static function add_update_transients_hook()
    {
        if (!has_action('shutdown', array('WC_Admin_Report', 'maybe_update_transients'))) {
            add_action('shutdown', array('WC_Admin_Report', 'maybe_update_transients'));
        }
    }
    protected static function enable_big_selects()
    {
        static $big_selects = false;
        global $wpdb;
        if (!$big_selects) {
            $wpdb->query('SET SESSION SQL_BIG_SELECTS=1');
            $big_selects = true;
        }
    }
    protected function get_cached_query($query_hash)
    {
        $class = strtolower(get_class($this));
        if (!isset(self::$cached_results[$class])) {
            self::$cached_results[$class] = get_transient(strtolower(get_class($this)));
        }
        if (isset(self::$cached_results[$class][$query_hash])) {
            return self::$cached_results[$class][$query_hash];
        }
        return null;
    }
    protected function set_cached_query($query_hash, $data)
    {
        $class = strtolower(get_class($this));
        if (!isset(self::$cached_results[$class])) {
            self::$cached_results[$class] = get_transient(strtolower(get_class($this)));
        }
        self::add_update_transients_hook();
        self::$transients_to_update[$class] = $class;
        self::$cached_results[$class][$query_hash] = $data;
    }
    public static function maybe_update_transients()
    {
        foreach (self::$transients_to_update as $key => $transient_name) {
            set_transient($transient_name, self::$cached_results[$transient_name], DAY_IN_SECONDS);
        }
        self::$transients_to_update = array();
    }
    public function prepare_chart_data($data, $date_key, $data_key, $interval, $start_date, $group_by)
    {
        $prepared_data = array();
        if ('day' === $group_by) {
            for ($i = 0; $i <= $interval; $i++) {
                $time = strtotime(date('Ymd', strtotime("+{$i} DAY", $start_date))) . '000';
                if (!isset($prepared_data[$time])) {
                    $prepared_data[$time] = array(esc_js($time), 0);
                }
            }
        } else {
            $current_yearnum = date('Y', $start_date);
            $current_monthnum = date('m', $start_date);
            for ($i = 0; $i <= $interval; $i++) {
                $time = strtotime($current_yearnum . str_pad($current_monthnum, 2, '0', STR_PAD_LEFT) . '01') . '000';
                if (!isset($prepared_data[$time])) {
                    $prepared_data[$time] = array(esc_js($time), 0);
                }
                $current_monthnum++;
                if ($current_monthnum > 12) {
                    $current_monthnum = 1;
                    $current_yearnum++;
                }
            }
        }
        foreach ($data as $d) {
            switch ($group_by) {
                case 'day':
                    $time = strtotime(date('Ymd', strtotime($d->{$date_key}))) . '000';
                    break;
                case 'month':
                default:
                    $time = strtotime(date('Ym', strtotime($d->{$date_key})) . '01') . '000';
                    break;
            }
            if (!isset($prepared_data[$time])) {
                continue;
            }
            if ($data_key) {
                $prepared_data[$time][1] += $d->{$data_key};
            } else {
                $prepared_data[$time][1]++;
            }
        }
        return $prepared_data;
    }
    public function sales_sparkline($id = '', $days = 7, $type = 'sales')
    {
        if ($id) {
            $meta_key = 'sales' === $type ? '_line_total' : '_qty';
            $data = $this->get_order_report_data(array('data' => array('_product_id' => array('type' => 'order_item_meta', 'order_item_type' => 'line_item', 'function' => '', 'name' => 'product_id'), $meta_key => array('type' => 'order_item_meta', 'order_item_type' => 'line_item', 'function' => 'SUM', 'name' => 'sparkline_value'), 'post_date' => array('type' => 'post_data', 'function' => '', 'name' => 'post_date')), 'where' => array(array('key' => 'post_date', 'value' => date('Y-m-d', strtotime('midnight -' . ($days - 1) . ' days', current_time('timestamp'))), 'operator' => '>'), array('key' => 'order_item_meta__product_id.meta_value', 'value' => $id, 'operator' => '=')), 'group_by' => 'YEAR(posts.post_date), MONTH(posts.post_date), DAY(posts.post_date)', 'query_type' => 'get_results', 'filter_range' => false));
        } else {
            $data = $this->get_order_report_data(array('data' => array('_order_total' => array('type' => 'meta', 'function' => 'SUM', 'name' => 'sparkline_value'), 'post_date' => array('type' => 'post_data', 'function' => '', 'name' => 'post_date')), 'where' => array(array('key' => 'post_date', 'value' => date('Y-m-d', strtotime('midnight -' . ($days - 1) . ' days', current_time('timestamp'))), 'operator' => '>')), 'group_by' => 'YEAR(posts.post_date), MONTH(posts.post_date), DAY(posts.post_date)', 'query_type' => 'get_results', 'filter_range' => false));
        }
        $total = 0;
        foreach ($data as $d) {
            $total += $d->sparkline_value;
        }
        if ('sales' === $type) {
            $tooltip = sprintf(__('Sold %1$s worth in the last %2$d days', 'woocommerce'), strip_tags(wc_price($total)), $days);
        } else {
            $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);
        }
        $sparkline_data = array_values($this->prepare_chart_data($data, 'post_date', 'sparkline_value', $days - 1, strtotime('midnight -' . ($days - 1) . ' days', current_time('timestamp')), 'day'));
        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>';
    }
    public function calculate_current_range($current_range)
    {
        switch ($current_range) {
            case 'custom':
                $this->start_date = max(strtotime('-20 years'), strtotime(sanitize_text_field($_GET['start_date'])));
                if (empty($_GET['end_date'])) {
                    $this->end_date = strtotime('midnight', current_time('timestamp'));
                } else {
                    $this->end_date = strtotime('midnight', strtotime(sanitize_text_field($_GET['end_date'])));
                }
                $interval = 0;
                $min_date = $this->start_date;
                while (($min_date = strtotime('+1 MONTH', $min_date)) <= $this->end_date) {
                    $interval++;
                }
                if ($interval > 3) {
                    $this->chart_groupby = 'month';
                } else {
                    $this->chart_groupby = 'day';
                }
                break;
            case 'year':
                $this->start_date = strtotime(date('Y-01-01', current_time('timestamp')));
                $this->end_date = strtotime('midnight', current_time('timestamp'));
                $this->chart_groupby = 'month';
                break;
            case 'last_month':
                $first_day_current_month = strtotime(date('Y-m-01', current_time('timestamp')));
                $this->start_date = strtotime(date('Y-m-01', strtotime('-1 DAY', $first_day_current_month)));
                $this->end_date = strtotime(date('Y-m-t', strtotime('-1 DAY', $first_day_current_month)));
                $this->chart_groupby = 'day';
                break;
            case 'month':
                $this->start_date = strtotime(date('Y-m-01', current_time('timestamp')));
                $this->end_date = strtotime('midnight', current_time('timestamp'));
                $this->chart_groupby = 'day';
                break;
            case '7day':
                $this->start_date = strtotime('-6 days', strtotime('midnight', current_time('timestamp')));
                $this->end_date = strtotime('midnight', current_time('timestamp'));
                $this->chart_groupby = 'day';
                break;
        }
        switch ($this->chart_groupby) {
            case 'day':
                $this->group_by_query = 'YEAR(posts.post_date), MONTH(posts.post_date), DAY(posts.post_date)';
                $this->chart_interval = absint(ceil(max(0, ($this->end_date - $this->start_date) / (60 * 60 * 24))));
                $this->barwidth = 60 * 60 * 24 * 1000;
                break;
            case 'month':
                $this->group_by_query = 'YEAR(posts.post_date), MONTH(posts.post_date)';
                $this->chart_interval = 0;
                $min_date = strtotime(date('Y-m-01', $this->start_date));
                while (($min_date = strtotime('+1 MONTH', $min_date)) <= $this->end_date) {
                    $this->chart_interval++;
                }
                $this->barwidth = 60 * 60 * 24 * 7 * 4 * 1000;
                break;
        }
    }
    public function get_currency_tooltip()
    {
        switch (get_option('woocommerce_currency_pos')) {
            case 'right':
                $currency_tooltip = 'append_tooltip: "' . get_woocommerce_currency_symbol() . '"';
                break;
            case 'right_space':
                $currency_tooltip = 'append_tooltip: "&nbsp;' . get_woocommerce_currency_symbol() . '"';
                break;
            case 'left':
                $currency_tooltip = 'prepend_tooltip: "' . get_woocommerce_currency_symbol() . '"';
                break;
            case 'left_space':
            default:
                $currency_tooltip = 'prepend_tooltip: "' . get_woocommerce_currency_symbol() . '&nbsp;"';
                break;
        }
        return $currency_tooltip;
    }
    public function get_main_chart()
    {
    }
    public function get_chart_legend()
    {
        return array();
    }
    public function get_chart_widgets()
    {
        return array();
    }
    public function get_export_button()
    {
    }
    public function output_report()
    {
    }
    public function check_current_range_nonce($current_range)
    {
        if ('custom' !== $current_range) {
            return;
        }
        if (!isset($_GET['wc_reports_nonce']) || !wp_verify_nonce(sanitize_key($_GET['wc_reports_nonce']), 'custom_range')) {
            wp_die(sprintf(esc_html__('This report link has expired. %1$sClick here to view the filtered report%2$s.', 'woocommerce'), '<a href="' . esc_url(wp_nonce_url(esc_url_raw(wp_unslash($_SERVER['REQUEST_URI'])), 'custom_range', 'wc_reports_nonce')) . '">', '</a>'), esc_attr__('Confirm navigation', 'woocommerce'));
            exit;
        }
    }
}