/** * Retrieves the terms associated with the given object(s), in the supplied taxonomies. * * The following information has to do the $args parameter and for what can be * contained in the string or array of that parameter, if it exists. * * The first argument is called, 'orderby' and has the default value of 'name'. * The other value that is supported is 'count'. * * The second argument is called, 'order' and has the default value of 'ASC'. * The only other value that will be acceptable is 'DESC'. * * The final argument supported is called, 'fields' and has the default value of * 'all'. There are multiple other options that can be used instead. Supported * values are as follows: 'all', 'ids', 'names', and finally * 'all_with_object_id'. * * The fields argument also decides what will be returned. If 'all' or * 'all_with_object_id' is choosen or the default kept intact, then all matching * terms objects will be returned. If either 'ids' or 'names' is used, then an * array of all matching term ids or term names will be returned respectively. * * @package WordPress * @subpackage Taxonomy * @since 2.3.0 * @uses $wpdb * * @param int|array $object_id The id of the object(s) to retrieve. * @param string|array $taxonomies The taxonomies to retrieve terms from. * @param array|string $args Change what is returned * @return array|WP_Error The requested term data or empty array if no terms found. WP_Error if $taxonomy does not exist. */ function wp_get_object_terms($object_ids, $taxonomies, $args = array()) { global $wpdb; if (!is_array($taxonomies)) { $taxonomies = array($taxonomies); } foreach ((array) $taxonomies as $taxonomy) { if (!is_taxonomy($taxonomy)) { return new WP_Error('invalid_taxonomy', __('Invalid Taxonomy')); } } if (!is_array($object_ids)) { $object_ids = array($object_ids); } $object_ids = array_map('intval', $object_ids); $defaults = array('orderby' => 'name', 'order' => 'ASC', 'fields' => 'all'); $args = wp_parse_args($args, $defaults); $terms = array(); if (count($taxonomies) > 1) { foreach ($taxonomies as $index => $taxonomy) { $t = get_taxonomy($taxonomy); if (isset($t->args) && is_array($t->args) && $args != array_merge($args, $t->args)) { unset($taxonomies[$index]); $terms = array_merge($terms, wp_get_object_terms($object_ids, $taxonomy, array_merge($args, $t->args))); } } } else { $t = get_taxonomy($taxonomies[0]); if (isset($t->args) && is_array($t->args)) { $args = array_merge($args, $t->args); } } extract($args, EXTR_SKIP); if ('count' == $orderby) { $orderby = 'tt.count'; } else { if ('name' == $orderby) { $orderby = 't.name'; } else { if ('slug' == $orderby) { $orderby = 't.slug'; } else { if ('term_group' == $orderby) { $orderby = 't.term_group'; } else { if ('term_order' == $orderby) { $orderby = 'tr.term_order'; } else { if ('none' == $orderby) { $orderby = ''; $order = ''; } else { $orderby = 't.term_id'; } } } } } } // tt_ids queries can only be none or tr.term_taxonomy_id if ('tt_ids' == $fields && !empty($orderby)) { $orderby = 'tr.term_taxonomy_id'; } if (!empty($orderby)) { $orderby = "ORDER BY {$orderby}"; } $taxonomies = "'" . implode("', '", $taxonomies) . "'"; $object_ids = implode(', ', $object_ids); $select_this = ''; if ('all' == $fields) { $select_this = 't.*, tt.*'; } else { if ('ids' == $fields) { $select_this = 't.term_id'; } else { if ('names' == $fields) { $select_this = 't.name'; } else { if ('all_with_object_id' == $fields) { $select_this = 't.*, tt.*, tr.object_id'; } } } } $query = "SELECT {$select_this} FROM {$wpdb->terms} AS t INNER JOIN {$wpdb->term_taxonomy} AS tt ON tt.term_id = t.term_id INNER JOIN {$wpdb->term_relationships} AS tr ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tt.taxonomy IN ({$taxonomies}) AND tr.object_id IN ({$object_ids}) {$orderby} {$order}"; if ('all' == $fields || 'all_with_object_id' == $fields) { $terms = array_merge($terms, $wpdb->get_results($query)); update_term_cache($terms); } else { if ('ids' == $fields || 'names' == $fields) { $terms = array_merge($terms, $wpdb->get_col($query)); } else { if ('tt_ids' == $fields) { $terms = $wpdb->get_col("SELECT tr.term_taxonomy_id FROM {$wpdb->term_relationships} AS tr INNER JOIN {$wpdb->term_taxonomy} AS tt ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tr.object_id IN ({$object_ids}) AND tt.taxonomy IN ({$taxonomies}) {$orderby} {$order}"); } } } if (!$terms) { $terms = array(); } return apply_filters('wp_get_object_terms', $terms, $object_ids, $taxonomies, $args); }
/** * Adds tags and categories to the sitemap. * * @since 1.3 */ protected function taxonomies() { global $wpdb; $taxonomy = $this->get_info('content_type'); if (!($taxonomy == 'category' || $taxonomy == 'post_tag')) { return false; } $tax_not_in = ''; $limit = $this->getLimit(); $exclude = $this->get_info('exclude', array()); if ($exclude && ($ids = wp_parse_id_list($exclude))) { $tax_not_in = 't.term_id NOT IN (' . implode(',', $ids) . ') AND'; } // t.slug and tt.taxonomy are necessary to make get_term_link() work properly $terms = $wpdb->get_results("SELECT t.term_id, t.slug, tt.taxonomy, MAX(p.post_modified) AS `last_modified`\n\t\t\t FROM {$wpdb->terms} AS t\n\t\t\t INNER JOIN {$wpdb->term_taxonomy} AS tt USING(term_id)\n\t\t\t \tCROSS JOIN {$wpdb->term_relationships} AS tr USING(term_taxonomy_id)\n\t\t\t \tCROSS JOIN {$wpdb->posts} AS p ON p.ID = tr.object_id\n\t\t\t WHERE {$tax_not_in} tt.taxonomy = '{$taxonomy}' AND p.post_type = 'post' AND p.post_status = 'publish'\n\t\t\t GROUP BY t.term_id\n\t\t\t ORDER BY p.post_modified DESC\n\t\t\t LIMIT {$limit}"); // This hack lets us save a lot of queries that would be performed when we call get_term_link() update_term_cache($terms); if ($terms) { $changefreq = $this->get_info('changefreq', 'none'); $priority = $this->get_info('priority', 'none'); foreach ($terms as $term) { $this->addUrlItem(get_term_link($term), $term->last_modified, $changefreq, $priority); } } }
/** * Retrieves the terms associated with the given object(s), in the supplied taxonomies. * * The following information has to do the $args parameter and for what can be * contained in the string or array of that parameter, if it exists. * * The first argument is called, 'orderby' and has the default value of 'name'. * The other value that is supported is 'count'. * * The second argument is called, 'order' and has the default value of 'ASC'. * The only other value that will be acceptable is 'DESC'. * * The final argument supported is called, 'fields' and has the default value of * 'all'. There are multiple other options that can be used instead. Supported * values are as follows: 'all', 'ids', 'names', and finally * 'all_with_object_id'. * * The fields argument also decides what will be returned. If 'all' or * 'all_with_object_id' is chosen or the default kept intact, then all matching * terms objects will be returned. If either 'ids' or 'names' is used, then an * array of all matching term ids or term names will be returned respectively. * * @since 2.3.0 * * @global wpdb $wpdb WordPress database abstraction object. * * @param int|array $object_ids The ID(s) of the object(s) to retrieve. * @param string|array $taxonomies The taxonomies to retrieve terms from. * @param array|string $args Change what is returned * @return array|WP_Error The requested term data or empty array if no terms found. WP_Error if any of the $taxonomies don't exist. */ function wp_get_object_terms($object_ids, $taxonomies, $args = array()) { global $wpdb; if ( empty( $object_ids ) || empty( $taxonomies ) ) return array(); if ( !is_array($taxonomies) ) $taxonomies = array($taxonomies); foreach ( $taxonomies as $taxonomy ) { if ( ! taxonomy_exists($taxonomy) ) return new WP_Error('invalid_taxonomy', __('Invalid taxonomy')); } if ( !is_array($object_ids) ) $object_ids = array($object_ids); $object_ids = array_map('intval', $object_ids); $defaults = array('orderby' => 'name', 'order' => 'ASC', 'fields' => 'all'); $args = wp_parse_args( $args, $defaults ); $terms = array(); if ( count($taxonomies) > 1 ) { foreach ( $taxonomies as $index => $taxonomy ) { $t = get_taxonomy($taxonomy); if ( isset($t->args) && is_array($t->args) && $args != array_merge($args, $t->args) ) { unset($taxonomies[$index]); $terms = array_merge($terms, wp_get_object_terms($object_ids, $taxonomy, array_merge($args, $t->args))); } } } else { $t = get_taxonomy($taxonomies[0]); if ( isset($t->args) && is_array($t->args) ) $args = array_merge($args, $t->args); } $orderby = $args['orderby']; $order = $args['order']; $fields = $args['fields']; if ( 'count' == $orderby ) $orderby = 'tt.count'; else if ( 'name' == $orderby ) $orderby = 't.name'; else if ( 'slug' == $orderby ) $orderby = 't.slug'; else if ( 'term_group' == $orderby ) $orderby = 't.term_group'; else if ( 'term_order' == $orderby ) $orderby = 'tr.term_order'; else if ( 'none' == $orderby ) { $orderby = ''; $order = ''; } else { $orderby = 't.term_id'; } // tt_ids queries can only be none or tr.term_taxonomy_id if ( ('tt_ids' == $fields) && !empty($orderby) ) $orderby = 'tr.term_taxonomy_id'; if ( !empty($orderby) ) $orderby = "ORDER BY $orderby"; $order = strtoupper( $order ); if ( '' !== $order && ! in_array( $order, array( 'ASC', 'DESC' ) ) ) $order = 'ASC'; $taxonomies = "'" . implode("', '", array_map( 'esc_sql', $taxonomies ) ) . "'"; $object_ids = implode(', ', $object_ids); $select_this = ''; if ( 'all' == $fields ) $select_this = 't.*, tt.*'; else if ( 'ids' == $fields ) $select_this = 't.term_id'; else if ( 'names' == $fields ) $select_this = 't.name'; else if ( 'slugs' == $fields ) $select_this = 't.slug'; else if ( 'all_with_object_id' == $fields ) $select_this = 't.*, tt.*, tr.object_id'; $query = "SELECT $select_this FROM $wpdb->terms AS t INNER JOIN $wpdb->term_taxonomy AS tt ON tt.term_id = t.term_id INNER JOIN $wpdb->term_relationships AS tr ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tt.taxonomy IN ($taxonomies) AND tr.object_id IN ($object_ids) $orderby $order"; $objects = false; if ( 'all' == $fields || 'all_with_object_id' == $fields ) { $_terms = $wpdb->get_results( $query ); foreach ( $_terms as $key => $term ) { $_terms[$key] = sanitize_term( $term, $taxonomy, 'raw' ); } $terms = array_merge( $terms, $_terms ); update_term_cache( $terms ); $objects = true; } else if ( 'ids' == $fields || 'names' == $fields || 'slugs' == $fields ) { $_terms = $wpdb->get_col( $query ); $_field = ( 'ids' == $fields ) ? 'term_id' : 'name'; foreach ( $_terms as $key => $term ) { $_terms[$key] = sanitize_term_field( $_field, $term, $term, $taxonomy, 'raw' ); } $terms = array_merge( $terms, $_terms ); } else if ( 'tt_ids' == $fields ) { $terms = $wpdb->get_col("SELECT tr.term_taxonomy_id FROM $wpdb->term_relationships AS tr INNER JOIN $wpdb->term_taxonomy AS tt ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tr.object_id IN ($object_ids) AND tt.taxonomy IN ($taxonomies) $orderby $order"); foreach ( $terms as $key => $tt_id ) { $terms[$key] = sanitize_term_field( 'term_taxonomy_id', $tt_id, 0, $taxonomy, 'raw' ); // 0 should be the term id, however is not needed when using raw context. } } if ( ! $terms ) { $terms = array(); } elseif ( $objects && 'all_with_object_id' !== $fields ) { $_tt_ids = array(); $_terms = array(); foreach ( $terms as $term ) { if ( in_array( $term->term_taxonomy_id, $_tt_ids ) ) { continue; } $_tt_ids[] = $term->term_taxonomy_id; $_terms[] = $term; } $terms = $_terms; } elseif ( ! $objects ) { $terms = array_values( array_unique( $terms ) ); } /** * Filter the terms for a given object or objects. * * @since 2.8.0 * * @param array $terms An array of terms for the given object or objects. * @param array|int $object_ids Object ID or array of IDs. * @param array|string $taxonomies A taxonomy or array of taxonomies. * @param array $args An array of arguments for retrieving terms for * the given object(s). */ return apply_filters( 'wp_get_object_terms', $terms, $object_ids, $taxonomies, $args ); }
/** * Get terms, based on query_vars. * * @param 4.6.0 * @access public * * @global wpdb $wpdb WordPress database abstraction object. * * @return array */ public function get_terms() { global $wpdb; $this->parse_query($this->query_vars); $args = $this->query_vars; // Set up meta_query so it's available to 'pre_get_terms'. $this->meta_query = new WP_Meta_Query(); $this->meta_query->parse_query_vars($args); /** * Fires before terms are retrieved. * * @since 4.6.0 * * @param WP_Term_Query $this Current instance of WP_Term_Query. */ do_action('pre_get_terms', $this); $taxonomies = $args['taxonomy']; // Save queries by not crawling the tree in the case of multiple taxes or a flat tax. $has_hierarchical_tax = false; if ($taxonomies) { foreach ($taxonomies as $_tax) { if (is_taxonomy_hierarchical($_tax)) { $has_hierarchical_tax = true; } } } if (!$has_hierarchical_tax) { $args['hierarchical'] = false; $args['pad_counts'] = false; } // 'parent' overrides 'child_of'. if (0 < intval($args['parent'])) { $args['child_of'] = false; } if ('all' == $args['get']) { $args['childless'] = false; $args['child_of'] = 0; $args['hide_empty'] = 0; $args['hierarchical'] = false; $args['pad_counts'] = false; } /** * 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. */ $args = apply_filters('get_terms_args', $args, $taxonomies); // Avoid the query if the queried parent/child_of term has no descendants. $child_of = $args['child_of']; $parent = $args['parent']; if ($child_of) { $_parent = $child_of; } elseif ($parent) { $_parent = $parent; } else { $_parent = false; } if ($_parent) { $in_hierarchy = false; foreach ($taxonomies as $_tax) { $hierarchy = _get_term_hierarchy($_tax); if (isset($hierarchy[$_parent])) { $in_hierarchy = true; } } if (!$in_hierarchy) { return array(); } } $orderby = $this->parse_orderby($this->query_vars['orderby']); $order = $this->parse_order($this->query_vars['order']); if ($taxonomies) { $this->sql_clauses['where']['taxonomy'] = "tt.taxonomy IN ('" . implode("', '", array_map('esc_sql', $taxonomies)) . "')"; } $exclude = $args['exclude']; $exclude_tree = $args['exclude_tree']; $include = $args['include']; $inclusions = ''; if (!empty($include)) { $exclude = ''; $exclude_tree = ''; $inclusions = implode(',', wp_parse_id_list($include)); } if (!empty($inclusions)) { $this->sql_clauses['where']['inclusions'] = 't.term_id IN ( ' . $inclusions . ' )'; } $exclusions = array(); if (!empty($exclude_tree)) { $exclude_tree = wp_parse_id_list($exclude_tree); $excluded_children = $exclude_tree; foreach ($exclude_tree as $extrunk) { $excluded_children = array_merge($excluded_children, (array) get_terms($taxonomies[0], array('child_of' => intval($extrunk), 'fields' => 'ids', 'hide_empty' => 0))); } $exclusions = array_merge($excluded_children, $exclusions); } if (!empty($exclude)) { $exclusions = array_merge(wp_parse_id_list($exclude), $exclusions); } // 'childless' terms are those without an entry in the flattened term hierarchy. $childless = (bool) $args['childless']; if ($childless) { foreach ($taxonomies as $_tax) { $term_hierarchy = _get_term_hierarchy($_tax); $exclusions = array_merge(array_keys($term_hierarchy), $exclusions); } } if (!empty($exclusions)) { $exclusions = 't.term_id NOT IN (' . implode(',', array_map('intval', $exclusions)) . ')'; } else { $exclusions = ''; } /** * Filters the terms to exclude from the terms query. * * @since 2.3.0 * * @param string $exclusions `NOT IN` clause of the terms query. * @param array $args An array of terms query arguments. * @param array $taxonomies An array of taxonomies. */ $exclusions = apply_filters('list_terms_exclusions', $exclusions, $args, $taxonomies); if (!empty($exclusions)) { // Must do string manipulation here for backward compatibility with filter. $this->sql_clauses['where']['exclusions'] = preg_replace('/^\\s*AND\\s*/', '', $exclusions); } if (!empty($args['name'])) { $names = (array) $args['name']; foreach ($names as &$_name) { // `sanitize_term_field()` returns slashed data. $_name = stripslashes(sanitize_term_field('name', $_name, 0, reset($taxonomies), 'db')); } $this->sql_clauses['where']['name'] = "t.name IN ('" . implode("', '", array_map('esc_sql', $names)) . "')"; } if (!empty($args['slug'])) { if (is_array($args['slug'])) { $slug = array_map('sanitize_title', $args['slug']); $this->sql_clauses['where']['slug'] = "t.slug IN ('" . implode("', '", $slug) . "')"; } else { $slug = sanitize_title($args['slug']); $this->sql_clauses['where']['slug'] = "t.slug = '{$slug}'"; } } if (!empty($args['term_taxonomy_id'])) { if (is_array($args['term_taxonomy_id'])) { $tt_ids = implode(',', array_map('intval', $args['term_taxonomy_id'])); $this->sql_clauses['where']['term_taxonomy_id'] = "tt.term_taxonomy_id IN ({$tt_ids})"; } else { $this->sql_clauses['where']['term_taxonomy_id'] = $wpdb->prepare("tt.term_taxonomy_id = %d", $args['term_taxonomy_id']); } } if (!empty($args['name__like'])) { $this->sql_clauses['where']['name__like'] = $wpdb->prepare("t.name LIKE %s", '%' . $wpdb->esc_like($args['name__like']) . '%'); } if (!empty($args['description__like'])) { $this->sql_clauses['where']['description__like'] = $wpdb->prepare("tt.description LIKE %s", '%' . $wpdb->esc_like($args['description__like']) . '%'); } if ('' !== $parent) { $parent = (int) $parent; $this->sql_clauses['where']['parent'] = "tt.parent = '{$parent}'"; } $hierarchical = $args['hierarchical']; if ('count' == $args['fields']) { $hierarchical = false; } if ($args['hide_empty'] && !$hierarchical) { $this->sql_clauses['where']['count'] = 'tt.count > 0'; } $number = $args['number']; $offset = $args['offset']; // Don't limit the query results when we have to descend the family tree. if ($number && !$hierarchical && !$child_of && '' === $parent) { if ($offset) { $limits = 'LIMIT ' . $offset . ',' . $number; } else { $limits = 'LIMIT ' . $number; } } else { $limits = ''; } if (!empty($args['search'])) { $this->sql_clauses['where']['search'] = $this->get_search_sql($args['search']); } // Meta query support. $join = ''; $distinct = ''; // Reparse meta_query query_vars, in case they were modified in a 'pre_get_terms' callback. $this->meta_query->parse_query_vars($this->query_vars); $mq_sql = $this->meta_query->get_sql('term', 't', 'term_id'); $meta_clauses = $this->meta_query->get_clauses(); if (!empty($meta_clauses)) { $join .= $mq_sql['join']; $this->sql_clauses['where']['meta_query'] = preg_replace('/^\\s*AND\\s*/', '', $mq_sql['where']); $distinct .= "DISTINCT"; } $selects = array(); switch ($args['fields']) { case 'all': $selects = array('t.*', 'tt.*'); break; case 'ids': case 'id=>parent': $selects = array('t.term_id', 'tt.parent', 'tt.count', 'tt.taxonomy'); break; case 'names': $selects = array('t.term_id', 'tt.parent', 'tt.count', 't.name', 'tt.taxonomy'); break; case 'count': $orderby = ''; $order = ''; $selects = array('COUNT(*)'); break; case 'id=>name': $selects = array('t.term_id', 't.name', 'tt.count', 'tt.taxonomy'); break; case 'id=>slug': $selects = array('t.term_id', 't.slug', 'tt.count', 'tt.taxonomy'); break; } $_fields = $args['fields']; /** * Filters the fields to select in the terms query. * * Field lists modified using this filter will only modify the term fields returned * by the function when the `$fields` parameter set to 'count' or 'all'. In all other * cases, the term fields in the results array will be determined by the `$fields` * parameter alone. * * Use of this filter can result in unpredictable behavior, and is not recommended. * * @since 2.8.0 * * @param array $selects An array of fields to select for the terms query. * @param array $args An array of term query arguments. * @param array $taxonomies An array of taxonomies. */ $fields = implode(', ', apply_filters('get_terms_fields', $selects, $args, $taxonomies)); $join .= " INNER JOIN {$wpdb->term_taxonomy} AS tt ON t.term_id = tt.term_id"; $where = implode(' AND ', $this->sql_clauses['where']); $pieces = array('fields', 'join', 'where', 'distinct', 'orderby', 'order', 'limits'); /** * Filters the terms query SQL clauses. * * @since 3.1.0 * * @param array $pieces Terms query SQL clauses. * @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); $fields = isset($clauses['fields']) ? $clauses['fields'] : ''; $join = isset($clauses['join']) ? $clauses['join'] : ''; $where = isset($clauses['where']) ? $clauses['where'] : ''; $distinct = isset($clauses['distinct']) ? $clauses['distinct'] : ''; $orderby = isset($clauses['orderby']) ? $clauses['orderby'] : ''; $order = isset($clauses['order']) ? $clauses['order'] : ''; $limits = isset($clauses['limits']) ? $clauses['limits'] : ''; if ($where) { $where = "WHERE {$where}"; } $this->sql_clauses['select'] = "SELECT {$distinct} {$fields}"; $this->sql_clauses['from'] = "FROM {$wpdb->terms} AS t {$join}"; $this->sql_clauses['orderby'] = $orderby ? "ORDER BY {$orderby} {$order}" : ''; $this->sql_clauses['limits'] = $limits; $this->request = "{$this->sql_clauses['select']} {$this->sql_clauses['from']} {$where} {$this->sql_clauses['orderby']} {$this->sql_clauses['limits']}"; // $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'); } $cache_key = "get_terms:{$key}:{$last_changed}"; $cache = wp_cache_get($cache_key, 'terms'); if (false !== $cache) { if ('all' === $_fields) { $cache = array_map('get_term', $cache); } return $cache; } if ('count' == $_fields) { return $wpdb->get_var($this->request); } $terms = $wpdb->get_results($this->request); if ('all' == $_fields) { update_term_cache($terms); } // Prime termmeta cache. if ($args['update_term_meta_cache']) { $term_ids = wp_list_pluck($terms, 'term_id'); update_termmeta_cache($term_ids); } if (empty($terms)) { wp_cache_add($cache_key, array(), 'terms', DAY_IN_SECONDS); return array(); } if ($child_of) { foreach ($taxonomies as $_tax) { $children = _get_term_hierarchy($_tax); if (!empty($children)) { $terms = _get_term_children($child_of, $terms, $_tax); } } } // Update term counts to include children. if ($args['pad_counts'] && 'all' == $_fields) { foreach ($taxonomies as $_tax) { _pad_term_counts($terms, $_tax); } } // Make sure we show empty categories that have children. if ($hierarchical && $args['hide_empty'] && is_array($terms)) { foreach ($terms as $k => $term) { if (!$term->count) { $children = get_term_children($term->term_id, $term->taxonomy); if (is_array($children)) { foreach ($children as $child_id) { $child = get_term($child_id, $term->taxonomy); if ($child->count) { continue 2; } } } // It really is empty. unset($terms[$k]); } } } $_terms = array(); if ('id=>parent' == $_fields) { foreach ($terms as $term) { $_terms[$term->term_id] = $term->parent; } } elseif ('ids' == $_fields) { foreach ($terms as $term) { $_terms[] = $term->term_id; } } elseif ('names' == $_fields) { foreach ($terms as $term) { $_terms[] = $term->name; } } elseif ('id=>name' == $_fields) { foreach ($terms as $term) { $_terms[$term->term_id] = $term->name; } } elseif ('id=>slug' == $_fields) { foreach ($terms as $term) { $_terms[$term->term_id] = $term->slug; } } if (!empty($_terms)) { $terms = $_terms; } // Hierarchical queries are not limited, so 'offset' and 'number' must be handled now. if ($hierarchical && $number && is_array($terms)) { if ($offset >= count($terms)) { $terms = array(); } else { $terms = array_slice($terms, $offset, $number, true); } } wp_cache_add($cache_key, $terms, 'terms', DAY_IN_SECONDS); if ('all' === $_fields) { $terms = array_map('get_term', $terms); } $this->terms = $terms; return $this->terms; }
/** * wp_get_object_terms() - Retrieves the terms associated with the given object(s), in the supplied taxonomies. * * The following information has to do the $args parameter and for what can be contained in the string * or array of that parameter, if it exists. * * The first argument is called, 'orderby' and has the default value of 'name'. The other value that is * supported is 'count'. * * The second argument is called, 'order' and has the default value of 'ASC'. The only other value that * will be acceptable is 'DESC'. * * The final argument supported is called, 'fields' and has the default value of 'all'. There are * multiple other options that can be used instead. Supported values are as follows: 'all', 'ids', * 'names', and finally 'all_with_object_id'. * * The fields argument also decides what will be returned. If 'all' or 'all_with_object_id' is choosen or * the default kept intact, then all matching terms objects will be returned. If either 'ids' or 'names' * is used, then an array of all matching term ids or term names will be returned respectively. * * @package WordPress * @subpackage Taxonomy * @since 2.3 * @uses $wpdb * * @param int|array $object_id The id of the object(s) to retrieve. * @param string|array $taxonomies The taxonomies to retrieve terms from. * @param array|string $args Change what is returned * @return array|WP_Error The requested term data or empty array if no terms found. WP_Error if $taxonomy does not exist. */ function wp_get_object_terms($object_ids, $taxonomies, $args = array()) { global $wpdb; if ( !is_array($taxonomies) ) $taxonomies = array($taxonomies); foreach ( $taxonomies as $taxonomy ) { if ( ! is_taxonomy($taxonomy) ) return new WP_Error('invalid_taxonomy', __('Invalid Taxonomy')); } if ( !is_array($object_ids) ) $object_ids = array($object_ids); $object_ids = array_map('intval', $object_ids); $defaults = array('orderby' => 'name', 'order' => 'ASC', 'fields' => 'all'); $args = wp_parse_args( $args, $defaults ); $terms = array(); if ( count($taxonomies) > 1 ) { foreach ( $taxonomies as $index => $taxonomy ) { $t = get_taxonomy($taxonomy); if ( is_array($t->args) && $args != array_merge($args, $t->args) ) { unset($taxonomies[$index]); $terms = array_merge($terms, wp_get_object_terms($object_ids, $taxonomy, array_merge($args, $t->args))); } } } else { $t = get_taxonomy($taxonomies[0]); if ( is_array($t->args) ) $args = array_merge($args, $t->args); } extract($args, EXTR_SKIP); if ( 'count' == $orderby ) $orderby = 'tt.count'; else if ( 'name' == $orderby ) $orderby = 't.name'; else if ( 'slug' == $orderby ) $orderby = 't.slug'; else if ( 'term_group' == $orderby ) $orderby = 't.term_group'; else if ( 'term_order' == $orderby ) $orderby = 'tr.term_order'; else $orderby = 't.term_id'; $taxonomies = "'" . implode("', '", $taxonomies) . "'"; $object_ids = implode(', ', $object_ids); $select_this = ''; if ( 'all' == $fields ) $select_this = 't.*, tt.*'; else if ( 'ids' == $fields ) $select_this = 't.term_id'; else if ( 'names' == $fields ) $select_this = 't.name'; else if ( 'all_with_object_id' == $fields ) $select_this = 't.*, tt.*, tr.object_id'; $query = "SELECT $select_this FROM $wpdb->terms AS t INNER JOIN $wpdb->term_taxonomy AS tt ON tt.term_id = t.term_id INNER JOIN $wpdb->term_relationships AS tr ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tt.taxonomy IN ($taxonomies) AND tr.object_id IN ($object_ids) ORDER BY $orderby $order"; if ( 'all' == $fields || 'all_with_object_id' == $fields ) { $terms = array_merge($terms, $wpdb->get_results($query)); update_term_cache($terms); } else if ( 'ids' == $fields || 'names' == $fields ) { $terms = array_merge($terms, $wpdb->get_col($query)); } else if ( 'tt_ids' == $fields ) { $terms = $wpdb->get_col("SELECT tr.term_taxonomy_id FROM $wpdb->term_relationships AS tr INNER JOIN $wpdb->term_taxonomy AS tt ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tr.object_id IN ($object_ids) AND tt.taxonomy IN ($taxonomies) ORDER BY tr.term_taxonomy_id $order"); } if ( ! $terms ) return array(); return $terms; }
/** * Extended get_terms function support * - Limit category * - Limit days * - Selection restrict * - Min usage * * @param string|array $taxonomies * @param string $args * @return array */ function getTerms($taxonomies, $args = '', $skip_cache = false) { global $wpdb; $single_taxonomy = false; if (!is_array($taxonomies)) { $single_taxonomy = true; $taxonomies = array($taxonomies); } foreach ((array) $taxonomies as $taxonomy) { if (!is_taxonomy($taxonomy)) { return new WP_Error('invalid_taxonomy', __('Invalid Taxonomy')); } } $in_taxonomies = "'" . implode("', '", $taxonomies) . "'"; $defaults = array('cloud_selection' => 'count-desc', 'hide_empty' => true, 'exclude' => '', 'include' => '', 'number' => '', 'fields' => 'all', 'slug' => '', 'parent' => '', 'hierarchical' => true, 'child_of' => 0, 'get' => '', 'name__like' => '', 'st_name_like' => '', 'pad_counts' => false, 'limit_days' => 0, 'category' => 0, 'min_usage' => 0); $args = wp_parse_args($args, $defaults); if (!$single_taxonomy || !is_taxonomy_hierarchical($taxonomies[0]) || '' != $args['parent']) { $args['child_of'] = 0; $args['hierarchical'] = false; $args['pad_counts'] = false; } if ('all' == $args['get']) { $args['child_of'] = 0; $args['hide_empty'] = 0; $args['hierarchical'] = false; $args['pad_counts'] = false; } extract($args, EXTR_SKIP); if ($child_of) { $hierarchy = _get_term_hierarchy($taxonomies[0]); if (!isset($hierarchy[$child_of])) { return array(); } } if ($parent) { $hierarchy = _get_term_hierarchy($taxonomies[0]); if (!isset($hierarchy[$parent])) { return array(); } } if ($skip_cache != true) { // Get cache if exist $key = md5(serialize($args) . serialize($taxonomies)); if ($cache = wp_cache_get('get_terms', 'terms')) { if (isset($cache[$key])) { return apply_filters('get_terms', $cache[$key], $taxonomies, $args); } } } // Restrict category $category_sql = ''; if (!empty($category) && $category != '0') { $incategories = preg_split('/[\\s,]+/', $category); $objects_id = get_objects_in_term($incategories, 'category'); $objects_id = array_unique($objects_id); // to be sure haven't duplicates if (empty($objects_id)) { // No posts for this category = no tags for this category return array(); } foreach ((array) $objects_id as $object_id) { $category_sql .= "'" . $object_id . "', "; } $category_sql = substr($category_sql, 0, strlen($category_sql) - 2); // Remove latest ", " $category_sql = 'AND p.ID IN (' . $category_sql . ')'; } // count-asc/count-desc/name-asc/name-desc/random $cloud_selection = strtolower($cloud_selection); switch ($cloud_selection) { case 'count-asc': $order_by = 'tt.count ASC'; break; case 'random': $order_by = 'RAND()'; break; case 'name-asc': $order_by = 't.name ASC'; break; case 'name-desc': $order_by = 't.name DESC'; break; default: // count-desc $order_by = 'tt.count DESC'; break; } // Min usage $restict_usage = ''; $min_usage = (int) $min_usage; if ($min_usage != 0) { $restict_usage = ' AND tt.count >= ' . $min_usage; } $where = ''; $inclusions = ''; if (!empty($include)) { $exclude = ''; $interms = preg_split('/[\\s,]+/', $include); foreach ((array) $interms as $interm) { if (empty($inclusions)) { $inclusions = ' AND ( t.term_id = ' . intval($interm) . ' '; } else { $inclusions .= ' OR t.term_id = ' . intval($interm) . ' '; } } } if (!empty($inclusions)) { $inclusions .= ')'; } $where .= $inclusions; $exclusions = ''; if (!empty($exclude)) { $exterms = preg_split('/[\\s,]+/', $exclude); foreach ((array) $exterms as $exterm) { if (empty($exclusions)) { $exclusions = ' AND ( t.term_id <> ' . intval($exterm) . ' '; } else { $exclusions .= ' AND t.term_id <> ' . intval($exterm) . ' '; } } } if (!empty($exclusions)) { $exclusions .= ')'; } $exclusions = apply_filters('list_terms_exclusions', $exclusions, $args); $where .= $exclusions; if (!empty($slug)) { $slug = sanitize_title($slug); $where .= " AND t.slug = '{$slug}'"; } if (!empty($name__like)) { $where .= " AND t.name LIKE '{$name__like}%'"; } if (strpos($st_name_like, ' ') != false || strpos($st_name_like, ' ') != null) { $tmp = ''; $sts = explode(' ', $st_name_like); foreach ((array) $sts as $st) { if (empty($st)) { continue; } $st = addslashes_gpc($st); $tmp .= " t.name LIKE '%{$st}%' OR "; } // Remove latest OR $tmp = substr($tmp, 0, strlen($tmp) - 4); $where .= " AND ( {$tmp} ) "; unset($tmp); } elseif (!empty($st_name_like)) { $where .= " AND t.name LIKE '%{$st_name_like}%'"; } if ('' != $parent) { $parent = (int) $parent; $where .= " AND tt.parent = '{$parent}'"; } if ($hide_empty && !$hierarchical) { $where .= ' AND tt.count > 0'; } $number_sql = ''; if (strpos($number, ',') != false || strpos($number, ',') != null) { $number_sql = $number; } else { $number = (int) $number; if ($number != 0) { $number_sql = 'LIMIT ' . $number; } } if ('all' == $fields) { $select_this = 't.*, tt.*'; } else { if ('ids' == $fields) { $select_this = 't.term_id'; } else { if ('names' == $fields) { $select_this == 't.name'; } } } // Limit posts date $limitdays_sql = ''; $limit_days = (int) $limit_days; if ($limit_days != 0) { $limitdays_sql = 'AND p.post_date > "' . date('Y-m-d H:i:s', time() - $limit_days * 86400) . '"'; } // Join posts ? $inner_posts = ''; if (!empty($limitdays_sql) | !empty($category_sql)) { $inner_posts = "\r\n\t\t\t\tINNER JOIN {$wpdb->term_relationships} AS tr ON tt.term_taxonomy_id = tr.term_taxonomy_id\r\n\t\t\t\tINNER JOIN {$wpdb->posts} AS p ON tr.object_id = p.ID"; } $query = "SELECT DISTINCT {$select_this}\r\n\t\t\tFROM {$wpdb->terms} AS t\r\n\t\t\tINNER JOIN {$wpdb->term_taxonomy} AS tt ON t.term_id = tt.term_id\r\n\t\t\t{$inner_posts}\r\n\t\t\tWHERE tt.taxonomy IN ( {$in_taxonomies} )\r\n\t\t\t{$limitdays_sql}\r\n\t\t\t{$category_sql}\r\n\t\t\t{$where}\r\n\t\t\t{$restict_usage}\r\n\t\t\tORDER BY {$order_by}\r\n\t\t\t{$number_sql}"; if ('all' == $fields) { $terms = $wpdb->get_results($query); if ($skip_cache != true) { update_term_cache($terms); } } elseif ('ids' == $fields) { $terms = $wpdb->get_col($query); } if (empty($terms)) { return array(); } if ($child_of || $hierarchical) { $children = _get_term_hierarchy($taxonomies[0]); if (!empty($children)) { $terms =& _get_term_children($child_of, $terms, $taxonomies[0]); } } // Update term counts to include children. if ($pad_counts) { _pad_term_counts($terms, $taxonomies[0]); } // Make sure we show empty categories that have children. if ($hierarchical && $hide_empty) { foreach ((array) $terms as $k => $term) { if (!$term->count) { $children = _get_term_children($term->term_id, $terms, $taxonomies[0]); foreach ((array) $children as $child) { if ($child->count) { continue 2; } } // It really is empty unset($terms[$k]); } } } reset($terms); if ($skip_cache != true) { $cache[$key] = $terms; wp_cache_set('get_terms', $cache, 'terms'); } $terms = apply_filters('get_terms', $terms, $taxonomies, $args); return $terms; }
function flt_get_terms($results, $taxonomies, $args) { global $wpdb; $empty_array = array(); //d_echo( 'flt_get_terms input:' ); $single_taxonomy = false; if (!is_array($taxonomies)) { $single_taxonomy = true; $taxonomies = array($taxonomies); } elseif (count($taxonomies) < 2) { $single_taxonomy = true; } // === END Role Scoper MODIFICATION === foreach ((array) $taxonomies as $taxonomy) { if (!taxonomy_exists($taxonomy)) { // === BEGIN Role Scoper MODIFICATION: this caused plugin activation error in some situations (though at that time, the error object was created and return on a single line, not byRef as now) === // //$error = & new WP_Error('invalid_taxonomy', __awp('Invalid Taxonomy')); //return $error; return array(); // // === END Role Scoper MODIFICATION === } } // === BEGIN Role Scoper ADDITION: global var; various special case exemption checks === // global $scoper; if ($tx_obj = get_taxonomy($taxonomies[0])) { // don't require use_taxonomies setting for link_categories or other non-post taxonomies if (array_intersect($tx_obj->object_type, get_post_types(array('public' => true)))) { $use_taxonomies = scoper_get_option('use_taxonomies'); if (empty($use_taxonomies[$taxonomy])) { return $results; } } } // no backend filter for administrators $parent_or = ''; if (is_admin() || defined('XMLRPC_REQUEST')) { if (is_content_administrator_rs()) { return $results; } else { if ($tx = $scoper->taxonomies->get($taxonomies[0])) { // is a Category Edit form being displayed? if (!empty($tx->uri_vars)) { $term_id = $scoper->data_sources->detect('id', $tx); } else { $term_id = $scoper->data_sources->detect('id', $tx->source); } if ($term_id) { // don't filter current parent category out of selection UI even if current user can't manage it $parent_or = " OR t.term_id = (SELECT parent FROM {$wpdb->term_taxonomy} WHERE term_id = '{$term_id}') "; } } } } // need to skip cache retrieval if QTranslate is filtering get_terms with a priority of 1 or less static $no_cache; if (!isset($no_cache)) { $no_cache = defined('SCOPER_NO_TERMS_CACHE') || !defined('SCOPER_QTRANSLATE_COMPAT') && awp_is_plugin_active('qtranslate'); } // this filter currently only supports a single taxonomy for each get_terms call // (although the terms_where filter does support multiple taxonomies and this function could be made to do so) if (!$single_taxonomy) { return $results; } // link category roles / restrictions are only scoped for management (TODO: abstract this) if ($single_taxonomy && 'link_category' == $taxonomies[0] && $scoper->is_front()) { return $results; } // depth is not really a get_terms arg, but remap exclude arg to exclude_tree if wp_list_terms called with depth=1 if (!empty($args['exclude']) && empty($args['exclude_tree']) && !empty($args['depth']) && 1 == $args['depth']) { $args['exclude_tree'] = $args['exclude']; } // don't offer to set a category as its own parent if ('edit-tags.php' == $GLOBALS['pagenow']) { if ($tx_obj->hierarchical) { if ($editing_cat_id = $scoper->data_sources->get_from_uri('id', 'term')) { if (!empty($args['exclude'])) { $args['exclude'] .= ','; } $args['exclude'] .= $editing_cat_id; } } } // we'll need this array in most cases, to support a disjointed tree with some parents missing (note alternate function call - was _get_term_hierarchy) $children = ScoperAncestry::get_terms_children($taxonomies[0]); // // === END Role Scoper ADDITION === // ================================= $in_taxonomies = "'" . implode("', '", $taxonomies) . "'"; $defaults = array('orderby' => 'name', 'order' => 'ASC', 'hide_empty' => true, 'exclude' => '', 'exclude_tree' => '', 'include' => '', 'number' => '', 'fields' => 'all', 'slug' => '', 'parent' => '', 'hierarchical' => true, 'child_of' => 0, 'get' => '', 'name__like' => '', 'pad_counts' => false, 'offset' => '', 'search' => '', 'skip_teaser' => false, 'depth' => 0, 'remap_parents' => -1, 'enforce_actual_depth' => -1, 'remap_thru_excluded_parent' => -1, 'post_type' => ''); // Role Scoper arguments added above $args = wp_parse_args($args, $defaults); $args['number'] = (int) $args['number']; $args['offset'] = absint($args['offset']); $args['child_of'] = (int) $args['child_of']; // Role Scoper modification: null value will confuse children array check if (!$single_taxonomy || !is_taxonomy_hierarchical($taxonomies[0]) || '' !== $args['parent']) { $args['child_of'] = 0; $args['hierarchical'] = false; $args['pad_counts'] = false; } if ('all' == $args['get']) { $args['child_of'] = 0; $args['hide_empty'] = 0; $args['hierarchical'] = false; $args['pad_counts'] = false; } extract($args, EXTR_SKIP); // === BEGIN Role Scoper MODIFICATION: use the $children array we already have === // if ('nav-menus.php' == $GLOBALS['pagenow']) { if ('nav_menu' != $taxonomies[0]) { if (!scoper_get_option('admin_nav_menu_filter_items')) { return $results; } else { $hide_empty = 1; } } } if ($child_of && !isset($children[$child_of])) { return array(); } if ($parent && !isset($children[$parent])) { return array(); } if ($post_type && is_string($post_type)) { $post_type = explode(',', $post_type); } // // === END Role Scoper MODIFICATION === // ==================================== $is_term_admin = in_array($GLOBALS['pagenow'], array('edit-tags.php', 'edit-link-categories.php')); $filter_key = has_filter('list_terms_exclusions') ? serialize($GLOBALS['wp_filter']['list_terms_exclusions']) : ''; $key = md5(serialize(compact(array_keys($defaults))) . serialize($taxonomies) . $filter_key); // === BEGIN Role Scoper MODIFICATION: cache key specific to access type and user/groups === // support Quick Post Widget plugin if (isset($name) && 'quick_post_cat' == $name) { $required_operation = 'edit'; $post_type = 'post'; $remap_parents = true; } elseif (isset($name) && 'quick_post_new_cat_parent' == $name) { $is_term_admin = true; $required_operation = ''; $remap_parents = true; } else { $required_operation = ''; } $object_src_name = $scoper->taxonomies->member_property($taxonomies[0], 'object_source', 'name'); $ckey = md5($key . serialize($scoper->get_terms_reqd_caps($taxonomies[0], $required_operation, $is_term_admin))); global $current_rs_user; $cache_flag = 'rs_get_terms'; $cache = $current_rs_user->cache_get($cache_flag); if (false !== $cache) { if (!is_array($cache)) { $cache = array(); } if (!$no_cache && isset($cache[$ckey])) { // RS Modification: alternate filter name (get_terms filter is already applied by WP) remove_filter('get_terms', array('ScoperHardwayTaxonomy', 'flt_get_terms'), 0, 3); $terms = apply_filters('get_terms', $cache[$ckey], $taxonomies, $args); $terms = apply_filters('get_terms_rs', $terms, $taxonomies, $args); add_filter('get_terms', array('ScoperHardwayTaxonomy', 'flt_get_terms'), 0, 3); return $terms; } } // buffer term names in case they were filtered previously if ('all' == $fields) { $term_names = scoper_get_property_array($results, 'term_id', 'name'); } // // === END Role Scoper MODIFICATION === // ===================================== $_orderby = strtolower($orderby); if ('count' == $_orderby) { $orderby = 'tt.count'; } else { if ('name' == $_orderby) { $orderby = 't.name'; } else { if ('slug' == $_orderby) { $orderby = 't.slug'; } else { if ('term_group' == $_orderby) { $orderby = 't.term_group'; } else { if ('none' == $_orderby) { $orderby = ''; $order = ''; } else { if (empty($_orderby) || 'id' == $_orderby) { $orderby = 't.term_id'; } elseif ('order' == $_orderby) { $orderby = 't.term_order'; } else { $orderby = 't.name'; } } } } } } $orderby = apply_filters('get_terms_orderby', $orderby, $args); if (!empty($orderby)) { $orderby = "ORDER BY {$orderby}"; } $where = ''; // === Role Scoper MODIFICATION: if an include argument is provided, strip out non-matching terms after filtering is done. === /* $inclusions = ''; if ( !empty($include) ) { $exclude = ''; $exclude_tree = ''; $interms = wp_parse_id_list($include); if ( count($interms) ) { foreach ( $interms as $interm ) { if (empty($inclusions)) $inclusions = ' AND ( t.term_id = ' . intval($interm) . ' '; else $inclusions .= ' OR t.term_id = ' . intval($interm) . ' '; } } } if ( !empty($inclusions) ) $inclusions .= ')'; $where .= $inclusions; */ // === END Role Scoper MODIFICATION === $exclusions = ''; if (!empty($exclude_tree)) { // === BEGIN Role Scoper MODIFICATION: temporarily unhook this filter for unfiltered get_terms calls === remove_filter('get_terms', array('ScoperHardwayTaxonomy', 'flt_get_terms'), 0, 3); // === END Role Scoper MODIFICATION === $excluded_trunks = wp_parse_id_list($exclude_tree); foreach ((array) $excluded_trunks as $extrunk) { $excluded_children = (array) get_terms($taxonomies[0], array('child_of' => intval($extrunk), 'fields' => 'ids')); $excluded_children[] = $extrunk; foreach ($excluded_children as $exterm) { if (empty($exclusions)) { $exclusions = ' AND ( t.term_id <> ' . intval($exterm) . ' '; } else { $exclusions .= ' AND t.term_id <> ' . intval($exterm) . ' '; } } } // === BEGIN Role Scoper MODIFICATION: re-hook this filter add_filter('get_terms', array('ScoperHardwayTaxonomy', 'flt_get_terms'), 0, 3); // === END Role Scoper MODIFICATION === } if (!empty($exclude)) { $exterms = wp_parse_id_list($exclude); foreach ($exterms as $exterm) { if (empty($exclusions)) { $exclusions = ' AND ( t.term_id <> "' . intval($exterm) . '" '; } else { $exclusions .= ' AND t.term_id <> "' . intval($exterm) . '" '; } } } if (!empty($exclusions)) { $exclusions .= ')'; } // WPML attempts to pull taxonomy out of debug_backtrace() unless set in $_GET or $_POST; previous filter execution throws it off if (defined('ICL_SITEPRESS_VERSION') && !isset($_GET['taxonomy'])) { $_GET['taxonomy'] = current($taxonomies); } $exclusions = apply_filters('list_terms_exclusions', $exclusions, $args); $where .= $exclusions; if (!empty($slug)) { $slug = sanitize_title($slug); $where .= " AND t.slug = '{$slug}'"; } if (!empty($name__like)) { $where .= " AND t.name LIKE '{$name__like}%'"; } if ('' !== $parent) { $parent = (int) $parent; // === BEGIN Role Scoper MODIFICATION: otherwise termroles only work if parent terms also have role if ($parent || 'ids' != $fields) { $where .= " AND tt.parent = '{$parent}'"; } // === END Role Scoper MODIFICATION === } // === BEGIN Role Scoper MODIFICATION: instead, manually remove truly empty cats at the bottom of this function, so we don't exclude cats with private but readable posts //if ( $hide_empty && !$hierarchical ) // $where .= ' AND tt.count > 0'; // === END Role Scoper MODIFICATION === // don't limit the query results when we have to descend the family tree if (!empty($number) && !$hierarchical && empty($child_of) && '' == $parent) { if ($offset) { $limit = 'LIMIT ' . $offset . ',' . $number; } else { $limit = 'LIMIT ' . $number; } } else { $limit = ''; } if (!empty($search)) { $search = like_escape($search); $where .= " AND (t.name LIKE '%{$search}%')"; } $selects = array(); switch ($fields) { case 'all': $selects = array('t.*', 'tt.*'); break; case 'ids': case 'id=>parent': $selects = array('t.term_id', 'tt.term_taxonomy_id', 'tt.parent', 'tt.count'); break; case 'names': $selects = array('t.term_id', 'tt.term_taxonomy_id', 'tt.parent', 'tt.count', 't.name'); break; case 'count': $orderby = ''; $order = ''; $selects = array('COUNT(*)'); } $select_this = implode(', ', apply_filters('get_terms_fields', $selects, $args)); // === BEGIN Role Scoper MODIFICATION: run the query through scoping filter // $query_base = "SELECT DISTINCT {$select_this} FROM {$wpdb->terms} AS t INNER JOIN {$wpdb->term_taxonomy} AS tt ON t.term_id = tt.term_id WHERE 1=1 AND tt.taxonomy IN ({$in_taxonomies}) {$where} {$parent_or} {$orderby} {$order} {$limit}"; // only force application of scoped query filter if we're NOT doing a teaser if ('all' == $fields) { $do_teaser = $scoper->is_front() && empty($skip_teaser) && scoper_get_otype_option('do_teaser', 'post'); } else { $do_teaser = false; } $query = apply_filters('terms_request_rs', $query_base, $taxonomies[0], array('skip_teaser' => !$do_teaser, 'is_term_admin' => $is_term_admin, 'required_operation' => $required_operation, 'post_type' => $post_type)); // if no filering was applied because the teaser is enabled, prevent a redundant query if (!empty($exclude_tree) || $query_base != $query || $parent || 'all' != $fields) { $terms = scoper_get_results($query); } else { $terms = $results; } if ('count' == $fields) { $term_count = $wpdb->get_var($query); return $term_count; } if ('all' == $fields && empty($include)) { update_term_cache($terms); } // RS: don't cache an empty array, just in case something went wrong if (empty($terms)) { return array(); } // // === END Role Scoper MODIFICATION === // ==================================== // === BEGIN Role Scoper ADDITION: Support a disjointed terms tree with some parents hidden // if ('all' == $fields) { $ancestors = ScoperAncestry::get_term_ancestors($taxonomy); // array of all ancestor IDs for keyed term_id, with direct parent first if ($parent > 0 || !$hierarchical) { // in Category Edit form, need to list all editable cats even if parent is not editable $remap_parents = false; $enforce_actual_depth = true; $remap_thru_excluded_parent = false; } else { // if these settings were passed into this get_terms call, use them if (is_admin()) { $remap_parents = true; } else { if (-1 === $remap_parents) { $remap_parents = scoper_get_option('remap_term_parents'); } if ($remap_parents) { if (-1 === $enforce_actual_depth) { $enforce_actual_depth = scoper_get_option('enforce_actual_term_depth'); } if (-1 === $remap_thru_excluded_parent) { $remap_thru_excluded_parent = scoper_get_option('remap_thru_excluded_term_parent'); } } } } $remap_args = compact('child_of', 'parent', 'depth', 'orderby', 'remap_parents', 'enforce_actual_depth', 'remap_thru_excluded_parent'); // one or more of these args may have been modified after extraction ScoperHardway::remap_tree($terms, $ancestors, 'term_id', 'parent', $remap_args); } // // === END Role Scoper ADDITION === // ================================ // === BEGIN Role Scoper MODIFICATION: call alternate functions // rs_tally_term_counts() replaces _pad_term_counts() // rs_get_term_descendants replaces _get_term_children() // if (($child_of || $hierarchical) && !empty($children)) { $terms = rs_get_term_descendants($child_of, $terms, $taxonomies[0]); } if (!$terms) { return array(); } // Replace DB-stored term counts with actual number of posts this user can read. // In addition, without the rs_tally_term_counts call, WP will hide categories that have no public posts (even if this user can read some of the pvt posts). // Post counts will be incremented to include child categories only if $pad_counts is true if (!defined('XMLRPC_REQUEST') && in_array($fields, array('all', 'ids', 'names')) && !$is_term_admin) { if (!is_admin() || !in_array($GLOBALS['pagenow'], array('post.php', 'post-new.php'))) { //-- RoleScoper Modification - alternate function call (was _pad_term_counts) --// rs_tally_term_counts($terms, $taxonomies[0], array('pad_counts' => $pad_counts, 'skip_teaser' => !$do_teaser, 'post_type' => $post_type)); } } // Make sure we show empty categories that have children. if ($hierarchical && $hide_empty) { foreach ($terms as $k => $term) { if (!$term->count) { //-- RoleScoper Modification - call alternate function (was _get_term_children) --// if ($children = rs_get_term_descendants($term->term_id, $terms, $taxonomies[0])) { foreach ($children as $child) { if ($child->count) { continue 2; } } } // It really is empty unset($terms[$k]); } } } reset($terms); // // === END Role Scoper MODIFICATION === // ==================================== // === BEGIN Role Scoper ADDITION: hide empty cats based on actual query result instead of 'count > 0' clause, so we don't exclude cats with private but readable posts if ($terms && empty($hierarchical) && !empty($hide_empty)) { foreach ($terms as $key => $term) { if (!$term->count) { unset($terms[$key]); } } } // // === END Role Scoper ADDITION === // ================================ if (!empty($include)) { $interms = wp_parse_id_list($include); foreach ($terms as $key => $term) { if (!in_array($term->term_id, $interms)) { unset($terms[$key]); } } } $_terms = array(); if ('id=>parent' == $fields) { while ($term = array_shift($terms)) { $_terms[$term->term_id] = $term->parent; } $terms = $_terms; } elseif ('ids' == $fields) { while ($term = array_shift($terms)) { $_terms[] = $term->term_id; } $terms = $_terms; } elseif ('names' == $fields) { while ($term = array_shift($terms)) { $_terms[] = $term->name; } $terms = $_terms; } if (0 < $number && intval(@count($terms)) > $number) { $terms = array_slice($terms, $offset, $number); } // === BEGIN Role Scoper MODIFICATION: cache key is specific to user/group // if (!$no_cache) { $cache[$ckey] = $terms; $current_rs_user->cache_set($cache, $cache_flag); } // RS Modification: alternate filter name (get_terms filter is already applied by WP) remove_filter('get_terms', array('ScoperHardwayTaxonomy', 'flt_get_terms'), 0, 3); $terms = apply_filters('get_terms', $terms, $taxonomies, $args); $terms = apply_filters('get_terms_rs', $terms, $taxonomies, $args); add_filter('get_terms', array('ScoperHardwayTaxonomy', 'flt_get_terms'), 0, 3); // restore buffered term names in case they were filtered previously if ('all' == $fields) { scoper_restore_property_array($terms, $term_names, 'term_id', 'name'); } // // === END Role Scoper MODIFICATION === // ==================================== //dump($terms); return $terms; }
/** * Extended get_terms public static function support * - Limit category * - Limit days * - Selection restrict * - Min usage * * @param string|array $taxonomies * @param string $args * @return array */ public static function getTerms($taxonomies, $args = '') { global $wpdb; $empty_array = array(); $join_relation = false; $single_taxonomy = false; if (!is_array($taxonomies)) { $single_taxonomy = true; $taxonomies = array($taxonomies); } foreach ((array) $taxonomies as $taxonomy) { if (!taxonomy_exists($taxonomy)) { $error = new WP_Error('invalid_taxonomy', __('Invalid Taxonomy')); return $error; } } $in_taxonomies = "'" . implode("', '", $taxonomies) . "'"; $defaults = array('orderby' => 'name', 'order' => 'ASC', 'hide_empty' => true, 'exclude' => array(), 'exclude_tree' => array(), 'include' => array(), 'number' => '', 'fields' => 'all', 'slug' => '', 'parent' => '', 'hierarchical' => true, 'child_of' => 0, 'get' => '', 'name__like' => '', 'pad_counts' => false, 'offset' => '', 'search' => '', 'limit_days' => 0, 'category' => 0, 'min_usage' => 0, 'st_name__like' => ''); $args = wp_parse_args($args, $defaults); // Translate selection order $args['orderby'] = self::compatOldOrder($args['selectionby'], 'orderby'); $args['order'] = self::compatOldOrder($args['selection'], 'order'); $args['number'] = absint($args['number']); $args['offset'] = absint($args['offset']); $args['limit_days'] = absint($args['limit_days']); $args['min_usage'] = absint($args['min_usage']); if (!$single_taxonomy || !is_taxonomy_hierarchical($taxonomies[0]) || '' !== $args['parent']) { $args['child_of'] = 0; $args['hierarchical'] = false; $args['pad_counts'] = false; } if ('all' == $args['get']) { $args['child_of'] = 0; $args['hide_empty'] = 0; $args['hierarchical'] = false; $args['pad_counts'] = false; } extract($args, EXTR_SKIP); if ($child_of) { $hierarchy = _get_term_hierarchy($taxonomies[0]); if (!isset($hierarchy[$child_of])) { return $empty_array; } } if ($parent) { $hierarchy = _get_term_hierarchy($taxonomies[0]); if (!isset($hierarchy[$parent])) { return $empty_array; } } // $args can be whatever, only use the args defined in defaults to compute the key $filter_key = has_filter('list_terms_exclusions') ? serialize($GLOBALS['wp_filter']['list_terms_exclusions']) : ''; $key = md5(serialize(compact(array_keys($defaults))) . serialize($taxonomies) . $filter_key); $last_changed = wp_cache_get('last_changed', 's-terms'); if (!$last_changed) { $last_changed = time(); wp_cache_set('last_changed', $last_changed, 's-terms'); } $cache_key = "get_terms:{$key}:{$last_changed}"; $cache = wp_cache_get($cache_key, 's-terms'); if (false !== $cache) { $cache = apply_filters('get_terms', $cache, $taxonomies, $args); return $cache; } $_orderby = strtolower($orderby); if ('count' == $_orderby) { $orderby = 'tt.count'; } if ('random' == $_orderby) { $orderby = 'RAND()'; } else { if ('name' == $_orderby) { $orderby = 't.name'; } else { if ('slug' == $_orderby) { $orderby = 't.slug'; } else { if ('term_group' == $_orderby) { $orderby = 't.term_group'; } elseif (empty($_orderby) || 'id' == $_orderby) { $orderby = 't.term_id'; } } } } $orderby = apply_filters('get_terms_orderby', $orderby, $args); if (!empty($orderby)) { $orderby = "ORDER BY {$orderby}"; } else { $order = ''; } $where = ''; $inclusions = ''; if (!empty($include)) { $exclude = ''; $exclude_tree = ''; $interms = wp_parse_id_list($include); foreach ($interms as $interm) { if (empty($inclusions)) { $inclusions = ' AND ( t.term_id = ' . intval($interm) . ' '; } else { $inclusions .= ' OR t.term_id = ' . intval($interm) . ' '; } } } if (!empty($inclusions)) { $inclusions .= ')'; } $where .= $inclusions; $exclusions = ''; if (!empty($exclude_tree)) { $excluded_trunks = wp_parse_id_list($exclude_tree); foreach ($excluded_trunks as $extrunk) { $excluded_children = (array) get_terms($taxonomies[0], array('child_of' => intval($extrunk), 'fields' => 'ids')); $excluded_children[] = $extrunk; foreach ($excluded_children as $exterm) { if (empty($exclusions)) { $exclusions = ' AND ( t.term_id <> ' . intval($exterm) . ' '; } else { $exclusions .= ' AND t.term_id <> ' . intval($exterm) . ' '; } } } } if (!empty($exclude)) { $exterms = wp_parse_id_list($exclude); foreach ($exterms as $exterm) { if (empty($exclusions)) { $exclusions = ' AND ( t.term_id <> ' . intval($exterm) . ' '; } else { $exclusions .= ' AND t.term_id <> ' . intval($exterm) . ' '; } } } if (!empty($exclusions)) { $exclusions .= ')'; } $exclusions = apply_filters('list_terms_exclusions', $exclusions, $args); $where .= $exclusions; // ST Features : Restrict category if ($category != 0) { if (!is_array($taxonomies)) { $taxonomies = array($taxonomies); } $incategories = wp_parse_id_list($category); $taxonomies = "'" . implode("', '", $taxonomies) . "'"; $incategories = "'" . implode("', '", $incategories) . "'"; $where .= " AND tr.object_id IN ( "; $where .= "SELECT tr.object_id FROM {$wpdb->term_relationships} AS tr INNER JOIN {$wpdb->term_taxonomy} AS tt ON tr.term_taxonomy_id = tt.term_taxonomy_id INNER JOIN {$wpdb->posts} as p ON tr.object_id=p.ID WHERE tt.term_id IN ({$incategories}) AND p.post_status='publish'"; $where .= " ) "; $join_relation = true; unset($incategories, $category); } // ST Features : Limit posts date if ($limit_days != 0) { $where .= " AND tr.object_id IN ( "; $where .= "SELECT DISTINCT ID FROM {$wpdb->posts} AS p WHERE p.post_status='publish' AND " . (is_page_have_tags() ? "p.post_type IN('page', 'post')" : "post_type = 'post'") . " AND p.post_date_gmt > '" . date('Y-m-d H:i:s', time() - $limit_days * 86400) . "'"; $where .= " ) "; $join_relation = true; unset($limit_days); } if (!empty($slug)) { $slug = sanitize_title($slug); $where .= " AND t.slug = '{$slug}'"; } if (!empty($name__like)) { $where .= " AND t.name LIKE '{$name__like}%'"; } if ('' !== $parent) { $parent = (int) $parent; $where .= " AND tt.parent = '{$parent}'"; } // ST Features : Another way to search if (strpos($st_name__like, ' ') !== false) { $st_terms_formatted = array(); $st_terms = preg_split('/[\\s,]+/', $st_name_like); foreach ((array) $st_terms as $st_term) { if (empty($st_term)) { continue; } $st_terms_formatted[] = "t.name LIKE '%" . like_escape($st_term) . "%'"; } $where .= " AND ( " . explode(' OR ', $st_terms_formatted) . " ) "; unset($st_term, $st_terms_formatted, $st_terms); } elseif (!empty($st_name__like)) { $where .= " AND t.name LIKE '%{$st_name__like}%'"; } // ST Features : Add min usage if ($hide_empty && !$hierarchical) { if ($min_usage == 0) { $where .= ' AND tt.count > 0'; } else { $where .= $wpdb->prepare(' AND tt.count >= %d', $min_usage); } } // don't limit the query results when we have to descend the family tree if (!empty($number) && !$hierarchical && empty($child_of) && '' === $parent) { if ($offset) { $limit = 'LIMIT ' . $offset . ',' . $number; } else { $limit = 'LIMIT ' . $number; } } else { $limit = ''; } if (!empty($search)) { $search = like_escape($search); $where .= " AND (t.name LIKE '%{$search}%')"; } $selects = array(); switch ($fields) { case 'all': $selects = array('t.*', 'tt.*'); break; case 'ids': case 'id=>parent': $selects = array('t.term_id', 'tt.parent', 'tt.count'); break; case 'names': $selects = array('t.term_id', 'tt.parent', 'tt.count', 't.name'); break; case 'count': $orderby = ''; $order = ''; $selects = array('COUNT(*)'); } $select_this = implode(', ', apply_filters('get_terms_fields', $selects, $args)); // Add inner to relation table ? $join_relation = $join_relation == false ? '' : "INNER JOIN {$wpdb->term_relationships} AS tr ON tt.term_taxonomy_id = tr.term_taxonomy_id"; $query = "SELECT {$select_this}\r\n\t\t\tFROM {$wpdb->terms} AS t\r\n\t\t\tINNER JOIN {$wpdb->term_taxonomy} AS tt ON t.term_id = tt.term_id\r\n\t\t\t{$join_relation}\r\n\t\t\tWHERE tt.taxonomy IN ({$in_taxonomies})\r\n\t\t\t{$where}\r\n\t\t\t{$orderby} {$order}\r\n\t\t\t{$limit}"; // GROUP BY t.term_id if ('count' == $fields) { $term_count = $wpdb->get_var($query); return $term_count; } $terms = $wpdb->get_results($query); if ('all' == $fields) { update_term_cache($terms); } if (empty($terms)) { wp_cache_add($cache_key, array(), 's-terms'); $terms = apply_filters('get_terms', array(), $taxonomies, $args); return $terms; } if ($child_of) { $children = _get_term_hierarchy($taxonomies[0]); if (!empty($children)) { $terms =& _get_term_children($child_of, $terms, $taxonomies[0]); } } // Update term counts to include children. if ($pad_counts && 'all' == $fields) { _pad_term_counts($terms, $taxonomies[0]); } // Make sure we show empty categories that have children. if ($hierarchical && $hide_empty && is_array($terms)) { foreach ($terms as $k => $term) { if (!$term->count) { $children = _get_term_children($term->term_id, $terms, $taxonomies[0]); if (is_array($children)) { foreach ($children as $child) { if ($child->count) { continue 2; } } } // It really is empty unset($terms[$k]); } } } reset($terms); $_terms = array(); if ('id=>parent' == $fields) { while ($term = array_shift($terms)) { $_terms[$term->term_id] = $term->parent; } $terms = $_terms; } elseif ('ids' == $fields) { while ($term = array_shift($terms)) { $_terms[] = $term->term_id; } $terms = $_terms; } elseif ('names' == $fields) { while ($term = array_shift($terms)) { $_terms[] = $term->name; } $terms = $_terms; } if (0 < $number && intval(@count($terms)) > $number) { $terms = array_slice($terms, $offset, $number); } wp_cache_add($cache_key, $terms, 's-terms'); $terms = apply_filters('get_terms', $terms, $taxonomies, $args); return $terms; }
/** * Retrieve the terms in a given taxonomy or list of taxonomies. * * NOTE: This is the Connections equivalent of @see get_terms() in WordPress core ../wp-includes/taxonomy.php * * Filters: * cn_get_terms_atts - The method variables. * Passes: (array) $atts, (array) $taxonomies * Return: $atts * * cn_get_terms_fields - The fields for the SELECT query clause. * Passes: (array) $select, (array) $atts, (array) $taxonomies * Return: $select * * cn_term_inclusions - Query clause which includes terms. * Passes: (string) $inclusions, (array) $atts, (array) $taxonomies * Return: $inclusions * * cn_term_exclusions - Query clause which excludes terms. * Passes: (string) $exclusions, (array) $atts, (array) $taxonomies * Return: $exclusions * * cn_term_orderby - The ORDER BY query clause. * Passes: (string) $orderBy, (array) $atts, (array) $taxonomies * Return: $orderBy * * cn_terms_clauses - An array containing the the query clause segments. * Passes: (array) $pieces, (array) $taxonomies, (array) $atts * Return: $pieces * * Accepted option for the $atts property are: * * get ( string ) * Default: '' * Valid: all * If set to 'all' instead of its default empty string, * returns terms regardless of ancestry or whether the terms are empty. * * fields ( string ) * Default: 'all' * Valid: all | ids | id=>parent | names | count | id=>name | id=>slug * Default is 'all', which returns an array of term objects. * If 'fields' is 'ids' or 'names', returns an array of integers or strings, respectively. * * include ( string | array ) * Default: array() * Valid: An indexed array, comma- or space-delimited string of term_id. * * exclude_tree ( string | array ) * Default: array() * Valid: An indexed array, comma- or space-delimited string of term_id. * If 'include' is non-empty, 'exclude_tree' is ignored. * * exclude ( string | array ) * Default: array() * Valid: An indexed array, comma- or space-delimited string of term_id. * If 'include' is non-empty, 'exclude' is ignored. * * slug ( string | array ) * Default: '' * Slug or array of slugs to return term(s) for. * * hide_empty ( bool ) * Default: TRUE * Will not return empty terms, which means terms whose count is 0. * * hierarchical ( bool ) * Default: TRUE * Whether to include terms that have non-empty descendants, even if 'hide_empty' is set to TRUE. * * orderby ( string | array ) * Default: name * Valid: term_id | name | slug | term_group | parent | count | include * * order ( string | array ) * Default: ASC * Valid: ASC | DESC * * number ( int ) * Default: 0 * The maximum number of terms to return. Default is to return them all. * * offset ( int ) * Default: 0 * The number by which to offset the terms query. * * search ( string ) * Default: '' * Returned terms' names will contain the value of 'search', case-insensitive. * * name__like ( string ) * Default: '' * Return terms' names will contain the value of 'name__like', case-insensitive. * * description__like ( string ) * Default: '' * Return terms' descriptions will contain the value of 'description__like', case-insensitive. * * child_of ( int ) * Default: 0 * The 'child_of' argument, when used, should be set to the integer of a term ID. * If set to a non-zero value, all returned terms will be descendants * of that term according to the given taxonomy. * Hence 'child_of' is set to 0 if more than one taxonomy is passed in $taxonomies, * because multiple taxonomies make term ancestry ambiguous. * * parent ( string | int ) * Default: '' * The integer of a term ID. * If set to an integer value, all returned terms will have as an immediate * ancestor the term whose ID is specified by that integer according to the given taxonomy. * The 'parent' argument is different from 'child_of' in that a term X is considered a 'parent' * of term Y only if term X is the father of term Y, not its grandfather or great-grandfather, etc. * * pad_counts ( bool ) * Default: FALSE * If set to true, include the quantity of a term's children * in the quantity of each term's 'count' property. * * @access public * @since 8.1 * @static * * @global $wpdb * * @param string|array $taxonomies Taxonomy name or array of taxonomy names. * @param array $atts * * @uses apply_filters() * @uses wp_parse_args() * @uses wp_parse_id_list() * @uses sanitize_title() * @uses wpdb::prepare() * @uses $wpdb::esc_like() * @uses absint() * @uses wpdb::get_results() * @uses cnTerm::filter() * @uses cnTerm::descendants() * @uses cnTerm::childrenIDs() * @uses cnTerm::padCounts() * @uses cnTerm::children() * * @return array|WP_Error Indexed array of term objects. Will return WP_Error, if any of $taxonomies do not exist.* */ public static function getTaxonomyTerms($taxonomies = array('category'), $atts = array()) { /** @var $wpdb wpdb */ global $wpdb; $select = array(); $where = array(); $orderBy = array(); $orderByClause = ''; /* * @TODO $taxonomies need to be checked against registered taxonomies. * Presently $taxonomies only support a string rather than array. * Additionally, category is the only supported taxonomy. */ $single_taxonomy = !is_array($taxonomies) || 1 === count($taxonomies); if (!is_array($taxonomies)) { $taxonomies = array($taxonomies); } $defaults = array('get' => '', 'orderby' => 'name', 'order' => 'ASC', 'hide_empty' => TRUE, 'exclude' => array(), 'exclude_tree' => array(), 'include' => array(), 'fields' => 'all', 'slug' => '', 'parent' => '', 'hierarchical' => TRUE, 'child_of' => 0, 'name__like' => '', 'meta_query' => array(), 'pad_counts' => FALSE, 'offset' => 0, 'number' => 0, 'search' => ''); /** * Filter the terms query arguments. * * @since 8.1 * * @param array $atts An array of arguments. * @param string|array $taxonomies A taxonomy or array of taxonomies. */ $atts = apply_filters('cn_get_terms_args', $atts, $taxonomies); $atts = wp_parse_args($atts, $defaults); // @TODO Implement is_taxonomy_hierarchical(). if (!$single_taxonomy || '' !== $atts['parent'] && 0 !== $atts['parent']) { $atts['child_of'] = 0; $atts['hierarchical'] = FALSE; $atts['pad_counts'] = FALSE; } if ('all' == $atts['get']) { $atts['child_of'] = 0; $atts['hide_empty'] = 0; $atts['hierarchical'] = FALSE; $atts['pad_counts'] = FALSE; } if ($atts['child_of']) { $hierarchy = self::childrenIDs(reset($taxonomies)); if (!isset($hierarchy[$atts['child_of']])) { return array(); } } if ($atts['parent']) { $hierarchy = self::childrenIDs(reset($taxonomies)); if (!isset($hierarchy[$atts['parent']])) { return array(); } } // $args can be whatever, only use the args defined in defaults to compute the key $filter_key = has_filter('cn_term_exclusions') ? serialize($GLOBALS['wp_filter']['cn_term_exclusions']) : ''; $key = md5(serialize(wp_array_slice_assoc($atts, array_keys($defaults))) . serialize($taxonomies) . $filter_key); $last_changed = wp_cache_get('last_changed', 'cn_terms'); if (!$last_changed) { $last_changed = microtime(); wp_cache_set('last_changed', $last_changed, 'cn_terms'); } $cache_key = "cn_get_terms:{$key}:{$last_changed}"; $cache = wp_cache_get($cache_key, 'cn_terms'); if (FALSE !== $cache) { /** * Filter the given taxonomy's terms cache. * * @since 8.1.6 * * @param array $cache Cached array of terms for the given taxonomy. * @param string|array $taxonomies A taxonomy or array of taxonomies. * @param array $args An array of arguments to get terms. */ $cache = apply_filters('cn_terms', $cache, $taxonomies, $atts); return $cache; } /* * Construct the ORDER By query clause. */ if (is_array($atts['orderby'])) { foreach ($atts['orderby'] as $i => $value) { if (!isset($order)) { $order = 'ASC'; } switch ($value) { case 'id': case 'term_id': $orderField = 't.term_id'; break; case 'slug': $orderField = 't.slug'; break; case 'include': $include = implode(',', wp_parse_id_list($atts['include'])); $orderField = "FIELD( t.term_id, {$include} )"; break; case 'term_group': $orderField = 't.term_group'; break; case 'none': $orderField = ''; // If an `none` order field was supplied, break out of both the switch and foreach statements. break 2; case 'parent': $orderField = 'tt.parent'; break; case 'count': $orderField = 'tt.count'; break; default: $orderField = 't.name'; break; } // Set the $order to align with $atts['orderby']. if (is_array($atts['order']) && isset($atts['order'][$i])) { $order = $atts['order'][$i]; // If an aligned $atts['order'] does not exist use the last $order set otherwise use $atts['order']. } else { $order = is_array($atts['order']) ? $order : $atts['order']; } $order = strtoupper($order); $order = in_array($order, array('ASC', 'DESC')) ? $order : 'ASC'; $orderBy[] = sprintf('%s %s', $orderField, $order); } // The @var $value will be set to the last value from the $atts['orderby'] foreach loop. // If a `none` $atts['orderby'] was found in the supplied array, no order by clause will be set. if (!empty($orderBy) && $value != 'none') { $orderByClause = 'ORDER BY ' . implode(', ', $orderBy); } } else { switch ($atts['orderby']) { case 'id': case 'term_id': $atts['orderby'] = 't.term_id'; break; case 'slug': $atts['orderby'] = 't.slug'; break; case 'include': $include = implode(',', wp_parse_id_list($atts['include'])); $atts['orderby'] = "FIELD( t.term_id, {$include} )"; break; case 'term_group': $atts['orderby'] = 't.term_group'; break; case 'none': $atts['orderby'] = ''; break; case 'parent': $atts['orderby'] = 'tt.parent'; break; case 'count': $atts['orderby'] = 'tt.count'; break; default: $atts['orderby'] = 't.name'; break; } if (is_array($atts['order'])) { // $atts['orderby'] was a string but an array was passed for $atts['order'], assume the 0 index. $order = $atts['order'][0]; } else { $order = $atts['order']; } if (!empty($atts['orderby'])) { $order = strtoupper($order); $order = in_array($order, array('ASC', 'DESC')) ? $order : 'ASC'; $orderByClause = 'ORDER BY ' . sprintf('%s %s', $atts['orderby'], $order); } } /* * Filter the ORDER BY clause of the terms query. * * @since 8.1 * * @param string $orderBy ORDER BY clause of the terms query. * @param array $atts An array of terms query arguments. * @param string|array $taxonomies A taxonomy or array of taxonomies. */ $orderBy = apply_filters('cn_terms_orderby', $orderByClause, $atts, $taxonomies); /* * Start construct the WHERE query clause. */ $where[] = 'tt.taxonomy IN (\'' . implode('\', \'', $taxonomies) . '\')'; /* * Define the included terms. */ $inclusions = ''; if (!empty($atts['include'])) { $atts['exclude'] = ''; $atts['exclude_tree'] = ''; $inclusions = implode(',', wp_parse_id_list($atts['include'])); } if (!empty($inclusions)) { $inclusions = 'AND t.term_id IN ( ' . $inclusions . ' )'; } /** * Filter the terms to be included in the terms query. * * @since 8.1 * * @param string $inclusions IN clause of the terms query. * @param array $atts An array of terms query arguments. * @param string|array $taxonomies A taxonomy or array of taxonomies. */ $inclusions = apply_filters('cn_term_inclusions', $inclusions, $atts, $taxonomies); if (!empty($inclusions)) { $where[] = $inclusions; } /* * Define the excluded terms. */ $exclusions = ''; if (!empty($atts['exclude_tree'])) { $atts['exclude_tree'] = wp_parse_id_list($atts['exclude_tree']); $excluded_children = $atts['exclude_tree']; foreach ($atts['exclude_tree'] as $extrunk) { $excluded_children = array_merge($excluded_children, (array) cnTerm::getTaxonomyTerms($taxonomies[0], array('child_of' => intval($extrunk), 'fields' => 'ids', 'hide_empty' => 0))); } $exclusions = implode(',', array_map('intval', $excluded_children)); } if (!empty($atts['exclude'])) { $exterms = wp_parse_id_list($atts['exclude']); if (empty($exclusions)) { $exclusions = implode(',', $exterms); } else { $exclusions .= ', ' . implode(',', $exterms); } } if (!empty($exclusions)) { $exclusions = 'AND t.term_id NOT IN (' . $exclusions . ')'; } /** * Filter the terms to exclude from the terms query. * * @since 8.1 * * @param string $exclusions NOT IN clause of the terms query. * @param array $atts An array of terms query arguments. * @param string|array $taxonomies A taxonomy or array of taxonomies. */ $exclusions = apply_filters('cn_term_exclusions', $exclusions, $atts, $taxonomies); if (!empty($exclusions)) { $where[] = $exclusions; } if (!empty($atts['slug'])) { if (is_array($atts['slug'])) { $slug = array_map('sanitize_title', $atts['slug']); $where[] = " AND t.slug IN ('" . implode("', '", $slug) . "')"; } else { $slug = sanitize_title($atts['slug']); $where[] = " AND t.slug = '{$slug}'"; } } if (!empty($atts['name__like'])) { //$atts['name__like'] = like_escape( $atts['name__like'] ); $where[] = $wpdb->prepare(" AND t.name LIKE %s", '%' . $wpdb->esc_like($atts['name__like']) . '%'); //$where[] = $wpdb->prepare( 'AND t.name LIKE %s', '%' . $atts['name__like'] . '%' ); } if (!empty($atts['description__like'])) { //$atts['description__like'] = like_escape( $atts['description__like'] ); $where[] = $wpdb->prepare(" AND tt.description LIKE %s", '%' . $wpdb->esc_like($atts['description__like']) . '%'); //$where[] = $wpdb->prepare( 'AND tt.description LIKE %s', '%' . $atts['description__like'] . '%' ); } if ('' !== $atts['parent']) { $where[] = $wpdb->prepare('AND tt.parent = %d', $atts['parent']); } if ('count' == $atts['fields']) { $atts['hierarchical'] = FALSE; } if ($atts['hide_empty'] && !$atts['hierarchical']) { $where[] = 'AND tt.count > 0'; } // Do not limit the query results when we have to descend the family tree. if ($atts['number'] && !$atts['hierarchical'] && !$atts['child_of'] && '' === $atts['parent']) { $atts['number'] = absint($atts['number']); $atts['offset'] = absint($atts['offset']); if ($atts['offset']) { $limit = $wpdb->prepare('LIMIT %d,%d', $atts['offset'], $atts['number']); } else { $limit = $wpdb->prepare('LIMIT %d', $atts['number']); } } else { $limit = ''; } if (!empty($atts['search'])) { //$atts['search'] = like_escape( $atts['search'] ); $atts['search'] = $wpdb->esc_like($atts['search']); $where[] = $wpdb->prepare('AND ( (t.name LIKE %s) OR (t.slug LIKE %s) )', '%' . $atts['search'] . '%', '%' . $atts['search'] . '%'); } switch ($atts['fields']) { case 'all': $select = array('t.*', 'tt.*'); break; case 'ids': case 'id=>parent': $select = array('t.term_id', 'tt.parent', 'tt.count'); break; case 'names': $select = array('t.term_id', 'tt.parent', 'tt.count', 't.name'); break; case 'count': $orderBy = ''; //$order = ''; $select = array('COUNT(*)'); break; case 'id=>name': $select = array('t.term_id', 't.name'); break; case 'id=>slug': $select = array('t.term_id', 't.slug'); break; } /** * Filter the fields to select in the terms query. * * @since 8.1 * * @param array $select An array of fields to select for the terms query. * @param array $atts An array of term query arguments. * @param string|array $taxonomies A taxonomy or array of taxonomies. */ $fields = implode(', ', apply_filters('cn_get_terms_fields', $select, $atts, $taxonomies)); $join = 'INNER JOIN ' . CN_TERM_TAXONOMY_TABLE . ' AS tt ON t.term_id = tt.term_id'; $pieces = array('fields', 'join', 'where', 'orderBy', 'limit'); /** * Filter the terms query SQL clauses. * * @since 8.1 * * @param array $pieces Terms query SQL clauses. * @param string|array $taxonomies A taxonomy or array of taxonomies. * @param array $atts An array of terms query arguments. */ $clauses = apply_filters('cn_terms_clauses', compact($pieces), $taxonomies, $atts); foreach ($pieces as $piece) { ${$piece} = isset($clauses[$piece]) ? $clauses[$piece] : ''; } $sql = sprintf('SELECT %1$s FROM %2$s AS t %3$s WHERE %4$s %5$s%6$s', $fields, CN_TERMS_TABLE, $join, implode(' ', $where), $orderBy, empty($limit) ? '' : ' ' . $limit); if ('count' == $atts['fields']) { $term_count = $wpdb->get_var($sql); return $term_count; } $terms = $wpdb->get_results($sql); if ('all' == $atts['fields']) { foreach ($taxonomies as $taxonomy) { update_term_cache($terms, 'cn_' . $taxonomy); } } if (empty($terms)) { wp_cache_add($cache_key, array(), 'cn_terms', DAY_IN_SECONDS); $terms = apply_filters('cn_terms', array(), $taxonomies, $atts); return $terms; } if ($atts['child_of']) { $children = self::childrenIDs(reset($taxonomies)); if (!empty($children)) { $terms = self::descendants($atts['child_of'], $terms, reset($taxonomies)); } } /* * @todo Add method to adjust counts based on user visibility permissions. */ // Update term counts to include children. if ($atts['pad_counts'] && 'all' == $atts['fields']) { self::padCounts($terms, reset($taxonomies)); } // Make sure we show empty categories that have children. if ($atts['hierarchical'] && $atts['hide_empty'] && is_array($terms)) { foreach ($terms as $k => $term) { if (!$term->count) { $children = self::children($term->term_id, reset($taxonomies)); if (is_array($children)) { foreach ($children as $child_id) { $child = self::filter($child_id, reset($taxonomies)); if ($child->count) { continue 2; } } } // It really is empty unset($terms[$k]); } } } reset($terms); $_terms = array(); if ('id=>parent' == $atts['fields']) { while ($term = array_shift($terms)) { $_terms[$term->term_id] = $term->parent; } } elseif ('ids' == $atts['fields']) { while ($term = array_shift($terms)) { $_terms[] = $term->term_id; } } elseif ('names' == $atts['fields']) { while ($term = array_shift($terms)) { $_terms[] = $term->name; } } elseif ('id=>name' == $atts['fields']) { while ($term = array_shift($terms)) { $_terms[$term->term_id] = $term->name; } } elseif ('id=>slug' == $atts['fields']) { while ($term = array_shift($terms)) { $_terms[$term->term_id] = $term->slug; } } if (!empty($_terms)) { $terms = $_terms; } if ($atts['number'] && is_array($terms) && count($terms) > $atts['number']) { $terms = array_slice($terms, $atts['offset'], $atts['number']); } wp_cache_add($cache_key, $terms, 'cn_terms', DAY_IN_SECONDS); $terms = apply_filters('cn_terms', $terms, $taxonomies, $atts); return $terms; }
/** * @ticket 35462 */ public function test_term_objects_should_not_be_modified_by_update_term_cache() { register_taxonomy('wptests_tax', 'post'); $t = self::factory()->term->create(array('taxonomy' => 'wptests_tax')); $p = self::factory()->post->create(); wp_set_object_terms($p, $t, 'wptests_tax'); $terms = wp_get_object_terms($p, 'wptests_tax', array('fields' => 'all_with_object_id')); update_term_cache($terms); foreach ($terms as $term) { $this->assertSame($p, $term->object_id); } }
/** * Retrieves the terms associated with the given object(s), in the supplied taxonomies. * * The following information has to do the $args parameter and for what can be * contained in the string or array of that parameter, if it exists. * * The first argument is called, 'orderby' and has the default value of 'name'. * The other value that is supported is 'count'. * * The second argument is called, 'order' and has the default value of 'ASC'. * The only other value that will be acceptable is 'DESC'. * * The final argument supported is called, 'fields' and has the default value of * 'all'. There are multiple other options that can be used instead. Supported * values are as follows: 'all', 'ids', 'names', and finally * 'all_with_object_id'. * * The fields argument also decides what will be returned. If 'all' or * 'all_with_object_id' is chosen or the default kept intact, then all matching * terms objects will be returned. If either 'ids' or 'names' is used, then an * array of all matching term ids or term names will be returned respectively. * * @see wp_get_object_terms() * @uses $wpdb * * @param int|array $object_ids The ID(s) of the object(s) to retrieve. * @param string|array $taxonomies The taxonomies to retrieve terms from. * @param array|string $args Change what is returned * * @return array|WP_Error The requested term data or empty array if no terms found. WP_Error if $taxonomy does not exist. */ function get_gmedia_terms($object_ids, $taxonomies, $args = array()) { /** @var $wpdb wpdb */ global $wpdb; $gmOptions = get_option('gmediaOptions'); if (!is_array($taxonomies)) { $taxonomies = array($taxonomies); } foreach ((array) $taxonomies as $taxonomy) { if (!isset($gmOptions['taxonomies'][$taxonomy])) { return new WP_Error('gm_invalid_taxonomy', __('Invalid Taxonomy')); } } if (!is_array($object_ids)) { $object_ids = array($object_ids); } $object_ids = array_map('intval', $object_ids); $defaults = array('orderby' => 'name', 'order' => 'ASC', 'fields' => 'all', 'unique' => true); $args = wp_parse_args($args, $defaults); $terms = array(); /** @var $orderby * @var $order * @var $fields * @var $unique */ extract($args, EXTR_SKIP); if ($unique) { $groupby = 'GROUP BY t.term_id'; } else { $groupby = ''; } if ('count' == $orderby) { $orderby = 't.count'; } else { if ('name' == $orderby) { $orderby = 't.name'; } else { if ('global' == $orderby) { $orderby = 't.global'; } else { if ('term_order' == $orderby) { $orderby = 'tr.term_order'; } else { if ('none' == $orderby) { $orderby = ''; $order = ''; } else { $orderby = 't.term_id'; } } } } } if (!empty($orderby)) { $orderby = "ORDER BY {$orderby}"; } $taxonomies = "'" . implode("', '", $taxonomies) . "'"; $object_ids = implode(', ', $object_ids); $select_this = ''; if ('all' == $fields) { $select_this = 't.*'; } else { if ('ids' == $fields) { $select_this = 't.term_id'; } else { if ('names' == $fields) { $select_this = 't.name'; } else { if ('all_with_object_id' == $fields) { $select_this = 't.*, tr.gmedia_id'; $groupby = ''; } } } } $query = "SELECT {$select_this} FROM {$wpdb->prefix}gmedia_term AS t INNER JOIN {$wpdb->prefix}gmedia_term_relationships AS tr ON tr.gmedia_term_id = t.term_id WHERE t.taxonomy IN ({$taxonomies}) AND tr.gmedia_id IN ({$object_ids}) {$groupby} {$orderby} {$order}"; if ('all' == $fields || 'all_with_object_id' == $fields) { $terms = array_merge($terms, $wpdb->get_results($query)); // todo ? maybe move function to plugin core update_term_cache($terms); } else { if ('ids' == $fields || 'names' == $fields) { $terms = array_merge($terms, $wpdb->get_col($query)); } } if (!$terms) { $terms = array(); } return apply_filters('get_gmedia_terms', $terms, $object_ids, $taxonomies, $args); }
/** * Retrieves the terms associated with the given object(s), in the supplied taxonomies. * * The following information has to do the $args parameter and for what can be * contained in the string or array of that parameter, if it exists. * * The first argument is called, 'orderby' and has the default value of 'name'. * The other value that is supported is 'count'. * * The second argument is called, 'order' and has the default value of 'ASC'. * The only other value that will be acceptable is 'DESC'. * * The final argument supported is called, 'fields' and has the default value of * 'all'. There are multiple other options that can be used instead. Supported * values are as follows: 'all', 'ids', 'names', and finally * 'all_with_object_id'. * * The fields argument also decides what will be returned. If 'all' or * 'all_with_object_id' is chosen or the default kept intact, then all matching * terms objects will be returned. If either 'ids' or 'names' is used, then an * array of all matching term ids or term names will be returned respectively. * * @package WordPress * @subpackage Taxonomy * @since 2.3.0 * @uses $wpdb * * @param int|array $object_ids The ID(s) of the object(s) to retrieve. * @param string|array $taxonomies The taxonomies to retrieve terms from. * @param array|string $args Change what is returned * @return array|WP_Error The requested term data or empty array if no terms found. WP_Error if any of the $taxonomies don't exist. */ function wp_get_object_terms($object_ids, $taxonomies, $args = array()) { global $wpdb; if (empty($object_ids) || empty($taxonomies)) { return array(); } if (!is_array($taxonomies)) { $taxonomies = array($taxonomies); } foreach ((array) $taxonomies as $taxonomy) { if (!taxonomy_exists($taxonomy)) { return new WP_Error('invalid_taxonomy', __('Invalid taxonomy')); } } if (!is_array($object_ids)) { $object_ids = array($object_ids); } $object_ids = array_map('intval', $object_ids); $defaults = array('orderby' => 'name', 'order' => 'ASC', 'fields' => 'all'); $args = wp_parse_args($args, $defaults); $terms = array(); if (count($taxonomies) > 1) { foreach ($taxonomies as $index => $taxonomy) { $t = get_taxonomy($taxonomy); if (isset($t->args) && is_array($t->args) && $args != array_merge($args, $t->args)) { unset($taxonomies[$index]); $terms = array_merge($terms, wp_get_object_terms($object_ids, $taxonomy, array_merge($args, $t->args))); } } } else { $t = get_taxonomy($taxonomies[0]); if (isset($t->args) && is_array($t->args)) { $args = array_merge($args, $t->args); } } extract($args, EXTR_SKIP); if ('count' == $orderby) { $orderby = 'tt.count'; } else { if ('name' == $orderby) { $orderby = 't.name'; } else { if ('slug' == $orderby) { $orderby = 't.slug'; } else { if ('term_group' == $orderby) { $orderby = 't.term_group'; } else { if ('term_order' == $orderby) { $orderby = 'tr.term_order'; } else { if ('none' == $orderby) { $orderby = ''; $order = ''; } else { $orderby = 't.term_id'; } } } } } } // tt_ids queries can only be none or tr.term_taxonomy_id if ('tt_ids' == $fields && !empty($orderby)) { $orderby = 'tr.term_taxonomy_id'; } if (!empty($orderby)) { $orderby = "ORDER BY {$orderby}"; } $order = strtoupper($order); if ('' !== $order && !in_array($order, array('ASC', 'DESC'))) { $order = 'ASC'; } $taxonomies = "'" . implode("', '", $taxonomies) . "'"; $object_ids = implode(', ', $object_ids); $select_this = ''; if ('all' == $fields) { $select_this = 't.*, tt.*'; } else { if ('ids' == $fields) { $select_this = 't.term_id'; } else { if ('names' == $fields) { $select_this = 't.name'; } else { if ('slugs' == $fields) { $select_this = 't.slug'; } else { if ('all_with_object_id' == $fields) { $select_this = 't.*, tt.*, tr.object_id'; } } } } } $query = "SELECT {$select_this} FROM {$wpdb->terms} AS t INNER JOIN {$wpdb->term_taxonomy} AS tt ON tt.term_id = t.term_id INNER JOIN {$wpdb->term_relationships} AS tr ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tt.taxonomy IN ({$taxonomies}) AND tr.object_id IN ({$object_ids}) {$orderby} {$order}"; if ('all' == $fields || 'all_with_object_id' == $fields) { $_terms = $wpdb->get_results($query); foreach ($_terms as $key => $term) { $_terms[$key] = sanitize_term($term, $taxonomy, 'raw'); } $terms = array_merge($terms, $_terms); update_term_cache($terms); } else { if ('ids' == $fields || 'names' == $fields || 'slugs' == $fields) { $_terms = $wpdb->get_col($query); $_field = 'ids' == $fields ? 'term_id' : 'name'; foreach ($_terms as $key => $term) { $_terms[$key] = sanitize_term_field($_field, $term, $term, $taxonomy, 'raw'); } $terms = array_merge($terms, $_terms); } else { if ('tt_ids' == $fields) { $terms = $wpdb->get_col("SELECT tr.term_taxonomy_id FROM {$wpdb->term_relationships} AS tr INNER JOIN {$wpdb->term_taxonomy} AS tt ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tr.object_id IN ({$object_ids}) AND tt.taxonomy IN ({$taxonomies}) {$orderby} {$order}"); foreach ($terms as $key => $tt_id) { $terms[$key] = sanitize_term_field('term_taxonomy_id', $tt_id, 0, $taxonomy, 'raw'); // 0 should be the term id, however is not needed when using raw context. } } } } if (!$terms) { $terms = array(); } return apply_filters('wp_get_object_terms', $terms, $object_ids, $taxonomies, $args); }
/** * Returns the terms associated with the given object(s), in the supplied taxonomies. * @param int|array $object_id The id of the object(s)) to retrieve for. * @param string|array $taxonomies The taxonomies to retrieve terms from. * @return array The requested term data. */ function wp_get_object_terms($object_ids, $taxonomies, $args = array()) { global $wpdb; if (!is_array($taxonomies)) { $taxonomies = array($taxonomies); } foreach ($taxonomies as $taxonomy) { if (!is_taxonomy($taxonomy)) { return new WP_Error('invalid_taxonomy', __('Invalid Taxonomy')); } } if (!is_array($object_ids)) { $object_ids = array($object_ids); } $object_ids = array_map('intval', $object_ids); $defaults = array('orderby' => 'name', 'order' => 'ASC', 'fields' => 'all'); $args = wp_parse_args($args, $defaults); extract($args, EXTR_SKIP); if ('count' == $orderby) { $orderby = 'tt.count'; } else { if ('name' == $orderby) { $orderby = 't.name'; } } $taxonomies = "'" . implode("', '", $taxonomies) . "'"; $object_ids = implode(', ', $object_ids); if ('all' == $fields) { $select_this = 't.*, tt.*'; } else { if ('ids' == $fields) { $select_this = 't.term_id'; } else { if ('names' == $fields) { $select_this = 't.name'; } else { if ('all_with_object_id' == $fields) { $select_this = 't.*, tt.*, tr.object_id'; } } } } $query = "SELECT {$select_this} FROM {$wpdb->terms} AS t INNER JOIN {$wpdb->term_taxonomy} AS tt ON tt.term_id = t.term_id INNER JOIN {$wpdb->term_relationships} AS tr ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tt.taxonomy IN ({$taxonomies}) AND tr.object_id IN ({$object_ids}) ORDER BY {$orderby} {$order}"; if ('all' == $fields || 'all_with_object_id' == $fields) { $terms = $wpdb->get_results($query); update_term_cache($terms); } else { if ('ids' == $fields || 'names' == $fields) { $terms = $wpdb->get_col($query); } else { if ('tt_ids' == $fields) { $terms = $wpdb->get_col("SELECT tr.term_taxonomy_id FROM {$wpdb->term_relationships} AS tr INNER JOIN {$wpdb->term_taxonomy} AS tt ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tr.object_id IN ({$object_ids}) AND tt.taxonomy IN ({$taxonomies}) ORDER BY tr.term_taxonomy_id {$order}"); } } } if (!$terms) { return array(); } return $terms; }
/** * Function called when query parameters are processed by Wordpress. * * @param $query query parameters * @return array() $query processed * * @since 1.0 */ function filter_request($query) { global $q_config, $wp_query, $wp; if (isset($wp->matched_query)) { $query = wp_parse_args($wp->matched_query); } foreach (get_post_types() as $post_type) { if (array_key_exists($post_type, $query) && !in_array($post_type, array('post', 'page'))) { $query['post_type'] = $post_type; } } $page_foundit = false; // -> page if (isset($query['pagename']) || isset($query['page_id'])) { $page = wp_cache_get('qts_page_request'); if (!$page) { $page = isset($query['page_id']) ? get_page($query['page_id']) : $this->get_page_by_path($query['pagename']); } if (!$page) { return $query; } $id = $page->ID; $cache_array = array($page); update_post_caches($cache_array, 'page'); // caching query :) wp_cache_delete('qts_page_request'); $query['pagename'] = get_page_uri($page); $function = 'get_page_link'; // -> custom post type } elseif (isset($query['post_type'])) { $page_slug = isset($query['name']) && !empty($query['name']) ? $query['name'] : $query[$query['post_type']]; $page = $this->get_page_by_path($page_slug, OBJECT, $query['post_type']); if (!$page) { return $query; } $id = $page->ID; $cache_array = array($page); update_post_caches($cache_array, $query['post_type']); // caching query :) $query['name'] = $query[$query['post_type']] = get_page_uri($page); $function = 'get_post_permalink'; // -> post } elseif (isset($query['name']) || isset($query['p'])) { $post = isset($query['p']) ? get_post($query['p']) : $this->get_page_by_path($query['name'], OBJECT, 'post'); if (!$post) { return $query; } $query['name'] = $post->post_name; $id = $post->ID; $cache_array = array($post); update_post_caches($cache_array); $function = 'get_permalink'; // -> category } elseif (isset($query['category_name']) || isset($query['cat'])) { if (isset($query['category_name'])) { $term_slug = $this->get_last_slash($query['category_name']); } $term = isset($query['cat']) ? get_term($query['cat'], 'category') : $this->get_term_by('slug', $term_slug, 'category'); if (!$term) { return $query; } $cache_array = array($term); update_term_cache($cache_array, 'category'); // caching query :) $id = $term->term_id; $query['category_name'] = $term->slug; // uri $function = 'get_category_link'; // -> tag } elseif (isset($query['tag'])) { $term = $this->get_term_by('slug', $query['tag'], 'post_tag'); if (!$term) { return $query; } $cache_array = array($term); update_term_cache($cache_array, 'post_tag'); // caching query :) $id = $term->term_id; $query['tag'] = $term->slug; $function = 'get_tag_link'; } // -> taxonomy $taxonomies = get_taxonomies(array('public' => true, '_builtin' => false)); foreach ($taxonomies as $term_name) { if (isset($query[$term_name])) { $term_slug = $this->get_last_slash($query[$term_name]); $term = $this->get_term_by('slug', $term_slug, $term_name); if (!$term) { return $query; } $cache_array = array($term); update_term_cache($cache_array, $term_name); // caching query :) $id = $term; $query[$term_name] = $term->slug; $function = 'get_term_link'; } } // -> home url if (empty($query)) { $function = 'home_url'; $id = ''; } if (isset($function)) { // parse all languages links foreach ($q_config['enabled_languages'] as $lang) { $this->lang = $lang; $this->current_url[$lang] = apply_filters('qts_url_args', call_user_func($function, $id)); } $this->lang = false; } return $query; }
/** * Retrieves the terms associated with the given object(s), in the * supplied taxonomies. * * This is a copy of WordPress' wp_get_object_terms function with a bunch * of edits to use term_order as a default sorting param. * * @since 1.0 * * @param array $terms The post's terms * @param int|array $object_ids The ID(s) of the object(s) to retrieve. * @param string|array $taxonomies The taxonomies to retrieve terms from. * @param array|string $args Change what is returned * * @return array|WP_Error The requested term data or empty array if no * terms found. WP_Error if any of the $taxonomies * don't exist. */ public static function get_ordered_object_terms($terms, $object_ids, $taxonomies, $args) { $total = count($terms); $original_terms = $terms; // Term ordering is killing quick/bulk edit, avoid it if (is_admin() && (function_exists('get_current_screen') && 'edit-movie' == get_current_screen()->id)) { return $terms; } $taxonomies = explode(', ', str_replace("'", "", $taxonomies)); if (empty($object_ids) || $taxonomies != "'collection', 'actor', 'genre'" && (!in_array('collection', $taxonomies) && !in_array('actor', $taxonomies) && !in_array('genre', $taxonomies))) { return $terms; } global $wpdb; foreach ((array) $taxonomies as $taxonomy) { if (!taxonomy_exists($taxonomy)) { return new WP_Error('invalid_taxonomy', __('Invalid taxonomy')); } } if (!is_array($object_ids)) { $object_ids = array($object_ids); } $object_ids = array_map('intval', $object_ids); $defaults = array('orderby' => 'term_order', 'order' => 'ASC', 'fields' => 'all'); $args = wp_parse_args($args, $defaults); $terms = array(); if (count($taxonomies) > 1) { foreach ($taxonomies as $index => $taxonomy) { $t = get_taxonomy($taxonomy); if (isset($t->args) && is_array($t->args) && $args != array_merge($args, $t->args)) { unset($taxonomies[$index]); $terms = array_merge($terms, self::get_ordered_object_terms($object_ids, $taxonomy, array_merge($args, $t->args))); } } } else { $t = get_taxonomy($taxonomies[0]); if (isset($t->args) && is_array($t->args)) { $args = array_merge($args, $t->args); } } extract($args, EXTR_SKIP); $orderby = "ORDER BY tr.term_order"; $order = 'ASC'; $taxonomies = "'" . implode("', '", $taxonomies) . "'"; $object_ids = implode(', ', $object_ids); $select_this = ''; if ('all' == $fields) { $select_this = 't.*, tt.*'; } else { if ('ids' == $fields) { $select_this = 't.term_id'; } else { if ('names' == $fields) { $select_this = 't.name'; } else { if ('slugs' == $fields) { $select_this = 't.slug'; } else { if ('all_with_object_id' == $fields) { $select_this = 't.*, tt.*, tr.object_id'; } } } } } $query = "SELECT {$select_this} FROM {$wpdb->terms} AS t INNER JOIN {$wpdb->term_taxonomy} AS tt ON tt.term_id = t.term_id INNER JOIN {$wpdb->term_relationships} AS tr ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tt.taxonomy IN ({$taxonomies}) AND tr.object_id IN ({$object_ids}) {$orderby} {$order}"; if ('all' == $fields || 'all_with_object_id' == $fields) { $_terms = $wpdb->get_results($query); foreach ($_terms as $key => $term) { $_terms[$key] = sanitize_term($term, $taxonomy, 'raw'); } $terms = array_merge($terms, $_terms); update_term_cache($terms); } else { if ('ids' == $fields || 'names' == $fields || 'slugs' == $fields) { $_terms = $wpdb->get_col($query); $_field = 'ids' == $fields ? 'term_id' : 'name'; foreach ($_terms as $key => $term) { $_terms[$key] = sanitize_term_field($_field, $term, $term, $taxonomy, 'raw'); } $terms = array_merge($terms, $_terms); } else { if ('tt_ids' == $fields) { $terms = $wpdb->get_col("SELECT tr.term_taxonomy_id FROM {$wpdb->term_relationships} AS tr INNER JOIN {$wpdb->term_taxonomy} AS tt ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tr.object_id IN ({$object_ids}) AND tt.taxonomy IN ({$taxonomies}) {$orderby} {$order}"); foreach ($terms as $key => $tt_id) { $terms[$key] = sanitize_term_field('term_taxonomy_id', $tt_id, 0, $taxonomy, 'raw'); // 0 should be the term id, however is not needed when using raw context. } } } } if (!$terms) { $terms = array(); } if ($total != count($terms)) { $terms = $original_terms; } return $terms; }
/** * Extended get_terms function support * - Limit category * - Limit days * - Selection restrict * - Min usage * * @param string|array $taxonomies * @param string $args * @return array */ function getTerms( $taxonomies, $args = '', $skip_cache = false, $internal_st = false ) { global $wpdb; $empty_array = array(); $single_taxonomy = false; if ( !is_array($taxonomies) ) { $single_taxonomy = true; $taxonomies = array($taxonomies); } foreach ( $taxonomies as $taxonomy ) { if ( ! is_taxonomy($taxonomy) ) { return new WP_Error('invalid_taxonomy', __('Invalid Taxonomy')); } } $in_taxonomies = "'" . implode("', '", $taxonomies) . "'"; $defaults = array( 'orderby' => 'name', 'order' => 'ASC', 'cloud_selection' => 'count-desc', 'hide_empty' => true, 'exclude' => '', 'include' => '', 'number' => '', 'fields' => 'all', 'slug' => '', 'parent' => '', 'hierarchical' => true, 'child_of' => 0, 'get' => '', 'name__like' => '', 'st_name_like' => '', 'pad_counts' => false, 'offset' => '', 'search' => '', 'limit_days' => 0, 'category' => 0, 'min_usage' => 0 ); $args = wp_parse_args( $args, $defaults ); if ( $internal_st != true ) { // Allow limit :) $args['number'] = absint( $args['number'] ); } $args['offset'] = absint( $args['offset'] ); if ( !$single_taxonomy || !is_taxonomy_hierarchical($taxonomies[0]) || '' != $args['parent'] ) { $args['child_of'] = 0; $args['hierarchical'] = false; $args['pad_counts'] = false; } if ( 'all' == $args['get'] ) { $args['child_of'] = 0; $args['hide_empty'] = 0; $args['hierarchical'] = false; $args['pad_counts'] = false; } extract($args, EXTR_SKIP); if ( $child_of ) { $hierarchy = _get_term_hierarchy($taxonomies[0]); if ( !isset($hierarchy[$child_of]) ) return $empty_array; } if ( $parent ) { $hierarchy = _get_term_hierarchy($taxonomies[0]); if ( !isset($hierarchy[$parent]) ) return $empty_array; } if ( $skip_cache != true ) { // $args can be whatever, only use the args defined in defaults to compute the key $filter_key = ( has_filter('list_terms_exclusions') ) ? serialize($GLOBALS['wp_filter']['list_terms_exclusions']) : ''; $key = md5( serialize( compact(array_keys($defaults)) ) . serialize( $taxonomies ) . $filter_key ); $last_changed = wp_cache_get('last_changed', 'terms'); if ( !$last_changed ) { $last_changed = time(); wp_cache_set('last_changed', $last_changed, 'terms'); } $cache_key = "get_terms:$key:$last_changed"; if ( $cache = wp_cache_get( $cache_key, 'terms' ) ) { $terms = apply_filters('get_terms', $cache, $taxonomies, $args); return $terms; } } // Restrict category $category_sql = ''; if ( !empty($category) && $category != '0' ) { $incategories = preg_split('/[\s,]+/', $category); $objects_id = get_objects_in_term( $incategories, 'category' ); $objects_id = array_unique ($objects_id); // to be sure haven't duplicates if ( empty($objects_id) ) { // No posts for this category = no tags for this category return array(); } foreach ( (array) $objects_id as $object_id ) { $category_sql .= "'". $object_id . "', "; } $category_sql = substr($category_sql, 0, strlen($category_sql) - 2); // Remove latest ", " $category_sql = 'AND p.ID IN ('.$category_sql.')'; } // count-asc/count-desc/name-asc/name-desc/random $cloud_selection = strtolower($cloud_selection); switch ( $cloud_selection ) { case 'count-asc': $order_by = 'tt.count ASC'; break; case 'random': $order_by = 'RAND()'; break; case 'name-asc': $order_by = 't.name ASC'; break; case 'name-desc': $order_by = 't.name DESC'; break; default: // count-desc $order_by = 'tt.count DESC'; break; } // Min usage $restict_usage = ''; $min_usage = (int) $min_usage; if ( $min_usage != 0 ) { $restict_usage = ' AND tt.count >= '. $min_usage; } $where = ''; $inclusions = ''; if ( !empty($include) ) { $exclude = ''; $interms = preg_split('/[\s,]+/',$include); foreach ( (array) $interms as $interm ) { if (empty($inclusions)) { $inclusions = ' AND ( t.term_id = ' . intval($interm) . ' '; } else { $inclusions .= ' OR t.term_id = ' . intval($interm) . ' '; } } } if ( !empty($inclusions) ) { $inclusions .= ')'; } $where .= $inclusions; $exclusions = ''; if ( !empty($exclude) ) { $exterms = preg_split('/[\s,]+/',$exclude); foreach ( (array) $exterms as $exterm ) { if (empty($exclusions)) { $exclusions = ' AND ( t.term_id <> ' . intval($exterm) . ' '; } else { $exclusions .= ' AND t.term_id <> ' . intval($exterm) . ' '; } } } if ( !empty($exclusions) ) { $exclusions .= ')'; } $exclusions = apply_filters('list_terms_exclusions', $exclusions, $args ); $where .= $exclusions; if ( !empty($slug) ) { $slug = sanitize_title($slug); $where .= " AND t.slug = '$slug'"; } if ( !empty($name__like) ) { $where .= " AND t.name LIKE '{$name__like}%'"; } if ( strpos($st_name_like, ' ') != false || strpos($st_name_like, ' ') != null ) { $tmp = ''; $sts = explode(' ', $st_name_like); foreach ( (array) $sts as $st ) { if ( empty($st) ) continue; $st = addslashes_gpc($st); $tmp .= " t.name LIKE '%{$st}%' OR "; } // Remove latest OR $tmp = substr( $tmp, 0, strlen($tmp) - 4); $where .= " AND ( $tmp ) "; unset($tmp) ; } elseif ( !empty($st_name_like) ) { $where .= " AND t.name LIKE '%{$st_name_like}%'"; } if ( '' != $parent ) { $parent = (int) $parent; $where .= " AND tt.parent = '$parent'"; } if ( $hide_empty && !$hierarchical ) { $where .= ' AND tt.count > 0'; } $number_sql = ''; if ( strpos($number, ',') != false || strpos($number, ',') != null ) { $number_sql = $number; } else { $number = (int) $number; if ( $number != 0 ) { $number_sql = 'LIMIT ' . $number; } } if ( !empty($search) ) { $search = like_escape($search); $where .= " AND (t.name LIKE '%$search%')"; } $select_this = ''; if ( 'all' == $fields ) { $select_this = 't.*, tt.*'; } else if ( 'ids' == $fields ) { $select_this = 't.term_id, tt.parent, tt.count'; } else if ( 'names' == $fields ) { $select_this = 't.term_id, tt.parent, tt.count, t.name'; } // Limit posts date $limitdays_sql = ''; $limit_days = (int) $limit_days; if ( $limit_days != 0 ) { $limitdays_sql = 'AND p.post_date_gmt > "' .date( 'Y-m-d H:i:s', time() - $limit_days * 86400 ). '"'; } $query = "SELECT {$select_this} FROM {$wpdb->terms} AS t INNER JOIN {$wpdb->term_taxonomy} AS tt ON t.term_id = tt.term_id INNER JOIN {$wpdb->term_relationships} AS tr ON tt.term_taxonomy_id = tr.term_taxonomy_id INNER JOIN {$wpdb->posts} AS p ON tr.object_id = p.ID WHERE tt.taxonomy IN ( {$in_taxonomies} ) AND p.post_date_gmt < '".current_time('mysql')."' {$limitdays_sql} {$category_sql} {$where} {$restict_usage} GROUP BY t.term_id ORDER BY {$order_by} {$number_sql}"; if ( 'all' == $fields ) { $terms = $wpdb->get_results($query); if ( $skip_cache != true ) { update_term_cache($terms); } } else if ( ('ids' == $fields) || ('names' == $fields) ) { $terms = $wpdb->get_results($query); } if ( empty($terms) ) { $cache[ $key ] = array(); wp_cache_set( 'get_terms', $cache, 'terms' ); $terms = apply_filters('get_terms', array(), $taxonomies, $args); return $terms; } if ( $child_of ) { $children = _get_term_hierarchy($taxonomies[0]); if ( ! empty($children) ) $terms = & _get_term_children($child_of, $terms, $taxonomies[0]); } // Update term counts to include children. if ( $pad_counts && 'all' == $fields ) _pad_term_counts($terms, $taxonomies[0]); // Make sure we show empty categories that have children. if ( $hierarchical && $hide_empty && is_array($terms) ) { foreach ( $terms as $k => $term ) { if ( ! $term->count ) { $children = _get_term_children($term->term_id, $terms, $taxonomies[0]); if( is_array($children) ) foreach ( $children as $child ) if ( $child->count ) continue 2; // It really is empty unset($terms[$k]); } } } reset ( $terms ); $_terms = array(); if ( 'ids' == $fields ) { while ( $term = array_shift($terms) ) $_terms[] = $term->term_id; $terms = $_terms; } elseif ( 'names' == $fields ) { while ( $term = array_shift($terms) ) $_terms[] = $term->name; $terms = $_terms; } if ( $skip_cache != true ) { wp_cache_add( $cache_key, $terms, 'terms' ); } $terms = apply_filters('get_terms', $terms, $taxonomies, $args); return $terms; }
/** * Retrieves the terms associated with the given object(s), in the supplied taxonomies. * * @since 2.3.0 * @since 4.2.0 Added support for 'taxonomy', 'parent', and 'term_taxonomy_id' values of `$orderby`. * Introduced `$parent` argument. * * @global wpdb $wpdb WordPress database abstraction object. * * @param int|array $object_ids The ID(s) of the object(s) to retrieve. * @param string|array $taxonomies The taxonomies to retrieve terms from. * @param array|string $args { * Array of arguments. * @type string $orderby Field by which results should be sorted. Accepts 'name', 'count', 'slug', 'term_group', * 'term_order', 'taxonomy', 'parent', or 'term_taxonomy_id'. Default 'name'. * @type string $order Sort order. Accepts 'ASC' or 'DESC'. Default 'ASC'. * @type string $fields Fields to return for matched terms. Accepts 'all', 'ids', 'names', and * 'all_with_object_id'. Note that 'all' or 'all_with_object_id' will result in an array of * term objects being returned, 'ids' will return an array of integers, and 'names' an array * of strings. * @type int $parent Optional. Limit results to the direct children of a given term ID. * } * @return array|WP_Error The requested term data or empty array if no terms found. * WP_Error if any of the $taxonomies don't exist. */ function wp_get_object_terms($object_ids, $taxonomies, $args = array()) { global $wpdb; if ( empty( $object_ids ) || empty( $taxonomies ) ) return array(); if ( !is_array($taxonomies) ) $taxonomies = array($taxonomies); foreach ( $taxonomies as $taxonomy ) { if ( ! taxonomy_exists($taxonomy) ) return new WP_Error('invalid_taxonomy', __('Invalid taxonomy')); } if ( !is_array($object_ids) ) $object_ids = array($object_ids); $object_ids = array_map('intval', $object_ids); $defaults = array( 'orderby' => 'name', 'order' => 'ASC', 'fields' => 'all', 'parent' => '', ); $args = wp_parse_args( $args, $defaults ); $terms = array(); if ( count($taxonomies) > 1 ) { foreach ( $taxonomies as $index => $taxonomy ) { $t = get_taxonomy($taxonomy); if ( isset($t->args) && is_array($t->args) && $args != array_merge($args, $t->args) ) { unset($taxonomies[$index]); $terms = array_merge($terms, wp_get_object_terms($object_ids, $taxonomy, array_merge($args, $t->args))); } } } else { $t = get_taxonomy($taxonomies[0]); if ( isset($t->args) && is_array($t->args) ) $args = array_merge($args, $t->args); } $orderby = $args['orderby']; $order = $args['order']; $fields = $args['fields']; if ( in_array( $orderby, array( 'term_id', 'name', 'slug', 'term_group' ) ) ) { $orderby = "t.$orderby"; } elseif ( in_array( $orderby, array( 'count', 'parent', 'taxonomy', 'term_taxonomy_id' ) ) ) { $orderby = "tt.$orderby"; } elseif ( 'term_order' === $orderby ) { $orderby = 'tr.term_order'; } elseif ( 'none' === $orderby ) { $orderby = ''; $order = ''; } else { $orderby = 't.term_id'; } // tt_ids queries can only be none or tr.term_taxonomy_id if ( ('tt_ids' == $fields) && !empty($orderby) ) $orderby = 'tr.term_taxonomy_id'; if ( !empty($orderby) ) $orderby = "ORDER BY $orderby"; $order = strtoupper( $order ); if ( '' !== $order && ! in_array( $order, array( 'ASC', 'DESC' ) ) ) $order = 'ASC'; $taxonomy_array = $taxonomies; $object_id_array = $object_ids; $taxonomies = "'" . implode("', '", $taxonomies) . "'"; $object_ids = implode(', ', $object_ids); $select_this = ''; if ( 'all' == $fields ) { $select_this = 't.*, tt.*'; } elseif ( 'ids' == $fields ) { $select_this = 't.term_id'; } elseif ( 'names' == $fields ) { $select_this = 't.name'; } elseif ( 'slugs' == $fields ) { $select_this = 't.slug'; } elseif ( 'all_with_object_id' == $fields ) { $select_this = 't.*, tt.*, tr.object_id'; } $where = array( "tt.taxonomy IN ($taxonomies)", "tr.object_id IN ($object_ids)", ); if ( '' !== $args['parent'] ) { $where[] = $wpdb->prepare( 'tt.parent = %d', $args['parent'] ); } $where = implode( ' AND ', $where ); $query = "SELECT $select_this FROM $wpdb->terms AS t INNER JOIN $wpdb->term_taxonomy AS tt ON tt.term_id = t.term_id INNER JOIN $wpdb->term_relationships AS tr ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE $where $orderby $order"; $objects = false; if ( 'all' == $fields || 'all_with_object_id' == $fields ) { $_terms = $wpdb->get_results( $query ); foreach ( $_terms as $key => $term ) { $_terms[$key] = sanitize_term( $term, $taxonomy, 'raw' ); } $terms = array_merge( $terms, $_terms ); update_term_cache( $terms ); $objects = true; } elseif ( 'ids' == $fields || 'names' == $fields || 'slugs' == $fields ) { $_terms = $wpdb->get_col( $query ); $_field = ( 'ids' == $fields ) ? 'term_id' : 'name'; foreach ( $_terms as $key => $term ) { $_terms[$key] = sanitize_term_field( $_field, $term, $term, $taxonomy, 'raw' ); } $terms = array_merge( $terms, $_terms ); } elseif ( 'tt_ids' == $fields ) { $terms = $wpdb->get_col("SELECT tr.term_taxonomy_id FROM $wpdb->term_relationships AS tr INNER JOIN $wpdb->term_taxonomy AS tt ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tr.object_id IN ($object_ids) AND tt.taxonomy IN ($taxonomies) $orderby $order"); foreach ( $terms as $key => $tt_id ) { $terms[$key] = sanitize_term_field( 'term_taxonomy_id', $tt_id, 0, $taxonomy, 'raw' ); // 0 should be the term id, however is not needed when using raw context. } } if ( ! $terms ) { $terms = array(); } elseif ( $objects && 'all_with_object_id' !== $fields ) { $_tt_ids = array(); $_terms = array(); foreach ( $terms as $term ) { if ( in_array( $term->term_taxonomy_id, $_tt_ids ) ) { continue; } $_tt_ids[] = $term->term_taxonomy_id; $_terms[] = $term; } $terms = $_terms; } elseif ( ! $objects ) { $terms = array_values( array_unique( $terms ) ); } /** * Filter the terms for a given object or objects. * * @since 4.2.0 * * @param array $terms An array of terms for the given object or objects. * @param array $object_id_array Array of object IDs for which `$terms` were retrieved. * @param array $taxonomy_array Array of taxonomies from which `$terms` were retrieved. * @param array $args An array of arguments for retrieving terms for the given * object(s). See wp_get_object_terms() for details. */ $terms = apply_filters( 'get_object_terms', $terms, $object_id_array, $taxonomy_array, $args ); /** * Filter the terms for a given object or objects. * * The `$taxonomies` parameter passed to this filter is formatted as a SQL fragment. The * {@see 'get_object_terms'} filter is recommended as an alternative. * * @since 2.8.0 * * @param array $terms An array of terms for the given object or objects. * @param int|array $object_ids Object ID or array of IDs. * @param string $taxonomies SQL-formatted (comma-separated and quoted) list of taxonomy names. * @param array $args An array of arguments for retrieving terms for the given object(s). * See {@see wp_get_object_terms()} for details. */ return apply_filters( 'wp_get_object_terms', $terms, $object_ids, $taxonomies, $args ); }
/** * Adds any terms from the given IDs to the cache that do not already exist in cache. * * @since 4.6.0 * @access private * * @global wpdb $wpdb WordPress database abstraction object. * * @param array $term_ids Array of term IDs. * @param bool $update_meta_cache Optional. Whether to update the meta cache. Default true. */ function _prime_term_caches($term_ids, $update_meta_cache = true) { global $wpdb; $non_cached_ids = _get_non_cached_ids($term_ids, 'terms'); if (!empty($non_cached_ids)) { $fresh_terms = $wpdb->get_results(sprintf("SELECT t.*, tt.* FROM {$wpdb->terms} AS t INNER JOIN {$wpdb->term_taxonomy} AS tt ON t.term_id = tt.term_id WHERE t.term_id IN (%s)", join(",", array_map('intval', $non_cached_ids)))); update_term_cache($fresh_terms, $update_meta_cache); if ($update_meta_cache) { update_termmeta_cache($non_cached_ids); } } }
/** * Extended get_terms function support * - Limit category * - Limit days * - Selection restrict * - Min usage * * @param string|array $taxonomies * @param string $args * @return array */ function getTerms( $taxonomies, $args = '', $internal_st = false ) { global $wpdb; $empty_array = array(); $single_taxonomy = false; if ( !is_array($taxonomies) ) { $single_taxonomy = true; $taxonomies = array($taxonomies); } foreach ( (array) $taxonomies as $taxonomy ) { if ( ! is_taxonomy($taxonomy) ) { $error = & new WP_Error('invalid_taxonomy', __('Invalid Taxonomy')); return $error; } } $in_taxonomies = "'" . implode("', '", $taxonomies) . "'"; $defaults = array('orderby' => 'name', 'order' => 'ASC', 'hide_empty' => true, 'exclude' => '', 'exclude_tree' => '', 'include' => '', 'number' => '', 'fields' => 'all', 'slug' => '', 'parent' => '', 'hierarchical' => true, 'child_of' => 0, 'get' => '', 'name__like' => '', 'pad_counts' => false, 'offset' => '', 'search' => '', // Simple tags added 'limit_days' => 0, 'category' => 0, 'min_usage' => 0, 'st_name__like' => '' ); $args = wp_parse_args( $args, $defaults ); // Translate selection order $args['orderby'] = $args['selectionby']; $args['order'] = $args['selection']; $args['number'] = absint( $args['number'] ); $args['offset'] = absint( $args['offset'] ); $args['limit_days'] = absint( $args['limit_days'] ); $args['min_usage'] = absint( $args['min_usage'] ); if ( !$single_taxonomy || !is_taxonomy_hierarchical($taxonomies[0]) || '' !== $args['parent'] ) { $args['child_of'] = 0; $args['hierarchical'] = false; $args['pad_counts'] = false; } if ( 'all' == $args['get'] ) { $args['child_of'] = 0; $args['hide_empty'] = 0; $args['hierarchical'] = false; $args['pad_counts'] = false; } extract($args, EXTR_SKIP); if ( $child_of ) { $hierarchy = _get_term_hierarchy($taxonomies[0]); if ( !isset($hierarchy[$child_of]) ) return $empty_array; } if ( $parent ) { $hierarchy = _get_term_hierarchy($taxonomies[0]); if ( !isset($hierarchy[$parent]) ) return $empty_array; } $_orderby = strtolower($orderby); if ( 'count' == $_orderby ) $orderby = 'tt.count'; if ( 'random' == $_orderby ) $orderby = 'RAND()'; else if ( 'name' == $_orderby ) $orderby = 't.name'; else if ( 'slug' == $_orderby ) $orderby = 't.slug'; else if ( 'term_group' == $_orderby ) $orderby = 't.term_group'; elseif ( empty($_orderby) || 'id' == $_orderby ) $orderby = 't.term_id'; $orderby = apply_filters( 'get_terms_orderby', $orderby, $args ); $where = ''; $inclusions = ''; if ( !empty($include) ) { $exclude = ''; $exclude_tree = ''; $interms = preg_split('/[\s,]+/',$include); if ( count($interms) ) { foreach ( (array) $interms as $interm ) { if (empty($inclusions)) $inclusions = ' AND ( t.term_id = ' . intval($interm) . ' '; else $inclusions .= ' OR t.term_id = ' . intval($interm) . ' '; } } } if ( !empty($inclusions) ) $inclusions .= ')'; $where .= $inclusions; $exclusions = ''; if ( ! empty( $exclude_tree ) ) { $excluded_trunks = preg_split('/[\s,]+/',$exclude_tree); foreach( (array) $excluded_trunks as $extrunk ) { $excluded_children = (array) get_terms($taxonomies[0], array('child_of' => intval($extrunk), 'fields' => 'ids')); $excluded_children[] = $extrunk; foreach( (array) $excluded_children as $exterm ) { if ( empty($exclusions) ) $exclusions = ' AND ( t.term_id <> ' . intval($exterm) . ' '; else $exclusions .= ' AND t.term_id <> ' . intval($exterm) . ' '; } } } if ( !empty($exclude) ) { $exterms = preg_split('/[\s,]+/',$exclude); if ( count($exterms) ) { foreach ( (array) $exterms as $exterm ) { if ( empty($exclusions) ) $exclusions = ' AND ( t.term_id <> ' . intval($exterm) . ' '; else $exclusions .= ' AND t.term_id <> ' . intval($exterm) . ' '; } } } if ( !empty($exclusions) ) $exclusions .= ')'; $exclusions = apply_filters('list_terms_exclusions', $exclusions, $args ); $where .= $exclusions; // $args can be whatever, only use the args defined in defaults to compute the key $filter_key = ( has_filter('list_terms_exclusions') ) ? serialize($GLOBALS['wp_filter']['list_terms_exclusions']) : ''; $key = md5( serialize( compact(array_keys($defaults)) ) . serialize( $taxonomies ) . $filter_key ); $last_changed = wp_cache_get('last_changed', 'terms'); if ( !$last_changed ) { $last_changed = time(); wp_cache_set('last_changed', $last_changed, 'terms'); } $cache_key = "st_get_terms:$key:$last_changed"; $cache = wp_cache_get( $cache_key, 'terms' ); if ( false !== $cache ) { $cache = apply_filters('get_terms', $cache, $taxonomies, $args); return $cache; } // ST Features : Restrict category if ( $category != 0 ) { if ( !is_array($taxonomies) ) $taxonomies = array($taxonomies); $incategories = preg_split('/[\s,]+/', $category); $incategories = array_map('intval', $incategories); $taxonomies = "'" . implode("', '", $taxonomies) . "'"; $incategories = "'" . implode("', '", $incategories) . "'"; $where .= " AND tr.object_id IN ( "; $where .= "SELECT tr.object_id FROM $wpdb->term_relationships AS tr INNER JOIN $wpdb->term_taxonomy AS tt ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tt.taxonomy IN ($taxonomies) AND tt.term_id IN ($incategories)"; $where .= " ) "; unset($incategories, $category); } // ST Features : Limit posts date if ( $limit_days != 0 ) { $where .= " AND tr.object_id IN ( "; $where .= "SELECT ID WHERE $wpdb->posts WHERE post_date_gmt > '" .date( 'Y-m-d H:i:s', time() - $limit_days * 86400 ). "'"; $where .= " ) "; unset($limit_days); } if ( !empty($slug) ) { $slug = sanitize_title($slug); $where .= " AND t.slug = '$slug'"; } if ( !empty($name__like) ) $where .= " AND t.name LIKE '{$name__like}%'"; if ( '' !== $parent ) { $parent = (int) $parent; $where .= " AND tt.parent = '$parent'"; } // ST Features : Another way to search if ( strpos($st_name__like, ' ') !== false ) { $st_terms_formatted = array(); $st_terms = preg_split('/[\s,]+/', $st_name_like); foreach ( (array) $st_terms as $st_term ) { if ( empty($st_term) ) continue; $st_terms_formatted[] = "t.name LIKE '%".like_escape($st_term)."%'"; } $where .= " AND ( " . explode( ' OR ', $st_terms_formatted ) . " ) "; unset( $st_term, $st_terms_formatted, $st_terms ); } elseif ( !empty($st_name__like) ) { $where .= " AND t.name LIKE '%{$st_name__like}%'"; } // ST Features : Add min usage if ( $hide_empty && !$hierarchical ) { if ( $min_usage == 0 ) $where .= ' AND tt.count > 0'; else $where .= $wpdb->prepare( ' AND tt.count >= %d', $min_usage ); } if ( !empty($search) ) { $search = like_escape($search); $where .= " AND (t.name LIKE '%$search%')"; } // don't limit the query results when we have to descend the family tree if ( ! empty($number) && ! $hierarchical && empty( $child_of ) && '' === $parent ) { if( $offset ) $limit = 'LIMIT ' . $offset . ',' . $number; else $limit = 'LIMIT ' . $number; } else $limit = ''; $selects = array(); if ( 'all' == $fields ) $selects = array('t.*', 'tt.*'); else if ( 'ids' == $fields ) $selects = array('t.term_id', 'tt.parent', 'tt.count'); else if ( 'names' == $fields ) $selects = array('t.term_id', 'tt.parent', 'tt.count', 't.name'); $select_this = implode(', ', apply_filters( 'get_terms_fields', $selects, $args )); $query = "SELECT $select_this FROM $wpdb->terms AS t INNER JOIN $wpdb->term_taxonomy AS tt ON t.term_id = tt.term_id INNER JOIN $wpdb->term_relationships AS tr ON tt.term_taxonomy_id = tr.term_taxonomy_id WHERE tt.taxonomy IN ($in_taxonomies) $where GROUP BY t.term_id ORDER BY $orderby $order $limit"; $terms = $wpdb->get_results($query); if ( 'all' == $fields ) { update_term_cache($terms); } if ( empty($terms) ) { wp_cache_add( $cache_key, array(), 'terms' ); $terms = apply_filters('get_terms', array(), $taxonomies, $args); return $terms; } if ( $child_of ) { $children = _get_term_hierarchy($taxonomies[0]); if ( ! empty($children) ) $terms = & _get_term_children($child_of, $terms, $taxonomies[0]); } // Update term counts to include children. if ( $pad_counts && 'all' == $fields ) _pad_term_counts($terms, $taxonomies[0]); // Make sure we show empty categories that have children. if ( $hierarchical && $hide_empty && is_array($terms) ) { foreach ( $terms as $k => $term ) { if ( ! $term->count ) { $children = _get_term_children($term->term_id, $terms, $taxonomies[0]); if( is_array($children) ) foreach ( $children as $child ) if ( $child->count ) continue 2; // It really is empty unset($terms[$k]); } } } reset ( $terms ); $_terms = array(); if ( 'ids' == $fields ) { while ( $term = array_shift($terms) ) $_terms[] = $term->term_id; $terms = $_terms; } elseif ( 'names' == $fields ) { while ( $term = array_shift($terms) ) $_terms[] = $term->name; $terms = $_terms; } if ( 0 < $number && intval(@count($terms)) > $number ) { $terms = array_slice($terms, $offset, $number); } wp_cache_add( $cache_key, $terms, 'terms' ); $terms = apply_filters('get_terms', $terms, $taxonomies, $args); return $terms; }
/** * Retrieves the terms associated with the given object(s), in the supplied taxonomies. * * @since 2.3.0 * @since 4.2.0 Added support for 'taxonomy', 'parent', and 'term_taxonomy_id' values of `$orderby`. * Introduced `$parent` argument. * @since 4.4.0 Introduced `$meta_query` and `$update_term_meta_cache` arguments. When `$fields` is 'all' or * 'all_with_object_id', an array of `WP_Term` objects will be returned. * * @global wpdb $wpdb WordPress database abstraction object. * * @param int|array $object_ids The ID(s) of the object(s) to retrieve. * @param string|array $taxonomies The taxonomies to retrieve terms from. * @param array|string $args { * Array of arguments. * @type string $orderby Field by which results should be sorted. Accepts 'name', 'count', 'slug', * 'term_group', 'term_order', 'taxonomy', 'parent', or 'term_taxonomy_id'. * Default 'name'. * @type string $order Sort order. Accepts 'ASC' or 'DESC'. Default 'ASC'. * @type string $fields Fields to return for matched terms. Accepts 'all', 'ids', 'names', and * 'all_with_object_id'. Note that 'all' or 'all_with_object_id' will result * in an array of term objects being returned, 'ids' will return an array of * integers, and 'names' an array of strings. * @type int $parent Optional. Limit results to the direct children of a given term ID. * @type bool $update_term_meta_cache Whether to prime termmeta cache for matched terms. Only applies when * `$fields` is 'all', 'all_with_object_id', or 'term_id'. Default true. * @type array $meta_query Meta query clauses to limit retrieved terms by. See `WP_Meta_Query`. * Default empty. * } * @return array|WP_Error The requested term data or empty array if no terms found. * WP_Error if any of the $taxonomies don't exist. */ function wp_get_object_terms($object_ids, $taxonomies, $args = array()) { global $wpdb; if (empty($object_ids) || empty($taxonomies)) { return array(); } if (!is_array($taxonomies)) { $taxonomies = array($taxonomies); } foreach ($taxonomies as $taxonomy) { if (!taxonomy_exists($taxonomy)) { return new WP_Error('invalid_taxonomy', __('Invalid taxonomy')); } } if (!is_array($object_ids)) { $object_ids = array($object_ids); } $object_ids = array_map('intval', $object_ids); $defaults = array('orderby' => 'name', 'order' => 'ASC', 'fields' => 'all', 'parent' => '', 'update_term_meta_cache' => true, 'meta_query' => ''); $args = wp_parse_args($args, $defaults); $terms = array(); if (count($taxonomies) > 1) { foreach ($taxonomies as $index => $taxonomy) { $t = get_taxonomy($taxonomy); if (isset($t->args) && is_array($t->args) && $args != array_merge($args, $t->args)) { unset($taxonomies[$index]); $terms = array_merge($terms, wp_get_object_terms($object_ids, $taxonomy, array_merge($args, $t->args))); } } } else { $t = get_taxonomy($taxonomies[0]); if (isset($t->args) && is_array($t->args)) { $args = array_merge($args, $t->args); } } $orderby = $args['orderby']; $order = $args['order']; $fields = $args['fields']; if (in_array($orderby, array('term_id', 'name', 'slug', 'term_group'))) { $orderby = "t.{$orderby}"; } elseif (in_array($orderby, array('count', 'parent', 'taxonomy', 'term_taxonomy_id'))) { $orderby = "tt.{$orderby}"; } elseif ('term_order' === $orderby) { $orderby = 'tr.term_order'; } elseif ('none' === $orderby) { $orderby = ''; $order = ''; } else { $orderby = 't.term_id'; } // tt_ids queries can only be none or tr.term_taxonomy_id if ('tt_ids' == $fields && !empty($orderby)) { $orderby = 'tr.term_taxonomy_id'; } if (!empty($orderby)) { $orderby = "ORDER BY {$orderby}"; } $order = strtoupper($order); if ('' !== $order && !in_array($order, array('ASC', 'DESC'))) { $order = 'ASC'; } $taxonomy_array = $taxonomies; $object_id_array = $object_ids; $taxonomies = "'" . implode("', '", $taxonomies) . "'"; $object_ids = implode(', ', $object_ids); $select_this = ''; if ('all' == $fields) { $select_this = 't.*, tt.*'; } elseif ('ids' == $fields) { $select_this = 't.term_id'; } elseif ('names' == $fields) { $select_this = 't.name'; } elseif ('slugs' == $fields) { $select_this = 't.slug'; } elseif ('all_with_object_id' == $fields) { $select_this = 't.*, tt.*, tr.object_id'; } $where = array("tt.taxonomy IN ({$taxonomies})", "tr.object_id IN ({$object_ids})"); if ('' !== $args['parent']) { $where[] = $wpdb->prepare('tt.parent = %d', $args['parent']); } // Meta query support. $meta_query_join = ''; if (!empty($args['meta_query'])) { $mquery = new WP_Meta_Query($args['meta_query']); $mq_sql = $mquery->get_sql('term', 't', 'term_id'); $meta_query_join .= $mq_sql['join']; // Strip leading AND. $where[] = preg_replace('/^\\s*AND/', '', $mq_sql['where']); } $where = implode(' AND ', $where); $query = "SELECT {$select_this} FROM {$wpdb->terms} AS t INNER JOIN {$wpdb->term_taxonomy} AS tt ON tt.term_id = t.term_id INNER JOIN {$wpdb->term_relationships} AS tr ON tr.term_taxonomy_id = tt.term_taxonomy_id {$meta_query_join} WHERE {$where} {$orderby} {$order}"; $objects = false; if ('all' == $fields || 'all_with_object_id' == $fields) { $_terms = $wpdb->get_results($query); $object_id_index = array(); foreach ($_terms as $key => $term) { $term = sanitize_term($term, $taxonomy, 'raw'); $_terms[$key] = $term; if (isset($term->object_id)) { $object_id_index[$key] = $term->object_id; } } update_term_cache($_terms); $_terms = array_map('get_term', $_terms); // Re-add the object_id data, which is lost when fetching terms from cache. if ('all_with_object_id' === $fields) { foreach ($_terms as $key => $_term) { if (isset($object_id_index[$key])) { $_term->object_id = $object_id_index[$key]; } } } $terms = array_merge($terms, $_terms); $objects = true; } elseif ('ids' == $fields || 'names' == $fields || 'slugs' == $fields) { $_terms = $wpdb->get_col($query); $_field = 'ids' == $fields ? 'term_id' : 'name'; foreach ($_terms as $key => $term) { $_terms[$key] = sanitize_term_field($_field, $term, $term, $taxonomy, 'raw'); } $terms = array_merge($terms, $_terms); } elseif ('tt_ids' == $fields) { $terms = $wpdb->get_col("SELECT tr.term_taxonomy_id FROM {$wpdb->term_relationships} AS tr INNER JOIN {$wpdb->term_taxonomy} AS tt ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tr.object_id IN ({$object_ids}) AND tt.taxonomy IN ({$taxonomies}) {$orderby} {$order}"); foreach ($terms as $key => $tt_id) { $terms[$key] = sanitize_term_field('term_taxonomy_id', $tt_id, 0, $taxonomy, 'raw'); // 0 should be the term id, however is not needed when using raw context. } } // Update termmeta cache, if necessary. if ($args['update_term_meta_cache'] && ('all' === $fields || 'all_with_object_ids' === $fields || 'term_id' === $fields)) { if ('term_id' === $fields) { $term_ids = $fields; } else { $term_ids = wp_list_pluck($terms, 'term_id'); } update_termmeta_cache($term_ids); } if (!$terms) { $terms = array(); } elseif ($objects && 'all_with_object_id' !== $fields) { $_tt_ids = array(); $_terms = array(); foreach ($terms as $term) { if (in_array($term->term_taxonomy_id, $_tt_ids)) { continue; } $_tt_ids[] = $term->term_taxonomy_id; $_terms[] = $term; } $terms = $_terms; } elseif (!$objects) { $terms = array_values(array_unique($terms)); } /** * Filter the terms for a given object or objects. * * @since 4.2.0 * * @param array $terms An array of terms for the given object or objects. * @param array $object_id_array Array of object IDs for which `$terms` were retrieved. * @param array $taxonomy_array Array of taxonomies from which `$terms` were retrieved. * @param array $args An array of arguments for retrieving terms for the given * object(s). See wp_get_object_terms() for details. */ $terms = apply_filters('get_object_terms', $terms, $object_id_array, $taxonomy_array, $args); /** * Filter the terms for a given object or objects. * * The `$taxonomies` parameter passed to this filter is formatted as a SQL fragment. The * {@see 'get_object_terms'} filter is recommended as an alternative. * * @since 2.8.0 * * @param array $terms An array of terms for the given object or objects. * @param int|array $object_ids Object ID or array of IDs. * @param string $taxonomies SQL-formatted (comma-separated and quoted) list of taxonomy names. * @param array $args An array of arguments for retrieving terms for the given object(s). * See {@see wp_get_object_terms()} for details. */ return apply_filters('wp_get_object_terms', $terms, $object_ids, $taxonomies, $args); }
/** * Filter the terms for a given object or objects. * * @since 1.0.0 * @access public * * @see wp_get_object_terms() * * @param array $terms An array of terms for the given object or objects. * @param array|int $object_ids Object ID or array of IDs. * @param array|string $taxonomies A taxonomy or array of taxonomies. * @param array $args An array of arguments for retrieving terms for * the given object(s). */ function get_object_terms($terms, $object_ids, $taxonomies, $args) { // 'term_order' == $args['orderby'] ... Enable only specified orderby argument. $do_term_order = true; if (!$terms || is_wp_error($terms) || !$do_term_order) { return $terms; } global $wpdb; extract($args, EXTR_SKIP); if ('term_order' != $args['orderby']) { if ('count' == $orderby) { $orderby = 'tt.count'; } else { if ('name' == $orderby) { $orderby = 't.name'; } else { if ('slug' == $orderby) { $orderby = 't.slug'; } else { if ('term_group' == $orderby) { $orderby = 't.term_group'; } else { if ('term_order' == $orderby) { $orderby = 'tr.term_order'; } else { if ('none' == $orderby) { $orderby = ''; $order = ''; } else { $orderby = 't.term_id'; } } } } } } // tt_ids queries can only be none or tr.term_taxonomy_id if ('tt_ids' == $fields && !empty($orderby)) { $orderby = 'tr.term_taxonomy_id'; } $orderby = implode(',', array_filter(array('tr.term_order ASC', $orderby))); } else { $orderby = 'tr.term_order'; $order = 'ASC'; } $order = strtoupper($order); if ('' !== $order && !in_array($order, array('ASC', 'DESC'))) { $order = 'ASC'; } $field = ''; $select_this = ''; $values = array(); switch ($fields) { case 'all': $field = 'term_id'; $select_this = 't.*, tt.*, tr.term_order'; $values = wp_list_pluck($terms, $field); break; case 'ids': $field = 'term_id'; $select_this = 't.term_id, tt.taxonomy'; $values = $terms; break; case 'names': $field = 'name'; $select_this = 't.name, t.term_id, tt.taxonomy'; $values = array_map(array($this, 'add_quote'), $terms); break; case 'slugs': $field = 'slug'; $select_this = 't.slug, t.term_id, tt.taxonomy'; $values = array_map(array($this, 'add_quote'), $terms); break; case 'all_with_object_id': $field = 'term_id'; $select_this = 't.*, tt.*, tr.term_order, tr.object_id'; $values = wp_list_pluck($terms, $field); break; case 'tt_ids': $values = $terms; break; } $values = implode(',', $values); $query = "SELECT {$select_this}" . " FROM {$wpdb->terms} AS t" . " INNER JOIN {$wpdb->term_taxonomy} AS tt ON tt.term_id = t.term_id" . " LEFT JOIN {$wpdb->term_relationships} AS tr ON (tr.term_taxonomy_id = tt.term_taxonomy_id AND tr.object_id = 0)" . " WHERE t.{$field} IN ({$values})" . " ORDER BY {$orderby} {$order}"; if ('all' == $fields || 'all_with_object_id' == $fields) { $terms = $wpdb->get_results($query); foreach ($terms as $key => $term) { $terms[$key] = sanitize_term($term, $term->taxonomy, 'raw'); } update_term_cache($terms); } else { if ('ids' == $fields || 'names' == $fields || 'slugs' == $fields) { $terms = $wpdb->get_results($query); $_field = 'ids' == $fields ? 'term_id' : 'name'; foreach ($terms as $key => $term) { $terms[$key] = sanitize_term_field($_field, $term->{$field}, $term->term_id, $term->taxonomy, 'raw'); } } else { if ('tt_ids' == $fields) { $terms = $wpdb->get_results("SELECT tt.term_taxonomy_id, tt.taxonomy" . " FROM {$wpdb->term_taxonomy} AS tt" . " LEFT JOIN {$wpdb->term_relationships} AS tr ON (tr.term_taxonomy_id = tt.term_taxonomy_id AND tr.object_id = 0)" . " WHERE tt.term_taxonomy_id IN ({$values})" . " ORDER BY {$orderby} {$order}"); foreach ($terms as $key => $term) { $terms[$key] = sanitize_term_field('term_taxonomy_id', $term->term_taxonomy_id, 0, $term->taxonomy, 'raw'); } } } } return $terms; }