86 * |
86 * |
87 * @since 4.6.0 |
87 * @since 4.6.0 |
88 * @since 4.6.0 Introduced 'term_taxonomy_id' parameter. |
88 * @since 4.6.0 Introduced 'term_taxonomy_id' parameter. |
89 * @since 4.7.0 Introduced 'object_ids' parameter. |
89 * @since 4.7.0 Introduced 'object_ids' parameter. |
90 * @since 4.9.0 Added 'slug__in' support for 'orderby'. |
90 * @since 4.9.0 Added 'slug__in' support for 'orderby'. |
|
91 * @since 5.1.0 Introduced the 'meta_compare_key' parameter. |
|
92 * @since 5.3.0 Introduced the 'meta_type_key' parameter. |
91 * |
93 * |
92 * @param string|array $query { |
94 * @param string|array $query { |
93 * Optional. Array or query string of term query parameters. Default empty. |
95 * Optional. Array or query string of term query parameters. Default empty. |
94 * |
96 * |
95 * @type string|array $taxonomy Taxonomy name, or array of taxonomies, to which results should |
97 * @type string|string[] $taxonomy Taxonomy name, or array of taxonomy names, to which results |
96 * be limited. |
98 * should be limited. |
97 * @type int|int[] $object_ids Optional. Object ID, or array of object IDs. Results will be |
99 * @type int|int[] $object_ids Object ID, or array of object IDs. Results will be |
98 * limited to terms associated with these objects. |
100 * limited to terms associated with these objects. |
99 * @type string $orderby Field(s) to order terms by. Accepts: |
101 * @type string $orderby Field(s) to order terms by. Accepts: |
100 * * term fields ('name', 'slug', 'term_group', 'term_id', 'id', |
102 * - Term fields ('name', 'slug', 'term_group', 'term_id', 'id', |
101 * 'description', 'parent', 'term_order'). Unless `$object_ids` |
103 * 'description', 'parent', 'term_order'). Unless `$object_ids` |
102 * is not empty, 'term_order' is treated the same as 'term_id'. |
104 * is not empty, 'term_order' is treated the same as 'term_id'. |
103 * * 'count' to use the number of objects associated with the term. |
105 * - 'count' to use the number of objects associated with the term. |
104 * * 'include' to match the 'order' of the $include param. |
106 * - 'include' to match the 'order' of the `$include` param. |
105 * * 'slug__in' to match the 'order' of the $slug param. |
107 * - 'slug__in' to match the 'order' of the `$slug` param. |
106 * * 'meta_value', 'meta_value_num'. |
108 * - 'meta_value' |
107 * the value of `$meta_key`. |
109 * - 'meta_value_num'. |
108 * the array keys of `$meta_query`. |
110 * - The value of `$meta_key`. |
109 * * 'none' to omit the ORDER BY clause. |
111 * - The array keys of `$meta_query`. |
110 * Defaults to 'name'. |
112 * - 'none' to omit the ORDER BY clause. |
111 * @type string $order Whether to order terms in ascending or descending order. |
113 * Default 'name'. |
112 * Accepts 'ASC' (ascending) or 'DESC' (descending). |
114 * @type string $order Whether to order terms in ascending or descending order. |
113 * Default 'ASC'. |
115 * Accepts 'ASC' (ascending) or 'DESC' (descending). |
114 * @type bool|int $hide_empty Whether to hide terms not assigned to any posts. Accepts |
116 * Default 'ASC'. |
115 * 1|true or 0|false. Default 1|true. |
117 * @type bool|int $hide_empty Whether to hide terms not assigned to any posts. Accepts |
116 * @type int[]|string $include Array or comma/space-separated string of term IDs to include. |
118 * 1|true or 0|false. Default 1|true. |
117 * Default empty array. |
119 * @type int[]|string $include Array or comma/space-separated string of term IDs to include. |
118 * @type int[]|string $exclude Array or comma/space-separated string of term IDs to exclude. |
120 * Default empty array. |
119 * If $include is non-empty, $exclude is ignored. |
121 * @type int[]|string $exclude Array or comma/space-separated string of term IDs to exclude. |
120 * Default empty array. |
122 * If `$include` is non-empty, `$exclude` is ignored. |
121 * @type int[]|string $exclude_tree Array or comma/space-separated string of term IDs to exclude |
123 * Default empty array. |
122 * along with all of their descendant terms. If $include is |
124 * @type int[]|string $exclude_tree Array or comma/space-separated string of term IDs to exclude |
123 * non-empty, $exclude_tree is ignored. Default empty array. |
125 * along with all of their descendant terms. If `$include` is |
124 * @type int|string $number Maximum number of terms to return. Accepts ''|0 (all) or any |
126 * non-empty, `$exclude_tree` is ignored. Default empty array. |
125 * positive number. Default ''|0 (all). Note that $number may |
127 * @type int|string $number Maximum number of terms to return. Accepts ''|0 (all) or any |
126 * not return accurate results when coupled with $object_ids. |
128 * positive number. Default ''|0 (all). Note that `$number` may |
127 * See #41796 for details. |
129 * not return accurate results when coupled with `$object_ids`. |
128 * @type int $offset The number by which to offset the terms query. Default empty. |
130 * See #41796 for details. |
129 * @type string $fields Term fields to query for. Accepts: |
131 * @type int $offset The number by which to offset the terms query. Default empty. |
130 * * 'all' Returns an array of complete term objects (`WP_Term[]`). |
132 * @type string $fields Term fields to query for. Accepts: |
131 * * 'all_with_object_id' Returns an array of term objects |
133 * - 'all' Returns an array of complete term objects (`WP_Term[]`). |
132 * with the 'object_id' param (`WP_Term[]`). Works only |
134 * - 'all_with_object_id' Returns an array of term objects |
133 * when the `$object_ids` parameter is populated. |
135 * with the 'object_id' param (`WP_Term[]`). Works only |
134 * * 'ids' Returns an array of term IDs (`int[]`). |
136 * when the `$object_ids` parameter is populated. |
135 * * 'tt_ids' Returns an array of term taxonomy IDs (`int[]`). |
137 * - 'ids' Returns an array of term IDs (`int[]`). |
136 * * 'names' Returns an array of term names (`string[]`). |
138 * - 'tt_ids' Returns an array of term taxonomy IDs (`int[]`). |
137 * * 'slugs' Returns an array of term slugs (`string[]`). |
139 * - 'names' Returns an array of term names (`string[]`). |
138 * * 'count' Returns the number of matching terms (`int`). |
140 * - 'slugs' Returns an array of term slugs (`string[]`). |
139 * * 'id=>parent' Returns an associative array of parent term IDs, |
141 * - 'count' Returns the number of matching terms (`int`). |
140 * keyed by term ID (`int[]`). |
142 * - 'id=>parent' Returns an associative array of parent term IDs, |
141 * * 'id=>name' Returns an associative array of term names, |
143 * keyed by term ID (`int[]`). |
142 * keyed by term ID (`string[]`). |
144 * - 'id=>name' Returns an associative array of term names, |
143 * * 'id=>slug' Returns an associative array of term slugs, |
145 * keyed by term ID (`string[]`). |
144 * keyed by term ID (`string[]`). |
146 * - 'id=>slug' Returns an associative array of term slugs, |
145 * Default 'all'. |
147 * keyed by term ID (`string[]`). |
146 * @type bool $count Whether to return a term count. If true, will take precedence |
148 * Default 'all'. |
147 * over `$fields`. Default false. |
149 * @type bool $count Whether to return a term count. If true, will take precedence |
148 * @type string|array $name Optional. Name or array of names to return term(s) for. |
150 * over `$fields`. Default false. |
149 * Default empty. |
151 * @type string|string[] $name Name or array of names to return term(s) for. |
150 * @type string|array $slug Optional. Slug or array of slugs to return term(s) for. |
152 * Default empty. |
151 * Default empty. |
153 * @type string|string[] $slug Slug or array of slugs to return term(s) for. |
152 * @type int|int[] $term_taxonomy_id Optional. Term taxonomy ID, or array of term taxonomy IDs, |
154 * Default empty. |
153 * to match when querying terms. |
155 * @type int|int[] $term_taxonomy_id Term taxonomy ID, or array of term taxonomy IDs, |
154 * @type bool $hierarchical Whether to include terms that have non-empty descendants |
156 * to match when querying terms. |
155 * (even if $hide_empty is set to true). Default true. |
157 * @type bool $hierarchical Whether to include terms that have non-empty descendants |
156 * @type string $search Search criteria to match terms. Will be SQL-formatted with |
158 * (even if `$hide_empty` is set to true). Default true. |
157 * wildcards before and after. Default empty. |
159 * @type string $search Search criteria to match terms. Will be SQL-formatted with |
158 * @type string $name__like Retrieve terms with criteria by which a term is LIKE |
160 * wildcards before and after. Default empty. |
159 * `$name__like`. Default empty. |
161 * @type string $name__like Retrieve terms with criteria by which a term is LIKE |
160 * @type string $description__like Retrieve terms where the description is LIKE |
162 * `$name__like`. Default empty. |
161 * `$description__like`. Default empty. |
163 * @type string $description__like Retrieve terms where the description is LIKE |
162 * @type bool $pad_counts Whether to pad the quantity of a term's children in the |
164 * `$description__like`. Default empty. |
163 * quantity of each term's "count" object variable. |
165 * @type bool $pad_counts Whether to pad the quantity of a term's children in the |
164 * Default false. |
166 * quantity of each term's "count" object variable. |
165 * @type string $get Whether to return terms regardless of ancestry or whether the |
167 * Default false. |
166 * terms are empty. Accepts 'all' or empty (disabled). |
168 * @type string $get Whether to return terms regardless of ancestry or whether the |
167 * Default empty. |
169 * terms are empty. Accepts 'all' or '' (disabled). |
168 * @type int $child_of Term ID to retrieve child terms of. If multiple taxonomies |
170 * Default ''. |
169 * are passed, $child_of is ignored. Default 0. |
171 * @type int $child_of Term ID to retrieve child terms of. If multiple taxonomies |
170 * @type int|string $parent Parent term ID to retrieve direct-child terms of. |
172 * are passed, `$child_of` is ignored. Default 0. |
171 * Default empty. |
173 * @type int $parent Parent term ID to retrieve direct-child terms of. |
172 * @type bool $childless True to limit results to terms that have no children. |
174 * Default empty. |
173 * This parameter has no effect on non-hierarchical taxonomies. |
175 * @type bool $childless True to limit results to terms that have no children. |
174 * Default false. |
176 * This parameter has no effect on non-hierarchical taxonomies. |
175 * @type string $cache_domain Unique cache key to be produced when this query is stored in |
177 * Default false. |
176 * an object cache. Default is 'core'. |
178 * @type string $cache_domain Unique cache key to be produced when this query is stored in |
177 * @type bool $update_term_meta_cache Whether to prime meta caches for matched terms. Default true. |
179 * an object cache. Default 'core'. |
178 * @type array $meta_query Optional. Meta query clauses to limit retrieved terms by. |
180 * @type bool $update_term_meta_cache Whether to prime meta caches for matched terms. Default true. |
179 * See `WP_Meta_Query`. Default empty. |
181 * @type string|string[] $meta_key Meta key or keys to filter by. |
180 * @type string $meta_key Limit terms to those matching a specific metadata key. |
182 * @type string|string[] $meta_value Meta value or values to filter by. |
181 * Can be used in conjunction with `$meta_value`. Default empty. |
183 * @type string $meta_compare MySQL operator used for comparing the meta value. |
182 * @type string $meta_value Limit terms to those matching a specific metadata value. |
184 * See WP_Meta_Query::__construct for accepted values and default value. |
183 * Usually used in conjunction with `$meta_key`. Default empty. |
185 * @type string $meta_compare_key MySQL operator used for comparing the meta key. |
184 * @type string $meta_type MySQL data type that the `$meta_value` will be CAST to for |
186 * See WP_Meta_Query::__construct for accepted values and default value. |
185 * comparisons. Default empty. |
187 * @type string $meta_type MySQL data type that the meta_value column will be CAST to for comparisons. |
186 * @type string $meta_compare Comparison operator to test the 'meta_value'. Default empty. |
188 * See WP_Meta_Query::__construct for accepted values and default value. |
|
189 * @type string $meta_type_key MySQL data type that the meta_key column will be CAST to for comparisons. |
|
190 * See WP_Meta_Query::__construct for accepted values and default value. |
|
191 * @type array $meta_query An associative array of WP_Meta_Query arguments. |
|
192 * See WP_Meta_Query::__construct for accepted values. |
187 * } |
193 * } |
188 */ |
194 */ |
189 public function __construct( $query = '' ) { |
195 public function __construct( $query = '' ) { |
190 $this->query_var_defaults = array( |
196 $this->query_var_defaults = array( |
191 'taxonomy' => null, |
197 'taxonomy' => null, |
518 if ( ! empty( $exclusions ) ) { |
533 if ( ! empty( $exclusions ) ) { |
519 // Must do string manipulation here for backward compatibility with filter. |
534 // Must do string manipulation here for backward compatibility with filter. |
520 $this->sql_clauses['where']['exclusions'] = preg_replace( '/^\s*AND\s*/', '', $exclusions ); |
535 $this->sql_clauses['where']['exclusions'] = preg_replace( '/^\s*AND\s*/', '', $exclusions ); |
521 } |
536 } |
522 |
537 |
523 if ( |
538 if ( '' === $args['name'] ) { |
524 ( ! empty( $args['name'] ) ) || |
539 $args['name'] = array(); |
525 ( is_string( $args['name'] ) && 0 !== strlen( $args['name'] ) ) |
540 } else { |
526 ) { |
541 $args['name'] = (array) $args['name']; |
527 $names = (array) $args['name']; |
542 } |
|
543 |
|
544 if ( ! empty( $args['name'] ) ) { |
|
545 $names = $args['name']; |
528 foreach ( $names as &$_name ) { |
546 foreach ( $names as &$_name ) { |
529 // `sanitize_term_field()` returns slashed data. |
547 // `sanitize_term_field()` returns slashed data. |
530 $_name = stripslashes( sanitize_term_field( 'name', $_name, 0, reset( $taxonomies ), 'db' ) ); |
548 $_name = stripslashes( sanitize_term_field( 'name', $_name, 0, reset( $taxonomies ), 'db' ) ); |
531 } |
549 } |
532 |
550 |
533 $this->sql_clauses['where']['name'] = "t.name IN ('" . implode( "', '", array_map( 'esc_sql', $names ) ) . "')"; |
551 $this->sql_clauses['where']['name'] = "t.name IN ('" . implode( "', '", array_map( 'esc_sql', $names ) ) . "')"; |
534 } |
552 } |
535 |
553 |
536 if ( |
554 if ( '' === $args['slug'] ) { |
537 ( ! empty( $args['slug'] ) ) || |
555 $args['slug'] = array(); |
538 ( is_string( $args['slug'] ) && 0 !== strlen( $args['slug'] ) ) |
556 } else { |
539 ) { |
557 $args['slug'] = array_map( 'sanitize_title', (array) $args['slug'] ); |
540 if ( is_array( $args['slug'] ) ) { |
558 } |
541 $slug = array_map( 'sanitize_title', $args['slug'] ); |
559 |
542 $this->sql_clauses['where']['slug'] = "t.slug IN ('" . implode( "', '", $slug ) . "')"; |
560 if ( ! empty( $args['slug'] ) ) { |
543 } else { |
561 $slug = implode( "', '", $args['slug'] ); |
544 $slug = sanitize_title( $args['slug'] ); |
562 |
545 $this->sql_clauses['where']['slug'] = "t.slug = '$slug'"; |
563 $this->sql_clauses['where']['slug'] = "t.slug IN ('" . $slug . "')"; |
546 } |
564 } |
|
565 |
|
566 if ( '' === $args['term_taxonomy_id'] ) { |
|
567 $args['term_taxonomy_id'] = array(); |
|
568 } else { |
|
569 $args['term_taxonomy_id'] = array_map( 'intval', (array) $args['term_taxonomy_id'] ); |
547 } |
570 } |
548 |
571 |
549 if ( ! empty( $args['term_taxonomy_id'] ) ) { |
572 if ( ! empty( $args['term_taxonomy_id'] ) ) { |
550 if ( is_array( $args['term_taxonomy_id'] ) ) { |
573 $tt_ids = implode( ',', $args['term_taxonomy_id'] ); |
551 $tt_ids = implode( ',', array_map( 'intval', $args['term_taxonomy_id'] ) ); |
574 |
552 $this->sql_clauses['where']['term_taxonomy_id'] = "tt.term_taxonomy_id IN ({$tt_ids})"; |
575 $this->sql_clauses['where']['term_taxonomy_id'] = "tt.term_taxonomy_id IN ({$tt_ids})"; |
553 } else { |
|
554 $this->sql_clauses['where']['term_taxonomy_id'] = $wpdb->prepare( 'tt.term_taxonomy_id = %d', $args['term_taxonomy_id'] ); |
|
555 } |
|
556 } |
576 } |
557 |
577 |
558 if ( ! empty( $args['name__like'] ) ) { |
578 if ( ! empty( $args['name__like'] ) ) { |
559 $this->sql_clauses['where']['name__like'] = $wpdb->prepare( 't.name LIKE %s', '%' . $wpdb->esc_like( $args['name__like'] ) . '%' ); |
579 $this->sql_clauses['where']['name__like'] = $wpdb->prepare( |
|
580 't.name LIKE %s', |
|
581 '%' . $wpdb->esc_like( $args['name__like'] ) . '%' |
|
582 ); |
560 } |
583 } |
561 |
584 |
562 if ( ! empty( $args['description__like'] ) ) { |
585 if ( ! empty( $args['description__like'] ) ) { |
563 $this->sql_clauses['where']['description__like'] = $wpdb->prepare( 'tt.description LIKE %s', '%' . $wpdb->esc_like( $args['description__like'] ) . '%' ); |
586 $this->sql_clauses['where']['description__like'] = $wpdb->prepare( |
|
587 'tt.description LIKE %s', |
|
588 '%' . $wpdb->esc_like( $args['description__like'] ) . '%' |
|
589 ); |
|
590 } |
|
591 |
|
592 if ( '' === $args['object_ids'] ) { |
|
593 $args['object_ids'] = array(); |
|
594 } else { |
|
595 $args['object_ids'] = array_map( 'intval', (array) $args['object_ids'] ); |
564 } |
596 } |
565 |
597 |
566 if ( ! empty( $args['object_ids'] ) ) { |
598 if ( ! empty( $args['object_ids'] ) ) { |
567 $object_ids = $args['object_ids']; |
599 $object_ids = implode( ', ', $args['object_ids'] ); |
568 if ( ! is_array( $object_ids ) ) { |
600 |
569 $object_ids = array( $object_ids ); |
|
570 } |
|
571 |
|
572 $object_ids = implode( ', ', array_map( 'intval', $object_ids ) ); |
|
573 $this->sql_clauses['where']['object_ids'] = "tr.object_id IN ($object_ids)"; |
601 $this->sql_clauses['where']['object_ids'] = "tr.object_id IN ($object_ids)"; |
574 } |
602 } |
575 |
603 |
576 /* |
604 /* |
577 * When querying for object relationships, the 'count > 0' check |
605 * When querying for object relationships, the 'count > 0' check |
680 $fields = implode( ', ', apply_filters( 'get_terms_fields', $selects, $args, $taxonomies ) ); |
692 $fields = implode( ', ', apply_filters( 'get_terms_fields', $selects, $args, $taxonomies ) ); |
681 |
693 |
682 $join .= " INNER JOIN $wpdb->term_taxonomy AS tt ON t.term_id = tt.term_id"; |
694 $join .= " INNER JOIN $wpdb->term_taxonomy AS tt ON t.term_id = tt.term_id"; |
683 |
695 |
684 if ( ! empty( $this->query_vars['object_ids'] ) ) { |
696 if ( ! empty( $this->query_vars['object_ids'] ) ) { |
685 $join .= " INNER JOIN {$wpdb->term_relationships} AS tr ON tr.term_taxonomy_id = tt.term_taxonomy_id"; |
697 $join .= " INNER JOIN {$wpdb->term_relationships} AS tr ON tr.term_taxonomy_id = tt.term_taxonomy_id"; |
|
698 $distinct = 'DISTINCT'; |
686 } |
699 } |
687 |
700 |
688 $where = implode( ' AND ', $this->sql_clauses['where'] ); |
701 $where = implode( ' AND ', $this->sql_clauses['where'] ); |
|
702 |
|
703 $clauses = array( 'fields', 'join', 'where', 'distinct', 'orderby', 'order', 'limits' ); |
689 |
704 |
690 /** |
705 /** |
691 * Filters the terms query SQL clauses. |
706 * Filters the terms query SQL clauses. |
692 * |
707 * |
693 * @since 3.1.0 |
708 * @since 3.1.0 |
694 * |
709 * |
695 * @param string[] $pieces Array of query SQL clauses. |
710 * @param string[] $clauses { |
|
711 * Associative array of the clauses for the query. |
|
712 * |
|
713 * @type string $fields The SELECT clause of the query. |
|
714 * @type string $join The JOIN clause of the query. |
|
715 * @type string $where The WHERE clause of the query. |
|
716 * @type string $distinct The DISTINCT clause of the query. |
|
717 * @type string $orderby The ORDER BY clause of the query. |
|
718 * @type string $order The ORDER clause of the query. |
|
719 * @type string $limits The LIMIT clause of the query. |
|
720 * } |
696 * @param string[] $taxonomies An array of taxonomy names. |
721 * @param string[] $taxonomies An array of taxonomy names. |
697 * @param array $args An array of term query arguments. |
722 * @param array $args An array of term query arguments. |
698 */ |
723 */ |
699 $clauses = apply_filters( 'terms_clauses', compact( 'fields', 'join', 'where', 'distinct', 'orderby', 'order', 'limits' ), $taxonomies, $args ); |
724 $clauses = apply_filters( 'terms_clauses', compact( $clauses ), $taxonomies, $args ); |
700 |
725 |
701 $fields = isset( $clauses['fields'] ) ? $clauses['fields'] : ''; |
726 $fields = isset( $clauses['fields'] ) ? $clauses['fields'] : ''; |
702 $join = isset( $clauses['join'] ) ? $clauses['join'] : ''; |
727 $join = isset( $clauses['join'] ) ? $clauses['join'] : ''; |
703 $where = isset( $clauses['where'] ) ? $clauses['where'] : ''; |
728 $where = isset( $clauses['where'] ) ? $clauses['where'] : ''; |
704 $distinct = isset( $clauses['distinct'] ) ? $clauses['distinct'] : ''; |
729 $distinct = isset( $clauses['distinct'] ) ? $clauses['distinct'] : ''; |
735 if ( null !== $this->terms ) { |
766 if ( null !== $this->terms ) { |
736 return $this->terms; |
767 return $this->terms; |
737 } |
768 } |
738 |
769 |
739 // $args can be anything. Only use the args defined in defaults to compute the key. |
770 // $args can be anything. Only use the args defined in defaults to compute the key. |
740 $key = md5( serialize( wp_array_slice_assoc( $args, array_keys( $this->query_var_defaults ) ) ) . serialize( $taxonomies ) . $this->request ); |
771 $cache_args = wp_array_slice_assoc( $args, array_keys( $this->query_var_defaults ) ); |
|
772 |
|
773 unset( $cache_args['update_term_meta_cache'] ); |
|
774 |
|
775 if ( 'count' !== $_fields && 'all_with_object_id' !== $_fields ) { |
|
776 $cache_args['fields'] = 'all'; |
|
777 } |
|
778 |
|
779 $key = md5( serialize( $cache_args ) . serialize( $taxonomies ) . $this->request ); |
741 $last_changed = wp_cache_get_last_changed( 'terms' ); |
780 $last_changed = wp_cache_get_last_changed( 'terms' ); |
742 $cache_key = "get_terms:$key:$last_changed"; |
781 $cache_key = "get_terms:$key:$last_changed"; |
743 $cache = wp_cache_get( $cache_key, 'terms' ); |
782 $cache = wp_cache_get( $cache_key, 'terms' ); |
|
783 |
744 if ( false !== $cache ) { |
784 if ( false !== $cache ) { |
745 if ( 'all' === $_fields || 'all_with_object_id' === $_fields ) { |
785 if ( 'ids' === $_fields ) { |
746 $cache = $this->populate_terms( $cache ); |
786 $cache = array_map( 'intval', $cache ); |
|
787 } elseif ( 'count' !== $_fields ) { |
|
788 if ( ( 'all_with_object_id' === $_fields && ! empty( $args['object_ids'] ) ) || ( 'all' === $_fields && $args['pad_counts'] ) ) { |
|
789 $term_ids = wp_list_pluck( $cache, 'term_id' ); |
|
790 } else { |
|
791 $term_ids = array_map( 'intval', $cache ); |
|
792 } |
|
793 _prime_term_caches( $term_ids, $args['update_term_meta_cache'] ); |
|
794 $term_objects = $this->populate_terms( $cache ); |
|
795 $cache = $this->format_terms( $term_objects, $_fields ); |
747 } |
796 } |
748 |
797 |
749 $this->terms = $cache; |
798 $this->terms = $cache; |
750 return $this->terms; |
799 return $this->terms; |
751 } |
800 } |
752 |
801 |
753 if ( 'count' === $_fields ) { |
802 if ( 'count' === $_fields ) { |
754 $count = $wpdb->get_var( $this->request ); |
803 $count = $wpdb->get_var( $this->request ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared |
755 wp_cache_set( $cache_key, $count, 'terms' ); |
804 wp_cache_set( $cache_key, $count, 'terms' ); |
756 return $count; |
805 return $count; |
757 } |
806 } |
758 |
807 |
759 $terms = $wpdb->get_results( $this->request ); |
808 $terms = $wpdb->get_results( $this->request ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared |
760 |
|
761 if ( 'all' === $_fields || 'all_with_object_id' === $_fields ) { |
|
762 update_term_cache( $terms ); |
|
763 } |
|
764 |
|
765 // Prime termmeta cache. |
|
766 if ( $args['update_term_meta_cache'] ) { |
|
767 $term_ids = wp_list_pluck( $terms, 'term_id' ); |
|
768 update_termmeta_cache( $term_ids ); |
|
769 } |
|
770 |
809 |
771 if ( empty( $terms ) ) { |
810 if ( empty( $terms ) ) { |
772 wp_cache_add( $cache_key, array(), 'terms', DAY_IN_SECONDS ); |
811 wp_cache_add( $cache_key, array(), 'terms' ); |
773 return array(); |
812 return array(); |
774 } |
813 } |
|
814 |
|
815 $term_ids = wp_list_pluck( $terms, 'term_id' ); |
|
816 _prime_term_caches( $term_ids, false ); |
|
817 $term_objects = $this->populate_terms( $terms ); |
775 |
818 |
776 if ( $child_of ) { |
819 if ( $child_of ) { |
777 foreach ( $taxonomies as $_tax ) { |
820 foreach ( $taxonomies as $_tax ) { |
778 $children = _get_term_hierarchy( $_tax ); |
821 $children = _get_term_hierarchy( $_tax ); |
779 if ( ! empty( $children ) ) { |
822 if ( ! empty( $children ) ) { |
780 $terms = _get_term_children( $child_of, $terms, $_tax ); |
823 $term_objects = _get_term_children( $child_of, $term_objects, $_tax ); |
781 } |
824 } |
782 } |
825 } |
783 } |
826 } |
784 |
827 |
785 // Update term counts to include children. |
828 // Update term counts to include children. |
786 if ( $args['pad_counts'] && 'all' === $_fields ) { |
829 if ( $args['pad_counts'] && 'all' === $_fields ) { |
787 foreach ( $taxonomies as $_tax ) { |
830 foreach ( $taxonomies as $_tax ) { |
788 _pad_term_counts( $terms, $_tax ); |
831 _pad_term_counts( $term_objects, $_tax ); |
789 } |
832 } |
790 } |
833 } |
791 |
834 |
792 // Make sure we show empty categories that have children. |
835 // Make sure we show empty categories that have children. |
793 if ( $hierarchical && $args['hide_empty'] && is_array( $terms ) ) { |
836 if ( $hierarchical && $args['hide_empty'] && is_array( $term_objects ) ) { |
794 foreach ( $terms as $k => $term ) { |
837 foreach ( $term_objects as $k => $term ) { |
795 if ( ! $term->count ) { |
838 if ( ! $term->count ) { |
796 $children = get_term_children( $term->term_id, $term->taxonomy ); |
839 $children = get_term_children( $term->term_id, $term->taxonomy ); |
797 if ( is_array( $children ) ) { |
840 if ( is_array( $children ) ) { |
798 foreach ( $children as $child_id ) { |
841 foreach ( $children as $child_id ) { |
799 $child = get_term( $child_id, $term->taxonomy ); |
842 $child = get_term( $child_id, $term->taxonomy ); |
802 } |
845 } |
803 } |
846 } |
804 } |
847 } |
805 |
848 |
806 // It really is empty. |
849 // It really is empty. |
807 unset( $terms[ $k ] ); |
850 unset( $term_objects[ $k ] ); |
808 } |
851 } |
809 } |
852 } |
810 } |
853 } |
811 |
854 |
812 /* |
|
813 * When querying for terms connected to objects, we may get |
|
814 * duplicate results. The duplicates should be preserved if |
|
815 * `$fields` is 'all_with_object_id', but should otherwise be |
|
816 * removed. |
|
817 */ |
|
818 if ( ! empty( $args['object_ids'] ) && 'all_with_object_id' !== $_fields ) { |
|
819 $_tt_ids = array(); |
|
820 $_terms = array(); |
|
821 foreach ( $terms as $term ) { |
|
822 if ( isset( $_tt_ids[ $term->term_id ] ) ) { |
|
823 continue; |
|
824 } |
|
825 |
|
826 $_tt_ids[ $term->term_id ] = 1; |
|
827 $_terms[] = $term; |
|
828 } |
|
829 |
|
830 $terms = $_terms; |
|
831 } |
|
832 |
|
833 $_terms = array(); |
|
834 if ( 'id=>parent' === $_fields ) { |
|
835 foreach ( $terms as $term ) { |
|
836 $_terms[ $term->term_id ] = $term->parent; |
|
837 } |
|
838 } elseif ( 'ids' === $_fields ) { |
|
839 foreach ( $terms as $term ) { |
|
840 $_terms[] = (int) $term->term_id; |
|
841 } |
|
842 } elseif ( 'tt_ids' === $_fields ) { |
|
843 foreach ( $terms as $term ) { |
|
844 $_terms[] = (int) $term->term_taxonomy_id; |
|
845 } |
|
846 } elseif ( 'names' === $_fields ) { |
|
847 foreach ( $terms as $term ) { |
|
848 $_terms[] = $term->name; |
|
849 } |
|
850 } elseif ( 'slugs' === $_fields ) { |
|
851 foreach ( $terms as $term ) { |
|
852 $_terms[] = $term->slug; |
|
853 } |
|
854 } elseif ( 'id=>name' === $_fields ) { |
|
855 foreach ( $terms as $term ) { |
|
856 $_terms[ $term->term_id ] = $term->name; |
|
857 } |
|
858 } elseif ( 'id=>slug' === $_fields ) { |
|
859 foreach ( $terms as $term ) { |
|
860 $_terms[ $term->term_id ] = $term->slug; |
|
861 } |
|
862 } |
|
863 |
|
864 if ( ! empty( $_terms ) ) { |
|
865 $terms = $_terms; |
|
866 } |
|
867 |
|
868 // Hierarchical queries are not limited, so 'offset' and 'number' must be handled now. |
855 // Hierarchical queries are not limited, so 'offset' and 'number' must be handled now. |
869 if ( $hierarchical && $number && is_array( $terms ) ) { |
856 if ( $hierarchical && $number && is_array( $term_objects ) ) { |
870 if ( $offset >= count( $terms ) ) { |
857 if ( $offset >= count( $term_objects ) ) { |
871 $terms = array(); |
858 $term_objects = array(); |
872 } else { |
859 } else { |
873 $terms = array_slice( $terms, $offset, $number, true ); |
860 $term_objects = array_slice( $term_objects, $offset, $number, true ); |
874 } |
861 } |
875 } |
862 } |
876 |
863 |
877 wp_cache_add( $cache_key, $terms, 'terms', DAY_IN_SECONDS ); |
864 // Prime termmeta cache. |
878 |
865 if ( $args['update_term_meta_cache'] ) { |
879 if ( 'all' === $_fields || 'all_with_object_id' === $_fields ) { |
866 $term_ids = wp_list_pluck( $term_objects, 'term_id' ); |
880 $terms = $this->populate_terms( $terms ); |
867 update_termmeta_cache( $term_ids ); |
881 } |
868 } |
882 |
869 |
883 $this->terms = $terms; |
870 if ( 'all_with_object_id' === $_fields && ! empty( $args['object_ids'] ) ) { |
|
871 $term_cache = array(); |
|
872 foreach ( $term_objects as $term ) { |
|
873 $object = new stdClass(); |
|
874 $object->term_id = $term->term_id; |
|
875 $object->object_id = $term->object_id; |
|
876 $term_cache[] = $object; |
|
877 } |
|
878 } elseif ( 'all' === $_fields && $args['pad_counts'] ) { |
|
879 $term_cache = array(); |
|
880 foreach ( $term_objects as $term ) { |
|
881 $object = new stdClass(); |
|
882 $object->term_id = $term->term_id; |
|
883 $object->count = $term->count; |
|
884 $term_cache[] = $object; |
|
885 } |
|
886 } else { |
|
887 $term_cache = wp_list_pluck( $term_objects, 'term_id' ); |
|
888 } |
|
889 wp_cache_add( $cache_key, $term_cache, 'terms' ); |
|
890 $this->terms = $this->format_terms( $term_objects, $_fields ); |
|
891 |
884 return $this->terms; |
892 return $this->terms; |
885 } |
893 } |
886 |
894 |
887 /** |
895 /** |
888 * Parse and sanitize 'orderby' keys passed to the term query. |
896 * Parse and sanitize 'orderby' keys passed to the term query. |