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