]> scripts.mit.edu Git - autoinstalls/wordpress.git/blobdiff - wp-includes/class-wp-term-query.php
WordPress 4.7
[autoinstalls/wordpress.git] / wp-includes / class-wp-term-query.php
index 38977f451c8e4dc6089d8cb2fa5fa927dbfe847c..434d810db021742318cf13edda770115ff18bed0 100644 (file)
@@ -93,6 +93,7 @@ class WP_Term_Query {
         *
         * @since 4.6.0
         * @since 4.6.0 Introduced 'term_taxonomy_id' parameter.
+        * @since 4.7.0 Introduced 'object_ids' parameter.
         * @access public
         *
         * @param string|array $query {
@@ -100,6 +101,8 @@ class WP_Term_Query {
         *
         *     @type string|array $taxonomy               Taxonomy name, or array of taxonomies, to which results should
         *                                                be limited.
+        *     @type int|array    $object_ids             Optional. Object ID, or array of object IDs. Results will be
+        *                                                limited to terms associated with these objects.
         *     @type string       $orderby                Field(s) to order terms by. Accepts term fields ('name',
         *                                                'slug', 'term_group', 'term_id', 'id', 'description'),
         *                                                'count' for term taxonomy count, 'include' to match the
@@ -123,13 +126,17 @@ class WP_Term_Query {
         *                                                positive number. Default ''|0 (all).
         *     @type int          $offset                 The number by which to offset the terms query. Default empty.
         *     @type string       $fields                 Term fields to query for. Accepts 'all' (returns an array of
-        *                                                complete term objects), 'ids' (returns an array of ids),
-        *                                                'id=>parent' (returns an associative array with ids as keys,
-        *                                                parent term IDs as values), 'names' (returns an array of term
-        *                                                names), 'count' (returns the number of matching terms),
-        *                                                'id=>name' (returns an associative array with ids as keys,
-        *                                                term names as values), or 'id=>slug' (returns an associative
-        *                                                array with ids as keys, term slugs as values). Default 'all'.
+        *                                                complete term objects), 'all_with_object_id' (returns an
+        *                                                array of term objects with the 'object_id' param; only works
+        *                                                when the `$fields` parameter is 'object_ids' ), 'ids'
+        *                                                (returns an array of ids), 'tt_ids' (returns an array of
+        *                                                term taxonomy ids), 'id=>parent' (returns an associative
+        *                                                array with ids as keys, parent term IDs as values), 'names'
+        *                                                (returns an array of term names), 'count' (returns the number
+        *                                                of matching terms), 'id=>name' (returns an associative array
+        *                                                with ids as keys, term names as values), or 'id=>slug'
+        *                                                (returns an associative array with ids as keys, term slugs
+        *                                                as values). Default 'all'.
         *     @type bool         $count                  Whether to return a term count (true) or array of term objects
         *                                                (false). Will take precedence over `$fields` if true.
         *                                                Default false.
@@ -174,6 +181,7 @@ class WP_Term_Query {
        public function __construct( $query = '' ) {
                $this->query_var_defaults = array(
                        'taxonomy'               => null,
+                       'object_ids'             => null,
                        'orderby'                => 'name',
                        'order'                  => 'ASC',
                        'hide_empty'             => true,
@@ -199,6 +207,10 @@ class WP_Term_Query {
                        'cache_domain'           => 'core',
                        'update_term_meta_cache' => true,
                        'meta_query'             => '',
+                       'meta_key'               => '',
+                       'meta_value'             => '',
+                       'meta_type'              => '',
+                       'meta_compare'           => '',
                );
 
                if ( ! empty( $query ) ) {
@@ -253,15 +265,7 @@ class WP_Term_Query {
 
                $query['taxonomy'] = $taxonomies;
 
-               /**
-                * Filters the terms query arguments.
-                *
-                * @since 3.1.0
-                *
-                * @param array $args       An array of get_terms() arguments.
-                * @param array $taxonomies An array of taxonomies.
-                */
-               $this->query_vars = apply_filters( 'get_terms_args', $query, $taxonomies );
+               $this->query_vars = $query;
 
                /**
                 * Fires after term query vars have been parsed.
@@ -383,7 +387,13 @@ class WP_Term_Query {
                        }
                }
 
-               $orderby = $this->parse_orderby( $this->query_vars['orderby'] );
+               // 'term_order' is a legal sort order only when joining the relationship table.
+               $_orderby = $this->query_vars['orderby'];
+               if ( 'term_order' === $_orderby && empty( $this->query_vars['object_ids'] ) ) {
+                       $_orderby = 'term_id';
+               }
+               $orderby = $this->parse_orderby( $_orderby );
+
                if ( $orderby ) {
                        $orderby = "ORDER BY $orderby";
                }
@@ -498,6 +508,24 @@ class WP_Term_Query {
                        $this->sql_clauses['where']['description__like'] = $wpdb->prepare( "tt.description LIKE %s", '%' . $wpdb->esc_like( $args['description__like'] ) . '%' );
                }
 
+               if ( ! empty( $args['object_ids'] ) ) {
+                       $object_ids = $args['object_ids'];
+                       if ( ! is_array( $object_ids ) ) {
+                               $object_ids = array( $object_ids );
+                       }
+
+                       $object_ids = implode( ', ', array_map( 'intval', $object_ids ) );
+                       $this->sql_clauses['where']['object_ids'] = "tr.object_id IN ($object_ids)";
+               }
+
+               /*
+                * When querying for object relationships, the 'count > 0' check
+                * added by 'hide_empty' is superfluous.
+                */
+               if ( ! empty( $args['object_ids'] ) ) {
+                       $args['hide_empty'] = false;
+               }
+
                if ( '' !== $parent ) {
                        $parent = (int) $parent;
                        $this->sql_clauses['where']['parent'] = "tt.parent = '$parent'";
@@ -549,7 +577,13 @@ class WP_Term_Query {
                $selects = array();
                switch ( $args['fields'] ) {
                        case 'all':
+                       case 'all_with_object_id' :
+                       case 'tt_ids' :
+                       case 'slugs' :
                                $selects = array( 't.*', 'tt.*' );
+                               if ( 'all_with_object_id' === $args['fields'] && ! empty( $args['object_ids'] ) ) {
+                                       $selects[] = 'tr.object_id';
+                               }
                                break;
                        case 'ids':
                        case 'id=>parent':
@@ -593,9 +627,11 @@ class WP_Term_Query {
 
                $join .= " INNER JOIN $wpdb->term_taxonomy AS tt ON t.term_id = tt.term_id";
 
-               $where = implode( ' AND ', $this->sql_clauses['where'] );
+               if ( ! empty( $this->query_vars['object_ids'] ) ) {
+                       $join .= " INNER JOIN {$wpdb->term_relationships} AS tr ON tr.term_taxonomy_id = tt.term_taxonomy_id";
+               }
 
-               $pieces = array( 'fields', 'join', 'where', 'distinct', 'orderby', 'order', 'limits' );
+               $where = implode( ' AND ', $this->sql_clauses['where'] );
 
                /**
                 * Filters the terms query SQL clauses.
@@ -606,7 +642,7 @@ class WP_Term_Query {
                 * @param array $taxonomies An array of taxonomies.
                 * @param array $args       An array of terms query arguments.
                 */
-               $clauses = apply_filters( 'terms_clauses', compact( $pieces ), $taxonomies, $args );
+               $clauses = apply_filters( 'terms_clauses', compact( 'fields', 'join', 'where', 'distinct', 'orderby', 'order', 'limits' ), $taxonomies, $args );
 
                $fields = isset( $clauses[ 'fields' ] ) ? $clauses[ 'fields' ] : '';
                $join = isset( $clauses[ 'join' ] ) ? $clauses[ 'join' ] : '';
@@ -629,11 +665,7 @@ class WP_Term_Query {
 
                // $args can be anything. Only use the args defined in defaults to compute the key.
                $key = md5( serialize( wp_array_slice_assoc( $args, array_keys( $this->query_var_defaults ) ) ) . serialize( $taxonomies ) . $this->request );
-               $last_changed = wp_cache_get( 'last_changed', 'terms' );
-               if ( ! $last_changed ) {
-                       $last_changed = microtime();
-                       wp_cache_set( 'last_changed', $last_changed, 'terms' );
-               }
+               $last_changed = wp_cache_get_last_changed( 'terms' );
                $cache_key = "get_terms:$key:$last_changed";
                $cache = wp_cache_get( $cache_key, 'terms' );
                if ( false !== $cache ) {
@@ -646,11 +678,13 @@ class WP_Term_Query {
                }
 
                if ( 'count' == $_fields ) {
-                       return $wpdb->get_var( $this->request );
+                       $count = $wpdb->get_var( $this->request );
+                       wp_cache_set( $cache_key, $count, 'terms' );
+                       return $count;
                }
 
                $terms = $wpdb->get_results( $this->request );
-               if ( 'all' == $_fields ) {
+               if ( 'all' == $_fields || 'all_with_object_id' === $_fields ) {
                        update_term_cache( $terms );
                }
 
@@ -701,6 +735,26 @@ class WP_Term_Query {
                        }
                }
 
+               /*
+                * When querying for terms connected to objects, we may get
+                * duplicate results. The duplicates should be preserved if
+                * `$fields` is 'all_with_object_id', but should otherwise be
+                * removed.
+                */
+               if ( ! empty( $args['object_ids'] ) && 'all_with_object_id' != $_fields ) {
+                       $_tt_ids = $_terms = array();
+                       foreach ( $terms as $term ) {
+                               if ( isset( $_tt_ids[ $term->term_id ] ) ) {
+                                       continue;
+                               }
+
+                               $_tt_ids[ $term->term_id ] = 1;
+                               $_terms[] = $term;
+                       }
+
+                       $terms = $_terms;
+               }
+
                $_terms = array();
                if ( 'id=>parent' == $_fields ) {
                        foreach ( $terms as $term ) {
@@ -708,12 +762,20 @@ class WP_Term_Query {
                        }
                } elseif ( 'ids' == $_fields ) {
                        foreach ( $terms as $term ) {
-                               $_terms[] = $term->term_id;
+                               $_terms[] = (int) $term->term_id;
+                       }
+               } elseif ( 'tt_ids' == $_fields ) {
+                       foreach ( $terms as $term ) {
+                               $_terms[] = (int) $term->term_taxonomy_id;
                        }
                } elseif ( 'names' == $_fields ) {
                        foreach ( $terms as $term ) {
                                $_terms[] = $term->name;
                        }
+               } elseif ( 'slugs' == $_fields ) {
+                       foreach ( $terms as $term ) {
+                               $_terms[] = $term->slug;
+                       }
                } elseif ( 'id=>name' == $_fields ) {
                        foreach ( $terms as $term ) {
                                $_terms[ $term->term_id ] = $term->name;
@@ -739,7 +801,7 @@ class WP_Term_Query {
 
                wp_cache_add( $cache_key, $terms, 'terms', DAY_IN_SECONDS );
 
-               if ( 'all' === $_fields ) {
+               if ( 'all' === $_fields || 'all_with_object_id' === $_fields ) {
                        $terms = array_map( 'get_term', $terms );
                }
 
@@ -761,19 +823,16 @@ class WP_Term_Query {
        protected function parse_orderby( $orderby_raw ) {
                $_orderby = strtolower( $orderby_raw );
                $maybe_orderby_meta = false;
-               if ( 'count' == $_orderby ) {
-                       $orderby = 'tt.count';
-               } elseif ( 'name' == $_orderby ) {
-                       $orderby = 't.name';
-               } elseif ( 'slug' == $_orderby ) {
-                       $orderby = 't.slug';
+
+               if ( in_array( $_orderby, array( 'term_id', 'name', 'slug', 'term_group' ), true ) ) {
+                       $orderby = "t.$_orderby";
+               } elseif ( in_array( $_orderby, array( 'count', 'parent', 'taxonomy', 'term_taxonomy_id', 'description' ), true ) ) {
+                       $orderby = "tt.$_orderby";
+               } elseif ( 'term_order' === $_orderby ) {
+                       $orderby = 'tr.term_order';
                } elseif ( 'include' == $_orderby && ! empty( $this->query_vars['include'] ) ) {
-                       $include = implode( ',', array_map( 'absint', $this->query_vars['include'] ) );
+                       $include = implode( ',', wp_parse_id_list( $this->query_vars['include'] ) );
                        $orderby = "FIELD( t.term_id, $include )";
-               } elseif ( 'term_group' == $_orderby ) {
-                       $orderby = 't.term_group';
-               } elseif ( 'description' == $_orderby ) {
-                       $orderby = 'tt.description';
                } elseif ( 'none' == $_orderby ) {
                        $orderby = '';
                } elseif ( empty( $_orderby ) || 'id' == $_orderby || 'term_id' === $_orderby ) {