mirror of
https://github.com/proelements/proelements.git
synced 2026-04-17 09:32:18 +00:00
v3.33.1
This commit is contained in:
44
modules/loop-filter/query/data/query-constants.php
Normal file
44
modules/loop-filter/query/data/query-constants.php
Normal file
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
namespace ElementorPro\Modules\LoopFilter\Query\Data;
|
||||
|
||||
class Query_Constants {
|
||||
public const DATA = [
|
||||
'AND' => [
|
||||
'separator' => [
|
||||
'decoded' => '+',
|
||||
'from-browser' => ' ',
|
||||
'encoded' => '%2B',
|
||||
],
|
||||
'operator' => 'AND',
|
||||
'relation' => 'AND',
|
||||
],
|
||||
'OR' => [
|
||||
'separator' => [
|
||||
'decoded' => '~',
|
||||
'from-browser' => '~',
|
||||
'encoded' => '%7C',
|
||||
],
|
||||
'operator' => 'IN',
|
||||
'relation' => 'OR',
|
||||
],
|
||||
'NOT' => [
|
||||
'separator' => [
|
||||
'decoded' => '!',
|
||||
'from-browser' => '!',
|
||||
'encoded' => '%21',
|
||||
],
|
||||
'operator' => 'NOT IN',
|
||||
'relation' => 'AND',
|
||||
],
|
||||
'DISABLED' => [
|
||||
'separator' => [
|
||||
'decoded' => '',
|
||||
'from-browser' => '',
|
||||
'encoded' => '',
|
||||
],
|
||||
'operator' => 'AND',
|
||||
'relation' => 'AND',
|
||||
],
|
||||
];
|
||||
}
|
||||
10
modules/loop-filter/query/interfaces/query-interface.php
Normal file
10
modules/loop-filter/query/interfaces/query-interface.php
Normal file
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
namespace ElementorPro\Modules\LoopFilter\Query\Interfaces;
|
||||
|
||||
use ElementorPro\Modules\LoopFilter\Query\Taxonomy_Manager;
|
||||
|
||||
interface Query_Interface {
|
||||
public function __construct( $filter_terms, Taxonomy_Manager $taxonomy_manager );
|
||||
public function get_query();
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
<?php
|
||||
namespace ElementorPro\Modules\LoopFilter\Query\QueryTypes;
|
||||
|
||||
use ElementorPro\Modules\LoopFilter\Query\Data\Query_Constants;
|
||||
use ElementorPro\Modules\LoopFilter\Query\Interfaces\Query_Interface;
|
||||
use ElementorPro\Modules\LoopFilter\Query\Taxonomy_Manager;
|
||||
|
||||
class Hierarchy_And_Query implements Query_Interface {
|
||||
private $query;
|
||||
private $terms;
|
||||
private $taxonomy;
|
||||
private $logical_join;
|
||||
private $taxonomy_manager;
|
||||
|
||||
public function __construct( $filter_terms, $taxonomy_manager ) {
|
||||
$this->query = Query_Constants::DATA;
|
||||
$this->taxonomy_manager = $taxonomy_manager;
|
||||
$this->terms = $filter_terms['hierarchical-terms'] ?? [];
|
||||
$this->taxonomy = $filter_terms['taxonomy'];
|
||||
$this->logical_join = $filter_terms['logicalJoin'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function get_query() {
|
||||
$query = [];
|
||||
|
||||
if ( empty( $this->terms ) ) {
|
||||
return $query;
|
||||
}
|
||||
|
||||
foreach ( $this->terms as $parent_term => $terms ) {
|
||||
$filtered_terms = $this->filter_query_terms( $parent_term, $terms );
|
||||
$query[] = $this->get_hierarchy_query( $filtered_terms );
|
||||
}
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $parent_term
|
||||
* @param $terms
|
||||
* @return array
|
||||
*/
|
||||
private function filter_query_terms( $parent_term, $terms ) {
|
||||
$query_terms = [];
|
||||
$filters_on_parent_term = in_array( $parent_term, $terms );
|
||||
$filters_on_parent_and_child_terms = count( $terms ) > 1 && $filters_on_parent_term;
|
||||
$is_parent_term_only = $filters_on_parent_term && ! $filters_on_parent_and_child_terms;
|
||||
$has_child_terms_only = ! $filters_on_parent_term;
|
||||
|
||||
// For an AND Queries exclude parent term if there are child and parent terms.
|
||||
if ( $filters_on_parent_and_child_terms ) {
|
||||
$query_terms = array_diff( $terms, [ $parent_term ] ); //drop parent term
|
||||
}
|
||||
|
||||
if ( $is_parent_term_only || $has_child_terms_only ) {
|
||||
$query_terms = $terms;
|
||||
}
|
||||
|
||||
return $query_terms;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create the Inner query for AND OR queries with one or more filter terms targeted at the same Widget.
|
||||
* @param array $terms
|
||||
* @return array
|
||||
*/
|
||||
private function get_hierarchy_query( $terms ) {
|
||||
$inner_query = [
|
||||
'taxonomy' => $this->taxonomy,
|
||||
'field' => 'slug',
|
||||
'terms' => [],
|
||||
'operator' => $this->query['OR']['operator'],
|
||||
];
|
||||
|
||||
foreach ( $terms as $term ) {
|
||||
if ( 1 < count( $terms ) && $this->taxonomy_manager->is_parent_term_with_children( $term, $this->taxonomy ) ) {
|
||||
$parent_query = $this->get_hierarchy_query( [ $term ] );
|
||||
continue;
|
||||
}
|
||||
|
||||
$inner_query['terms'] = [ urldecode( sanitize_title( $term ?? '' ) ) ]; //decode non-latin strings
|
||||
$child_queries[] = $inner_query;
|
||||
}
|
||||
|
||||
$hierarchy_query = array_merge( $parent_query ?? [], $child_queries ?? [] );
|
||||
$hierarchy_query['relation'] = $this->query['OR']['relation']; //broaden search results when two child terms are selected. And relation between unrelated terms.
|
||||
return $hierarchy_query;
|
||||
}
|
||||
}
|
||||
90
modules/loop-filter/query/query-types/hierarchy-or-query.php
Normal file
90
modules/loop-filter/query/query-types/hierarchy-or-query.php
Normal file
@@ -0,0 +1,90 @@
|
||||
<?php
|
||||
namespace ElementorPro\Modules\LoopFilter\Query\QueryTypes;
|
||||
|
||||
use ElementorPro\Modules\LoopFilter\Query\Data\Query_Constants;
|
||||
use ElementorPro\Modules\LoopFilter\Query\Interfaces\Query_Interface;
|
||||
|
||||
class Hierarchy_Or_Query implements Query_Interface {
|
||||
private $query;
|
||||
private $terms;
|
||||
private $taxonomy;
|
||||
private $logical_join;
|
||||
|
||||
public function __construct( $filter_terms, $taxonomy_manager ) {
|
||||
$this->query = Query_Constants::DATA;
|
||||
$this->terms = $filter_terms['hierarchical-terms'] ?? [];
|
||||
$this->taxonomy = $filter_terms['taxonomy'];
|
||||
$this->logical_join = $filter_terms['logicalJoin'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function get_query() {
|
||||
$query = [];
|
||||
|
||||
if ( empty( $this->terms ) ) {
|
||||
return $query;
|
||||
}
|
||||
|
||||
foreach ( $this->terms as $parent_term => $terms ) {
|
||||
$filtered_terms = $this->filter_query_terms( $parent_term, $terms );
|
||||
$query[] = $this->get_hierarchy_query( $filtered_terms );
|
||||
}
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description
|
||||
* @param $parent_term
|
||||
* @param $terms
|
||||
* @return array
|
||||
*/
|
||||
private function filter_query_terms( $parent_term, $terms ) {
|
||||
$query_terms = [];
|
||||
$filters_on_parent_term = in_array( $parent_term, $terms );
|
||||
$filters_on_parent_and_child_terms = count( $terms ) > 1 && $filters_on_parent_term;
|
||||
$is_parent_term_only = $filters_on_parent_term && ! $filters_on_parent_and_child_terms;
|
||||
$has_child_terms_only = ! $filters_on_parent_term;
|
||||
|
||||
// For an OR Queries exclude child terms if there is a parent term in the terms.
|
||||
if ( $filters_on_parent_and_child_terms ) {
|
||||
$query_terms = [ $parent_term ]; // drop child terms
|
||||
}
|
||||
|
||||
if ( $is_parent_term_only || $has_child_terms_only ) {
|
||||
$query_terms = $terms;
|
||||
}
|
||||
|
||||
return $query_terms;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the Inner query for AND OR queries with one or more filter terms targeted at the same Widget.
|
||||
* @param array $terms
|
||||
* @return array
|
||||
*/
|
||||
private function get_hierarchy_query( $terms ) {
|
||||
$inner_query = [
|
||||
'taxonomy' => $this->taxonomy,
|
||||
'field' => 'slug',
|
||||
'terms' => [],
|
||||
'operator' => $this->query['OR']['operator'],
|
||||
];
|
||||
|
||||
foreach ( $terms as $term ) {
|
||||
if ( 1 < count( $terms ) && $this->taxonomy_manager->is_parent_term_with_children( $term, $this->taxonomy ) ) {
|
||||
$parent_query = $this->get_hierarchy_query( [ $term ] );
|
||||
continue;
|
||||
}
|
||||
|
||||
$inner_query['terms'] = [ urldecode( sanitize_title( $term ?? '' ) ) ]; //decode non-latin strings
|
||||
$child_queries[] = $inner_query;
|
||||
}
|
||||
|
||||
$hierarchy_query = array_merge( $parent_query ?? [], $child_queries ?? [] );
|
||||
$hierarchy_query['relation'] = $this->query['OR']['relation']; //broaden search results when two child terms are selected. And relation between unrelated terms.
|
||||
return $hierarchy_query;
|
||||
}
|
||||
}
|
||||
88
modules/loop-filter/query/query-types/single-terms-query.php
Normal file
88
modules/loop-filter/query/query-types/single-terms-query.php
Normal file
@@ -0,0 +1,88 @@
|
||||
<?php
|
||||
namespace ElementorPro\Modules\LoopFilter\Query\QueryTypes;
|
||||
|
||||
use ElementorPro\Modules\LoopFilter\Query\Data\Query_Constants;
|
||||
use ElementorPro\Modules\LoopFilter\Query\Interfaces\Query_Interface;
|
||||
|
||||
class Single_Terms_Query implements Query_Interface {
|
||||
private $query;
|
||||
private $terms;
|
||||
private $taxonomy;
|
||||
private $logical_join;
|
||||
private $taxonomy_manager;
|
||||
|
||||
public function __construct( $filter_terms, $taxonomy_manager ) {
|
||||
$this->query = Query_Constants::DATA;
|
||||
$this->taxonomy_manager = $taxonomy_manager;
|
||||
$this->set_single_or_multiple_selection_terms( $filter_terms );
|
||||
$this->taxonomy = $filter_terms['taxonomy'] ?? [];
|
||||
$this->logical_join = $filter_terms['logicalJoin'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the Inner query for AND OR queries with one or more filter terms targeted at the same Widget using terms with no parent and no children
|
||||
* @return array
|
||||
*/
|
||||
public function get_query() {
|
||||
if ( empty( $this->terms ) ) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$query = [
|
||||
[
|
||||
'taxonomy' => $this->taxonomy,
|
||||
'field' => 'slug',
|
||||
'terms' => [],
|
||||
'operator' => $this->get_inner_query_operator(),
|
||||
],
|
||||
];
|
||||
|
||||
foreach ( $this->terms as $term ) {
|
||||
$query[0]['terms'][] = urldecode( sanitize_title( $term ?? '' ) ); //decode non-latin strings
|
||||
}
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $filter_terms
|
||||
* @return void
|
||||
*/
|
||||
private function set_single_or_multiple_selection_terms( $filter_terms ) {
|
||||
// Single Selection
|
||||
if ( ! empty( $filter_terms['single-term'][0] ) ) {
|
||||
$this->terms = $filter_terms['single-term'];
|
||||
return;
|
||||
}
|
||||
|
||||
$this->terms = $filter_terms['parent-terms-without-children'];
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string 'IN' / 'AND' (default)
|
||||
*/
|
||||
private function get_inner_query_operator() {
|
||||
if ( $this->is_single_parent_term() ) {
|
||||
return $this->query['OR']['operator']; // Allow showing posts from parent category when it's selected.
|
||||
}
|
||||
|
||||
if ( 'DISABLED' !== $this->logical_join ) {
|
||||
return $this->query[ $this->logical_join ?? 'DISABLED' ]['operator'];
|
||||
}
|
||||
|
||||
return $this->query['AND']['operator'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return boolean
|
||||
*/
|
||||
private function is_single_parent_term() {
|
||||
if ( empty( $this->terms ?? [] ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$is_parent_term = $this->taxonomy_manager->is_parent_term_with_children( $this->terms[0], $this->taxonomy );
|
||||
return 1 === count( $this->terms ?? [] ) && $is_parent_term;
|
||||
}
|
||||
}
|
||||
260
modules/loop-filter/query/taxonomy-manager.php
Normal file
260
modules/loop-filter/query/taxonomy-manager.php
Normal file
@@ -0,0 +1,260 @@
|
||||
<?php
|
||||
namespace ElementorPro\Modules\LoopFilter\Query;
|
||||
|
||||
class Taxonomy_Manager {
|
||||
private $terms_by_slug = [];
|
||||
private $terms_by_id = [];
|
||||
private $terms_hierarchy = [];
|
||||
|
||||
/**
|
||||
* @param string $taxonomy default 'category'. Use taxonomy string i.e. 'product_cat'. This generates the terms_by_slug and terms_by_id arrays.
|
||||
* @return void
|
||||
*/
|
||||
public function get_taxonomy_terms( $taxonomy = 'category' ) {
|
||||
$args = [
|
||||
'taxonomy' => $taxonomy,
|
||||
'hide_empty' => true,
|
||||
];
|
||||
|
||||
$terms = get_terms( $args );
|
||||
|
||||
if ( is_wp_error( $terms ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->get_terms_by_slug_and_id( $terms );
|
||||
$this->terms_hierarchy = $this->filter_child_terms_by_depth( $terms, 100 );
|
||||
}
|
||||
|
||||
private function get_term_id( $slug, $taxonomy ) {
|
||||
if ( ! isset( $this->terms_by_slug[ $taxonomy ][ $slug ] ) ) {
|
||||
return -1;
|
||||
}
|
||||
return $this->terms_by_slug[ $taxonomy ][ $slug ]['term_id'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a term is a parent term.
|
||||
* @param string $slug
|
||||
* @param string $taxonomy
|
||||
* @return bool;
|
||||
*/
|
||||
public function is_parent_term_without_children( $slug, $taxonomy ) {
|
||||
// Empty terms do not exist in $terms_by_slug
|
||||
$has_children = $this->has_children( $slug, $taxonomy );
|
||||
$is_top_level_parent_term = $this->is_top_level_parent_term( $slug, $taxonomy );
|
||||
return ( isset( $this->terms_by_slug[ $taxonomy ][ $slug ] ) && $is_top_level_parent_term && ! $has_children );
|
||||
}
|
||||
|
||||
public function is_parent_term_with_children( $slug, $taxonomy ) {
|
||||
// Empty terms do not exist in $terms_by_slug
|
||||
return ( isset( $this->terms_by_slug[ $taxonomy ][ $slug ] ) && $this->has_children( $slug, $taxonomy ) );
|
||||
}
|
||||
|
||||
private function has_children( $slug, $taxonomy ) {
|
||||
$term_id = $this->get_term_id( $slug, $taxonomy );
|
||||
return isset( $this->terms_hierarchy[ $term_id ] ) && count( $this->terms_hierarchy[ $term_id ] ) > 0;
|
||||
}
|
||||
|
||||
private function get_children( $slug, $taxonomy ) {
|
||||
$term_id = $this->get_term_id( $slug, $taxonomy );
|
||||
return $this->terms_hierarchy[ $term_id ];
|
||||
}
|
||||
|
||||
private function is_child_term( $slug, $taxonomy ) {
|
||||
return ( isset( $this->terms_by_slug[ $taxonomy ][ $slug ] ) && 0 !== $this->terms_by_slug[ $taxonomy ][ $slug ]['parent'] );
|
||||
}
|
||||
|
||||
public function is_top_level_parent_term( $slug, $taxonomy ) {
|
||||
return ( isset( $this->terms_by_slug[ $taxonomy ][ $slug ] ) && 0 === $this->terms_by_slug[ $taxonomy ][ $slug ]['parent'] );
|
||||
}
|
||||
|
||||
private function get_parent( $slug, $taxonomy ) {
|
||||
return $this->terms_by_slug[ $taxonomy ][ $slug ]['parent'];
|
||||
}
|
||||
|
||||
private function get_parent_id( $child_slug, $taxonomy ) {
|
||||
if ( ! isset( $this->terms_by_slug[ $taxonomy ][ $child_slug ]['parent'] ) ) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return $this->terms_by_slug[ $taxonomy ][ $child_slug ]['parent'];
|
||||
}
|
||||
|
||||
private function get_parent_slug( $child_slug, $taxonomy ) {
|
||||
$parent_id = $this->get_parent_id( $child_slug, $taxonomy );
|
||||
|
||||
if ( -1 === $parent_id ) {
|
||||
return 'UNDEFINED';
|
||||
}
|
||||
|
||||
return $this->terms_by_id[ $taxonomy ][ $parent_id ]['slug'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $filter_terms
|
||||
* @param string $taxonomy
|
||||
* @return array
|
||||
*/
|
||||
public function get_hierarchy_of_selected_terms( $filter_terms, $taxonomy ) {
|
||||
// Taxonomy Filter parameter is empty i.e. `e-filter-389c132-product_cat=`.
|
||||
if ( ! empty( $filter_terms['terms'] ) && '' === $filter_terms['terms'][0] ) {
|
||||
return [
|
||||
'single-term' => [],
|
||||
'parent-terms-without-children' => [],
|
||||
'hierarchical-terms' => [],
|
||||
'logicalJoin' => $filter_terms['logicalJoin'],
|
||||
'taxonomy' => $taxonomy,
|
||||
];
|
||||
}
|
||||
|
||||
$parents_without_children = [];
|
||||
$parents_with_children_by_parent = [];
|
||||
$single_selection_term = [];
|
||||
|
||||
if ( 1 === count( $filter_terms['terms'] ) ) {
|
||||
$single_selection_term = $filter_terms['terms'];
|
||||
}
|
||||
|
||||
foreach ( $filter_terms['terms'] as $term ) {
|
||||
|
||||
if ( ! empty( $single_selection_term ) ) {
|
||||
break;
|
||||
}
|
||||
|
||||
$term = urldecode( sanitize_title( $term ) ); // decode non-latin slugs.
|
||||
$is_parent_term_without_children = $this->is_parent_term_without_children( $term, $taxonomy );
|
||||
$is_parent_term_with_children = $this->is_parent_term_with_children( $term, $taxonomy );
|
||||
|
||||
if ( $is_parent_term_without_children ) {
|
||||
$parents_without_children[] = $term;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( $is_parent_term_with_children ) {
|
||||
$parents_with_children_by_parent[ $term ][] = $term;
|
||||
continue;
|
||||
}
|
||||
|
||||
$parent_slug = $this->get_parent_slug( $term, $taxonomy );
|
||||
if ( 'UNDEFINED' === $parent_slug ) {
|
||||
continue;
|
||||
}
|
||||
$parents_with_children_by_parent[ $parent_slug ][] = $term;
|
||||
}
|
||||
|
||||
return [
|
||||
'single-term' => $single_selection_term,
|
||||
'parent-terms-without-children' => $parents_without_children,
|
||||
'hierarchical-terms' => $parents_with_children_by_parent,
|
||||
'logicalJoin' => $filter_terms['logicalJoin'],
|
||||
'taxonomy' => $taxonomy,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $terms
|
||||
* @return void
|
||||
*/
|
||||
private function get_terms_by_slug_and_id( $terms = [] ) {
|
||||
$this->terms_by_slug = [];
|
||||
foreach ( $terms as $term ) {
|
||||
$slug = urldecode( $term->slug );
|
||||
|
||||
$this->try_set_terms_by_slug( $slug, $term );
|
||||
$this->try_set_terms_by_id( $slug, $term );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $slug
|
||||
* @param string $term
|
||||
* @return void
|
||||
*/
|
||||
public function try_set_terms_by_slug( $slug, $term ) {
|
||||
$term_id = $term->term_id;
|
||||
$taxonomy = $term->taxonomy;
|
||||
|
||||
if ( ! isset( $this->terms_by_slug[ $taxonomy ][ $slug ] ) ) {
|
||||
$this->terms_by_slug[ $taxonomy ][ $slug ] = [
|
||||
'term_id' => $term_id,
|
||||
'parent' => $term->parent,
|
||||
'count' => $term->count,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $slug
|
||||
* @param string $term
|
||||
* @return void
|
||||
*/
|
||||
public function try_set_terms_by_id( $slug, $term ) {
|
||||
$term_id = $term->term_id;
|
||||
$taxonomy = $term->taxonomy;
|
||||
|
||||
if ( ! isset( $this->terms_by_id[ $taxonomy ][ $slug ] ) ) {
|
||||
$this->terms_by_id[ $taxonomy ][ $term_id ] = [
|
||||
'slug' => $slug,
|
||||
'parent' => $term->parent,
|
||||
'count' => $term->count,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \WP_Term[] $terms
|
||||
* @param int $target_depth
|
||||
* @return \WP_Term[]
|
||||
*/
|
||||
private function filter_child_terms_by_depth( $terms, $target_depth ) {
|
||||
$filtered = [];
|
||||
|
||||
foreach ( $terms as $term ) {
|
||||
$this->filter_single_term( $filtered, $terms, $term, $target_depth );
|
||||
}
|
||||
|
||||
return $filtered;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \WP_Term[] $terms
|
||||
* @param \WP_Term $current_term
|
||||
* @param int $target_depth
|
||||
* @return void
|
||||
*/
|
||||
private function filter_single_term( &$result, $terms, $current_term, $target_depth ) {
|
||||
if ( 0 === $current_term->parent ) {
|
||||
$result[ $current_term->parent ][ $current_term->term_id ] = $current_term;
|
||||
return;
|
||||
}
|
||||
|
||||
$item_depth = $this->calculate_depth_for_child_term_recursively( $terms, $current_term, 0 );
|
||||
|
||||
if ( $item_depth <= $target_depth ) {
|
||||
$result[ $current_term->parent ][ $current_term->term_id ] = $current_term;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \WP_Term[] $terms
|
||||
* @param \WP_Term $child_term
|
||||
* @param int $depth
|
||||
* @return int|void
|
||||
*/
|
||||
private function calculate_depth_for_child_term_recursively( $terms, $child_term, $depth ) {
|
||||
$depth++;
|
||||
|
||||
foreach ( $terms as $term ) {
|
||||
if ( $term->term_id !== $child_term->parent ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( 0 === $term->parent ) {
|
||||
return $depth;
|
||||
}
|
||||
return $this->calculate_depth_for_child_term_recursively( $terms, $term, $depth );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
81
modules/loop-filter/query/taxonomy-query-builder.php
Normal file
81
modules/loop-filter/query/taxonomy-query-builder.php
Normal file
@@ -0,0 +1,81 @@
|
||||
<?php
|
||||
|
||||
namespace ElementorPro\Modules\LoopFilter\Query;
|
||||
|
||||
use ElementorPro\Modules\LoopFilter\Query\Data\Query_Constants;
|
||||
use ElementorPro\Modules\LoopFilter\Query\Interfaces\Query_Interface;
|
||||
use ElementorPro\Modules\LoopFilter\Query\QueryTypes\Hierarchy_And_Query;
|
||||
use ElementorPro\Modules\LoopFilter\Query\QueryTypes\Hierarchy_Or_Query;
|
||||
use ElementorPro\Modules\LoopFilter\Query\QueryTypes\Single_Terms_Query;
|
||||
|
||||
class Taxonomy_Query_Builder {
|
||||
private $query;
|
||||
private $single_terms_query;
|
||||
private $hierarchy_query;
|
||||
private $filter_terms;
|
||||
private $tax_query;
|
||||
private $taxonomy_manager;
|
||||
|
||||
public function __construct() {
|
||||
$this->query = Query_Constants::DATA;
|
||||
}
|
||||
|
||||
public function get_merged_queries( &$tax_query, $taxonomy, $filter ) {
|
||||
$this->tax_query = &$tax_query;
|
||||
|
||||
// Taxonomy Filter parameter is empty i.e. `e-filter-389c132-product_cat=`.
|
||||
if ( ! empty( $filter['terms'] ) && '' === $filter['terms'][0] ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->taxonomy_manager = new Taxonomy_Manager();
|
||||
$this->taxonomy_manager->get_taxonomy_terms( $taxonomy );
|
||||
$this->filter_terms = $this->taxonomy_manager->get_hierarchy_of_selected_terms( $filter, $taxonomy );
|
||||
|
||||
if ( ! empty( $this->filter_terms['single-term'] ) ) {
|
||||
$this->get_single_selection_query( $tax_query );
|
||||
return;
|
||||
}
|
||||
|
||||
$this->get_multiple_selection_query( $tax_query );
|
||||
}
|
||||
|
||||
private function get_single_selection_query( &$tax_query ) {
|
||||
$this->single_terms_query = $this->get_query( new Single_Terms_Query( $this->filter_terms, $this->taxonomy_manager ) );
|
||||
$this->merge_single_selection_query( $tax_query );
|
||||
}
|
||||
|
||||
private function get_multiple_selection_query( &$tax_query ) {
|
||||
$this->single_terms_query = $this->get_query( new Single_Terms_Query( $this->filter_terms, $this->taxonomy_manager ) );
|
||||
|
||||
if ( 'AND' === $this->filter_terms['logicalJoin'] ) {
|
||||
$this->hierarchy_query = $this->get_query( new Hierarchy_And_Query( $this->filter_terms, $this->taxonomy_manager ) );
|
||||
}
|
||||
|
||||
if ( 'OR' === $this->filter_terms['logicalJoin'] ) {
|
||||
$this->hierarchy_query = $this->get_query( new Hierarchy_Or_Query( $this->filter_terms, $this->taxonomy_manager ) );
|
||||
}
|
||||
|
||||
$this->merge_multiple_selection_query( $tax_query );
|
||||
}
|
||||
|
||||
private function merge_single_selection_query( &$tax_query ) {
|
||||
if ( empty( $this->single_terms_query ?? [] ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$tax_query = array_merge( $tax_query, $this->single_terms_query ?? [] );
|
||||
}
|
||||
|
||||
private function merge_multiple_selection_query( &$tax_query ) {
|
||||
if ( empty( $this->single_terms_query ?? [] ) && empty( $this->hierarchy_query ?? [] ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$tax_query = [ array_merge( $tax_query, $this->single_terms_query ?? [], $this->hierarchy_query ?? [], [ 'relation' => $this->query[ $this->filter_terms['logicalJoin'] ]['relation'] ] ) ];
|
||||
}
|
||||
|
||||
private function get_query( Query_Interface $query_type ) {
|
||||
return $query_type->get_query();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user