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