PageRenderTime 51ms CodeModel.GetById 18ms RepoModel.GetById 1ms app.codeStats 0ms

/wp-includes/category-template.php

https://github.com/schr/wordpress
PHP | 919 lines | 446 code | 113 blank | 360 comment | 106 complexity | cbb7d816cea2a973616696b7f048a337 MD5 | raw file
  1. <?php
  2. /**
  3. * Category Template Tags and API.
  4. *
  5. * @package WordPress
  6. * @subpackage Template
  7. */
  8. /**
  9. * Retrieve category link URL.
  10. *
  11. * @since 1.0.0
  12. * @uses apply_filters() Calls 'category_link' filter on category link and category ID.
  13. *
  14. * @param int $category_id Category ID.
  15. * @return string
  16. */
  17. function get_category_link( $category_id ) {
  18. global $wp_rewrite;
  19. $catlink = $wp_rewrite->get_category_permastruct();
  20. if ( empty( $catlink ) ) {
  21. $file = get_option( 'home' ) . '/';
  22. $catlink = $file . '?cat=' . $category_id;
  23. } else {
  24. $category = &get_category( $category_id );
  25. if ( is_wp_error( $category ) )
  26. return $category;
  27. $category_nicename = $category->slug;
  28. if ( $category->parent == $category_id ) // recursive recursion
  29. $category->parent = 0;
  30. elseif ($category->parent != 0 )
  31. $category_nicename = get_category_parents( $category->parent, false, '/', true ) . $category_nicename;
  32. $catlink = str_replace( '%category%', $category_nicename, $catlink );
  33. $catlink = get_option( 'home' ) . user_trailingslashit( $catlink, 'category' );
  34. }
  35. return apply_filters( 'category_link', $catlink, $category_id );
  36. }
  37. /**
  38. * Retrieve category parents with separator.
  39. *
  40. * @since 1.2.0
  41. *
  42. * @param int $id Category ID.
  43. * @param bool $link Optional, default is false. Whether to format with link.
  44. * @param string $separator Optional, default is '/'. How to separate categories.
  45. * @param bool $nicename Optional, default is false. Whether to use nice name for display.
  46. * @param array $visited Optional. Already linked to categories to prevent duplicates.
  47. * @return string
  48. */
  49. function get_category_parents( $id, $link = false, $separator = '/', $nicename = false, $visited = array() ) {
  50. $chain = '';
  51. $parent = &get_category( $id );
  52. if ( is_wp_error( $parent ) )
  53. return $parent;
  54. if ( $nicename )
  55. $name = $parent->slug;
  56. else
  57. $name = $parent->cat_name;
  58. if ( $parent->parent && ( $parent->parent != $parent->term_id ) && !in_array( $parent->parent, $visited ) ) {
  59. $visited[] = $parent->parent;
  60. $chain .= get_category_parents( $parent->parent, $link, $separator, $nicename, $visited );
  61. }
  62. if ( $link )
  63. $chain .= '<a href="' . get_category_link( $parent->term_id ) . '" title="' . sprintf( __( "View all posts in %s" ), $parent->cat_name ) . '">'.$name.'</a>' . $separator;
  64. else
  65. $chain .= $name.$separator;
  66. return $chain;
  67. }
  68. /**
  69. * Retrieve post categories.
  70. *
  71. * @since 0.71
  72. * @uses $post
  73. *
  74. * @param int $id Optional, default to current post ID. The post ID.
  75. * @return array
  76. */
  77. function get_the_category( $id = false ) {
  78. global $post;
  79. $id = (int) $id;
  80. if ( !$id )
  81. $id = (int) $post->ID;
  82. $categories = get_object_term_cache( $id, 'category' );
  83. if ( false === $categories ) {
  84. $categories = wp_get_object_terms( $id, 'category' );
  85. wp_cache_add($id, $categories, 'category_relationships');
  86. }
  87. if ( !empty( $categories ) )
  88. usort( $categories, '_usort_terms_by_name' );
  89. else
  90. $categories = array();
  91. foreach ( (array) array_keys( $categories ) as $key ) {
  92. _make_cat_compat( $categories[$key] );
  93. }
  94. return $categories;
  95. }
  96. /**
  97. * Sort categories by name.
  98. *
  99. * Used by usort() as a callback, should not be used directly. Can actually be
  100. * used to sort any term object.
  101. *
  102. * @since 2.3.0
  103. * @access private
  104. *
  105. * @param object $a
  106. * @param object $b
  107. * @return int
  108. */
  109. function _usort_terms_by_name( $a, $b ) {
  110. return strcmp( $a->name, $b->name );
  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. * Retrieve category name based on category ID.
  135. *
  136. * @since 0.71
  137. *
  138. * @param int $cat_ID Category ID.
  139. * @return string Category name.
  140. */
  141. function get_the_category_by_ID( $cat_ID ) {
  142. $cat_ID = (int) $cat_ID;
  143. $category = &get_category( $cat_ID );
  144. if ( is_wp_error( $category ) )
  145. return $category;
  146. return $category->name;
  147. }
  148. /**
  149. * Retrieve category list in either HTML list or custom format.
  150. *
  151. * @since 1.5.1
  152. *
  153. * @param string $separator Optional, default is empty string. Separator for between the categories.
  154. * @param string $parents Optional. How to display the parents.
  155. * @param int $post_id Optional. Post ID to retrieve categories.
  156. * @return string
  157. */
  158. function get_the_category_list( $separator = '', $parents='', $post_id = false ) {
  159. global $wp_rewrite;
  160. $categories = get_the_category( $post_id );
  161. if ( empty( $categories ) )
  162. return apply_filters( 'the_category', __( 'Uncategorized' ), $separator, $parents );
  163. $rel = ( is_object( $wp_rewrite ) && $wp_rewrite->using_permalinks() ) ? 'rel="category tag"' : 'rel="category"';
  164. $thelist = '';
  165. if ( '' == $separator ) {
  166. $thelist .= '<ul class="post-categories">';
  167. foreach ( $categories as $category ) {
  168. $thelist .= "\n\t<li>";
  169. switch ( strtolower( $parents ) ) {
  170. case 'multiple':
  171. if ( $category->parent )
  172. $thelist .= get_category_parents( $category->parent, true, $separator );
  173. $thelist .= '<a href="' . get_category_link( $category->term_id ) . '" title="' . sprintf( __( "View all posts in %s" ), $category->name ) . '" ' . $rel . '>' . $category->name.'</a></li>';
  174. break;
  175. case 'single':
  176. $thelist .= '<a href="' . get_category_link( $category->term_id ) . '" title="' . sprintf( __( "View all posts in %s" ), $category->name ) . '" ' . $rel . '>';
  177. if ( $category->parent )
  178. $thelist .= get_category_parents( $category->parent, false, $separator );
  179. $thelist .= $category->name.'</a></li>';
  180. break;
  181. case '':
  182. default:
  183. $thelist .= '<a href="' . get_category_link( $category->term_id ) . '" title="' . sprintf( __( "View all posts in %s" ), $category->name ) . '" ' . $rel . '>' . $category->cat_name.'</a></li>';
  184. }
  185. }
  186. $thelist .= '</ul>';
  187. } else {
  188. $i = 0;
  189. foreach ( $categories as $category ) {
  190. if ( 0 < $i )
  191. $thelist .= $separator . ' ';
  192. switch ( strtolower( $parents ) ) {
  193. case 'multiple':
  194. if ( $category->parent )
  195. $thelist .= get_category_parents( $category->parent, true, $separator );
  196. $thelist .= '<a href="' . get_category_link( $category->term_id ) . '" title="' . sprintf( __( "View all posts in %s" ), $category->name ) . '" ' . $rel . '>' . $category->cat_name.'</a>';
  197. break;
  198. case 'single':
  199. $thelist .= '<a href="' . get_category_link( $category->term_id ) . '" title="' . sprintf( __( "View all posts in %s" ), $category->name ) . '" ' . $rel . '>';
  200. if ( $category->parent )
  201. $thelist .= get_category_parents( $category->parent, false, $separator );
  202. $thelist .= "$category->cat_name</a>";
  203. break;
  204. case '':
  205. default:
  206. $thelist .= '<a href="' . get_category_link( $category->term_id ) . '" title="' . sprintf( __( "View all posts in %s" ), $category->name ) . '" ' . $rel . '>' . $category->name.'</a>';
  207. }
  208. ++$i;
  209. }
  210. }
  211. return apply_filters( 'the_category', $thelist, $separator, $parents );
  212. }
  213. /**
  214. * Check if the current post in within any of the given categories.
  215. *
  216. * The given categories are checked against the post's categories' term_ids, names and slugs.
  217. * Categories given as integers will only be checked against the post's categories' term_ids.
  218. *
  219. * Prior to v2.5 of WordPress, category names were not supported.
  220. * Prior to v2.7, category slugs were not supported.
  221. * Prior to v2.7, only one category could be compared: in_category( $single_category ).
  222. * Prior to v2.7, this function could only be used in the WordPress Loop.
  223. * As of 2.7, the function can be used anywhere if it is provided a post ID or post object.
  224. *
  225. * @since 1.2.0
  226. *
  227. * @uses is_object_in_term()
  228. *
  229. * @param int|string|array $category. Category ID, name or slug, or array of said.
  230. * @param int|post object Optional. Post to check instead of the current post. @since 2.7.0
  231. * @return bool True if the current post is in any of the given categories.
  232. */
  233. function in_category( $category, $_post = null ) {
  234. if ( empty( $category ) )
  235. return false;
  236. if ( $_post ) {
  237. $_post = get_post( $_post );
  238. } else {
  239. $_post =& $GLOBALS['post'];
  240. }
  241. if ( !$_post )
  242. return false;
  243. $r = is_object_in_term( $_post->ID, 'category', $category );
  244. if ( is_wp_error( $r ) )
  245. return false;
  246. return $r;
  247. }
  248. /**
  249. * Display the category list for the post.
  250. *
  251. * @since 0.71
  252. *
  253. * @param string $separator Optional, default is empty string. Separator for between the categories.
  254. * @param string $parents Optional. How to display the parents.
  255. * @param int $post_id Optional. Post ID to retrieve categories.
  256. */
  257. function the_category( $separator = '', $parents='', $post_id = false ) {
  258. echo get_the_category_list( $separator, $parents, $post_id );
  259. }
  260. /**
  261. * Retrieve category description.
  262. *
  263. * @since 1.0.0
  264. *
  265. * @param int $category Optional. Category ID. Will use global category ID by default.
  266. * @return string Category description, available.
  267. */
  268. function category_description( $category = 0 ) {
  269. global $cat;
  270. if ( !$category )
  271. $category = $cat;
  272. return get_term_field( 'description', $category, 'category' );
  273. }
  274. /**
  275. * Display or retrieve the HTML dropdown list of categories.
  276. *
  277. * The list of arguments is below:
  278. * 'show_option_all' (string) - Text to display for showing all categories.
  279. * 'show_option_none' (string) - Text to display for showing no categories.
  280. * 'orderby' (string) default is 'ID' - What column to use for ordering the
  281. * categories.
  282. * 'order' (string) default is 'ASC' - What direction to order categories.
  283. * 'show_last_update' (bool|int) default is 0 - See {@link get_categories()}
  284. * 'show_count' (bool|int) default is 0 - Whether to show how many posts are
  285. * in the category.
  286. * 'hide_empty' (bool|int) default is 1 - Whether to hide categories that
  287. * don't have any posts attached to them.
  288. * 'child_of' (int) default is 0 - See {@link get_categories()}.
  289. * 'exclude' (string) - See {@link get_categories()}.
  290. * 'echo' (bool|int) default is 1 - Whether to display or retrieve content.
  291. * 'depth' (int) - The max depth.
  292. * 'tab_index' (int) - Tab index for select element.
  293. * 'name' (string) - The name attribute value for selected element.
  294. * 'class' (string) - The class attribute value for selected element.
  295. * 'selected' (int) - Which category ID is selected.
  296. *
  297. * The 'hierarchical' argument, which is disabled by default, will override the
  298. * depth argument, unless it is true. When the argument is false, it will
  299. * display all of the categories. When it is enabled it will use the value in
  300. * the 'depth' argument.
  301. *
  302. * @since 2.1.0
  303. *
  304. * @param string|array $args Optional. Override default arguments.
  305. * @return string HTML content only if 'echo' argument is 0.
  306. */
  307. function wp_dropdown_categories( $args = '' ) {
  308. $defaults = array(
  309. 'show_option_all' => '', 'show_option_none' => '',
  310. 'orderby' => 'ID', 'order' => 'ASC',
  311. 'show_last_update' => 0, 'show_count' => 0,
  312. 'hide_empty' => 1, 'child_of' => 0,
  313. 'exclude' => '', 'echo' => 1,
  314. 'selected' => 0, 'hierarchical' => 0,
  315. 'name' => 'cat', 'class' => 'postform',
  316. 'depth' => 0, 'tab_index' => 0
  317. );
  318. $defaults['selected'] = ( is_category() ) ? get_query_var( 'cat' ) : 0;
  319. $r = wp_parse_args( $args, $defaults );
  320. $r['include_last_update_time'] = $r['show_last_update'];
  321. extract( $r );
  322. $tab_index_attribute = '';
  323. if ( (int) $tab_index > 0 )
  324. $tab_index_attribute = " tabindex=\"$tab_index\"";
  325. $categories = get_categories( $r );
  326. $output = '';
  327. if ( ! empty( $categories ) ) {
  328. $output = "<select name='$name' id='$name' class='$class' $tab_index_attribute>\n";
  329. if ( $show_option_all ) {
  330. $show_option_all = apply_filters( 'list_cats', $show_option_all );
  331. $selected = ( '0' === strval($r['selected']) ) ? " selected='selected'" : '';
  332. $output .= "\t<option value='0'$selected>$show_option_all</option>\n";
  333. }
  334. if ( $show_option_none ) {
  335. $show_option_none = apply_filters( 'list_cats', $show_option_none );
  336. $selected = ( '-1' === strval($r['selected']) ) ? " selected='selected'" : '';
  337. $output .= "\t<option value='-1'$selected>$show_option_none</option>\n";
  338. }
  339. if ( $hierarchical )
  340. $depth = $r['depth']; // Walk the full depth.
  341. else
  342. $depth = -1; // Flat.
  343. $output .= walk_category_dropdown_tree( $categories, $depth, $r );
  344. $output .= "</select>\n";
  345. }
  346. $output = apply_filters( 'wp_dropdown_cats', $output );
  347. if ( $echo )
  348. echo $output;
  349. return $output;
  350. }
  351. /**
  352. * Display or retrieve the HTML list of categories.
  353. *
  354. * The list of arguments is below:
  355. * 'show_option_all' (string) - Text to display for showing all categories.
  356. * 'orderby' (string) default is 'ID' - What column to use for ordering the
  357. * categories.
  358. * 'order' (string) default is 'ASC' - What direction to order categories.
  359. * 'show_last_update' (bool|int) default is 0 - See {@link
  360. * walk_category_dropdown_tree()}
  361. * 'show_count' (bool|int) default is 0 - Whether to show how many posts are
  362. * in the category.
  363. * 'hide_empty' (bool|int) default is 1 - Whether to hide categories that
  364. * don't have any posts attached to them.
  365. * 'use_desc_for_title' (bool|int) default is 1 - Whether to use the
  366. * description instead of the category title.
  367. * 'feed' - See {@link get_categories()}.
  368. * 'feed_type' - See {@link get_categories()}.
  369. * 'feed_image' - See {@link get_categories()}.
  370. * 'child_of' (int) default is 0 - See {@link get_categories()}.
  371. * 'exclude' (string) - See {@link get_categories()}.
  372. * 'exclude_tree' (string) - See {@link get_categories()}.
  373. * 'echo' (bool|int) default is 1 - Whether to display or retrieve content.
  374. * 'current_category' (int) - See {@link get_categories()}.
  375. * 'hierarchical' (bool) - See {@link get_categories()}.
  376. * 'title_li' (string) - See {@link get_categories()}.
  377. * 'depth' (int) - The max depth.
  378. *
  379. * @since 2.1.0
  380. *
  381. * @param string|array $args Optional. Override default arguments.
  382. * @return string HTML content only if 'echo' argument is 0.
  383. */
  384. function wp_list_categories( $args = '' ) {
  385. $defaults = array(
  386. 'show_option_all' => '', 'orderby' => 'name',
  387. 'order' => 'ASC', 'show_last_update' => 0,
  388. 'style' => 'list', 'show_count' => 0,
  389. 'hide_empty' => 1, 'use_desc_for_title' => 1,
  390. 'child_of' => 0, 'feed' => '', 'feed_type' => '',
  391. 'feed_image' => '', 'exclude' => '', 'exclude_tree' => '', 'current_category' => 0,
  392. 'hierarchical' => true, 'title_li' => __( 'Categories' ),
  393. 'echo' => 1, 'depth' => 0
  394. );
  395. $r = wp_parse_args( $args, $defaults );
  396. if ( !isset( $r['pad_counts'] ) && $r['show_count'] && $r['hierarchical'] ) {
  397. $r['pad_counts'] = true;
  398. }
  399. if ( isset( $r['show_date'] ) ) {
  400. $r['include_last_update_time'] = $r['show_date'];
  401. }
  402. if ( true == $r['hierarchical'] ) {
  403. $r['exclude_tree'] = $r['exclude'];
  404. $r['exclude'] = '';
  405. }
  406. extract( $r );
  407. $categories = get_categories( $r );
  408. $output = '';
  409. if ( $title_li && 'list' == $style )
  410. $output = '<li class="categories">' . $r['title_li'] . '<ul>';
  411. if ( empty( $categories ) ) {
  412. if ( 'list' == $style )
  413. $output .= '<li>' . __( "No categories" ) . '</li>';
  414. else
  415. $output .= __( "No categories" );
  416. } else {
  417. global $wp_query;
  418. if( !empty( $show_option_all ) )
  419. if ( 'list' == $style )
  420. $output .= '<li><a href="' . get_bloginfo( 'url' ) . '">' . $show_option_all . '</a></li>';
  421. else
  422. $output .= '<a href="' . get_bloginfo( 'url' ) . '">' . $show_option_all . '</a>';
  423. if ( empty( $r['current_category'] ) && is_category() )
  424. $r['current_category'] = $wp_query->get_queried_object_id();
  425. if ( $hierarchical )
  426. $depth = $r['depth'];
  427. else
  428. $depth = -1; // Flat.
  429. $output .= walk_category_tree( $categories, $depth, $r );
  430. }
  431. if ( $title_li && 'list' == $style )
  432. $output .= '</ul></li>';
  433. $output = apply_filters( 'wp_list_categories', $output );
  434. if ( $echo )
  435. echo $output;
  436. else
  437. return $output;
  438. }
  439. /**
  440. * Display tag cloud.
  441. *
  442. * The text size is set by the 'smallest' and 'largest' arguments, which will
  443. * use the 'unit' argument value for the CSS text size unit. The 'format'
  444. * argument can be 'flat' (default), 'list', or 'array'. The flat value for the
  445. * 'format' argument will separate tags with spaces. The list value for the
  446. * 'format' argument will format the tags in a UL HTML list. The array value for
  447. * the 'format' argument will return in PHP array type format.
  448. *
  449. * The 'orderby' argument will accept 'name' or 'count' and defaults to 'name'.
  450. * The 'order' is the direction to sort, defaults to 'ASC' and can be 'DESC'.
  451. *
  452. * The 'number' argument is how many tags to return. By default, the limit will
  453. * be to return the top 45 tags in the tag cloud list.
  454. *
  455. * The 'topic_count_text_callback' argument is a function, which, given the count
  456. * of the posts with that tag, returns a text for the tooltip of the tag link.
  457. *
  458. * The 'exclude' and 'include' arguments are used for the {@link get_tags()}
  459. * function. Only one should be used, because only one will be used and the
  460. * other ignored, if they are both set.
  461. *
  462. * @since 2.3.0
  463. *
  464. * @param array|string $args Optional. Override default arguments.
  465. * @return array Generated tag cloud, only if no failures and 'array' is set for the 'format' argument.
  466. */
  467. function wp_tag_cloud( $args = '' ) {
  468. $defaults = array(
  469. 'smallest' => 8, 'largest' => 22, 'unit' => 'pt', 'number' => 45,
  470. 'format' => 'flat', 'orderby' => 'name', 'order' => 'ASC',
  471. 'exclude' => '', 'include' => '', 'link' => 'view', 'taxonomy' => 'post_tag'
  472. );
  473. $args = wp_parse_args( $args, $defaults );
  474. $tags = get_terms( $args['taxonomy'], array_merge( $args, array( 'orderby' => 'count', 'order' => 'DESC' ) ) ); // Always query top tags
  475. if ( empty( $tags ) )
  476. return;
  477. foreach ( $tags as $key => $tag ) {
  478. if ( 'edit' == $args['link'] )
  479. $link = get_edit_tag_link( $tag->term_id, $args['taxonomy'] );
  480. else
  481. $link = get_term_link( intval($tag->term_id), $args['taxonomy'] );
  482. if ( is_wp_error( $link ) )
  483. return false;
  484. $tags[ $key ]->link = $link;
  485. $tags[ $key ]->id = $tag->term_id;
  486. }
  487. $return = wp_generate_tag_cloud( $tags, $args ); // Here's where those top tags get sorted according to $args
  488. $return = apply_filters( 'wp_tag_cloud', $return, $args );
  489. if ( 'array' == $args['format'] )
  490. return $return;
  491. echo $return;
  492. }
  493. /**
  494. * Default text for tooltip for tag links
  495. *
  496. * @param integer $count number of posts with that tag
  497. * @return string text for the tooltip of a tag link.
  498. */
  499. function default_topic_count_text( $count ) {
  500. return sprintf( _n('%s topic', '%s topics', $count), number_format_i18n( $count ) );
  501. }
  502. /**
  503. * Generates a tag cloud (heatmap) from provided data.
  504. *
  505. * The text size is set by the 'smallest' and 'largest' arguments, which will
  506. * use the 'unit' argument value for the CSS text size unit. The 'format'
  507. * argument can be 'flat' (default), 'list', or 'array'. The flat value for the
  508. * 'format' argument will separate tags with spaces. The list value for the
  509. * 'format' argument will format the tags in a UL HTML list. The array value for
  510. * the 'format' argument will return in PHP array type format.
  511. *
  512. * The 'orderby' argument will accept 'name' or 'count' and defaults to 'name'.
  513. * The 'order' is the direction to sort, defaults to 'ASC' and can be 'DESC' or
  514. * 'RAND'.
  515. *
  516. * The 'number' argument is how many tags to return. By default, the limit will
  517. * be to return the entire tag cloud list.
  518. *
  519. * The 'topic_count_text_callback' argument is a function, which given the count
  520. * of the posts with that tag returns a text for the tooltip of the tag link.
  521. *
  522. * @todo Complete functionality.
  523. * @since 2.3.0
  524. *
  525. * @param array $tags List of tags.
  526. * @param string|array $args Optional, override default arguments.
  527. * @return string
  528. */
  529. function wp_generate_tag_cloud( $tags, $args = '' ) {
  530. global $wp_rewrite;
  531. $defaults = array(
  532. 'smallest' => 8, 'largest' => 22, 'unit' => 'pt', 'number' => 0,
  533. 'format' => 'flat', 'orderby' => 'name', 'order' => 'ASC',
  534. 'topic_count_text_callback' => 'default_topic_count_text',
  535. );
  536. if ( !isset( $args['topic_count_text_callback'] ) && isset( $args['single_text'] ) && isset( $args['multiple_text'] ) ) {
  537. $body = 'return sprintf (
  538. _n('.var_export($args['single_text'], true).', '.var_export($args['multiple_text'], true).', $count),
  539. number_format_i18n( $count ));';
  540. $args['topic_count_text_callback'] = create_function('$count', $body);
  541. }
  542. $args = wp_parse_args( $args, $defaults );
  543. extract( $args );
  544. if ( empty( $tags ) )
  545. return;
  546. // SQL cannot save you; this is a second (potentially different) sort on a subset of data.
  547. if ( 'name' == $orderby )
  548. uasort( $tags, create_function('$a, $b', 'return strnatcasecmp($a->name, $b->name);') );
  549. else
  550. uasort( $tags, create_function('$a, $b', 'return ($a->count > $b->count);') );
  551. if ( 'DESC' == $order )
  552. $tags = array_reverse( $tags, true );
  553. elseif ( 'RAND' == $order ) {
  554. $keys = (array) array_rand( $tags, count( $tags ) );
  555. $temp = array();
  556. foreach ( $keys as $key )
  557. $temp[$key] = $tags[$key];
  558. $tags = $temp;
  559. $temp = null;
  560. unset( $temp );
  561. }
  562. if ( $number > 0 )
  563. $tags = array_slice($tags, 0, $number);
  564. $counts = array();
  565. foreach ( (array) $tags as $key => $tag )
  566. $counts[ $key ] = $tag->count;
  567. $min_count = min( $counts );
  568. $spread = max( $counts ) - $min_count;
  569. if ( $spread <= 0 )
  570. $spread = 1;
  571. $font_spread = $largest - $smallest;
  572. if ( $font_spread < 0 )
  573. $font_spread = 1;
  574. $font_step = $font_spread / $spread;
  575. $a = array();
  576. $rel = ( is_object( $wp_rewrite ) && $wp_rewrite->using_permalinks() ) ? ' rel="tag"' : '';
  577. foreach ( $tags as $key => $tag ) {
  578. $count = $counts[ $key ];
  579. $tag_link = '#' != $tag->link ? clean_url( $tag->link ) : '#';
  580. $tag_id = isset($tags[ $key ]->id) ? $tags[ $key ]->id : $key;
  581. $tag_name = $tags[ $key ]->name;
  582. $a[] = "<a href='$tag_link' class='tag-link-$tag_id' title='" . attribute_escape( $topic_count_text_callback( $count ) ) . "'$rel style='font-size: " .
  583. ( $smallest + ( ( $count - $min_count ) * $font_step ) )
  584. . "$unit;'>$tag_name</a>";
  585. }
  586. switch ( $format ) :
  587. case 'array' :
  588. $return =& $a;
  589. break;
  590. case 'list' :
  591. $return = "<ul class='wp-tag-cloud'>\n\t<li>";
  592. $return .= join( "</li>\n\t<li>", $a );
  593. $return .= "</li>\n</ul>\n";
  594. break;
  595. default :
  596. $return = join( "\n", $a );
  597. break;
  598. endswitch;
  599. return apply_filters( 'wp_generate_tag_cloud', $return, $tags, $args );
  600. }
  601. //
  602. // Helper functions
  603. //
  604. /**
  605. * Retrieve HTML list content for category list.
  606. *
  607. * @uses Walker_Category to create HTML list content.
  608. * @since 2.1.0
  609. * @see Walker_Category::walk() for parameters and return description.
  610. */
  611. function walk_category_tree() {
  612. $args = func_get_args();
  613. // the user's options are the third parameter
  614. if ( empty($args[2]['walker']) || !is_a($args[2]['walker'], 'Walker') )
  615. $walker = new Walker_Category;
  616. else
  617. $walker = $args[2]['walker'];
  618. return call_user_func_array(array( &$walker, 'walk' ), $args );
  619. }
  620. /**
  621. * Retrieve HTML dropdown (select) content for category list.
  622. *
  623. * @uses Walker_CategoryDropdown to create HTML dropdown content.
  624. * @since 2.1.0
  625. * @see Walker_CategoryDropdown::walk() for parameters and return description.
  626. */
  627. function walk_category_dropdown_tree() {
  628. $args = func_get_args();
  629. // the user's options are the third parameter
  630. if ( empty($args[2]['walker']) || !is_a($args[2]['walker'], 'Walker') )
  631. $walker = new Walker_CategoryDropdown;
  632. else
  633. $walker = $args[2]['walker'];
  634. return call_user_func_array(array( &$walker, 'walk' ), $args );
  635. }
  636. //
  637. // Tags
  638. //
  639. /**
  640. * Retrieve the link to the tag.
  641. *
  642. * @since 2.3.0
  643. * @uses apply_filters() Calls 'tag_link' with tag link and tag ID as parameters.
  644. *
  645. * @param int $tag_id Tag (term) ID.
  646. * @return string
  647. */
  648. function get_tag_link( $tag_id ) {
  649. global $wp_rewrite;
  650. $taglink = $wp_rewrite->get_tag_permastruct();
  651. $tag = &get_term( $tag_id, 'post_tag' );
  652. if ( is_wp_error( $tag ) )
  653. return $tag;
  654. $slug = $tag->slug;
  655. if ( empty( $taglink ) ) {
  656. $file = get_option( 'home' ) . '/';
  657. $taglink = $file . '?tag=' . $slug;
  658. } else {
  659. $taglink = str_replace( '%tag%', $slug, $taglink );
  660. $taglink = get_option( 'home' ) . user_trailingslashit( $taglink, 'category' );
  661. }
  662. return apply_filters( 'tag_link', $taglink, $tag_id );
  663. }
  664. /**
  665. * Retrieve the tags for a post.
  666. *
  667. * @since 2.3.0
  668. * @uses apply_filters() Calls 'get_the_tags' filter on the list of post tags.
  669. *
  670. * @param int $id Post ID.
  671. * @return array
  672. */
  673. function get_the_tags( $id = 0 ) {
  674. return apply_filters( 'get_the_tags', get_the_terms( $id, 'post_tag' ) );
  675. }
  676. /**
  677. * Retrieve the tags for a post formatted as a string.
  678. *
  679. * @since 2.3.0
  680. * @uses apply_filters() Calls 'the_tags' filter on string list of tags.
  681. *
  682. * @param string $before Optional. Before tags.
  683. * @param string $sep Optional. Between tags.
  684. * @param string $after Optional. After tags.
  685. * @return string
  686. */
  687. function get_the_tag_list( $before = '', $sep = '', $after = '' ) {
  688. return apply_filters( 'the_tags', get_the_term_list( 0, 'post_tag', $before, $sep, $after ) );
  689. }
  690. /**
  691. * Retrieve the tags for a post.
  692. *
  693. * @since 2.3.0
  694. *
  695. * @param string $before Optional. Before list.
  696. * @param string $sep Optional. Separate items using this.
  697. * @param string $after Optional. After list.
  698. * @return string
  699. */
  700. function the_tags( $before = 'Tags: ', $sep = ', ', $after = '' ) {
  701. return the_terms( 0, 'post_tag', $before, $sep, $after );
  702. }
  703. /**
  704. * Retrieve the terms of the taxonomy that are attached to the post.
  705. *
  706. * This function can only be used within the loop.
  707. *
  708. * @since 2.5.0
  709. *
  710. * @param int $id Post ID. Is not optional.
  711. * @param string $taxonomy Taxonomy name.
  712. * @return array|bool False on failure. Array of term objects on success.
  713. */
  714. function get_the_terms( $id = 0, $taxonomy ) {
  715. global $post;
  716. $id = (int) $id;
  717. if ( ! $id && ! in_the_loop() )
  718. return false; // in-the-loop function
  719. if ( !$id )
  720. $id = (int) $post->ID;
  721. $terms = get_object_term_cache( $id, $taxonomy );
  722. if ( false === $terms )
  723. $terms = wp_get_object_terms( $id, $taxonomy );
  724. if ( empty( $terms ) )
  725. return false;
  726. return $terms;
  727. }
  728. /**
  729. * Retrieve terms as a list with specified format.
  730. *
  731. * @since 2.5.0
  732. *
  733. * @param int $id Term ID.
  734. * @param string $taxonomy Taxonomy name.
  735. * @param string $before Optional. Before list.
  736. * @param string $sep Optional. Separate items using this.
  737. * @param string $after Optional. After list.
  738. * @return string
  739. */
  740. function get_the_term_list( $id = 0, $taxonomy, $before = '', $sep = '', $after = '' ) {
  741. $terms = get_the_terms( $id, $taxonomy );
  742. if ( is_wp_error( $terms ) )
  743. return $terms;
  744. if ( empty( $terms ) )
  745. return false;
  746. foreach ( $terms as $term ) {
  747. $link = get_term_link( $term, $taxonomy );
  748. if ( is_wp_error( $link ) )
  749. return $link;
  750. $term_links[] = '<a href="' . $link . '" rel="tag">' . $term->name . '</a>';
  751. }
  752. $term_links = apply_filters( "term_links-$taxonomy", $term_links );
  753. return $before . join( $sep, $term_links ) . $after;
  754. }
  755. /**
  756. * Display the terms in a list.
  757. *
  758. * @since 2.5.0
  759. *
  760. * @param int $id Term ID.
  761. * @param string $taxonomy Taxonomy name.
  762. * @param string $before Optional. Before list.
  763. * @param string $sep Optional. Separate items using this.
  764. * @param string $after Optional. After list.
  765. * @return null|bool False on WordPress error. Returns null when displaying.
  766. */
  767. function the_terms( $id, $taxonomy, $before = '', $sep = '', $after = '' ) {
  768. $return = get_the_term_list( $id, $taxonomy, $before, $sep, $after );
  769. if ( is_wp_error( $return ) )
  770. return false;
  771. else
  772. echo $return;
  773. }
  774. /**
  775. * Check if the current post has any of given tags.
  776. *
  777. * The given tags are checked against the post's tags' term_ids, names and slugs.
  778. * Tags given as integers will only be checked against the post's tags' term_ids.
  779. * If no tags are given, determines if post has any tags.
  780. *
  781. * 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)
  782. * Prior to v2.7, this function could only be used in the WordPress Loop.
  783. * As of 2.7, the function can be used anywhere if it is provided a post ID or post object.
  784. *
  785. * @since 2.6.0
  786. *
  787. * @uses is_object_in_term()
  788. *
  789. * @param string|int|array $tag Optional. The tag name/term_id/slug or array of them to check for.
  790. * @param int|post object Optional. Post to check instead of the current post. @since 2.7.0
  791. * @return bool True if the current post has any of the the given tags (or any tag, if no tag specified).
  792. */
  793. function has_tag( $tag = '', $_post = null ) {
  794. if ( $_post ) {
  795. $_post = get_post( $_post );
  796. } else {
  797. $_post =& $GLOBALS['post'];
  798. }
  799. if ( !$_post )
  800. return false;
  801. $r = is_object_in_term( $_post->ID, 'post_tag', $tag );
  802. if ( is_wp_error( $r ) )
  803. return false;
  804. return $r;
  805. }
  806. ?>