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