/home/awneajlw/faizastore.com/wp-content/plugins/shopengine/core/query-modifier.php
<?php
namespace ShopEngine\Core;
use ShopEngine\Traits\Singleton;
use ShopEngine\Core\Register\Widget_List;
class Query_Modifier
{
use Singleton;
private $custom_query = [];
public function init()
{
add_action('pre_get_posts', [$this, 'modify_query']);
}
public function modify_query($query)
{
if (is_admin() || !$query->is_main_query() || $query->is_single === true) {
return;
}
// Only proceed when it's the product query from widgets OR we're on the shop/product archive
$is_product_query_flag = isset($query->query_vars['wc_query']) && $query->query_vars['wc_query'] == 'product_query';
$is_shop_archive = ( function_exists('is_shop') && is_shop() ) || ( isset($query->query_vars['post_type']) && $query->query_vars['post_type'] === 'product' ) || ( isset($query->is_post_type_archive) && $query->is_post_type_archive === true );
if ( ! $is_product_query_flag && ! $is_shop_archive ) {
return;
}
// query filter begins
// update query for product per page filter
//phpcs:ignore WordPress.Security.NonceVerification.Recommended -- It's a fronted user part, not possible to verify nonce here
if (!empty($_GET['shopengine_products_per_page'])) {
//phpcs:ignore WordPress.Security.NonceVerification.Recommended
$query->set('posts_per_page', absint(intval($_GET['shopengine_products_per_page'])));
}
// checking product filter widget active or not
// but if `filter_pa_*` params are present on shop archive, allow processing even if widget not active
$has_filter_params = false;
if ( $is_shop_archive ) {
foreach ( $_GET as $k => $v ) {
if ( strpos( $k, 'filter_pa_' ) === 0 && ! empty( $v ) ) {
$taxonomy = substr( $k, strlen('filter_') ); // e.g. pa_color
$values = explode(',', trim( $v ));
$this->custom_query['relation'] = 'AND';
$this->custom_query[] = [
'taxonomy' => $taxonomy,
'field' => 'slug',
'terms' => $values,
'operator' => 'IN',
];
$has_filter_params = true;
}
}
}
$active_widgets = Widget_List::instance()->get_list(true, 'active');
if (!isset($active_widgets['product-filters']) && !$has_filter_params) {
return;
}
$color_prefix = 'shopengine_filter_color_';
$attribute_prefix = 'shopengine_filter_attribute_';
$image_prefix = 'shopengine_filter_image_';
$label_prefix = 'shopengine_filter_label_';
$shipping_prefix = 'shopengine_filter_shipping_';
$category_prefix = 'shopengine_filter_category';
$stock_prefix = 'shopengine_filter_stock';
$sale_prefix = 'shopengine_filter_onsale';
$brand_prefix = 'shopengine_filter_brand';
$meta_query = ['relation' => 'AND'];
//phpcs:ignore WordPress.Security.NonceVerification.Recommended -- It's a fronted user part, not possible to verify nonce here
foreach ($_GET as $key => $value) {
if ($key === 'rating_filter') {
$meta_query[] = [
'key' => '_wc_average_rating',
'value' => explode(',', trim($value)),
'type' => 'numeric',
'compare' => 'IN'
];
}
if ($key === $category_prefix) {
$query->query['product_cat'] = '';
$query->query_vars['product_cat'] = '';
$query = $this->query($key . 'product_cat', $category_prefix, $value, $query);
} elseif (strpos($key, $color_prefix) !== false) {
$query = $this->query($key, $color_prefix, $value, $query);
} elseif (strpos($key, $attribute_prefix) !== false) {
$query = $this->query($key, $attribute_prefix, $value, $query);
} elseif (strpos($key, $image_prefix) !== false) {
$query = $this->query($key, $image_prefix, $value, $query);
} elseif (strpos($key, $label_prefix) !== false) {
$query = $this->query($key, $label_prefix, $value, $query);
} elseif (strpos($key, $shipping_prefix) !== false) {
$query = $this->query($key, $shipping_prefix, $value, $query);
} elseif ($key === $brand_prefix) {
$query = $this->query($key, $brand_prefix, $value, $query);
} elseif ($key === $stock_prefix) {
$meta_query[] = [
'key' => '_stock_status',
'value' => $value,
'compare' => 'IN'
];
} elseif ($key === $sale_prefix) {
$s = explode(',', $value);
foreach ($s as $v) {
if ($v === 'on_sale') {
$product_ids_on_sale = wc_get_product_ids_on_sale(); // including varriation products
$query->set( 'post__in', (array) $product_ids_on_sale );
} else {
$meta_query[] = [
'key' => '_sale_price',
'compare' => 'NOT EXISTS',
'operator' => 'OR',
];
}
}
}
// Support custom attribute filtering (filter_custom_{slug})
elseif (strpos($key, 'filter_custom_') === 0) {
$attr_slug = substr($key, strlen('filter_custom_')); // e.g. material, brand
$values = array_map('sanitize_text_field', explode(',', trim($value)));
// Search in serialized _product_attributes meta for custom attributes
foreach ($values as $val) {
$meta_query[] = [
'key' => '_product_attributes',
'value' => '"' . $val . '"',
'compare' => 'LIKE'
];
}
}
}
if (!empty($meta_query)) {
$query->set('meta_query', $meta_query);
}
$product_visibility_terms = wc_get_product_visibility_term_ids();
$product_visibility_not_in = array( $product_visibility_terms['exclude-from-catalog'] );
if ( 'yes' === get_option( 'woocommerce_hide_out_of_stock_items' ) ) {
$product_visibility_not_in[] = $product_visibility_terms['outofstock'];
}
$this->custom_query['tax_query'][] = apply_filters('shopengine-product-visibility-modifier',[
'taxonomy' => 'product_visibility',
'terms' => $product_visibility_not_in,
'field' => 'term_taxonomy_id',
'operator' => 'NOT IN',
]);
$query->set('tax_query', apply_filters('shopengine-tax-query-modifier', $this->custom_query));
}
public function query($key, $prefix, $values, $query)
{
// Handle brand filter specifically
if ($prefix === 'shopengine_filter_brand') {
$taxonomy = 'product_brand';
} else {
$taxonomy = str_replace($prefix, '', $key);
}
$values = explode(',', trim($values));
$this->custom_query['relation'] = 'AND';
$this->custom_query[] = [
'taxonomy' => $taxonomy,
'field' => 'slug',
'terms' => $values,
'operator' => 'IN',
];
return $query;
}
}