Make WordPress Core

Ticket #36171: category-template.php

File category-template.php, 44.3 KB (added by pietergoosen, 9 years ago)
Line 
1<?php
2/**
3 * Taxonomy API: Core category-specific template tags
4 *
5 * @package WordPress
6 * @subpackage Template
7 * @since 1.2.0
8 */
9
10/**
11 * Retrieve category link URL.
12 *
13 * @since 1.0.0
14 * @see get_term_link()
15 *
16 * @param int|object $category Category ID or object.
17 * @return string Link on success, empty string if category does not exist.
18 */
19function get_category_link( $category ) {
20        if ( ! is_object( $category ) )
21                $category = (int) $category;
22
23        $category = get_term_link( $category, 'category' );
24
25        if ( is_wp_error( $category ) )
26                return '';
27
28        return $category;
29}
30
31/**
32 * Retrieve category parents with separator.
33 *
34 * @since 1.2.0
35 *
36 * @param int $id Category ID.
37 * @param bool $link Optional, default is false. Whether to format with link.
38 * @param string $separator Optional, default is '/'. How to separate categories.
39 * @param bool $nicename Optional, default is false. Whether to use nice name for display.
40 * @param array $visited Optional. Already linked to categories to prevent duplicates.
41 * @return string|WP_Error A list of category parents on success, WP_Error on failure.
42 */
43function get_category_parents( $id, $link = false, $separator = '/', $nicename = false, $visited = array() ) {
44        $chain = '';
45        $parent = get_term( $id, 'category' );
46        if ( is_wp_error( $parent ) )
47                return $parent;
48
49        if ( $nicename )
50                $name = $parent->slug;
51        else
52                $name = $parent->name;
53
54        if ( $parent->parent && ( $parent->parent != $parent->term_id ) && !in_array( $parent->parent, $visited ) ) {
55                $visited[] = $parent->parent;
56                $chain .= get_category_parents( $parent->parent, $link, $separator, $nicename, $visited );
57        }
58
59        if ( $link )
60                $chain .= '<a href="' . esc_url( get_category_link( $parent->term_id ) ) . '">'.$name.'</a>' . $separator;
61        else
62                $chain .= $name.$separator;
63        return $chain;
64}
65
66/**
67 * Retrieve post categories.
68 *
69 * This tag may be used outside The Loop by passing a post id as the parameter.
70 *
71 * Note: This function only returns results from the default "category" taxonomy.
72 * For custom taxonomies use get_the_terms().
73 *
74 * @since 0.71
75 *
76 * @param int $id Optional, default to current post ID. The post ID.
77 * @return array Array of objects, one for each category assigned to the post.
78 */
79function get_the_category( $id = false ) {
80        $categories = get_the_terms( $id, 'category' );
81        if ( ! $categories || is_wp_error( $categories ) )
82                $categories = array();
83
84        $categories = array_values( $categories );
85
86        foreach ( array_keys( $categories ) as $key ) {
87                _make_cat_compat( $categories[$key] );
88        }
89
90        /**
91         * Filter the array of categories to return for a post.
92         *
93         * @since 3.1.0
94         * @since 4.4.0 Added `$id` parameter.
95         *
96         * @param array $categories An array of categories to return for the post.
97         * @param int   $id         ID of the post.
98         */
99        return apply_filters( 'get_the_categories', $categories, $id );
100}
101
102/**
103 * Sort categories by name.
104 *
105 * Used by usort() as a callback, should not be used directly. Can actually be
106 * used to sort any term object.
107 *
108 * @since 2.3.0
109 * @access private
110 *
111 * @param object $a
112 * @param object $b
113 * @return int
114 */
115function _usort_terms_by_name( $a, $b ) {
116        return strcmp( $a->name, $b->name );
117}
118
119/**
120 * Sort categories by ID.
121 *
122 * Used by usort() as a callback, should not be used directly. Can actually be
123 * used to sort any term object.
124 *
125 * @since 2.3.0
126 * @access private
127 *
128 * @param object $a
129 * @param object $b
130 * @return int
131 */
132function _usort_terms_by_ID( $a, $b ) {
133        if ( $a->term_id > $b->term_id )
134                return 1;
135        elseif ( $a->term_id < $b->term_id )
136                return -1;
137        else
138                return 0;
139}
140
141/**
142 * Retrieve category name based on category ID.
143 *
144 * @since 0.71
145 *
146 * @param int $cat_ID Category ID.
147 * @return string|WP_Error Category name on success, WP_Error on failure.
148 */
149function get_the_category_by_ID( $cat_ID ) {
150        $cat_ID = (int) $cat_ID;
151        $category = get_term( $cat_ID, 'category' );
152
153        if ( is_wp_error( $category ) )
154                return $category;
155
156        return ( $category ) ? $category->name : '';
157}
158
159/**
160 * Retrieve category list in either HTML list or custom format.
161 *
162 * @since 1.5.1
163 *
164 * @global WP_Rewrite $wp_rewrite
165 *
166 * @param string $separator Optional, default is empty string. Separator for between the categories.
167 * @param string $parents Optional. How to display the parents.
168 * @param int $post_id Optional. Post ID to retrieve categories.
169 * @return string
170 */
171function get_the_category_list( $separator = '', $parents = '', $post_id = false ) 
172{
173        global $wp_rewrite;
174       
175        if ( ! is_object_in_taxonomy( get_post_type( $post_id ), 'category' ) ) {
176                /** This filter is documented in wp-includes/category-template.php */
177                return apply_filters( 'the_category', '', $separator, $parents );
178        }
179
180        /**
181         * Filter the categories before building the category list.
182         *
183         * @since 4.4.0
184         *
185         * @param array    $categories An array of the post's categories.
186         * @param int|bool $post_id    ID of the post we're retrieving categories for. When `false`, we assume the
187         *                             current post in the loop.
188         */
189        $categories = apply_filters( 'the_category_list', get_the_category( $post_id ), $post_id );
190
191        if ( empty( $categories ) ) {
192                /** This filter is documented in wp-includes/category-template.php */
193                return apply_filters( 'the_category', __( 'Uncategorized' ), $separator, $parents );
194        }
195
196        $rel = ( is_object( $wp_rewrite ) && $wp_rewrite->using_permalinks() ) ? 'rel="category tag"' : 'rel="category"';
197
198        $links = array();
199        foreach ( $categories as $category ) {
200                /**
201                 * Break the link for better link building
202                 */
203                $start_link = '<a href="' . esc_url( get_category_link( $category->term_id ) ) . '" ' . $rel . '>';
204                $end_link   = $category->name . '</a>';
205               
206                /**
207                 * Build the category links
208                 */
209                $the_link_list = '';   
210                switch ( strtolower( $parents ) ) {
211                        case 'multiple':
212                                $cat_parents   = $category->parent ? get_category_parents( $category->parent, true, $separator ) : '';
213                                $the_link_list = $cat_parents . ' ' . $start_link . $end_link;
214                                break;
215                        case 'single':
216                                $cat_parents   = $category->parent ? get_category_parents( $category->parent, false, $separator ) : '';
217                                $the_link_list = $start_link . $cat_parents . $end_link;
218                                break;
219                        case '':
220                        default:
221                                $the_link_list = $start_link . $end_link;
222                }
223
224                /**
225                 * Filter the category links on category level.
226                 *
227                 * @since X.X.X
228                 *
229                 * @param string $the_link_list Post category link.
230                 * @param object $category      The current category object
231                 */
232                $links[] = apply_filters( 'the_category_list_links', $the_link_list, $category );
233        }
234
235        $thelist = '';
236        if( '' === $separator ) {
237                $thelist .= '<ul class="post-categories">';
238                        $thelist .= "\n\t<li>";
239
240                                $thelist .= implode( "</li>\n\t<li>", $links );
241
242                        $thelist .= '</li>';
243                $thelist .= '</ul>';
244        } else {
245                $thelist .= implode( $separator, $links );
246        }       
247
248        /**
249         * Filter the category or list of categories.
250         *
251         * @since 1.2.0
252         *
253         * @param array  $thelist   List of categories for the current post.
254         * @param string $separator Separator used between the categories.
255         * @param string $parents   How to display the category parents. Accepts 'multiple',
256         *                          'single', or empty.
257         */
258        return apply_filters( 'the_category', $thelist, $separator, $parents );
259}
260/**
261 * Check if the current post in within any of the given categories.
262 *
263 * The given categories are checked against the post's categories' term_ids, names and slugs.
264 * Categories given as integers will only be checked against the post's categories' term_ids.
265 *
266 * Prior to v2.5 of WordPress, category names were not supported.
267 * Prior to v2.7, category slugs were not supported.
268 * Prior to v2.7, only one category could be compared: in_category( $single_category ).
269 * Prior to v2.7, this function could only be used in the WordPress Loop.
270 * As of 2.7, the function can be used anywhere if it is provided a post ID or post object.
271 *
272 * @since 1.2.0
273 *
274 * @param int|string|array $category Category ID, name or slug, or array of said.
275 * @param int|object $post Optional. Post to check instead of the current post. (since 2.7.0)
276 * @return bool True if the current post is in any of the given categories.
277 */
278function in_category( $category, $post = null ) {
279        if ( empty( $category ) )
280                return false;
281
282        return has_category( $category, $post );
283}
284
285/**
286 * Display the category list for the post.
287 *
288 * @since 0.71
289 *
290 * @param string $separator Optional, default is empty string. Separator for between the categories.
291 * @param string $parents Optional. How to display the parents.
292 * @param int $post_id Optional. Post ID to retrieve categories.
293 */
294function the_category( $separator = '', $parents='', $post_id = false ) {
295        echo get_the_category_list( $separator, $parents, $post_id );
296}
297
298/**
299 * Retrieve category description.
300 *
301 * @since 1.0.0
302 *
303 * @param int $category Optional. Category ID. Will use global category ID by default.
304 * @return string Category description, available.
305 */
306function category_description( $category = 0 ) {
307        return term_description( $category, 'category' );
308}
309
310/**
311 * Display or retrieve the HTML dropdown list of categories.
312 *
313 * The 'hierarchical' argument, which is disabled by default, will override the
314 * depth argument, unless it is true. When the argument is false, it will
315 * display all of the categories. When it is enabled it will use the value in
316 * the 'depth' argument.
317 *
318 * @since 2.1.0
319 * @since 4.2.0 Introduced the `value_field` argument.
320 *
321 * @param string|array $args {
322 *     Optional. Array or string of arguments to generate a categories drop-down element.
323 *
324 *     @type string       $show_option_all   Text to display for showing all categories. Default empty.
325 *     @type string       $show_option_none  Text to display for showing no categories. Default empty.
326 *     @type string       $option_none_value Value to use when no category is selected. Default empty.
327 *     @type string       $orderby           Which column to use for ordering categories. See get_terms() for a list
328 *                                           of accepted values. Default 'id' (term_id).
329 *     @type string       $order             Whether to order terms in ascending or descending order. Accepts 'ASC'
330 *                                           or 'DESC'. Default 'ASC'.
331 *     @type bool         $pad_counts        See get_terms() for an argument description. Default false.
332 *     @type bool|int     $show_count        Whether to include post counts. Accepts 0, 1, or their bool equivalents.
333 *                                           Default 0.
334 *     @type bool|int     $hide_empty        Whether to hide categories that don't have any posts. Accepts 0, 1, or
335 *                                           their bool equivalents. Default 1.
336 *     @type int          $child_of          Term ID to retrieve child terms of. See get_terms(). Default 0.
337 *     @type array|string $exclude           Array or comma/space-separated string of term ids to exclude.
338 *                                           If `$include` is non-empty, `$exclude` is ignored. Default empty array.
339 *     @type bool|int     $echo              Whether to echo or return the generated markup. Accepts 0, 1, or their
340 *                                           bool equivalents. Default 1.
341 *     @type bool|int     $hierarchical      Whether to traverse the taxonomy hierarchy. Accepts 0, 1, or their bool
342 *                                           equivalents. Default 0.
343 *     @type int          $depth             Maximum depth. Default 0.
344 *     @type int          $tab_index         Tab index for the select element. Default 0 (no tabindex).
345 *     @type string       $name              Value for the 'name' attribute of the select element. Default 'cat'.
346 *     @type string       $id                Value for the 'id' attribute of the select element. Defaults to the value
347 *                                           of `$name`.
348 *     @type string       $class             Value for the 'class' attribute of the select element. Default 'postform'.
349 *     @type int|string   $selected          Value of the option that should be selected. Default 0.
350 *     @type string       $value_field       Term field that should be used to populate the 'value' attribute
351 *                                           of the option elements. Accepts any valid term field: 'term_id', 'name',
352 *                                           'slug', 'term_group', 'term_taxonomy_id', 'taxonomy', 'description',
353 *                                           'parent', 'count'. Default 'term_id'.
354 *     @type string       $taxonomy          Name of the category to retrieve. Default 'category'.
355 *     @type bool         $hide_if_empty     True to skip generating markup if no categories are found.
356 *                                           Default false (create select element even if no categories are found).
357 * }
358 * @return string HTML content only if 'echo' argument is 0.
359 */
360function wp_dropdown_categories( $args = '' ) {
361        $defaults = array(
362                'show_option_all' => '', 'show_option_none' => '',
363                'orderby' => 'id', 'order' => 'ASC',
364                'show_count' => 0,
365                'hide_empty' => 1, 'child_of' => 0,
366                'exclude' => '', 'echo' => 1,
367                'selected' => 0, 'hierarchical' => 0,
368                'name' => 'cat', 'id' => '',
369                'class' => 'postform', 'depth' => 0,
370                'tab_index' => 0, 'taxonomy' => 'category',
371                'hide_if_empty' => false, 'option_none_value' => -1,
372                'value_field' => 'term_id',
373        );
374
375        $defaults['selected'] = ( is_category() ) ? get_query_var( 'cat' ) : 0;
376
377        // Back compat.
378        if ( isset( $args['type'] ) && 'link' == $args['type'] ) {
379                /* translators: 1: "type => link", 2: "taxonomy => link_category" alternative */
380                _deprecated_argument( __FUNCTION__, '3.0',
381                        sprintf( __( '%1$s is deprecated. Use %2$s instead.' ),
382                                '<code>type => link</code>',
383                                '<code>taxonomy => link_category</code>'
384                        )
385                );
386                $args['taxonomy'] = 'link_category';
387        }
388
389        $r = wp_parse_args( $args, $defaults );
390        $option_none_value = $r['option_none_value'];
391
392        if ( ! isset( $r['pad_counts'] ) && $r['show_count'] && $r['hierarchical'] ) {
393                $r['pad_counts'] = true;
394        }
395
396        $tab_index = $r['tab_index'];
397
398        $tab_index_attribute = '';
399        if ( (int) $tab_index > 0 ) {
400                $tab_index_attribute = " tabindex=\"$tab_index\"";
401        }
402
403        // Avoid clashes with the 'name' param of get_terms().
404        $get_terms_args = $r;
405        unset( $get_terms_args['name'] );
406        $categories = get_terms( $r['taxonomy'], $get_terms_args );
407
408        $name = esc_attr( $r['name'] );
409        $class = esc_attr( $r['class'] );
410        $id = $r['id'] ? esc_attr( $r['id'] ) : $name;
411
412        if ( ! $r['hide_if_empty'] || ! empty( $categories ) ) {
413                $output = "<select name='$name' id='$id' class='$class' $tab_index_attribute>\n";
414        } else {
415                $output = '';
416        }
417        if ( empty( $categories ) && ! $r['hide_if_empty'] && ! empty( $r['show_option_none'] ) ) {
418
419                /**
420                 * Filter a taxonomy drop-down display element.
421                 *
422                 * A variety of taxonomy drop-down display elements can be modified
423                 * just prior to display via this filter. Filterable arguments include
424                 * 'show_option_none', 'show_option_all', and various forms of the
425                 * term name.
426                 *
427                 * @since 1.2.0
428                 *
429                 * @see wp_dropdown_categories()
430                 *
431                 * @param string $element Taxonomy element to list.
432                 */
433                $show_option_none = apply_filters( 'list_cats', $r['show_option_none'] );
434                $output .= "\t<option value='" . esc_attr( $option_none_value ) . "' selected='selected'>$show_option_none</option>\n";
435        }
436
437        if ( ! empty( $categories ) ) {
438
439                if ( $r['show_option_all'] ) {
440
441                        /** This filter is documented in wp-includes/category-template.php */
442                        $show_option_all = apply_filters( 'list_cats', $r['show_option_all'] );
443                        $selected = ( '0' === strval($r['selected']) ) ? " selected='selected'" : '';
444                        $output .= "\t<option value='0'$selected>$show_option_all</option>\n";
445                }
446
447                if ( $r['show_option_none'] ) {
448
449                        /** This filter is documented in wp-includes/category-template.php */
450                        $show_option_none = apply_filters( 'list_cats', $r['show_option_none'] );
451                        $selected = selected( $option_none_value, $r['selected'], false );
452                        $output .= "\t<option value='" . esc_attr( $option_none_value ) . "'$selected>$show_option_none</option>\n";
453                }
454
455                if ( $r['hierarchical'] ) {
456                        $depth = $r['depth'];  // Walk the full depth.
457                } else {
458                        $depth = -1; // Flat.
459                }
460                $output .= walk_category_dropdown_tree( $categories, $depth, $r );
461        }
462
463        if ( ! $r['hide_if_empty'] || ! empty( $categories ) ) {
464                $output .= "</select>\n";
465        }
466        /**
467         * Filter the taxonomy drop-down output.
468         *
469         * @since 2.1.0
470         *
471         * @param string $output HTML output.
472         * @param array  $r      Arguments used to build the drop-down.
473         */
474        $output = apply_filters( 'wp_dropdown_cats', $output, $r );
475
476        if ( $r['echo'] ) {
477                echo $output;
478        }
479        return $output;
480}
481
482/**
483 * Display or retrieve the HTML list of categories.
484 *
485 * @since 2.1.0
486 * @since 4.4.0 Introduced the `hide_title_if_empty` and `separator` arguments. The `current_category` argument was modified to
487 *              optionally accept an array of values.
488 *
489 * @param string|array $args {
490 *     Array of optional arguments.
491 *
492 *     @type string       $show_option_all       Text to display for showing all categories. Default empty string.
493 *     @type string       $show_option_none      Text to display for the 'no categories' option.
494 *                                               Default 'No categories'.
495 *     @type string       $orderby               The column to use for ordering categories. Default 'ID'.
496 *     @type string       $order                 Which direction to order categories. Accepts 'ASC' or 'DESC'.
497 *                                               Default 'ASC'.
498 *     @type bool|int     $show_count            Whether to show how many posts are in the category. Default 0.
499 *     @type bool|int     $hide_empty            Whether to hide categories that don't have any posts attached to them.
500 *                                               Default 1.
501 *     @type bool|int     $use_desc_for_title    Whether to use the category description as the title attribute.
502 *                                               Default 1.
503 *     @type string       $feed                  Text to use for the feed link. Default 'Feed for all posts filed
504 *                                               under [cat name]'.
505 *     @type string       $feed_type             Feed type. Used to build feed link. See {@link get_term_feed_link()}.
506 *                                               Default empty string (default feed).
507 *     @type string       $feed_image            URL of an image to use for the feed link. Default empty string.
508 *     @type int          $child_of              Term ID to retrieve child terms of. See {@link get_terms()}. Default 0.
509 *     @type array|string $exclude               Array or comma/space-separated string of term IDs to exclude.
510 *                                               If `$hierarchical` is true, descendants of `$exclude` terms will also
511 *                                               be excluded; see `$exclude_tree`. See {@link get_terms()}.
512 *                                               Default empty string.
513 *     @type array|string $exclude_tree          Array or comma/space-separated string of term IDs to exclude, along
514 *                                               with their descendants. See {@link get_terms()}. Default empty string.
515 *     @type bool|int     $echo                  True to echo markup, false to return it. Default 1.
516 *     @type int|array    $current_category      ID of category, or array of IDs of categories, that should get the
517 *                                               'current-cat' class. Default 0.
518 *     @type bool         $hierarchical          Whether to include terms that have non-empty descendants.
519 *                                               See {@link get_terms()}. Default true.
520 *     @type string       $title_li              Text to use for the list title `<li>` element. Pass an empty string
521 *                                               to disable. Default 'Categories'.
522 *     @type bool         $hide_title_if_empty   Whether to hide the `$title_li` element if there are no terms in
523 *                                               the list. Default false (title will always be shown).
524 *     @type int          $depth                 Category depth. Used for tab indentation. Default 0.
525 *     @type string       $taxonomy              Taxonomy name. Default 'category'.
526 * }
527 * @return false|string HTML content only if 'echo' argument is 0.
528 */
529function wp_list_categories( $args = '' ) {
530        $defaults = array(
531                'show_option_all' => '', 'show_option_none' => __('No categories'),
532                'orderby' => 'name', 'order' => 'ASC',
533                'style' => 'list',
534                'show_count' => 0, 'hide_empty' => 1,
535                'use_desc_for_title' => 1, 'child_of' => 0,
536                'feed' => '', 'feed_type' => '',
537                'feed_image' => '', 'exclude' => '',
538                'exclude_tree' => '', 'current_category' => 0,
539                'hierarchical' => true, 'title_li' => __( 'Categories' ),
540                'hide_title_if_empty' => false,
541                'echo' => 1, 'depth' => 0,
542                'separator' => '<br />',
543                'taxonomy' => 'category'
544        );
545
546        $r = wp_parse_args( $args, $defaults );
547
548        if ( !isset( $r['pad_counts'] ) && $r['show_count'] && $r['hierarchical'] )
549                $r['pad_counts'] = true;
550
551        // Descendants of exclusions should be excluded too.
552        if ( true == $r['hierarchical'] ) {
553                $exclude_tree = array();
554
555                if ( $r['exclude_tree'] ) {
556                        $exclude_tree = array_merge( $exclude_tree, wp_parse_id_list( $r['exclude_tree'] ) );
557                }
558
559                if ( $r['exclude'] ) {
560                        $exclude_tree = array_merge( $exclude_tree, wp_parse_id_list( $r['exclude'] ) );
561                }
562
563                $r['exclude_tree'] = $exclude_tree;
564                $r['exclude'] = '';
565        }
566
567        if ( ! isset( $r['class'] ) )
568                $r['class'] = ( 'category' == $r['taxonomy'] ) ? 'categories' : $r['taxonomy'];
569
570        if ( ! taxonomy_exists( $r['taxonomy'] ) ) {
571                return false;
572        }
573
574        $show_option_all = $r['show_option_all'];
575        $show_option_none = $r['show_option_none'];
576
577        $categories = get_categories( $r );
578
579        $output = '';
580        if ( $r['title_li'] && 'list' == $r['style'] && ( ! empty( $categories ) || ! $r['hide_title_if_empty'] ) ) {
581                $output = '<li class="' . esc_attr( $r['class'] ) . '">' . $r['title_li'] . '<ul>';
582        }
583        if ( empty( $categories ) ) {
584                if ( ! empty( $show_option_none ) ) {
585                        if ( 'list' == $r['style'] ) {
586                                $output .= '<li class="cat-item-none">' . $show_option_none . '</li>';
587                        } else {
588                                $output .= $show_option_none;
589                        }
590                }
591        } else {
592                if ( ! empty( $show_option_all ) ) {
593
594                        $posts_page = '';
595
596                        // For taxonomies that belong only to custom post types, point to a valid archive.
597                        $taxonomy_object = get_taxonomy( $r['taxonomy'] );
598                        if ( ! in_array( 'post', $taxonomy_object->object_type ) && ! in_array( 'page', $taxonomy_object->object_type ) ) {
599                                foreach ( $taxonomy_object->object_type as $object_type ) {
600                                        $_object_type = get_post_type_object( $object_type );
601
602                                        // Grab the first one.
603                                        if ( ! empty( $_object_type->has_archive ) ) {
604                                                $posts_page = get_post_type_archive_link( $object_type );
605                                                break;
606                                        }
607                                }
608                        }
609
610                        // Fallback for the 'All' link is the posts page.
611                        if ( ! $posts_page ) {
612                                if ( 'page' == get_option( 'show_on_front' ) && get_option( 'page_for_posts' ) ) {
613                                        $posts_page = get_permalink( get_option( 'page_for_posts' ) );
614                                } else {
615                                        $posts_page = home_url( '/' );
616                                }
617                        }
618
619                        $posts_page = esc_url( $posts_page );
620                        if ( 'list' == $r['style'] ) {
621                                $output .= "<li class='cat-item-all'><a href='$posts_page'>$show_option_all</a></li>";
622                        } else {
623                                $output .= "<a href='$posts_page'>$show_option_all</a>";
624                        }
625                }
626
627                if ( empty( $r['current_category'] ) && ( is_category() || is_tax() || is_tag() ) ) {
628                        $current_term_object = get_queried_object();
629                        if ( $current_term_object && $r['taxonomy'] === $current_term_object->taxonomy ) {
630                                $r['current_category'] = get_queried_object_id();
631                        }
632                }
633
634                if ( $r['hierarchical'] ) {
635                        $depth = $r['depth'];
636                } else {
637                        $depth = -1; // Flat.
638                }
639                $output .= walk_category_tree( $categories, $depth, $r );
640        }
641
642        if ( $r['title_li'] && 'list' == $r['style'] )
643                $output .= '</ul></li>';
644
645        /**
646         * Filter the HTML output of a taxonomy list.
647         *
648         * @since 2.1.0
649         *
650         * @param string $output HTML output.
651         * @param array  $args   An array of taxonomy-listing arguments.
652         */
653        $html = apply_filters( 'wp_list_categories', $output, $args );
654
655        if ( $r['echo'] ) {
656                echo $html;
657        } else {
658                return $html;
659        }
660}
661
662/**
663 * Display tag cloud.
664 *
665 * The text size is set by the 'smallest' and 'largest' arguments, which will
666 * use the 'unit' argument value for the CSS text size unit. The 'format'
667 * argument can be 'flat' (default), 'list', or 'array'. The flat value for the
668 * 'format' argument will separate tags with spaces. The list value for the
669 * 'format' argument will format the tags in a UL HTML list. The array value for
670 * the 'format' argument will return in PHP array type format.
671 *
672 * The 'orderby' argument will accept 'name' or 'count' and defaults to 'name'.
673 * The 'order' is the direction to sort, defaults to 'ASC' and can be 'DESC'.
674 *
675 * The 'number' argument is how many tags to return. By default, the limit will
676 * be to return the top 45 tags in the tag cloud list.
677 *
678 * The 'topic_count_text' argument is a nooped plural from _n_noop() to generate the
679 * text for the tooltip of the tag link.
680 *
681 * The 'topic_count_text_callback' argument is a function, which given the count
682 * of the posts with that tag returns a text for the tooltip of the tag link.
683 *
684 * The 'post_type' argument is used only when 'link' is set to 'edit'. It determines the post_type
685 * passed to edit.php for the popular tags edit links.
686 *
687 * The 'exclude' and 'include' arguments are used for the {@link get_tags()}
688 * function. Only one should be used, because only one will be used and the
689 * other ignored, if they are both set.
690 *
691 * @since 2.3.0
692 *
693 * @param array|string|null $args Optional. Override default arguments.
694 * @return void|array Generated tag cloud, only if no failures and 'array' is set for the 'format' argument.
695 *                    Otherwise, this function outputs the tag cloud.
696 */
697function wp_tag_cloud( $args = '' ) {
698        $defaults = array(
699                'smallest' => 8, 'largest' => 22, 'unit' => 'pt', 'number' => 45,
700                'format' => 'flat', 'separator' => "\n", 'orderby' => 'name', 'order' => 'ASC',
701                'exclude' => '', 'include' => '', 'link' => 'view', 'taxonomy' => 'post_tag', 'post_type' => '', 'echo' => true
702        );
703        $args = wp_parse_args( $args, $defaults );
704
705        $tags = get_terms( $args['taxonomy'], array_merge( $args, array( 'orderby' => 'count', 'order' => 'DESC' ) ) ); // Always query top tags
706
707        if ( empty( $tags ) || is_wp_error( $tags ) )
708                return;
709
710        foreach ( $tags as $key => $tag ) {
711                if ( 'edit' == $args['link'] )
712                        $link = get_edit_term_link( $tag->term_id, $tag->taxonomy, $args['post_type'] );
713                else
714                        $link = get_term_link( intval($tag->term_id), $tag->taxonomy );
715                if ( is_wp_error( $link ) )
716                        return;
717
718                $tags[ $key ]->link = $link;
719                $tags[ $key ]->id = $tag->term_id;
720        }
721
722        $return = wp_generate_tag_cloud( $tags, $args ); // Here's where those top tags get sorted according to $args
723
724        /**
725         * Filter the tag cloud output.
726         *
727         * @since 2.3.0
728         *
729         * @param string $return HTML output of the tag cloud.
730         * @param array  $args   An array of tag cloud arguments.
731         */
732        $return = apply_filters( 'wp_tag_cloud', $return, $args );
733
734        if ( 'array' == $args['format'] || empty($args['echo']) )
735                return $return;
736
737        echo $return;
738}
739
740/**
741 * Default topic count scaling for tag links
742 *
743 * @param int $count number of posts with that tag
744 * @return int scaled count
745 */
746function default_topic_count_scale( $count ) {
747        return round(log10($count + 1) * 100);
748}
749
750/**
751 * Generates a tag cloud (heatmap) from provided data.
752 *
753 * The text size is set by the 'smallest' and 'largest' arguments, which will
754 * use the 'unit' argument value for the CSS text size unit. The 'format'
755 * argument can be 'flat' (default), 'list', or 'array'. The flat value for the
756 * 'format' argument will separate tags with spaces. The list value for the
757 * 'format' argument will format the tags in a UL HTML list. The array value for
758 * the 'format' argument will return in PHP array type format.
759 *
760 * The 'tag_cloud_sort' filter allows you to override the sorting.
761 * Passed to the filter: $tags array and $args array, has to return the $tags array
762 * after sorting it.
763 *
764 * The 'orderby' argument will accept 'name' or 'count' and defaults to 'name'.
765 * The 'order' is the direction to sort, defaults to 'ASC' and can be 'DESC' or
766 * 'RAND'.
767 *
768 * The 'number' argument is how many tags to return. By default, the limit will
769 * be to return the entire tag cloud list.
770 *
771 * The 'topic_count_text' argument is a nooped plural from _n_noop() to generate the
772 * text for the tooltip of the tag link.
773 *
774 * The 'topic_count_text_callback' argument is a function, which given the count
775 * of the posts with that tag returns a text for the tooltip of the tag link.
776 *
777 * @todo Complete functionality.
778 * @since 2.3.0
779 *
780 * @param array $tags List of tags.
781 * @param string|array $args Optional, override default arguments.
782 * @return string|array Tag cloud as a string or an array, depending on 'format' argument.
783 */
784function wp_generate_tag_cloud( $tags, $args = '' ) {
785        $defaults = array(
786                'smallest' => 8, 'largest' => 22, 'unit' => 'pt', 'number' => 0,
787                'format' => 'flat', 'separator' => "\n", 'orderby' => 'name', 'order' => 'ASC',
788                'topic_count_text' => null, 'topic_count_text_callback' => null,
789                'topic_count_scale_callback' => 'default_topic_count_scale', 'filter' => 1,
790        );
791
792        $args = wp_parse_args( $args, $defaults );
793
794        $return = ( 'array' === $args['format'] ) ? array() : '';
795
796        if ( empty( $tags ) ) {
797                return $return;
798        }
799
800        // Juggle topic count tooltips:
801        if ( isset( $args['topic_count_text'] ) ) {
802                // First look for nooped plural support via topic_count_text.
803                $translate_nooped_plural = $args['topic_count_text'];
804        } elseif ( ! empty( $args['topic_count_text_callback'] ) ) {
805                // Look for the alternative callback style. Ignore the previous default.
806                if ( $args['topic_count_text_callback'] === 'default_topic_count_text' ) {
807                        $translate_nooped_plural = _n_noop( '%s topic', '%s topics' );
808                } else {
809                        $translate_nooped_plural = false;
810                }
811        } elseif ( isset( $args['single_text'] ) && isset( $args['multiple_text'] ) ) {
812                // If no callback exists, look for the old-style single_text and multiple_text arguments.
813                $translate_nooped_plural = _n_noop( $args['single_text'], $args['multiple_text'] );
814        } else {
815                // This is the default for when no callback, plural, or argument is passed in.
816                $translate_nooped_plural = _n_noop( '%s topic', '%s topics' );
817        }
818
819        /**
820         * Filter how the items in a tag cloud are sorted.
821         *
822         * @since 2.8.0
823         *
824         * @param array $tags Ordered array of terms.
825         * @param array $args An array of tag cloud arguments.
826         */
827        $tags_sorted = apply_filters( 'tag_cloud_sort', $tags, $args );
828        if ( empty( $tags_sorted ) ) {
829                return $return;
830        }
831
832        if ( $tags_sorted !== $tags ) {
833                $tags = $tags_sorted;
834                unset( $tags_sorted );
835        } else {
836                if ( 'RAND' === $args['order'] ) {
837                        shuffle( $tags );
838                } else {
839                        // SQL cannot save you; this is a second (potentially different) sort on a subset of data.
840                        if ( 'name' === $args['orderby'] ) {
841                                uasort( $tags, '_wp_object_name_sort_cb' );
842                        } else {
843                                uasort( $tags, '_wp_object_count_sort_cb' );
844                        }
845
846                        if ( 'DESC' === $args['order'] ) {
847                                $tags = array_reverse( $tags, true );
848                        }
849                }
850        }
851
852        if ( $args['number'] > 0 )
853                $tags = array_slice( $tags, 0, $args['number'] );
854
855        $counts = array();
856        $real_counts = array(); // For the alt tag
857        foreach ( (array) $tags as $key => $tag ) {
858                $real_counts[ $key ] = $tag->count;
859                $counts[ $key ] = call_user_func( $args['topic_count_scale_callback'], $tag->count );
860        }
861
862        $min_count = min( $counts );
863        $spread = max( $counts ) - $min_count;
864        if ( $spread <= 0 )
865                $spread = 1;
866        $font_spread = $args['largest'] - $args['smallest'];
867        if ( $font_spread < 0 )
868                $font_spread = 1;
869        $font_step = $font_spread / $spread;
870
871        // Assemble the data that will be used to generate the tag cloud markup.
872        $tags_data = array();
873        foreach ( $tags as $key => $tag ) {
874                $tag_id = isset( $tag->id ) ? $tag->id : $key;
875
876                $count = $counts[ $key ];
877                $real_count = $real_counts[ $key ];
878
879                if ( $translate_nooped_plural ) {
880                        $title = sprintf( translate_nooped_plural( $translate_nooped_plural, $real_count ), number_format_i18n( $real_count ) );
881                } else {
882                        $title = call_user_func( $args['topic_count_text_callback'], $real_count, $tag, $args );
883                }
884
885                $tags_data[] = array(
886                        'id'         => $tag_id,
887                        'url'        => '#' != $tag->link ? $tag->link : '#',
888                        'name'       => $tag->name,
889                        'title'      => $title,
890                        'slug'       => $tag->slug,
891                        'real_count' => $real_count,
892                        'class'      => 'tag-link-' . $tag_id,
893                        'font_size'  => $args['smallest'] + ( $count - $min_count ) * $font_step,
894                );
895        }
896
897        /**
898         * Filter the data used to generate the tag cloud.
899         *
900         * @since 4.3.0
901         *
902         * @param array $tags_data An array of term data for term used to generate the tag cloud.
903         */
904        $tags_data = apply_filters( 'wp_generate_tag_cloud_data', $tags_data );
905
906        $a = array();
907
908        // generate the output links array
909        foreach ( $tags_data as $key => $tag_data ) {
910                $a[] = "<a href='" . esc_url( $tag_data['url'] ) . "' class='" . esc_attr( $tag_data['class'] ) . "' title='" . esc_attr( $tag_data['title'] ) . "' style='font-size: " . esc_attr( str_replace( ',', '.', $tag_data['font_size'] ) . $args['unit'] ) . ";'>" . esc_html( $tag_data['name'] ) . "</a>";
911        }
912
913        switch ( $args['format'] ) {
914                case 'array' :
915                        $return =& $a;
916                        break;
917                case 'list' :
918                        $return = "<ul class='wp-tag-cloud'>\n\t<li>";
919                        $return .= join( "</li>\n\t<li>", $a );
920                        $return .= "</li>\n</ul>\n";
921                        break;
922                default :
923                        $return = join( $args['separator'], $a );
924                        break;
925        }
926
927        if ( $args['filter'] ) {
928                /**
929                 * Filter the generated output of a tag cloud.
930                 *
931                 * The filter is only evaluated if a true value is passed
932                 * to the $filter argument in wp_generate_tag_cloud().
933                 *
934                 * @since 2.3.0
935                 *
936                 * @see wp_generate_tag_cloud()
937                 *
938                 * @param array|string $return String containing the generated HTML tag cloud output
939                 *                             or an array of tag links if the 'format' argument
940                 *                             equals 'array'.
941                 * @param array        $tags   An array of terms used in the tag cloud.
942                 * @param array        $args   An array of wp_generate_tag_cloud() arguments.
943                 */
944                return apply_filters( 'wp_generate_tag_cloud', $return, $tags, $args );
945        }
946
947        else
948                return $return;
949}
950
951/**
952 * Callback for comparing objects based on name
953 *
954 * @since 3.1.0
955 * @access private
956 * @return int
957 */
958function _wp_object_name_sort_cb( $a, $b ) {
959        return strnatcasecmp( $a->name, $b->name );
960}
961
962/**
963 * Callback for comparing objects based on count
964 *
965 * @since 3.1.0
966 * @access private
967 * @return bool
968 */
969function _wp_object_count_sort_cb( $a, $b ) {
970        return ( $a->count > $b->count );
971}
972
973//
974// Helper functions
975//
976
977/**
978 * Retrieve HTML list content for category list.
979 *
980 * @uses Walker_Category to create HTML list content.
981 * @since 2.1.0
982 * @see Walker_Category::walk() for parameters and return description.
983 * @return string
984 */
985function walk_category_tree() {
986        $args = func_get_args();
987        // the user's options are the third parameter
988        if ( empty( $args[2]['walker'] ) || ! ( $args[2]['walker'] instanceof Walker ) ) {
989                $walker = new Walker_Category;
990        } else {
991                $walker = $args[2]['walker'];
992        }
993        return call_user_func_array( array( $walker, 'walk' ), $args );
994}
995
996/**
997 * Retrieve HTML dropdown (select) content for category list.
998 *
999 * @uses Walker_CategoryDropdown to create HTML dropdown content.
1000 * @since 2.1.0
1001 * @see Walker_CategoryDropdown::walk() for parameters and return description.
1002 * @return string
1003 */
1004function walk_category_dropdown_tree() {
1005        $args = func_get_args();
1006        // the user's options are the third parameter
1007        if ( empty( $args[2]['walker'] ) || ! ( $args[2]['walker'] instanceof Walker ) ) {
1008                $walker = new Walker_CategoryDropdown;
1009        } else {
1010                $walker = $args[2]['walker'];
1011        }
1012        return call_user_func_array( array( $walker, 'walk' ), $args );
1013}
1014
1015//
1016// Tags
1017//
1018
1019/**
1020 * Retrieve the link to the tag.
1021 *
1022 * @since 2.3.0
1023 * @see get_term_link()
1024 *
1025 * @param int|object $tag Tag ID or object.
1026 * @return string Link on success, empty string if tag does not exist.
1027 */
1028function get_tag_link( $tag ) {
1029        if ( ! is_object( $tag ) )
1030                $tag = (int) $tag;
1031
1032        $tag = get_term_link( $tag, 'post_tag' );
1033
1034        if ( is_wp_error( $tag ) )
1035                return '';
1036
1037        return $tag;
1038}
1039
1040/**
1041 * Retrieve the tags for a post.
1042 *
1043 * @since 2.3.0
1044 *
1045 * @param int $id Post ID.
1046 * @return array|false|WP_Error Array of tag objects on success, false on failure.
1047 */
1048function get_the_tags( $id = 0 ) {
1049
1050        /**
1051         * Filter the array of tags for the given post.
1052         *
1053         * @since 2.3.0
1054         *
1055         * @see get_the_terms()
1056         *
1057         * @param array $terms An array of tags for the given post.
1058         */
1059        return apply_filters( 'get_the_tags', get_the_terms( $id, 'post_tag' ) );
1060}
1061
1062/**
1063 * Retrieve the tags for a post formatted as a string.
1064 *
1065 * @since 2.3.0
1066 *
1067 * @param string $before Optional. Before tags.
1068 * @param string $sep Optional. Between tags.
1069 * @param string $after Optional. After tags.
1070 * @param int $id Optional. Post ID. Defaults to the current post.
1071 * @return string|false|WP_Error A list of tags on success, false if there are no terms, WP_Error on failure.
1072 */
1073function get_the_tag_list( $before = '', $sep = '', $after = '', $id = 0 ) {
1074
1075        /**
1076         * Filter the tags list for a given post.
1077         *
1078         * @since 2.3.0
1079         *
1080         * @param string $tag_list List of tags.
1081         * @param string $before   String to use before tags.
1082         * @param string $sep      String to use between the tags.
1083         * @param string $after    String to use after tags.
1084         * @param int    $id       Post ID.
1085         */
1086        return apply_filters( 'the_tags', get_the_term_list( $id, 'post_tag', $before, $sep, $after ), $before, $sep, $after, $id );
1087}
1088
1089/**
1090 * Retrieve the tags for a post.
1091 *
1092 * @since 2.3.0
1093 *
1094 * @param string $before Optional. Before list.
1095 * @param string $sep Optional. Separate items using this.
1096 * @param string $after Optional. After list.
1097 */
1098function the_tags( $before = null, $sep = ', ', $after = '' ) {
1099        if ( null === $before )
1100                $before = __('Tags: ');
1101        echo get_the_tag_list($before, $sep, $after);
1102}
1103
1104/**
1105 * Retrieve tag description.
1106 *
1107 * @since 2.8.0
1108 *
1109 * @param int $tag Optional. Tag ID. Will use global tag ID by default.
1110 * @return string Tag description, available.
1111 */
1112function tag_description( $tag = 0 ) {
1113        return term_description( $tag );
1114}
1115
1116/**
1117 * Retrieve term description.
1118 *
1119 * @since 2.8.0
1120 *
1121 * @param int $term Optional. Term ID. Will use global term ID by default.
1122 * @param string $taxonomy Optional taxonomy name. Defaults to 'post_tag'.
1123 * @return string Term description, available.
1124 */
1125function term_description( $term = 0, $taxonomy = 'post_tag' ) {
1126        if ( ! $term && ( is_tax() || is_tag() || is_category() ) ) {
1127                $term = get_queried_object();
1128                if ( $term ) {
1129                        $taxonomy = $term->taxonomy;
1130                        $term = $term->term_id;
1131                }
1132        }
1133        $description = get_term_field( 'description', $term, $taxonomy );
1134        return is_wp_error( $description ) ? '' : $description;
1135}
1136
1137/**
1138 * Retrieve the terms of the taxonomy that are attached to the post.
1139 *
1140 * @since 2.5.0
1141 *
1142 * @param int|object $post Post ID or object.
1143 * @param string $taxonomy Taxonomy name.
1144 * @return array|false|WP_Error Array of term objects on success, false if there are no terms
1145 *                              or the post does not exist, WP_Error on failure.
1146 */
1147function get_the_terms( $post, $taxonomy ) {
1148        if ( ! $post = get_post( $post ) )
1149                return false;
1150
1151        $terms = get_object_term_cache( $post->ID, $taxonomy );
1152        if ( false === $terms ) {
1153                $terms = wp_get_object_terms( $post->ID, $taxonomy );
1154                if ( ! is_wp_error( $terms ) ) {
1155                        $to_cache = array();
1156                        foreach ( $terms as $key => $term ) {
1157                                $to_cache[ $key ] = $term->data;
1158                        }
1159                        wp_cache_add( $post->ID, $to_cache, $taxonomy . '_relationships' );
1160                }
1161        }
1162
1163        if ( ! is_wp_error( $terms ) ) {
1164                $terms = array_map( 'get_term', $terms );
1165        }
1166
1167        /**
1168         * Filter the list of terms attached to the given post.
1169         *
1170         * @since 3.1.0
1171         *
1172         * @param array|WP_Error $terms    List of attached terms, or WP_Error on failure.
1173         * @param int            $post_id  Post ID.
1174         * @param string         $taxonomy Name of the taxonomy.
1175         */
1176        $terms = apply_filters( 'get_the_terms', $terms, $post->ID, $taxonomy );
1177
1178        if ( empty( $terms ) )
1179                return false;
1180
1181        return $terms;
1182}
1183
1184/**
1185 * Retrieve a post's terms as a list with specified format.
1186 *
1187 * @since 2.5.0
1188 *
1189 * @param int $id Post ID.
1190 * @param string $taxonomy Taxonomy name.
1191 * @param string $before Optional. Before list.
1192 * @param string $sep Optional. Separate items using this.
1193 * @param string $after Optional. After list.
1194 * @return string|false|WP_Error A list of terms on success, false if there are no terms, WP_Error on failure.
1195 */
1196function get_the_term_list( $id, $taxonomy, $before = '', $sep = '', $after = '' ) {
1197        $terms = get_the_terms( $id, $taxonomy );
1198
1199        if ( is_wp_error( $terms ) )
1200                return $terms;
1201
1202        if ( empty( $terms ) )
1203                return false;
1204
1205        $links = array();
1206
1207        foreach ( $terms as $term ) {
1208                $link = get_term_link( $term, $taxonomy );
1209                if ( is_wp_error( $link ) ) {
1210                        return $link;
1211                }
1212                $links[] = '<a href="' . esc_url( $link ) . '" rel="tag">' . $term->name . '</a>';
1213        }
1214
1215        /**
1216         * Filter the term links for a given taxonomy.
1217         *
1218         * The dynamic portion of the filter name, `$taxonomy`, refers
1219         * to the taxonomy slug.
1220         *
1221         * @since 2.5.0
1222         *
1223         * @param array $links An array of term links.
1224         */
1225        $term_links = apply_filters( "term_links-$taxonomy", $links );
1226
1227        return $before . join( $sep, $term_links ) . $after;
1228}
1229
1230/**
1231 * Display the terms in a list.
1232 *
1233 * @since 2.5.0
1234 *
1235 * @param int $id Post ID.
1236 * @param string $taxonomy Taxonomy name.
1237 * @param string $before Optional. Before list.
1238 * @param string $sep Optional. Separate items using this.
1239 * @param string $after Optional. After list.
1240 * @return false|void False on WordPress error.
1241 */
1242function the_terms( $id, $taxonomy, $before = '', $sep = ', ', $after = '' ) {
1243        $term_list = get_the_term_list( $id, $taxonomy, $before, $sep, $after );
1244
1245        if ( is_wp_error( $term_list ) )
1246                return false;
1247
1248        /**
1249         * Filter the list of terms to display.
1250         *
1251         * @since 2.9.0
1252         *
1253         * @param array  $term_list List of terms to display.
1254         * @param string $taxonomy  The taxonomy name.
1255         * @param string $before    String to use before the terms.
1256         * @param string $sep       String to use between the terms.
1257         * @param string $after     String to use after the terms.
1258         */
1259        echo apply_filters( 'the_terms', $term_list, $taxonomy, $before, $sep, $after );
1260}
1261
1262/**
1263 * Check if the current post has any of given category.
1264 *
1265 * @since 3.1.0
1266 *
1267 * @param string|int|array $category Optional. The category name/term_id/slug or array of them to check for.
1268 * @param int|object $post Optional. Post to check instead of the current post.
1269 * @return bool True if the current post has any of the given categories (or any category, if no category specified).
1270 */
1271function has_category( $category = '', $post = null ) {
1272        return has_term( $category, 'category', $post );
1273}
1274
1275/**
1276 * Check if the current post has any of given tags.
1277 *
1278 * The given tags are checked against the post's tags' term_ids, names and slugs.
1279 * Tags given as integers will only be checked against the post's tags' term_ids.
1280 * If no tags are given, determines if post has any tags.
1281 *
1282 * Prior to v2.7 of WordPress, tags given as integers would also be checked against the post's tags' names and slugs (in addition to term_ids)
1283 * Prior to v2.7, this function could only be used in the WordPress Loop.
1284 * As of 2.7, the function can be used anywhere if it is provided a post ID or post object.
1285 *
1286 * @since 2.6.0
1287 *
1288 * @param string|int|array $tag Optional. The tag name/term_id/slug or array of them to check for.
1289 * @param int|object $post Optional. Post to check instead of the current post. (since 2.7.0)
1290 * @return bool True if the current post has any of the given tags (or any tag, if no tag specified).
1291 */
1292function has_tag( $tag = '', $post = null ) {
1293        return has_term( $tag, 'post_tag', $post );
1294}
1295
1296/**
1297 * Check if the current post has any of given terms.
1298 *
1299 * The given terms are checked against the post's terms' term_ids, names and slugs.
1300 * Terms given as integers will only be checked against the post's terms' term_ids.
1301 * If no terms are given, determines if post has any terms.
1302 *
1303 * @since 3.1.0
1304 *
1305 * @param string|int|array $term Optional. The term name/term_id/slug or array of them to check for.
1306 * @param string $taxonomy Taxonomy name
1307 * @param int|object $post Optional. Post to check instead of the current post.
1308 * @return bool True if the current post has any of the given tags (or any tag, if no tag specified).
1309 */
1310function has_term( $term = '', $taxonomy = '', $post = null ) {
1311        $post = get_post($post);
1312
1313        if ( !$post )
1314                return false;
1315
1316        $r = is_object_in_term( $post->ID, $taxonomy, $term );
1317        if ( is_wp_error( $r ) )
1318                return false;
1319
1320        return $r;
1321}