root/trunk/wp-includes/category-template.php

Revision 1522, 27.7 kB (checked in by donncha, 3 days ago)

WP Merge with revision 9730

Line 
1 <?php
2 /**
3  * Category Template Tags and API.
4  *
5  * @package WordPress
6  * @subpackage Template
7  */
8
9 /**
10  * Retrieve category children list separated before and after the term IDs.
11  *
12  * @since 1.2.0
13  *
14  * @param int $id Category ID to retrieve children.
15  * @param string $before Optional. Prepend before category term ID.
16  * @param string $after Optional, default is empty string. Append after category term ID.
17  * @param array $visited Optional. Category Term IDs that have already been added.
18  * @return string
19  */
20 function get_category_children( $id, $before = '/', $after = '', $visited = array() ) {
21     if ( 0 == $id )
22         return '';
23
24     $chain = '';
25     /** TODO: consult hierarchy */
26     $cat_ids = get_all_category_ids();
27     foreach ( (array) $cat_ids as $cat_id ) {
28         if ( $cat_id == $id )
29             continue;
30
31         $category = get_category( $cat_id );
32         if ( is_wp_error( $category ) )
33             return $category;
34         if ( $category->parent == $id && !in_array( $category->term_id, $visited ) ) {
35             $visited[] = $category->term_id;
36             $chain .= $before.$category->term_id.$after;
37             $chain .= get_category_children( $category->term_id, $before, $after );
38         }
39     }
40     return $chain;
41 }
42
43 /**
44  * Retrieve category link URL.
45  *
46  * @since 1.0.0
47  * @uses apply_filters() Calls 'category_link' filter on category link and category ID.
48  *
49  * @param int $category_id Category ID.
50  * @return string
51  */
52 function get_category_link( $category_id ) {
53     global $wp_rewrite;
54     $catlink = $wp_rewrite->get_category_permastruct();
55
56     if ( empty( $catlink ) ) {
57         $file = get_option( 'home' ) . '/';
58         $catlink = $file . '?cat=' . $category_id;
59     } else {
60         $category = &get_category( $category_id );
61         if ( is_wp_error( $category ) )
62             return $category;
63         $category_nicename = $category->slug;
64
65         if ( $category->parent == $category_id ) // recursive recursion
66             $category->parent = 0;
67         elseif ($category->parent != 0 )
68             $category_nicename = get_category_parents( $category->parent, false, '/', true ) . $category_nicename;
69
70         $catlink = str_replace( '%category%', $category_nicename, $catlink );
71         $catlink = get_option( 'home' ) . user_trailingslashit( $catlink, 'category' );
72     }
73     return apply_filters( 'category_link', $catlink, $category_id );
74 }
75
76 /**
77  * Retrieve category parents with separator.
78  *
79  * @since 1.2.0
80  *
81  * @param int $id Category ID.
82  * @param bool $link Optional, default is false. Whether to format with link.
83  * @param string $separator Optional, default is '/'. How to separate categories.
84  * @param bool $nicename Optional, default is false. Whether to use nice name for display.
85  * @param array $visited Optional. Already linked to categories to prevent duplicates.
86  * @return string
87  */
88 function get_category_parents( $id, $link = false, $separator = '/', $nicename = false, $visited = array() ) {
89     $chain = '';
90     $parent = &get_category( $id );
91     if ( is_wp_error( $parent ) )
92         return $parent;
93
94     if ( $nicename )
95         $name = $parent->slug;
96     else
97         $name = $parent->cat_name;
98
99     if ( $parent->parent && ( $parent->parent != $parent->term_id ) && !in_array( $parent->parent, $visited ) ) {
100         $visited[] = $parent->parent;
101         $chain .= get_category_parents( $parent->parent, $link, $separator, $nicename, $visited );
102     }
103
104     if ( $link )
105         $chain .= '<a href="' . get_category_link( $parent->term_id ) . '" title="' . sprintf( __( "View all posts in %s" ), $parent->cat_name ) . '">'.$name.'</a>' . $separator;
106     else
107         $chain .= $name.$separator;
108     return $chain;
109 }
110
111 /**
112  * Retrieve post categories.
113  *
114  * @since 0.71
115  * @uses $post
116  *
117  * @param int $id Optional, default to current post ID. The post ID.
118  * @return array
119  */
120 function get_the_category( $id = false ) {
121     global $post;
122
123     $id = (int) $id;
124     if ( !$id )
125         $id = (int) $post->ID;
126
127     $categories = get_object_term_cache( $id, 'category' );
128     if ( false === $categories )
129         $categories = wp_get_object_terms( $id, 'category' );
130
131     if ( !empty( $categories ) )
132         usort( $categories, '_usort_terms_by_name' );
133     else
134         $categories = array();
135
136     foreach ( (array) array_keys( $categories ) as $key ) {
137         _make_cat_compat( $categories[$key] );
138     }
139
140     return $categories;
141 }
142
143 /**
144  * Sort categories by name.
145  *
146  * Used by usort() as a callback, should not be used directly. Can actually be
147  * used to sort any term object.
148  *
149  * @since 2.3.0
150  * @access private
151  *
152  * @param object $a
153  * @param object $b
154  * @return int
155  */
156 function _usort_terms_by_name( $a, $b ) {
157     return strcmp( $a->name, $b->name );
158 }
159
160 /**
161  * Sort categories by ID.
162  *
163  * Used by usort() as a callback, should not be used directly. Can actually be
164  * used to sort any term object.
165  *
166  * @since 2.3.0
167  * @access private
168  *
169  * @param object $a
170  * @param object $b
171  * @return int
172  */
173 function _usort_terms_by_ID( $a, $b ) {
174     if ( $a->term_id > $b->term_id )
175         return 1;
176     elseif ( $a->term_id < $b->term_id )
177         return -1;
178     else
179         return 0;
180 }
181
182 /**
183  * Retrieve category name based on category ID.
184  *
185  * @since 0.71
186  *
187  * @param int $cat_ID Category ID.
188  * @return string Category name.
189  */
190 function get_the_category_by_ID( $cat_ID ) {
191     $cat_ID = (int) $cat_ID;
192     $category = &get_category( $cat_ID );
193     if ( is_wp_error( $category ) )
194         return $category;
195     return $category->name;
196 }
197
198 /**
199  * Retrieve category list in either HTML list or custom format.
200  *
201  * @since 1.5.1
202  *
203  * @param string $separator Optional, default is empty string. Separator for between the categories.
204  * @param string $parents Optional. How to display the parents.
205  * @param int $post_id Optional. Post ID to retrieve categories.
206  * @return string
207  */
208 function get_the_category_list( $separator = '', $parents='', $post_id = false ) {
209     global $wp_rewrite;
210     $categories = get_the_category( $post_id );
211     if ( empty( $categories ) )
212         return apply_filters( 'the_category', __( 'Uncategorized' ), $separator, $parents );
213
214     $rel = ( is_object( $wp_rewrite ) && $wp_rewrite->using_permalinks() ) ? 'rel="category tag"' : 'rel="category"';
215
216     $thelist = '';
217     if ( '' == $separator ) {
218         $thelist .= '<ul class="post-categories">';
219         foreach ( $categories as $category ) {
220             $thelist .= "\n\t<li>";
221             switch ( strtolower( $parents ) ) {
222                 case 'multiple':
223                     if ( $category->parent )
224                         $thelist .= get_category_parents( $category->parent, true, $separator );
225                     $thelist .= '<a href="' . get_category_link( $category->term_id ) . '" title="' . sprintf( __( "View all posts in %s" ), $category->name ) . '" ' . $rel . '>' . $category->name.'</a></li>';
226                     break;
227                 case 'single':
228                     $thelist .= '<a href="' . get_category_link( $category->term_id ) . '" title="' . sprintf( __( "View all posts in %s" ), $category->name ) . '" ' . $rel . '>';
229                     if ( $category->parent )
230                         $thelist .= get_category_parents( $category->parent, false, $separator );
231                     $thelist .= $category->name.'</a></li>';
232                     break;
233                 case '':
234                 default:
235                     $thelist .= '<a href="' . get_category_link( $category->term_id ) . '" title="' . sprintf( __( "View all posts in %s" ), $category->name ) . '" ' . $rel . '>' . $category->cat_name.'</a></li>';
236             }
237         }
238         $thelist .= '</ul>';
239     } else {
240         $i = 0;
241         foreach ( $categories as $category ) {
242             if ( 0 < $i )
243                 $thelist .= $separator . ' ';
244             switch ( strtolower( $parents ) ) {
245                 case 'multiple':
246                     if ( $category->parent )
247                         $thelist .= get_category_parents( $category->parent, true, $separator );
248                     $thelist .= '<a href="' . get_category_link( $category->term_id ) . '" title="' . sprintf( __( "View all posts in %s" ), $category->name ) . '" ' . $rel . '>' . $category->cat_name.'</a>';
249                     break;
250                 case 'single':
251                     $thelist .= '<a href="' . get_category_link( $category->term_id ) . '" title="' . sprintf( __( "View all posts in %s" ), $category->name ) . '" ' . $rel . '>';
252                     if ( $category->parent )
253                         $thelist .= get_category_parents( $category->parent, false, $separator );
254                     $thelist .= "$category->cat_name</a>";
255                     break;
256                 case '':
257                 default:
258                     $thelist .= '<a href="' . get_category_link( $category->term_id ) . '" title="' . sprintf( __( "View all posts in %s" ), $category->name ) . '" ' . $rel . '>' . $category->name.'</a>';
259             }
260             ++$i;
261         }
262     }
263     return apply_filters( 'the_category', $thelist, $separator, $parents );
264 }
265
266 /**
267  * Checks whether the current post is within a particular category.
268  *
269  * This function checks to see if the post is within the supplied category. The
270  * category can be specified by number or name and will be checked as a name
271  * first to allow for categories with numeric names. Note: Prior to v2.5 of
272  * WordPress category names were not supported.
273  *
274  * @since 1.2.0
275  *
276  * @param int|string $category Category ID or category name.
277  * @return bool True, if the post is in the supplied category.
278 */
279 function in_category( $category ) {
280     global $post;
281
282     if ( empty( $category ) )
283         return false;
284
285     // If category is not an int, check to see if it's a name
286     if ( ! is_int( $category ) ) {
287         $cat_ID = get_cat_ID( $category );
288         if ( $cat_ID )
289             $category = $cat_ID;
290     }
291
292     $categories = get_object_term_cache( $post->ID, 'category' );
293     if ( false !== $categories ) {
294         if ( array_key_exists( $category, $categories ) )
295             return true;
296         else
297             return false;
298     }
299
300     $categories = wp_get_object_terms( $post->ID, 'category', 'fields=ids' );
301     if ( is_array($categories) && in_array($category, $categories) )
302         return true;
303     else
304         return false;
305     
306 }
307
308 /**
309  * Display the category list for the post.
310  *
311  * @since 0.71
312  *
313  * @param string $separator Optional, default is empty string. Separator for between the categories.
314  * @param string $parents Optional. How to display the parents.
315  * @param int $post_id Optional. Post ID to retrieve categories.
316  */
317 function the_category( $separator = '', $parents='', $post_id = false ) {
318     echo get_the_category_list( $separator, $parents, $post_id );
319 }
320
321 /**
322  * Retrieve category description.
323  *
324  * @since 1.0.0
325  *
326  * @param int $category Optional. Category ID. Will use global category ID by default.
327  * @return string Category description, available.
328  */
329 function category_description( $category = 0 ) {
330     global $cat;
331     if ( !$category )
332         $category = $cat;
333
334     return get_term_field( 'description', $category, 'category' );
335 }
336
337 /**
338  * Display or retrieve the HTML dropdown list of categories.
339  *
340  * The list of arguments is below:
341  *     'show_option_all' (string) - Text to display for showing all categories.
342  *     'show_option_none' (string) - Text to display for showing no categories.
343  *     'orderby' (string) default is 'ID' - What column to use for ordering the
344  * categories.
345  *     'order' (string) default is 'ASC' - What direction to order categories.
346  *     'show_last_update' (bool|int) default is 0 - See {@link get_categories()}
347  *     'show_count' (bool|int) default is 0 - Whether to show how many posts are
348  * in the category.
349  *     'hide_empty' (bool|int) default is 1 - Whether to hide categories that
350  * don't have any posts attached to them.
351  *     'child_of' (int) default is 0 - See {@link get_categories()}.
352  *     'exclude' (string) - See {@link get_categories()}.
353  *     'echo' (bool|int) default is 1 - Whether to display or retrieve content.
354  *     'depth' (int) - The max depth.
355  *     'tab_index' (int) - Tab index for select element.
356  *     'name' (string) - The name attribute value for selected element.
357  *     'class' (string) - The class attribute value for selected element.
358  *     'selected' (int) - Which category ID is selected.
359  *
360  * The 'hierarchical' argument, which is disabled by default, will override the
361  * depth argument, unless it is true. When the argument is false, it will
362  * display all of the categories. When it is enabled it will use the value in
363  * the 'depth' argument.
364  *
365  * @since 2.1.0
366  *
367  * @param string|array $args Optional. Override default arguments.
368  * @return string HTML content only if 'echo' argument is 0.
369  */
370 function wp_dropdown_categories( $args = '' ) {
371     $defaults = array(
372         'show_option_all' => '', 'show_option_none' => '',
373         'orderby' => 'ID', 'order' => 'ASC',
374         'show_last_update' => 0, 'show_count' => 0,
375         'hide_empty' => 1, 'child_of' => 0,
376         'exclude' => '', 'echo' => 1,
377         'selected' => 0, 'hierarchical' => 0,
378         'name' => 'cat', 'class' => 'postform',
379         'depth' => 0, 'tab_index' => 0
380     );
381
382     $defaults['selected'] = ( is_category() ) ? get_query_var( 'cat' ) : 0;
383
384     $r = wp_parse_args( $args, $defaults );
385     $r['include_last_update_time'] = $r['show_last_update'];
386     extract( $r );
387
388     $tab_index_attribute = '';
389     if ( (int) $tab_index > 0 )
390         $tab_index_attribute = " tabindex=\"$tab_index\"";
391
392     $categories = get_categories( $r );
393
394     $output = '';
395     if ( ! empty( $categories ) ) {
396         $output = "<select name='$name' id='$name' class='$class' $tab_index_attribute>\n";
397
398         if ( $show_option_all ) {
399             $show_option_all = apply_filters( 'list_cats', $show_option_all );
400             $output .= "\t<option value='0'>$show_option_all</option>\n";
401         }
402
403         if ( $show_option_none ) {
404             $show_option_none = apply_filters( 'list_cats', $show_option_none );
405             $output .= "\t<option value='-1'>$show_option_none</option>\n";
406         }
407
408         if ( $hierarchical )
409             $depth = $r['depth'];  // Walk the full depth.
410         else
411             $depth = -1; // Flat.
412
413         $output .= walk_category_dropdown_tree( $categories, $depth, $r );
414         $output .= "</select>\n";
415     }
416
417     $output = apply_filters( 'wp_dropdown_cats', $output );
418
419     if ( $echo )
420         echo $output;
421
422     return $output;
423 }
424
425 /**
426  * Display or retrieve the HTML list of categories.
427  *
428  * The list of arguments is below:
429  *     'show_option_all' (string) - Text to display for showing all categories.
430  *     'orderby' (string) default is 'ID' - What column to use for ordering the
431  * categories.
432  *     'order' (string) default is 'ASC' - What direction to order categories.
433  *     'show_last_update' (bool|int) default is 0 - See {@link
434  * walk_category_dropdown_tree()}
435  *     'show_count' (bool|int) default is 0 - Whether to show how many posts are
436  * in the category.
437  *     'hide_empty' (bool|int) default is 1 - Whether to hide categories that
438  * don't have any posts attached to them.
439  *     'use_desc_for_title' (bool|int) default is 1 - Whether to use the
440  * description instead of the category title.
441  *     'feed' - See {@link get_categories()}.
442  *     'feed_type' - See {@link get_categories()}.
443  *     'feed_image' - See {@link get_categories()}.
444  *     'child_of' (int) default is 0 - See {@link get_categories()}.
445  *     'exclude' (string) - See {@link get_categories()}.
446  *     'echo' (bool|int) default is 1 - Whether to display or retrieve content.
447  *     'current_category' (int) - See {@link get_categories()}.
448  *     'hierarchical' (bool) - See {@link get_categories()}.
449  *     'title_li' (string) - See {@link get_categories()}.
450  *     'depth' (int) - The max depth.
451  *
452  * @since 2.1.0
453  *
454  * @param string|array $args Optional. Override default arguments.
455  * @return string HTML content only if 'echo' argument is 0.
456  */
457 function wp_list_categories( $args = '' ) {
458     $defaults = array(
459         'show_option_all' => '', 'orderby' => 'name',
460         'order' => 'ASC', 'show_last_update' => 0,
461         'style' => 'list', 'show_count' => 0,
462         'hide_empty' => 1, 'use_desc_for_title' => 1,
463         'child_of' => 0, 'feed' => '', 'feed_type' => '',
464         'feed_image' => '', 'exclude' => '', 'current_category' => 0,
465         'hierarchical' => true, 'title_li' => __( 'Categories' ),
466         'echo' => 1, 'depth' => 0
467     );
468
469     $r = wp_parse_args( $args, $defaults );
470
471     if ( !isset( $r['pad_counts'] ) && $r['show_count'] && $r['hierarchical'] ) {
472         $r['pad_counts'] = true;
473     }
474
475     if ( isset( $r['show_date'] ) ) {
476         $r['include_last_update_time'] = $r['show_date'];
477     }
478
479     extract( $r );
480
481     $categories = get_categories( $r );
482
483     $output = '';
484     if ( $title_li && 'list' == $style )
485             $output = '<li class="categories">' . $r['title_li'] . '<ul>';
486
487     if ( empty( $categories ) ) {
488         if ( 'list' == $style )
489             $output .= '<li>' . __( "No categories" ) . '</li>';
490         else
491             $output .= __( "No categories" );
492     } else {
493         global $wp_query;
494
495         if( !empty( $show_option_all ) )
496             if ( 'list' == $style )
497                 $output .= '<li><a href="' get_bloginfo( 'url' )  . '">' . $show_option_all . '</a></li>';
498             else
499                 $output .= '<a href="' get_bloginfo( 'url' )  . '">' . $show_option_all . '</a>';
500
501         if ( empty( $r['current_category'] ) && is_category() )
502             $r['current_category'] = $wp_query->get_queried_object_id();
503
504         if ( $hierarchical )
505             $depth = $r['depth'];
506         else
507             $depth = -1; // Flat.
508
509         $output .= walk_category_tree( $categories, $depth, $r );
510     }
511
512     if ( $title_li && 'list' == $style )
513         $output .= '</ul></li>';
514
515     $output = apply_filters( 'wp_list_categories', $output );
516
517     if ( $echo )
518         echo $output;
519     else
520         return $output;
521 }
522
523 /**
524  * Display tag cloud.
525  *
526  * The text size is set by the 'smallest' and 'largest' arguments, which will
527  * use the 'unit' argument value for the CSS text size unit. The 'format'
528  * argument can be 'flat' (default), 'list', or 'array'. The flat value for the
529  * 'format' argument will separate tags with spaces. The list value for the
530  * 'format' argument will format the tags in a UL HTML list. The array value for
531  * the 'format' argument will return in PHP array type format.
532  *
533  * The 'orderby' argument will accept 'name' or 'count' and defaults to 'name'.
534  * The 'order' is the direction to sort, defaults to 'ASC' and can be 'DESC'.
535  *
536  * The 'number' argument is how many tags to return. By default, the limit will
537  * be to return the top 45 tags in the tag cloud list.
538  *
539  * The 'single_text' and 'multiple_text' arguments are used for the link title
540  * for the tag link. If the tag only has one, it will use the text in the
541  * 'single_text' or if it has more than one it will use 'multiple_text' instead.
542  *
543  * The 'exclude' and 'include' arguments are used for the {@link get_tags()}
544  * function. Only one should be used, because only one will be used and the
545  * other ignored, if they are both set.
546  *
547  * @since 2.3.0
548  *
549</