File "class-wc-query.php"

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

Download   Open   Edit   Advanced Editor   Back

<?php

use Automattic\WooCommerce\Internal\ProductAttributesLookup\Filterer;
defined('ABSPATH') || exit;
class WC_Query
{
    public $query_vars = array();
    private static $product_query;
    private static $chosen_attributes;
    private $filterer;
    public function __construct()
    {
        $this->filterer = wc_get_container()->get(Filterer::class);
        add_action('init', array($this, 'add_endpoints'));
        if (!is_admin()) {
            add_action('wp_loaded', array($this, 'get_errors'), 20);
            add_filter('query_vars', array($this, 'add_query_vars'), 0);
            add_action('parse_request', array($this, 'parse_request'), 0);
            add_action('pre_get_posts', array($this, 'pre_get_posts'));
            add_filter('get_pagenum_link', array($this, 'remove_add_to_cart_pagination'), 10, 1);
        }
        $this->init_query_vars();
    }
    public static function reset_chosen_attributes()
    {
        self::$chosen_attributes = null;
    }
    public function get_errors()
    {
        $error = !empty($_GET['wc_error']) ? sanitize_text_field(wp_unslash($_GET['wc_error'])) : '';
        if ($error && !wc_has_notice($error, 'error')) {
            wc_add_notice($error, 'error');
        }
    }
    public function init_query_vars()
    {
        $this->query_vars = array('order-pay' => get_option('woocommerce_checkout_pay_endpoint', 'order-pay'), 'order-received' => get_option('woocommerce_checkout_order_received_endpoint', 'order-received'), 'orders' => get_option('woocommerce_myaccount_orders_endpoint', 'orders'), 'view-order' => get_option('woocommerce_myaccount_view_order_endpoint', 'view-order'), 'downloads' => get_option('woocommerce_myaccount_downloads_endpoint', 'downloads'), 'edit-account' => get_option('woocommerce_myaccount_edit_account_endpoint', 'edit-account'), 'edit-address' => get_option('woocommerce_myaccount_edit_address_endpoint', 'edit-address'), 'payment-methods' => get_option('woocommerce_myaccount_payment_methods_endpoint', 'payment-methods'), 'lost-password' => get_option('woocommerce_myaccount_lost_password_endpoint', 'lost-password'), 'customer-logout' => get_option('woocommerce_logout_endpoint', 'customer-logout'), 'add-payment-method' => get_option('woocommerce_myaccount_add_payment_method_endpoint', 'add-payment-method'), 'delete-payment-method' => get_option('woocommerce_myaccount_delete_payment_method_endpoint', 'delete-payment-method'), 'set-default-payment-method' => get_option('woocommerce_myaccount_set_default_payment_method_endpoint', 'set-default-payment-method'));
    }
    public function get_endpoint_title($endpoint, $action = '')
    {
        global $wp;
        switch ($endpoint) {
            case 'order-pay':
                $title = __('Pay for order', 'woocommerce');
                break;
            case 'order-received':
                $title = __('Order received', 'woocommerce');
                break;
            case 'orders':
                if (!empty($wp->query_vars['orders'])) {
                    $title = sprintf(__('Orders (page %d)', 'woocommerce'), intval($wp->query_vars['orders']));
                } else {
                    $title = __('Orders', 'woocommerce');
                }
                break;
            case 'view-order':
                $order = wc_get_order($wp->query_vars['view-order']);
                $title = $order ? sprintf(__('Order #%s', 'woocommerce'), $order->get_order_number()) : '';
                break;
            case 'downloads':
                $title = __('Downloads', 'woocommerce');
                break;
            case 'edit-account':
                $title = __('Account details', 'woocommerce');
                break;
            case 'edit-address':
                $title = __('Addresses', 'woocommerce');
                break;
            case 'payment-methods':
                $title = __('Payment methods', 'woocommerce');
                break;
            case 'add-payment-method':
                $title = __('Add payment method', 'woocommerce');
                break;
            case 'lost-password':
                if (in_array($action, array('rp', 'resetpass', 'newaccount'), true)) {
                    $title = __('Set password', 'woocommerce');
                } else {
                    $title = __('Lost password', 'woocommerce');
                }
                break;
            default:
                $title = '';
                break;
        }
        return apply_filters('woocommerce_endpoint_' . $endpoint . '_title', $title, $endpoint, $action);
    }
    public function get_endpoints_mask()
    {
        if ('page' === get_option('show_on_front')) {
            $page_on_front = get_option('page_on_front');
            $myaccount_page_id = get_option('woocommerce_myaccount_page_id');
            $checkout_page_id = get_option('woocommerce_checkout_page_id');
            if (in_array($page_on_front, array($myaccount_page_id, $checkout_page_id), true)) {
                return EP_ROOT | EP_PAGES;
            }
        }
        return EP_PAGES;
    }
    public function add_endpoints()
    {
        $mask = $this->get_endpoints_mask();
        foreach ($this->get_query_vars() as $key => $var) {
            if (!empty($var)) {
                add_rewrite_endpoint($var, $mask);
            }
        }
    }
    public function add_query_vars($vars)
    {
        foreach ($this->get_query_vars() as $key => $var) {
            $vars[] = $key;
        }
        return $vars;
    }
    public function get_query_vars()
    {
        return apply_filters('woocommerce_get_query_vars', $this->query_vars);
    }
    public function get_current_endpoint()
    {
        global $wp;
        foreach ($this->get_query_vars() as $key => $value) {
            if (isset($wp->query_vars[$key])) {
                return $key;
            }
        }
        return '';
    }
    public function parse_request()
    {
        global $wp;
        foreach ($this->get_query_vars() as $key => $var) {
            if (isset($_GET[$var])) {
                $wp->query_vars[$key] = sanitize_text_field(wp_unslash($_GET[$var]));
            } elseif (isset($wp->query_vars[$var])) {
                $wp->query_vars[$key] = $wp->query_vars[$var];
            }
        }
    }
    private function is_showing_page_on_front($q)
    {
        return $q->is_home() && !$q->is_posts_page && 'page' === get_option('show_on_front');
    }
    private function page_on_front_is($page_id)
    {
        return absint(get_option('page_on_front')) === absint($page_id);
    }
    public function pre_get_posts($q)
    {
        if (!$q->is_main_query()) {
            return;
        }
        if ($this->is_showing_page_on_front($q)) {
            if (!$this->page_on_front_is($q->get('page_id'))) {
                $_query = wp_parse_args($q->query);
                if (!empty($_query) && array_intersect(array_keys($_query), array_keys($this->get_query_vars()))) {
                    $q->is_page = true;
                    $q->is_home = false;
                    $q->is_singular = true;
                    $q->set('page_id', (int) get_option('page_on_front'));
                    add_filter('redirect_canonical', '__return_false');
                }
            }
            if ($this->page_on_front_is(wc_get_page_id('shop'))) {
                $_query = wp_parse_args($q->query);
                if (empty($_query) || !array_diff(array_keys($_query), array('preview', 'page', 'paged', 'cpage', 'orderby'))) {
                    $q->set('page_id', (int) get_option('page_on_front'));
                    $q->is_page = true;
                    $q->is_home = false;
                    if (current_theme_supports('woocommerce')) {
                        $q->set('post_type', 'product');
                    } else {
                        $q->is_singular = true;
                    }
                }
            } elseif (!empty($_GET['orderby'])) {
                $q->set('page_id', (int) get_option('page_on_front'));
                $q->is_page = true;
                $q->is_home = false;
                $q->is_singular = true;
            }
        }
        if ($q->is_feed() && $q->is_post_type_archive('product')) {
            $q->is_comment_feed = false;
        }
        if (current_theme_supports('woocommerce') && $q->is_page() && 'page' === get_option('show_on_front') && absint($q->get('page_id')) === wc_get_page_id('shop')) {
            $q->set('post_type', 'product');
            $q->set('page_id', '');
            if (isset($q->query['paged'])) {
                $q->set('paged', $q->query['paged']);
            }
            wc_maybe_define_constant('SHOP_IS_ON_FRONT', true);
            global $wp_post_types;
            $shop_page = get_post(wc_get_page_id('shop'));
            $wp_post_types['product']->ID = $shop_page->ID;
            $wp_post_types['product']->post_title = $shop_page->post_title;
            $wp_post_types['product']->post_name = $shop_page->post_name;
            $wp_post_types['product']->post_type = $shop_page->post_type;
            $wp_post_types['product']->ancestors = get_ancestors($shop_page->ID, $shop_page->post_type);
            $q->is_singular = false;
            $q->is_post_type_archive = true;
            $q->is_archive = true;
            $q->is_page = true;
            add_filter('post_type_archive_title', '__return_empty_string', 5);
            if (class_exists('WPSEO_Meta')) {
                add_filter('wpseo_metadesc', array($this, 'wpseo_metadesc'));
                add_filter('wpseo_metakey', array($this, 'wpseo_metakey'));
            }
        } elseif (!$q->is_post_type_archive('product') && !$q->is_tax(get_object_taxonomies('product'))) {
            return;
        }
        $this->product_query($q);
    }
    public function handle_get_posts($posts, $query)
    {
        if ('product_query' !== $query->get('wc_query')) {
            return $posts;
        }
        $this->remove_product_query_filters($posts);
        return $posts;
    }
    public function remove_product_query_filters($posts)
    {
        $this->remove_ordering_args();
        remove_filter('posts_clauses', array($this, 'price_filter_post_clauses'), 10, 2);
        return $posts;
    }
    public function adjust_posts_count($count, $query)
    {
        return $count;
    }
    protected function get_layered_nav_chosen_attributes_inst()
    {
        return self::get_layered_nav_chosen_attributes();
    }
    protected function get_current_posts()
    {
        return $GLOBALS['wp_query']->posts;
    }
    public function wpseo_metadesc()
    {
        return WPSEO_Meta::get_value('metadesc', wc_get_page_id('shop'));
    }
    public function wpseo_metakey()
    {
        return WPSEO_Meta::get_value('metakey', wc_get_page_id('shop'));
    }
    public function product_query($q)
    {
        if (!is_feed()) {
            $ordering = $this->get_catalog_ordering_args();
            $q->set('orderby', $ordering['orderby']);
            $q->set('order', $ordering['order']);
            if (isset($ordering['meta_key'])) {
                $q->set('meta_key', $ordering['meta_key']);
            }
        }
        $q->set('meta_query', $this->get_meta_query($q->get('meta_query'), true));
        $q->set('tax_query', $this->get_tax_query($q->get('tax_query'), true));
        $q->set('wc_query', 'product_query');
        $q->set('post__in', array_unique((array) apply_filters('loop_shop_post_in', array())));
        $q->set('posts_per_page', $q->get('posts_per_page') ? $q->get('posts_per_page') : apply_filters('loop_shop_per_page', wc_get_default_products_per_row() * wc_get_default_product_rows_per_page()));
        self::$product_query = $q;
        add_filter('posts_clauses', function ($args, $wp_query) {
            return $this->product_query_post_clauses($args, $wp_query);
        }, 10, 2);
        add_filter('the_posts', array($this, 'handle_get_posts'), 10, 2);
        do_action('woocommerce_product_query', $q, $this);
    }
    private function product_query_post_clauses($args, $wp_query)
    {
        $args = $this->price_filter_post_clauses($args, $wp_query);
        $args = $this->filterer->filter_by_attribute_post_clauses($args, $wp_query, $this->get_layered_nav_chosen_attributes());
        return $args;
    }
    public function remove_product_query()
    {
        remove_action('pre_get_posts', array($this, 'pre_get_posts'));
    }
    public function remove_ordering_args()
    {
        remove_filter('posts_clauses', array($this, 'order_by_price_asc_post_clauses'));
        remove_filter('posts_clauses', array($this, 'order_by_price_desc_post_clauses'));
        remove_filter('posts_clauses', array($this, 'order_by_popularity_post_clauses'));
        remove_filter('posts_clauses', array($this, 'order_by_rating_post_clauses'));
    }
    public function get_catalog_ordering_args($orderby = '', $order = '')
    {
        if (!$orderby) {
            $orderby_value = isset($_GET['orderby']) ? wc_clean((string) wp_unslash($_GET['orderby'])) : wc_clean(get_query_var('orderby'));
            if (!$orderby_value) {
                if (is_search()) {
                    $orderby_value = 'relevance';
                } else {
                    $orderby_value = apply_filters('woocommerce_default_catalog_orderby', get_option('woocommerce_default_catalog_orderby', 'menu_order'));
                }
            }
            $orderby_value = is_array($orderby_value) ? $orderby_value : explode('-', $orderby_value);
            $orderby = esc_attr($orderby_value[0]);
            $order = !empty($orderby_value[1]) ? $orderby_value[1] : $order;
        }
        $orderby = strtolower(is_array($orderby) ? (string) current($orderby) : (string) $orderby);
        $order = strtoupper(is_array($order) ? (string) current($order) : (string) $order);
        $args = array('orderby' => $orderby, 'order' => 'DESC' === $order ? 'DESC' : 'ASC', 'meta_key' => '');
        switch ($orderby) {
            case 'id':
                $args['orderby'] = 'ID';
                break;
            case 'menu_order':
                $args['orderby'] = 'menu_order title';
                break;
            case 'title':
                $args['orderby'] = 'title';
                $args['order'] = 'DESC' === $order ? 'DESC' : 'ASC';
                break;
            case 'relevance':
                $args['orderby'] = 'relevance';
                $args['order'] = 'DESC';
                break;
            case 'rand':
                $args['orderby'] = 'rand';
                break;
            case 'date':
                $args['orderby'] = 'date ID';
                $args['order'] = 'ASC' === $order ? 'ASC' : 'DESC';
                break;
            case 'price':
                $callback = 'DESC' === $order ? 'order_by_price_desc_post_clauses' : 'order_by_price_asc_post_clauses';
                add_filter('posts_clauses', array($this, $callback));
                break;
            case 'popularity':
                add_filter('posts_clauses', array($this, 'order_by_popularity_post_clauses'));
                break;
            case 'rating':
                add_filter('posts_clauses', array($this, 'order_by_rating_post_clauses'));
                break;
        }
        return apply_filters('woocommerce_get_catalog_ordering_args', $args, $orderby, $order);
    }
    public function price_filter_post_clauses($args, $wp_query)
    {
        global $wpdb;
        if (!$wp_query->is_main_query() || !isset($_GET['max_price']) && !isset($_GET['min_price'])) {
            return $args;
        }
        $current_min_price = isset($_GET['min_price']) ? floatval(wp_unslash($_GET['min_price'])) : 0;
        $current_max_price = isset($_GET['max_price']) ? floatval(wp_unslash($_GET['max_price'])) : PHP_INT_MAX;
        if (wc_tax_enabled() && 'incl' === get_option('woocommerce_tax_display_shop') && !wc_prices_include_tax()) {
            $tax_class = apply_filters('woocommerce_price_filter_widget_tax_class', '');
            $tax_rates = WC_Tax::get_rates($tax_class);
            if ($tax_rates) {
                $current_min_price -= WC_Tax::get_tax_total(WC_Tax::calc_inclusive_tax($current_min_price, $tax_rates));
                $current_max_price -= WC_Tax::get_tax_total(WC_Tax::calc_inclusive_tax($current_max_price, $tax_rates));
            }
        }
        $args['join'] = $this->append_product_sorting_table_join($args['join']);
        $args['where'] .= $wpdb->prepare(' AND NOT (%f<wc_product_meta_lookup.min_price OR %f>wc_product_meta_lookup.max_price ) ', $current_max_price, $current_min_price);
        return $args;
    }
    public function order_by_price_asc_post_clauses($args)
    {
        $args['join'] = $this->append_product_sorting_table_join($args['join']);
        $args['orderby'] = ' wc_product_meta_lookup.min_price ASC, wc_product_meta_lookup.product_id ASC ';
        return $args;
    }
    public function order_by_price_desc_post_clauses($args)
    {
        $args['join'] = $this->append_product_sorting_table_join($args['join']);
        $args['orderby'] = ' wc_product_meta_lookup.max_price DESC, wc_product_meta_lookup.product_id DESC ';
        return $args;
    }
    public function order_by_popularity_post_clauses($args)
    {
        $args['join'] = $this->append_product_sorting_table_join($args['join']);
        $args['orderby'] = ' wc_product_meta_lookup.total_sales DESC, wc_product_meta_lookup.product_id DESC ';
        return $args;
    }
    public function order_by_rating_post_clauses($args)
    {
        $args['join'] = $this->append_product_sorting_table_join($args['join']);
        $args['orderby'] = ' wc_product_meta_lookup.average_rating DESC, wc_product_meta_lookup.rating_count DESC, wc_product_meta_lookup.product_id DESC ';
        return $args;
    }
    private function append_product_sorting_table_join($sql)
    {
        global $wpdb;
        if (!strstr($sql, 'wc_product_meta_lookup')) {
            $sql .= " LEFT JOIN {$wpdb->wc_product_meta_lookup} wc_product_meta_lookup ON {$wpdb->posts}.ID = wc_product_meta_lookup.product_id ";
        }
        return $sql;
    }
    public function get_meta_query($meta_query = array(), $main_query = false)
    {
        if (!is_array($meta_query)) {
            $meta_query = array();
        }
        return array_filter(apply_filters('woocommerce_product_query_meta_query', $meta_query, $this));
    }
    public function get_tax_query($tax_query = array(), $main_query = false)
    {
        if (!is_array($tax_query)) {
            $tax_query = array('relation' => 'AND');
        }
        if ($main_query && !$this->filterer->filtering_via_lookup_table_is_active()) {
            foreach ($this->get_layered_nav_chosen_attributes() as $taxonomy => $data) {
                $tax_query[] = array('taxonomy' => $taxonomy, 'field' => 'slug', 'terms' => $data['terms'], 'operator' => 'and' === $data['query_type'] ? 'AND' : 'IN', 'include_children' => false);
            }
        }
        $product_visibility_terms = wc_get_product_visibility_term_ids();
        $product_visibility_not_in = array(is_search() && $main_query ? $product_visibility_terms['exclude-from-search'] : $product_visibility_terms['exclude-from-catalog']);
        if ('yes' === get_option('woocommerce_hide_out_of_stock_items')) {
            $product_visibility_not_in[] = $product_visibility_terms['outofstock'];
        }
        if (isset($_GET['rating_filter'])) {
            $rating_filter = array_filter(array_map('absint', explode(',', wp_unslash($_GET['rating_filter']))));
            $rating_terms = array();
            for ($i = 1; $i <= 5; $i++) {
                if (in_array($i, $rating_filter, true) && isset($product_visibility_terms['rated-' . $i])) {
                    $rating_terms[] = $product_visibility_terms['rated-' . $i];
                }
            }
            if (!empty($rating_terms)) {
                $tax_query[] = array('taxonomy' => 'product_visibility', 'field' => 'term_taxonomy_id', 'terms' => $rating_terms, 'operator' => 'IN', 'rating_filter' => true);
            }
        }
        if (!empty($product_visibility_not_in)) {
            $tax_query[] = array('taxonomy' => 'product_visibility', 'field' => 'term_taxonomy_id', 'terms' => $product_visibility_not_in, 'operator' => 'NOT IN');
        }
        return array_filter(apply_filters('woocommerce_product_query_tax_query', $tax_query, $this));
    }
    public static function get_main_query()
    {
        return self::$product_query;
    }
    public static function get_main_tax_query()
    {
        $tax_query = isset(self::$product_query->tax_query, self::$product_query->tax_query->queries) ? self::$product_query->tax_query->queries : array();
        return $tax_query;
    }
    public static function get_main_meta_query()
    {
        $args = self::$product_query->query_vars;
        $meta_query = isset($args['meta_query']) ? $args['meta_query'] : array();
        return $meta_query;
    }
    public static function get_main_search_query_sql()
    {
        global $wpdb;
        $args = self::$product_query->query_vars;
        $search_terms = isset($args['search_terms']) ? $args['search_terms'] : array();
        $sql = array();
        foreach ($search_terms as $term) {
            $include = '-' !== substr($term, 0, 1);
            if ($include) {
                $like_op = 'LIKE';
                $andor_op = 'OR';
            } else {
                $like_op = 'NOT LIKE';
                $andor_op = 'AND';
                $term = substr($term, 1);
            }
            $like = '%' . $wpdb->esc_like($term) . '%';
            $sql[] = $wpdb->prepare("(({$wpdb->posts}.post_title {$like_op} %s) {$andor_op} ({$wpdb->posts}.post_excerpt {$like_op} %s) {$andor_op} ({$wpdb->posts}.post_content {$like_op} %s))", $like, $like, $like);
        }
        if (!empty($sql) && !is_user_logged_in()) {
            $sql[] = "({$wpdb->posts}.post_password = '')";
        }
        return implode(' AND ', $sql);
    }
    public static function get_layered_nav_chosen_attributes()
    {
        if (!is_array(self::$chosen_attributes)) {
            self::$chosen_attributes = array();
            if (!empty($_GET)) {
                foreach ($_GET as $key => $value) {
                    if (0 === strpos($key, 'filter_')) {
                        $attribute = wc_sanitize_taxonomy_name(str_replace('filter_', '', $key));
                        $taxonomy = wc_attribute_taxonomy_name($attribute);
                        $filter_terms = !empty($value) ? explode(',', wc_clean(wp_unslash($value))) : array();
                        if (empty($filter_terms) || !taxonomy_exists($taxonomy) || !wc_attribute_taxonomy_id_by_name($attribute)) {
                            continue;
                        }
                        $query_type = !empty($_GET['query_type_' . $attribute]) && in_array($_GET['query_type_' . $attribute], array('and', 'or'), true) ? wc_clean(wp_unslash($_GET['query_type_' . $attribute])) : '';
                        self::$chosen_attributes[$taxonomy]['terms'] = array_map('sanitize_title', $filter_terms);
                        self::$chosen_attributes[$taxonomy]['query_type'] = $query_type ? $query_type : apply_filters('woocommerce_layered_nav_default_query_type', 'and');
                    }
                }
            }
        }
        return self::$chosen_attributes;
    }
    public function remove_add_to_cart_pagination($url)
    {
        return remove_query_arg('add-to-cart', $url);
    }
    public function rating_filter_meta_query()
    {
        return array();
    }
    public function visibility_meta_query($compare = 'IN')
    {
        return array();
    }
    public function stock_status_meta_query($status = 'instock')
    {
        return array();
    }
    public function layered_nav_init()
    {
        wc_deprecated_function('layered_nav_init', '2.6');
    }
    public function get_products_in_view()
    {
        wc_deprecated_function('get_products_in_view', '2.6');
    }
    public function layered_nav_query($deprecated)
    {
        wc_deprecated_function('layered_nav_query', '2.6');
    }
    public function search_post_excerpt($where = '')
    {
        wc_deprecated_function('WC_Query::search_post_excerpt', '3.2.0', 'Excerpt added to search query by default since WordPress 4.5.');
        return $where;
    }
    public function remove_posts_where()
    {
        wc_deprecated_function('WC_Query::remove_posts_where', '3.2.0', 'Nothing to remove anymore because search_post_excerpt() is deprecated.');
    }
}