diff --git a/includes/class-top-ten-core-query.php b/includes/class-top-ten-core-query.php index a3bc1f6..05f266a 100644 --- a/includes/class-top-ten-core-query.php +++ b/includes/class-top-ten-core-query.php @@ -249,17 +249,45 @@ public function prepare_query_args( $args = array() ) { } if ( ! empty( $args['include_cat_ids'] ) ) { + + /** + * Filter to include the parent terms when including terms. + * + * @since 3.4.0 + * + * @param bool|string $include_terms_include_parents False to exclude only the categories specified, + * 'parent' to include the parent categories and + * 'all' to include all the ancestors. Default is false. + */ + $include_terms_include_parents = apply_filters( 'top_ten_query_include_terms_include_parents', false ); + + $include_terms_include_parents = $include_terms_include_parents ? wz_get_all_parent_ids( wp_parse_id_list( $args['include_cat_ids'] ), $include_terms_include_parents ) : wp_parse_id_list( $args['include_cat_ids'] ); + $tax_query[] = array( 'field' => 'term_taxonomy_id', - 'terms' => wp_parse_id_list( $args['include_cat_ids'] ), + 'terms' => $include_terms_include_parents, 'include_children' => false, ); } if ( ! empty( $args['exclude_categories'] ) ) { + + /** + * Filter to include the parent categories when excluding categories. + * + * @since 3.4.0 + * + * @param bool|string $exclude_terms_include_parents False to exclude only the categories specified, + * 'parent' to include the parent categories and + * 'all' to include all the ancestors. Default is false. + */ + $exclude_terms_include_parents = apply_filters( 'top_ten_query_exclude_terms_include_parents', false ); + + $exclude_categories = $exclude_terms_include_parents ? wz_get_all_parent_ids( wp_parse_id_list( $args['exclude_categories'] ), $exclude_terms_include_parents ) : wp_parse_id_list( $args['exclude_categories'] ); + $tax_query[] = array( 'field' => 'term_taxonomy_id', - 'terms' => wp_parse_id_list( $args['exclude_categories'] ), + 'terms' => $exclude_categories, 'operator' => 'NOT IN', 'include_children' => false, ); diff --git a/includes/wz-pluggables.php b/includes/wz-pluggables.php index 142bf97..3315bc6 100644 --- a/includes/wz-pluggables.php +++ b/includes/wz-pluggables.php @@ -74,3 +74,68 @@ function wz_switch_site_rewrite() { } endif; + +if ( ! function_exists( 'wz_get_all_parent_ids' ) ) : + + /** + * Get all parent term_taxonomy_ids for a given array of term_taxonomy_ids. + * + * @param int|int[] $term_taxonomy_ids Array of term_taxonomy_ids or a single term_taxonomy_id. + * @param string $levels Use 'all' for ancestors, 'parent' for the immediate parent. + * @return int[] Array of all parent term_taxonomy_ids merged with $term_taxonomy_ids. + */ + function wz_get_all_parent_ids( $term_taxonomy_ids, $levels = 'parent' ) { + $all_ids = array(); + $cache = array(); + + foreach ( (array) $term_taxonomy_ids as $term_taxonomy_id ) { + if ( isset( $cache[ $term_taxonomy_id ] ) ) { + $term = $cache[ $term_taxonomy_id ]; + } else { + $term = WP_Term::get_instance( $term_taxonomy_id ); + $cache[ $term_taxonomy_id ] = $term; + } + + if ( $term && ! is_wp_error( $term ) ) { + $taxonomy = $term->taxonomy; + + if ( 'all' === $levels ) { + $ancestors = get_ancestors( $term->term_id, $taxonomy, 'taxonomy' ); + + foreach ( $ancestors as $ancestor_term_id ) { + if ( isset( $cache[ $ancestor_term_id ] ) ) { + $ancestor_term = $cache[ $ancestor_term_id ]; + } else { + $ancestor_term = WP_Term::get_instance( $ancestor_term_id ); + $cache[ $ancestor_term_id ] = $ancestor_term; + } + + if ( $ancestor_term && ! is_wp_error( $ancestor_term ) ) { + $all_ids[] = $ancestor_term->term_taxonomy_id; + } + } + } else { + $parent_id = $term->parent; + if ( $parent_id > 0 ) { + if ( isset( $cache[ $parent_id ] ) ) { + $parent_term = $cache[ $parent_id ]; + } else { + $parent_term = WP_Term::get_instance( $parent_id ); + $cache[ $parent_id ] = $parent_term; + } + + if ( $parent_term && ! is_wp_error( $parent_term ) ) { + $all_ids[] = $parent_term->term_taxonomy_id; + } + } + } + } + } + + // Perform array operations outside the loop for better performance. + $result_ids = array_merge( $term_taxonomy_ids, $all_ids ); + + return array_unique( $result_ids ); + } + +endif;