WordPress.org

Make WordPress Core

Changeset 34110


Ignore:
Timestamp:
09/14/2015 03:09:37 AM (6 years ago)
Author:
wonderboymusic
Message:

Move Walker_Category and Walker_CategoryDropdown into their own files via svn cp. Remove them from category-template.php. Load them in category.php. svn cp category.php over to category-functions.php, which also loads now in category.php.

See #33413.

Location:
trunk/src/wp-includes
Files:
2 edited
3 copied

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/category-template.php

    r33804 r34110  
    973973}
    974974
    975 /**
    976  * Create HTML list of categories.
    977  *
    978  * @package WordPress
    979  * @since 2.1.0
    980  * @uses Walker
    981  */
    982 class Walker_Category extends Walker {
    983     /**
    984      * What the class handles.
    985      *
    986      * @see Walker::$tree_type
    987      * @since 2.1.0
    988      * @var string
    989      */
    990     public $tree_type = 'category';
    991 
    992     /**
    993      * Database fields to use.
    994      *
    995      * @see Walker::$db_fields
    996      * @since 2.1.0
    997      * @todo Decouple this
    998      * @var array
    999      */
    1000     public $db_fields = array ('parent' => 'parent', 'id' => 'term_id');
    1001 
    1002     /**
    1003      * Starts the list before the elements are added.
    1004      *
    1005      * @see Walker::start_lvl()
    1006      *
    1007      * @since 2.1.0
    1008      *
    1009      * @param string $output Passed by reference. Used to append additional content.
    1010      * @param int    $depth  Depth of category. Used for tab indentation.
    1011      * @param array  $args   An array of arguments. Will only append content if style argument value is 'list'.
    1012      *                       @see wp_list_categories()
    1013      */
    1014     public function start_lvl( &$output, $depth = 0, $args = array() ) {
    1015         if ( 'list' != $args['style'] )
    1016             return;
    1017 
    1018         $indent = str_repeat("\t", $depth);
    1019         $output .= "$indent<ul class='children'>\n";
    1020     }
    1021 
    1022     /**
    1023      * Ends the list of after the elements are added.
    1024      *
    1025      * @see Walker::end_lvl()
    1026      *
    1027      * @since 2.1.0
    1028      *
    1029      * @param string $output Passed by reference. Used to append additional content.
    1030      * @param int    $depth  Depth of category. Used for tab indentation.
    1031      * @param array  $args   An array of arguments. Will only append content if style argument value is 'list'.
    1032      *                       @wsee wp_list_categories()
    1033      */
    1034     public function end_lvl( &$output, $depth = 0, $args = array() ) {
    1035         if ( 'list' != $args['style'] )
    1036             return;
    1037 
    1038         $indent = str_repeat("\t", $depth);
    1039         $output .= "$indent</ul>\n";
    1040     }
    1041 
    1042     /**
    1043      * Start the element output.
    1044      *
    1045      * @see Walker::start_el()
    1046      *
    1047      * @since 2.1.0
    1048      *
    1049      * @param string $output   Passed by reference. Used to append additional content.
    1050      * @param object $category Category data object.
    1051      * @param int    $depth    Depth of category in reference to parents. Default 0.
    1052      * @param array  $args     An array of arguments. @see wp_list_categories()
    1053      * @param int    $id       ID of the current category.
    1054      */
    1055     public function start_el( &$output, $category, $depth = 0, $args = array(), $id = 0 ) {
    1056         /** This filter is documented in wp-includes/category-template.php */
    1057         $cat_name = apply_filters(
    1058             'list_cats',
    1059             esc_attr( $category->name ),
    1060             $category
    1061         );
    1062 
    1063         // Don't generate an element if the category name is empty.
    1064         if ( ! $cat_name ) {
    1065             return;
    1066         }
    1067 
    1068         $link = '<a href="' . esc_url( get_term_link( $category ) ) . '" ';
    1069         if ( $args['use_desc_for_title'] && ! empty( $category->description ) ) {
    1070             /**
    1071              * Filter the category description for display.
    1072              *
    1073              * @since 1.2.0
    1074              *
    1075              * @param string $description Category description.
    1076              * @param object $category    Category object.
    1077              */
    1078             $link .= 'title="' . esc_attr( strip_tags( apply_filters( 'category_description', $category->description, $category ) ) ) . '"';
    1079         }
    1080 
    1081         $link .= '>';
    1082         $link .= $cat_name . '</a>';
    1083 
    1084         if ( ! empty( $args['feed_image'] ) || ! empty( $args['feed'] ) ) {
    1085             $link .= ' ';
    1086 
    1087             if ( empty( $args['feed_image'] ) ) {
    1088                 $link .= '(';
    1089             }
    1090 
    1091             $link .= '<a href="' . esc_url( get_term_feed_link( $category->term_id, $category->taxonomy, $args['feed_type'] ) ) . '"';
    1092 
    1093             if ( empty( $args['feed'] ) ) {
    1094                 $alt = ' alt="' . sprintf(__( 'Feed for all posts filed under %s' ), $cat_name ) . '"';
    1095             } else {
    1096                 $alt = ' alt="' . $args['feed'] . '"';
    1097                 $name = $args['feed'];
    1098                 $link .= empty( $args['title'] ) ? '' : $args['title'];
    1099             }
    1100 
    1101             $link .= '>';
    1102 
    1103             if ( empty( $args['feed_image'] ) ) {
    1104                 $link .= $name;
    1105             } else {
    1106                 $link .= "<img src='" . $args['feed_image'] . "'$alt" . ' />';
    1107             }
    1108             $link .= '</a>';
    1109 
    1110             if ( empty( $args['feed_image'] ) ) {
    1111                 $link .= ')';
    1112             }
    1113         }
    1114 
    1115         if ( ! empty( $args['show_count'] ) ) {
    1116             $link .= ' (' . number_format_i18n( $category->count ) . ')';
    1117         }
    1118         if ( 'list' == $args['style'] ) {
    1119             $output .= "\t<li";
    1120             $css_classes = array(
    1121                 'cat-item',
    1122                 'cat-item-' . $category->term_id,
    1123             );
    1124 
    1125             if ( ! empty( $args['current_category'] ) ) {
    1126                 // 'current_category' can be an array, so we use `get_terms()`.
    1127                 $_current_terms = get_terms( $category->taxonomy, array(
    1128                     'include' => $args['current_category'],
    1129                     'hide_empty' => false,
    1130                 ) );
    1131 
    1132                 foreach ( $_current_terms as $_current_term ) {
    1133                     if ( $category->term_id == $_current_term->term_id ) {
    1134                         $css_classes[] = 'current-cat';
    1135                     } elseif ( $category->term_id == $_current_term->parent ) {
    1136                         $css_classes[] = 'current-cat-parent';
    1137                     }
    1138                 }
    1139             }
    1140 
    1141             /**
    1142              * Filter the list of CSS classes to include with each category in the list.
    1143              *
    1144              * @since 4.2.0
    1145              *
    1146              * @see wp_list_categories()
    1147              *
    1148              * @param array  $css_classes An array of CSS classes to be applied to each list item.
    1149              * @param object $category    Category data object.
    1150              * @param int    $depth       Depth of page, used for padding.
    1151              * @param array  $args        An array of wp_list_categories() arguments.
    1152              */
    1153             $css_classes = implode( ' ', apply_filters( 'category_css_class', $css_classes, $category, $depth, $args ) );
    1154 
    1155             $output .=  ' class="' . $css_classes . '"';
    1156             $output .= ">$link\n";
    1157         } else {
    1158             $output .= "\t$link<br />\n";
    1159         }
    1160     }
    1161 
    1162     /**
    1163      * Ends the element output, if needed.
    1164      *
    1165      * @see Walker::end_el()
    1166      *
    1167      * @since 2.1.0
    1168      *
    1169      * @param string $output Passed by reference. Used to append additional content.
    1170      * @param object $page   Not used.
    1171      * @param int    $depth  Depth of category. Not used.
    1172      * @param array  $args   An array of arguments. Only uses 'list' for whether should append to output. @see wp_list_categories()
    1173      */
    1174     public function end_el( &$output, $page, $depth = 0, $args = array() ) {
    1175         if ( 'list' != $args['style'] )
    1176             return;
    1177 
    1178         $output .= "</li>\n";
    1179     }
    1180 
    1181 }
    1182 
    1183 /**
    1184  * Create HTML dropdown list of Categories.
    1185  *
    1186  * @package WordPress
    1187  * @since 2.1.0
    1188  * @uses Walker
    1189  */
    1190 class Walker_CategoryDropdown extends Walker {
    1191     /**
    1192      * @see Walker::$tree_type
    1193      * @since 2.1.0
    1194      * @var string
    1195      */
    1196     public $tree_type = 'category';
    1197 
    1198     /**
    1199      * @see Walker::$db_fields
    1200      * @since 2.1.0
    1201      * @todo Decouple this
    1202      * @var array
    1203      */
    1204     public $db_fields = array ('parent' => 'parent', 'id' => 'term_id');
    1205 
    1206     /**
    1207      * Start the element output.
    1208      *
    1209      * @see Walker::start_el()
    1210      * @since 2.1.0
    1211      *
    1212      * @param string $output   Passed by reference. Used to append additional content.
    1213      * @param object $category Category data object.
    1214      * @param int    $depth    Depth of category. Used for padding.
    1215      * @param array  $args     Uses 'selected', 'show_count', and 'value_field' keys, if they exist.
    1216      *                         See {@see wp_dropdown_categories()}.
    1217      */
    1218     public function start_el( &$output, $category, $depth = 0, $args = array(), $id = 0 ) {
    1219         $pad = str_repeat('&nbsp;', $depth * 3);
    1220 
    1221         /** This filter is documented in wp-includes/category-template.php */
    1222         $cat_name = apply_filters( 'list_cats', $category->name, $category );
    1223 
    1224         if ( isset( $args['value_field'] ) && isset( $category->{$args['value_field']} ) ) {
    1225             $value_field = $args['value_field'];
    1226         } else {
    1227             $value_field = 'term_id';
    1228         }
    1229 
    1230         $output .= "\t<option class=\"level-$depth\" value=\"" . esc_attr( $category->{$value_field} ) . "\"";
    1231 
    1232         // Type-juggling causes false matches, so we force everything to a string.
    1233         if ( (string) $category->{$value_field} === (string) $args['selected'] )
    1234             $output .= ' selected="selected"';
    1235         $output .= '>';
    1236         $output .= $pad.$cat_name;
    1237         if ( $args['show_count'] )
    1238             $output .= '&nbsp;&nbsp;('. number_format_i18n( $category->count ) .')';
    1239         $output .= "</option>\n";
    1240     }
    1241 }
    1242 
    1243975//
    1244976// Tags
  • trunk/src/wp-includes/category.php

    r32568 r34110  
    66 */
    77
    8 /**
    9  * Retrieve list of category objects.
    10  *
    11  * If you change the type to 'link' in the arguments, then the link categories
    12  * will be returned instead. Also all categories will be updated to be backwards
    13  * compatible with pre-2.3 plugins and themes.
    14  *
    15  * @since 2.1.0
    16  * @see get_terms() Type of arguments that can be changed.
    17  * @link https://codex.wordpress.org/Function_Reference/get_categories
    18  *
    19  * @param string|array $args Optional. Change the defaults retrieving categories.
    20  * @return array List of categories.
    21  */
    22 function get_categories( $args = '' ) {
    23     $defaults = array( 'taxonomy' => 'category' );
    24     $args = wp_parse_args( $args, $defaults );
     8/** Core category functionality */
     9require_once( ABSPATH . WPINC . '/category-functions.php' );
    2510
    26     $taxonomy = $args['taxonomy'];
     11/** Walker_Category class */
     12require_once( ABSPATH . WPINC . '/class-walker-category.php' );
    2713
    28     /**
    29      * Filter the taxonomy used to retrieve terms when calling {@see get_categories()}.
    30      *
    31      * @since 2.7.0
    32      *
    33      * @param string $taxonomy Taxonomy to retrieve terms from.
    34      * @param array  $args     An array of arguments. See {@see get_terms()}.
    35      */
    36     $taxonomy = apply_filters( 'get_categories_taxonomy', $taxonomy, $args );
    37 
    38     // Back compat
    39     if ( isset($args['type']) && 'link' == $args['type'] ) {
    40         _deprecated_argument( __FUNCTION__, '3.0', '' );
    41         $taxonomy = $args['taxonomy'] = 'link_category';
    42     }
    43 
    44     $categories = (array) get_terms( $taxonomy, $args );
    45 
    46     foreach ( array_keys( $categories ) as $k )
    47         _make_cat_compat( $categories[$k] );
    48 
    49     return $categories;
    50 }
    51 
    52 /**
    53  * Retrieves category data given a category ID or category object.
    54  *
    55  * If you pass the $category parameter an object, which is assumed to be the
    56  * category row object retrieved the database. It will cache the category data.
    57  *
    58  * If you pass $category an integer of the category ID, then that category will
    59  * be retrieved from the database, if it isn't already cached, and pass it back.
    60  *
    61  * If you look at get_term(), then both types will be passed through several
    62  * filters and finally sanitized based on the $filter parameter value.
    63  *
    64  * The category will converted to maintain backwards compatibility.
    65  *
    66  * @since 1.5.1
    67  *
    68  * @param int|object $category Category ID or Category row object
    69  * @param string $output Optional. Constant OBJECT, ARRAY_A, or ARRAY_N
    70  * @param string $filter Optional. Default is raw or no WordPress defined filter will applied.
    71  * @return object|array|WP_Error|null Category data in type defined by $output parameter.
    72  *                                    WP_Error if $category is empty, null if it does not exist.
    73  */
    74 function get_category( $category, $output = OBJECT, $filter = 'raw' ) {
    75     $category = get_term( $category, 'category', $output, $filter );
    76 
    77     if ( is_wp_error( $category ) )
    78         return $category;
    79 
    80     _make_cat_compat( $category );
    81 
    82     return $category;
    83 }
    84 
    85 /**
    86  * Retrieve category based on URL containing the category slug.
    87  *
    88  * Breaks the $category_path parameter up to get the category slug.
    89  *
    90  * Tries to find the child path and will return it. If it doesn't find a
    91  * match, then it will return the first category matching slug, if $full_match,
    92  * is set to false. If it does not, then it will return null.
    93  *
    94  * It is also possible that it will return a WP_Error object on failure. Check
    95  * for it when using this function.
    96  *
    97  * @since 2.1.0
    98  *
    99  * @param string $category_path URL containing category slugs.
    100  * @param bool $full_match Optional. Whether full path should be matched.
    101  * @param string $output Optional. Constant OBJECT, ARRAY_A, or ARRAY_N
    102  * @return object|array|WP_Error|void Type is based on $output value.
    103  */
    104 function get_category_by_path( $category_path, $full_match = true, $output = OBJECT ) {
    105     $category_path = rawurlencode( urldecode( $category_path ) );
    106     $category_path = str_replace( '%2F', '/', $category_path );
    107     $category_path = str_replace( '%20', ' ', $category_path );
    108     $category_paths = '/' . trim( $category_path, '/' );
    109     $leaf_path  = sanitize_title( basename( $category_paths ) );
    110     $category_paths = explode( '/', $category_paths );
    111     $full_path = '';
    112     foreach ( (array) $category_paths as $pathdir ) {
    113         $full_path .= ( $pathdir != '' ? '/' : '' ) . sanitize_title( $pathdir );
    114     }
    115     $categories = get_terms( 'category', array('get' => 'all', 'slug' => $leaf_path) );
    116 
    117     if ( empty( $categories ) ) {
    118         return;
    119     }
    120 
    121     foreach ( $categories as $category ) {
    122         $path = '/' . $leaf_path;
    123         $curcategory = $category;
    124         while ( ( $curcategory->parent != 0 ) && ( $curcategory->parent != $curcategory->term_id ) ) {
    125             $curcategory = get_term( $curcategory->parent, 'category' );
    126             if ( is_wp_error( $curcategory ) ) {
    127                 return $curcategory;
    128             }
    129             $path = '/' . $curcategory->slug . $path;
    130         }
    131 
    132         if ( $path == $full_path ) {
    133             $category = get_term( $category->term_id, 'category', $output );
    134             _make_cat_compat( $category );
    135             return $category;
    136         }
    137     }
    138 
    139     // If full matching is not required, return the first cat that matches the leaf.
    140     if ( ! $full_match ) {
    141         $category = get_term( reset( $categories )->term_id, 'category', $output );
    142         _make_cat_compat( $category );
    143         return $category;
    144     }
    145 }
    146 
    147 /**
    148  * Retrieve category object by category slug.
    149  *
    150  * @since 2.3.0
    151  *
    152  * @param string $slug The category slug.
    153  * @return object Category data object
    154  */
    155 function get_category_by_slug( $slug  ) {
    156     $category = get_term_by( 'slug', $slug, 'category' );
    157     if ( $category )
    158         _make_cat_compat( $category );
    159 
    160     return $category;
    161 }
    162 
    163 /**
    164  * Retrieve the ID of a category from its name.
    165  *
    166  * @since 1.0.0
    167  *
    168  * @param string $cat_name Category name.
    169  * @return int 0, if failure and ID of category on success.
    170  */
    171 function get_cat_ID( $cat_name ) {
    172     $cat = get_term_by( 'name', $cat_name, 'category' );
    173     if ( $cat )
    174         return $cat->term_id;
    175     return 0;
    176 }
    177 
    178 /**
    179  * Retrieve the name of a category from its ID.
    180  *
    181  * @since 1.0.0
    182  *
    183  * @param int $cat_id Category ID
    184  * @return string Category name, or an empty string if category doesn't exist.
    185  */
    186 function get_cat_name( $cat_id ) {
    187     $cat_id = (int) $cat_id;
    188     $category = get_term( $cat_id, 'category' );
    189     if ( ! $category || is_wp_error( $category ) )
    190         return '';
    191     return $category->name;
    192 }
    193 
    194 /**
    195  * Check if a category is an ancestor of another category.
    196  *
    197  * You can use either an id or the category object for both parameters. If you
    198  * use an integer the category will be retrieved.
    199  *
    200  * @since 2.1.0
    201  *
    202  * @param int|object $cat1 ID or object to check if this is the parent category.
    203  * @param int|object $cat2 The child category.
    204  * @return bool Whether $cat2 is child of $cat1
    205  */
    206 function cat_is_ancestor_of( $cat1, $cat2 ) {
    207     return term_is_ancestor_of( $cat1, $cat2, 'category' );
    208 }
    209 
    210 /**
    211  * Sanitizes category data based on context.
    212  *
    213  * @since 2.3.0
    214  *
    215  * @param object|array $category Category data
    216  * @param string $context Optional. Default is 'display'.
    217  * @return object|array Same type as $category with sanitized data for safe use.
    218  */
    219 function sanitize_category( $category, $context = 'display' ) {
    220     return sanitize_term( $category, 'category', $context );
    221 }
    222 
    223 /**
    224  * Sanitizes data in single category key field.
    225  *
    226  * @since 2.3.0
    227  *
    228  * @param string $field Category key to sanitize
    229  * @param mixed $value Category value to sanitize
    230  * @param int $cat_id Category ID
    231  * @param string $context What filter to use, 'raw', 'display', etc.
    232  * @return mixed Same type as $value after $value has been sanitized.
    233  */
    234 function sanitize_category_field( $field, $value, $cat_id, $context ) {
    235     return sanitize_term_field( $field, $value, $cat_id, 'category', $context );
    236 }
    237 
    238 /* Tags */
    239 
    240 /**
    241  * Retrieves all post tags.
    242  *
    243  * @since 2.3.0
    244  * @see get_terms() For list of arguments to pass.
    245  *
    246  * @param string|array $args Tag arguments to use when retrieving tags.
    247  * @return array List of tags.
    248  */
    249 function get_tags( $args = '' ) {
    250     $tags = get_terms( 'post_tag', $args );
    251 
    252     if ( empty( $tags ) ) {
    253         $return = array();
    254         return $return;
    255     }
    256 
    257     /**
    258      * Filter the array of term objects returned for the 'post_tag' taxonomy.
    259      *
    260      * @since 2.3.0
    261      *
    262      * @param array $tags Array of 'post_tag' term objects.
    263      * @param array $args An array of arguments. @see get_terms()
    264      */
    265     $tags = apply_filters( 'get_tags', $tags, $args );
    266     return $tags;
    267 }
    268 
    269 /**
    270  * Retrieve post tag by tag ID or tag object.
    271  *
    272  * If you pass the $tag parameter an object, which is assumed to be the tag row
    273  * object retrieved the database. It will cache the tag data.
    274  *
    275  * If you pass $tag an integer of the tag ID, then that tag will
    276  * be retrieved from the database, if it isn't already cached, and pass it back.
    277  *
    278  * If you look at get_term(), then both types will be passed through several
    279  * filters and finally sanitized based on the $filter parameter value.
    280  *
    281  * @since 2.3.0
    282  *
    283  * @param int|object $tag
    284  * @param string $output Optional. Constant OBJECT, ARRAY_A, or ARRAY_N
    285  * @param string $filter Optional. Default is raw or no WordPress defined filter will applied.
    286  * @return object|array|WP_Error|null Tag data in type defined by $output parameter. WP_Error if $tag is empty, null if it does not exist.
    287  */
    288 function get_tag( $tag, $output = OBJECT, $filter = 'raw' ) {
    289     return get_term( $tag, 'post_tag', $output, $filter );
    290 }
    291 
    292 /* Cache */
    293 
    294 /**
    295  * Remove the category cache data based on ID.
    296  *
    297  * @since 2.1.0
    298  *
    299  * @param int $id Category ID
    300  */
    301 function clean_category_cache( $id ) {
    302     clean_term_cache( $id, 'category' );
    303 }
    304 
    305 /**
    306  * Update category structure to old pre 2.3 from new taxonomy structure.
    307  *
    308  * This function was added for the taxonomy support to update the new category
    309  * structure with the old category one. This will maintain compatibility with
    310  * plugins and themes which depend on the old key or property names.
    311  *
    312  * The parameter should only be passed a variable and not create the array or
    313  * object inline to the parameter. The reason for this is that parameter is
    314  * passed by reference and PHP will fail unless it has the variable.
    315  *
    316  * There is no return value, because everything is updated on the variable you
    317  * pass to it. This is one of the features with using pass by reference in PHP.
    318  *
    319  * @since 2.3.0
    320  * @access private
    321  *
    322  * @param array|object $category Category Row object or array
    323  */
    324 function _make_cat_compat( &$category ) {
    325     if ( is_object( $category ) && ! is_wp_error( $category ) ) {
    326         $category->cat_ID = &$category->term_id;
    327         $category->category_count = &$category->count;
    328         $category->category_description = &$category->description;
    329         $category->cat_name = &$category->name;
    330         $category->category_nicename = &$category->slug;
    331         $category->category_parent = &$category->parent;
    332     } elseif ( is_array( $category ) && isset( $category['term_id'] ) ) {
    333         $category['cat_ID'] = &$category['term_id'];
    334         $category['category_count'] = &$category['count'];
    335         $category['category_description'] = &$category['description'];
    336         $category['cat_name'] = &$category['name'];
    337         $category['category_nicename'] = &$category['slug'];
    338         $category['category_parent'] = &$category['parent'];
    339     }
    340 }
     14/** Walker_CategoryDropdown class */
     15require_once( ABSPATH . WPINC . '/class-walker-category-dropdown.php' );
  • trunk/src/wp-includes/class-walker-category-dropdown.php

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

    r34109 r34110  
    11<?php
    22/**
    3  * Category Template Tags and API.
     3 * Category API: Walker_Category class
    44 *
    55 * @package WordPress
    66 * @subpackage Template
    77 */
    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  * This tag may be used outside The Loop by passing a post id as the parameter.
    69  *
    70  * Note: This function only returns results from the default "category" taxonomy.
    71  * For custom taxonomies use get_the_terms().
    72  *
    73  * @since 0.71
    74  *
    75  * @param int $id Optional, default to current post ID. The post ID.
    76  * @return array Array of objects, one for each category assigned to the post.
    77  */
    78 function get_the_category( $id = false ) {
    79     $categories = get_the_terms( $id, 'category' );
    80     if ( ! $categories || is_wp_error( $categories ) )
    81         $categories = array();
    82 
    83     $categories = array_values( $categories );
    84 
    85     foreach ( array_keys( $categories ) as $key ) {
    86         _make_cat_compat( $categories[$key] );
    87     }
    88 
    89     /**
    90      * Filter the array of categories to return for a post.
    91      *
    92      * @since 3.1.0
    93      *
    94      * @param array $categories An array of categories to return for the post.
    95      */
    96     return apply_filters( 'get_the_categories', $categories );
    97 }
    98 
    99 /**
    100  * Sort categories by name.
    101  *
    102  * Used by usort() as a callback, should not be used directly. Can actually be
    103  * used to sort any term object.
    104  *
    105  * @since 2.3.0
    106  * @access private
    107  *
    108  * @param object $a
    109  * @param object $b
    110  * @return int
    111  */
    112 function _usort_terms_by_name( $a, $b ) {
    113     return strcmp( $a->name, $b->name );
    114 }
    115 
    116 /**
    117  * Sort categories by ID.
    118  *
    119  * Used by usort() as a callback, should not be used directly. Can actually be
    120  * used to sort any term object.
    121  *
    122  * @since 2.3.0
    123  * @access private
    124  *
    125  * @param object $a
    126  * @param object $b
    127  * @return int
    128  */
    129 function _usort_terms_by_ID( $a, $b ) {
    130     if ( $a->term_id > $b->term_id )
    131         return 1;
    132     elseif ( $a->term_id < $b->term_id )
    133         return -1;
    134     else
    135         return 0;
    136 }
    137 
    138 /**
    139  * Retrieve category name based on category ID.
    140  *
    141  * @since 0.71
    142  *
    143  * @param int $cat_ID Category ID.
    144  * @return string|WP_Error Category name on success, WP_Error on failure.
    145  */
    146 function get_the_category_by_ID( $cat_ID ) {
    147     $cat_ID = (int) $cat_ID;
    148     $category = get_term( $cat_ID, 'category' );
    149 
    150     if ( is_wp_error( $category ) )
    151         return $category;
    152 
    153     return ( $category ) ? $category->name : '';
    154 }
    155 
    156 /**
    157  * Retrieve category list in either HTML list or custom format.
    158  *
    159  * @since 1.5.1
    160  *
    161  * @global WP_Rewrite $wp_rewrite
    162  *
    163  * @param string $separator Optional, default is empty string. Separator for between the categories.
    164  * @param string $parents Optional. How to display the parents.
    165  * @param int $post_id Optional. Post ID to retrieve categories.
    166  * @return string
    167  */
    168 function get_the_category_list( $separator = '', $parents='', $post_id = false ) {
    169     global $wp_rewrite;
    170     if ( ! is_object_in_taxonomy( get_post_type( $post_id ), 'category' ) ) {
    171         /** This filter is documented in wp-includes/category-template.php */
    172         return apply_filters( 'the_category', '', $separator, $parents );
    173     }
    174 
    175     $categories = get_the_category( $post_id );
    176     if ( empty( $categories ) ) {
    177         /** This filter is documented in wp-includes/category-template.php */
    178         return apply_filters( 'the_category', __( 'Uncategorized' ), $separator, $parents );
    179     }
    180 
    181     $rel = ( is_object( $wp_rewrite ) && $wp_rewrite->using_permalinks() ) ? 'rel="category tag"' : 'rel="category"';
    182 
    183     $thelist = '';
    184     if ( '' == $separator ) {
    185         $thelist .= '<ul class="post-categories">';
    186         foreach ( $categories as $category ) {
    187             $thelist .= "\n\t<li>";
    188             switch ( strtolower( $parents ) ) {
    189                 case 'multiple':
    190                     if ( $category->parent )
    191                         $thelist .= get_category_parents( $category->parent, true, $separator );
    192                     $thelist .= '<a href="' . esc_url( get_category_link( $category->term_id ) ) . '" ' . $rel . '>' . $category->name.'</a></li>';
    193                     break;
    194                 case 'single':
    195                     $thelist .= '<a href="' . esc_url( get_category_link( $category->term_id ) ) . '"  ' . $rel . '>';
    196                     if ( $category->parent )
    197                         $thelist .= get_category_parents( $category->parent, false, $separator );
    198                     $thelist .= $category->name.'</a></li>';
    199                     break;
    200                 case '':
    201                 default:
    202                     $thelist .= '<a href="' . esc_url( get_category_link( $category->term_id ) ) . '" ' . $rel . '>' . $category->name.'</a></li>';
    203             }
    204         }
    205         $thelist .= '</ul>';
    206     } else {
    207         $i = 0;
    208         foreach ( $categories as $category ) {
    209             if ( 0 < $i )
    210                 $thelist .= $separator;
    211             switch ( strtolower( $parents ) ) {
    212                 case 'multiple':
    213                     if ( $category->parent )
    214                         $thelist .= get_category_parents( $category->parent, true, $separator );
    215                     $thelist .= '<a href="' . esc_url( get_category_link( $category->term_id ) ) . '" ' . $rel . '>' . $category->name.'</a>';
    216                     break;
    217                 case 'single':
    218                     $thelist .= '<a href="' . esc_url( get_category_link( $category->term_id ) ) . '" ' . $rel . '>';
    219                     if ( $category->parent )
    220                         $thelist .= get_category_parents( $category->parent, false, $separator );
    221                     $thelist .= "$category->name</a>";
    222                     break;
    223                 case '':
    224                 default:
    225                     $thelist .= '<a href="' . esc_url( get_category_link( $category->term_id ) ) . '" ' . $rel . '>' . $category->name.'</a>';
    226             }
    227             ++$i;
    228         }
    229     }
    230 
    231     /**
    232      * Filter the category or list of categories.
    233      *
    234      * @since 1.2.0
    235      *
    236      * @param array  $thelist   List of categories for the current post.
    237      * @param string $separator Separator used between the categories.
    238      * @param string $parents   How to display the category parents. Accepts 'multiple',
    239      *                          'single', or empty.
    240      */
    241     return apply_filters( 'the_category', $thelist, $separator, $parents );
    242 }
    243 
    244 /**
    245  * Check if the current post in within any of the given categories.
    246  *
    247  * The given categories are checked against the post's categories' term_ids, names and slugs.
    248  * Categories given as integers will only be checked against the post's categories' term_ids.
    249  *
    250  * Prior to v2.5 of WordPress, category names were not supported.
    251  * Prior to v2.7, category slugs were not supported.
    252  * Prior to v2.7, only one category could be compared: in_category( $single_category ).
    253  * Prior to v2.7, this function could only be used in the WordPress Loop.
    254  * As of 2.7, the function can be used anywhere if it is provided a post ID or post object.
    255  *
    256  * @since 1.2.0
    257  *
    258  * @param int|string|array $category Category ID, name or slug, or array of said.
    259  * @param int|object $post Optional. Post to check instead of the current post. (since 2.7.0)
    260  * @return bool True if the current post is in any of the given categories.
    261  */
    262 function in_category( $category, $post = null ) {
    263     if ( empty( $category ) )
    264         return false;
    265 
    266     return has_category( $category, $post );
    267 }
    268 
    269 /**
    270  * Display the category list for the post.
    271  *
    272  * @since 0.71
    273  *
    274  * @param string $separator Optional, default is empty string. Separator for between the categories.
    275  * @param string $parents Optional. How to display the parents.
    276  * @param int $post_id Optional. Post ID to retrieve categories.
    277  */
    278 function the_category( $separator = '', $parents='', $post_id = false ) {
    279     echo get_the_category_list( $separator, $parents, $post_id );
    280 }
    281 
    282 /**
    283  * Retrieve category description.
    284  *
    285  * @since 1.0.0
    286  *
    287  * @param int $category Optional. Category ID. Will use global category ID by default.
    288  * @return string Category description, available.
    289  */
    290 function category_description( $category = 0 ) {
    291     return term_description( $category, 'category' );
    292 }
    293 
    294 /**
    295  * Display or retrieve the HTML dropdown list of categories.
    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  * @since 4.2.0 Introduced the `value_field` argument.
    304  *
    305  * @param string|array $args {
    306  *     Optional. Array or string of arguments to generate a categories drop-down element.
    307  *
    308  *     @type string       $show_option_all   Text to display for showing all categories. Default empty.
    309  *     @type string       $show_option_none  Text to display for showing no categories. Default empty.
    310  *     @type string       $option_none_value Value to use when no category is selected. Default empty.
    311  *     @type string       $orderby           Which column to use for ordering categories. See get_terms() for a list
    312  *                                           of accepted values. Default 'id' (term_id).
    313  *     @type string       $order             Whether to order terms in ascending or descending order. Accepts 'ASC'
    314  *                                           or 'DESC'. Default 'ASC'.
    315  *     @type bool         $pad_counts        See get_terms() for an argument description. Default false.
    316  *     @type bool|int     $show_count        Whether to include post counts. Accepts 0, 1, or their bool equivalents.
    317  *                                           Default 0.
    318  *     @type bool|int     $hide_empty        Whether to hide categories that don't have any posts. Accepts 0, 1, or
    319  *                                           their bool equivalents. Default 1.
    320  *     @type int          $child_of          Term ID to retrieve child terms of. See get_terms(). Default 0.
    321  *     @type array|string $exclude           Array or comma/space-separated string of term ids to exclude.
    322  *                                           If `$include` is non-empty, `$exclude` is ignored. Default empty array.
    323  *     @type bool|int     $echo              Whether to echo or return the generated markup. Accepts 0, 1, or their
    324  *                                           bool equivalents. Default 1.
    325  *     @type bool|int     $hierarchical      Whether to traverse the taxonomy hierarchy. Accepts 0, 1, or their bool
    326  *                                           equivalents. Default 0.
    327  *     @type int          $depth             Maximum depth. Default 0.
    328  *     @type int          $tab_index         Tab index for the select element. Default 0 (no tabindex).
    329  *     @type string       $name              Value for the 'name' attribute of the select element. Default 'cat'.
    330  *     @type string       $id                Value for the 'id' attribute of the select element. Defaults to the value
    331  *                                           of `$name`.
    332  *     @type string       $class             Value for the 'class' attribute of the select element. Default 'postform'.
    333  *     @type int|string   $selected          Value of the option that should be selected. Default 0.
    334  *     @type string       $value_field       Term field that should be used to populate the 'value' attribute
    335  *                                           of the option elements. Accepts any valid term field: 'term_id', 'name',
    336  *                                           'slug', 'term_group', 'term_taxonomy_id', 'taxonomy', 'description',
    337  *                                           'parent', 'count'. Default 'term_id'.
    338  *     @type string       $taxonomy          Name of the category to retrieve. Default 'category'.
    339  *     @type bool         $hide_if_empty     True to skip generating markup if no categories are found.
    340  *                                           Default false (create select element even if no categories are found).
    341  * }
    342  * @return string HTML content only if 'echo' argument is 0.
    343  */
    344 function wp_dropdown_categories( $args = '' ) {
    345     $defaults = array(
    346         'show_option_all' => '', 'show_option_none' => '',
    347         'orderby' => 'id', 'order' => 'ASC',
    348         'show_count' => 0,
    349         'hide_empty' => 1, 'child_of' => 0,
    350         'exclude' => '', 'echo' => 1,
    351         'selected' => 0, 'hierarchical' => 0,
    352         'name' => 'cat', 'id' => '',
    353         'class' => 'postform', 'depth' => 0,
    354         'tab_index' => 0, 'taxonomy' => 'category',
    355         'hide_if_empty' => false, 'option_none_value' => -1,
    356         'value_field' => 'term_id',
    357     );
    358 
    359     $defaults['selected'] = ( is_category() ) ? get_query_var( 'cat' ) : 0;
    360 
    361     // Back compat.
    362     if ( isset( $args['type'] ) && 'link' == $args['type'] ) {
    363         _deprecated_argument( __FUNCTION__, '3.0', '' );
    364         $args['taxonomy'] = 'link_category';
    365     }
    366 
    367     $r = wp_parse_args( $args, $defaults );
    368     $option_none_value = $r['option_none_value'];
    369 
    370     if ( ! isset( $r['pad_counts'] ) && $r['show_count'] && $r['hierarchical'] ) {
    371         $r['pad_counts'] = true;
    372     }
    373 
    374     $tab_index = $r['tab_index'];
    375 
    376     $tab_index_attribute = '';
    377     if ( (int) $tab_index > 0 ) {
    378         $tab_index_attribute = " tabindex=\"$tab_index\"";
    379     }
    380 
    381     // Avoid clashes with the 'name' param of get_terms().
    382     $get_terms_args = $r;
    383     unset( $get_terms_args['name'] );
    384     $categories = get_terms( $r['taxonomy'], $get_terms_args );
    385 
    386     $name = esc_attr( $r['name'] );
    387     $class = esc_attr( $r['class'] );
    388     $id = $r['id'] ? esc_attr( $r['id'] ) : $name;
    389 
    390     if ( ! $r['hide_if_empty'] || ! empty( $categories ) ) {
    391         $output = "<select name='$name' id='$id' class='$class' $tab_index_attribute>\n";
    392     } else {
    393         $output = '';
    394     }
    395     if ( empty( $categories ) && ! $r['hide_if_empty'] && ! empty( $r['show_option_none'] ) ) {
    396 
    397         /**
    398          * Filter a taxonomy drop-down display element.
    399          *
    400          * A variety of taxonomy drop-down display elements can be modified
    401          * just prior to display via this filter. Filterable arguments include
    402          * 'show_option_none', 'show_option_all', and various forms of the
    403          * term name.
    404          *
    405          * @since 1.2.0
    406          *
    407          * @see wp_dropdown_categories()
    408          *
    409          * @param string $element Taxonomy element to list.
    410          */
    411         $show_option_none = apply_filters( 'list_cats', $r['show_option_none'] );
    412         $output .= "\t<option value='" . esc_attr( $option_none_value ) . "' selected='selected'>$show_option_none</option>\n";
    413     }
    414 
    415     if ( ! empty( $categories ) ) {
    416 
    417         if ( $r['show_option_all'] ) {
    418 
    419             /** This filter is documented in wp-includes/category-template.php */
    420             $show_option_all = apply_filters( 'list_cats', $r['show_option_all'] );
    421             $selected = ( '0' === strval($r['selected']) ) ? " selected='selected'" : '';
    422             $output .= "\t<option value='0'$selected>$show_option_all</option>\n";
    423         }
    424 
    425         if ( $r['show_option_none'] ) {
    426 
    427             /** This filter is documented in wp-includes/category-template.php */
    428             $show_option_none = apply_filters( 'list_cats', $r['show_option_none'] );
    429             $selected = selected( $option_none_value, $r['selected'], false );
    430             $output .= "\t<option value='" . esc_attr( $option_none_value ) . "'$selected>$show_option_none</option>\n";
    431         }
    432 
    433         if ( $r['hierarchical'] ) {
    434             $depth = $r['depth'];  // Walk the full depth.
    435         } else {
    436             $depth = -1; // Flat.
    437         }
    438         $output .= walk_category_dropdown_tree( $categories, $depth, $r );
    439     }
    440 
    441     if ( ! $r['hide_if_empty'] || ! empty( $categories ) ) {
    442         $output .= "</select>\n";
    443     }
    444     /**
    445      * Filter the taxonomy drop-down output.
    446      *
    447      * @since 2.1.0
    448      *
    449      * @param string $output HTML output.
    450      * @param array  $r      Arguments used to build the drop-down.
    451      */
    452     $output = apply_filters( 'wp_dropdown_cats', $output, $r );
    453 
    454     if ( $r['echo'] ) {
    455         echo $output;
    456     }
    457     return $output;
    458 }
    459 
    460 /**
    461  * Display or retrieve the HTML list of categories.
    462  *
    463  * @since 2.1.0
    464  * @since 4.4.0 Introduced the `hide_title_if_empty` argument. The `current_category` argument was modified to
    465  *              optionally accept an array of values.
    466  *
    467  * @param string|array $args {
    468  *     Array of optional arguments.
    469  *
    470  *     @type string       $show_option_all       Text to display for showing all categories. Default empty string.
    471  *     @type string       $show_option_none      Text to display for the 'no categories' option.
    472  *                                               Default 'No categories'.
    473  *     @type string       $orderby               The column to use for ordering categories. Default 'ID'.
    474  *     @type string       $order                 Which direction to order categories. Accepts 'ASC' or 'DESC'.
    475  *                                               Default 'ASC'.
    476  *     @type bool|int     $show_count            Whether to show how many posts are in the category. Default 0.
    477  *     @type bool|int     $hide_empty            Whether to hide categories that don't have any posts attached to them.
    478  *                                               Default 1.
    479  *     @type bool|int     $use_desc_for_title    Whether to use the category description as the title attribute.
    480  *                                               Default 1.
    481  *     @type string       $feed                  Text to use for the feed link. Default 'Feed for all posts filed
    482  *                                               under [cat name]'.
    483  *     @type string       $feed_type             Feed type. Used to build feed link. See {@link get_term_feed_link()}.
    484  *                                               Default empty string (default feed).
    485  *     @type string       $feed_image            URL of an image to use for the feed link. Default empty string.
    486  *     @type int          $child_of              Term ID to retrieve child terms of. See {@link get_terms()}. Default 0.
    487  *     @type array|string $exclude               Array or comma/space-separated string of term IDs to exclude.
    488  *                                               See {@link get_terms()}. Default empty string.
    489  *     @type array|string $exclude_tree          Array or comma/space-separated string of term IDs to exclude, along
    490  *                                               with their descendants. See {@link get_terms()}. Default empty string.
    491  *     @type bool|int     $echo                  True to echo markup, false to return it. Default 1.
    492  *     @type int|array    $current_category      ID of category, or array of IDs of categories, that should get the
    493  *                                               'current-cat' class. Default 0.
    494  *     @type bool         $hierarchical          Whether to include terms that have non-empty descendants.
    495  *                                               See {@link get_terms()}. Default true.
    496  *     @type string       $title_li              Text to use for the list title `<li>` element. Pass an empty string
    497  *                                               to disable. Default 'Categories'.
    498  *     @type bool         $hide_title_if_empty   Whether to hide the `$title_li` element if there are no terms in
    499  *                                               the list. Default false (title will always be shown).
    500  *     @type int          $depth                 Category depth. Used for tab indentation. Default 0.
    501  *     @type string       $taxonomy              Taxonomy name. Default 'category'.
    502  * }
    503  * @return false|string HTML content only if 'echo' argument is 0.
    504  */
    505 function wp_list_categories( $args = '' ) {
    506     $defaults = array(
    507         'show_option_all' => '', 'show_option_none' => __('No categories'),
    508         'orderby' => 'name', 'order' => 'ASC',
    509         'style' => 'list',
    510         'show_count' => 0, 'hide_empty' => 1,
    511         'use_desc_for_title' => 1, 'child_of' => 0,
    512         'feed' => '', 'feed_type' => '',
    513         'feed_image' => '', 'exclude' => '',
    514         'exclude_tree' => '', 'current_category' => 0,
    515         'hierarchical' => true, 'title_li' => __( 'Categories' ),
    516         'hide_title_if_empty' => false,
    517         'echo' => 1, 'depth' => 0,
    518         'taxonomy' => 'category'
    519     );
    520 
    521     $r = wp_parse_args( $args, $defaults );
    522 
    523     if ( !isset( $r['pad_counts'] ) && $r['show_count'] && $r['hierarchical'] )
    524         $r['pad_counts'] = true;
    525 
    526     if ( true == $r['hierarchical'] ) {
    527         $r['exclude_tree'] = $r['exclude'];
    528         $r['exclude'] = '';
    529     }
    530 
    531     if ( ! isset( $r['class'] ) )
    532         $r['class'] = ( 'category' == $r['taxonomy'] ) ? 'categories' : $r['taxonomy'];
    533 
    534     if ( ! taxonomy_exists( $r['taxonomy'] ) ) {
    535         return false;
    536     }
    537 
    538     $show_option_all = $r['show_option_all'];
    539     $show_option_none = $r['show_option_none'];
    540 
    541     $categories = get_categories( $r );
    542 
    543     $output = '';
    544     if ( $r['title_li'] && 'list' == $r['style'] && ( ! empty( $categories ) || ! $r['hide_title_if_empty'] ) ) {
    545         $output = '<li class="' . esc_attr( $r['class'] ) . '">' . $r['title_li'] . '<ul>';
    546     }
    547     if ( empty( $categories ) ) {
    548         if ( ! empty( $show_option_none ) ) {
    549             if ( 'list' == $r['style'] ) {
    550                 $output .= '<li class="cat-item-none">' . $show_option_none . '</li>';
    551             } else {
    552                 $output .= $show_option_none;
    553             }
    554         }
    555     } else {
    556         if ( ! empty( $show_option_all ) ) {
    557 
    558             $posts_page = '';
    559 
    560             // For taxonomies that belong only to custom post types, point to a valid archive.
    561             $taxonomy_object = get_taxonomy( $r['taxonomy'] );
    562             if ( ! in_array( 'post', $taxonomy_object->object_type ) && ! in_array( 'page', $taxonomy_object->object_type ) ) {
    563                 foreach ( $taxonomy_object->object_type as $object_type ) {
    564                     $_object_type = get_post_type_object( $object_type );
    565 
    566                     // Grab the first one.
    567                     if ( ! empty( $_object_type->has_archive ) ) {
    568                         $posts_page = get_post_type_archive_link( $object_type );
    569                         break;
    570                     }
    571                 }
    572             }
    573 
    574             // Fallback for the 'All' link is the front page.
    575             if ( ! $posts_page ) {
    576                 $posts_page = 'page' == get_option( 'show_on_front' ) && get_option( 'page_for_posts' ) ? get_permalink( get_option( 'page_for_posts' ) ) : home_url( '/' );
    577             }
    578 
    579             $posts_page = esc_url( $posts_page );
    580             if ( 'list' == $r['style'] ) {
    581                 $output .= "<li class='cat-item-all'><a href='$posts_page'>$show_option_all</a></li>";
    582             } else {
    583                 $output .= "<a href='$posts_page'>$show_option_all</a>";
    584             }
    585         }
    586 
    587         if ( empty( $r['current_category'] ) && ( is_category() || is_tax() || is_tag() ) ) {
    588             $current_term_object = get_queried_object();
    589             if ( $current_term_object && $r['taxonomy'] === $current_term_object->taxonomy ) {
    590                 $r['current_category'] = get_queried_object_id();
    591             }
    592         }
    593 
    594         if ( $r['hierarchical'] ) {
    595             $depth = $r['depth'];
    596         } else {
    597             $depth = -1; // Flat.
    598         }
    599         $output .= walk_category_tree( $categories, $depth, $r );
    600     }
    601 
    602     if ( $r['title_li'] && 'list' == $r['style'] )
    603         $output .= '</ul></li>';
    604 
    605     /**
    606      * Filter the HTML output of a taxonomy list.
    607      *
    608      * @since 2.1.0
    609      *
    610      * @param string $output HTML output.
    611      * @param array  $args   An array of taxonomy-listing arguments.
    612      */
    613     $html = apply_filters( 'wp_list_categories', $output, $args );
    614 
    615     if ( $r['echo'] ) {
    616         echo $html;
    617     } else {
    618         return $html;
    619     }
    620 }
    621 
    622 /**
    623  * Display tag cloud.
    624  *
    625  * The text size is set by the 'smallest' and 'largest' arguments, which will
    626  * use the 'unit' argument value for the CSS text size unit. The 'format'
    627  * argument can be 'flat' (default), 'list', or 'array'. The flat value for the
    628  * 'format' argument will separate tags with spaces. The list value for the
    629  * 'format' argument will format the tags in a UL HTML list. The array value for
    630  * the 'format' argument will return in PHP array type format.
    631  *
    632  * The 'orderby' argument will accept 'name' or 'count' and defaults to 'name'.
    633  * The 'order' is the direction to sort, defaults to 'ASC' and can be 'DESC'.
    634  *
    635  * The 'number' argument is how many tags to return. By default, the limit will
    636  * be to return the top 45 tags in the tag cloud list.
    637  *
    638  * The 'topic_count_text' argument is a nooped plural from _n_noop() to generate the
    639  * text for the tooltip of the tag link.
    640  *
    641  * The 'topic_count_text_callback' argument is a function, which given the count
    642  * of the posts with that tag returns a text for the tooltip of the tag link.
    643  *
    644  * The 'post_type' argument is used only when 'link' is set to 'edit'. It determines the post_type
    645  * passed to edit.php for the popular tags edit links.
    646  *
    647  * The 'exclude' and 'include' arguments are used for the {@link get_tags()}
    648  * function. Only one should be used, because only one will be used and the
    649  * other ignored, if they are both set.
    650  *
    651  * @since 2.3.0
    652  *
    653  * @param array|string|null $args Optional. Override default arguments.
    654  * @return void|array Generated tag cloud, only if no failures and 'array' is set for the 'format' argument.
    655  *                    Otherwise, this function outputs the tag cloud.
    656  */
    657 function wp_tag_cloud( $args = '' ) {
    658     $defaults = array(
    659         'smallest' => 8, 'largest' => 22, 'unit' => 'pt', 'number' => 45,
    660         'format' => 'flat', 'separator' => "\n", 'orderby' => 'name', 'order' => 'ASC',
    661         'exclude' => '', 'include' => '', 'link' => 'view', 'taxonomy' => 'post_tag', 'post_type' => '', 'echo' => true
    662     );
    663     $args = wp_parse_args( $args, $defaults );
    664 
    665     $tags = get_terms( $args['taxonomy'], array_merge( $args, array( 'orderby' => 'count', 'order' => 'DESC' ) ) ); // Always query top tags
    666 
    667     if ( empty( $tags ) || is_wp_error( $tags ) )
    668         return;
    669 
    670     foreach ( $tags as $key => $tag ) {
    671         if ( 'edit' == $args['link'] )
    672             $link = get_edit_term_link( $tag->term_id, $tag->taxonomy, $args['post_type'] );
    673         else
    674             $link = get_term_link( intval($tag->term_id), $tag->taxonomy );
    675         if ( is_wp_error( $link ) )
    676             return;
    677 
    678         $tags[ $key ]->link = $link;
    679         $tags[ $key ]->id = $tag->term_id;
    680     }
    681 
    682     $return = wp_generate_tag_cloud( $tags, $args ); // Here's where those top tags get sorted according to $args
    683 
    684     /**
    685      * Filter the tag cloud output.
    686      *
    687      * @since 2.3.0
    688      *
    689      * @param string $return HTML output of the tag cloud.
    690      * @param array  $args   An array of tag cloud arguments.
    691      */
    692     $return = apply_filters( 'wp_tag_cloud', $return, $args );
    693 
    694     if ( 'array' == $args['format'] || empty($args['echo']) )
    695         return $return;
    696 
    697     echo $return;
    698 }
    699 
    700 /**
    701  * Default topic count scaling for tag links
    702  *
    703  * @param int $count number of posts with that tag
    704  * @return int scaled count
    705  */
    706 function default_topic_count_scale( $count ) {
    707     return round(log10($count + 1) * 100);
    708 }
    709 
    710 /**
    711  * Generates a tag cloud (heatmap) from provided data.
    712  *
    713  * The text size is set by the 'smallest' and 'largest' arguments, which will
    714  * use the 'unit' argument value for the CSS text size unit. The 'format'
    715  * argument can be 'flat' (default), 'list', or 'array'. The flat value for the
    716  * 'format' argument will separate tags with spaces. The list value for the
    717  * 'format' argument will format the tags in a UL HTML list. The array value for
    718  * the 'format' argument will return in PHP array type format.
    719  *
    720  * The 'tag_cloud_sort' filter allows you to override the sorting.
    721  * Passed to the filter: $tags array and $args array, has to return the $tags array
    722  * after sorting it.
    723  *
    724  * The 'orderby' argument will accept 'name' or 'count' and defaults to 'name'.
    725  * The 'order' is the direction to sort, defaults to 'ASC' and can be 'DESC' or
    726  * 'RAND'.
    727  *
    728  * The 'number' argument is how many tags to return. By default, the limit will
    729  * be to return the entire tag cloud list.
    730  *
    731  * The 'topic_count_text' argument is a nooped plural from _n_noop() to generate the
    732  * text for the tooltip of the tag link.
    733  *
    734  * The 'topic_count_text_callback' argument is a function, which given the count
    735  * of the posts with that tag returns a text for the tooltip of the tag link.
    736  *
    737  * @todo Complete functionality.
    738  * @since 2.3.0
    739  *
    740  * @param array $tags List of tags.
    741  * @param string|array $args Optional, override default arguments.
    742  * @return string|array Tag cloud as a string or an array, depending on 'format' argument.
    743  */
    744 function wp_generate_tag_cloud( $tags, $args = '' ) {
    745     $defaults = array(
    746         'smallest' => 8, 'largest' => 22, 'unit' => 'pt', 'number' => 0,
    747         'format' => 'flat', 'separator' => "\n", 'orderby' => 'name', 'order' => 'ASC',
    748         'topic_count_text' => null, 'topic_count_text_callback' => null,
    749         'topic_count_scale_callback' => 'default_topic_count_scale', 'filter' => 1,
    750     );
    751 
    752     $args = wp_parse_args( $args, $defaults );
    753 
    754     $return = ( 'array' === $args['format'] ) ? array() : '';
    755 
    756     if ( empty( $tags ) ) {
    757         return $return;
    758     }
    759 
    760     // Juggle topic count tooltips:
    761     if ( isset( $args['topic_count_text'] ) ) {
    762         // First look for nooped plural support via topic_count_text.
    763         $translate_nooped_plural = $args['topic_count_text'];
    764     } elseif ( ! empty( $args['topic_count_text_callback'] ) ) {
    765         // Look for the alternative callback style. Ignore the previous default.
    766         if ( $args['topic_count_text_callback'] === 'default_topic_count_text' ) {
    767             $translate_nooped_plural = _n_noop( '%s topic', '%s topics' );
    768         } else {
    769             $translate_nooped_plural = false;
    770         }
    771     } elseif ( isset( $args['single_text'] ) && isset( $args['multiple_text'] ) ) {
    772         // If no callback exists, look for the old-style single_text and multiple_text arguments.
    773         $translate_nooped_plural = _n_noop( $args['single_text'], $args['multiple_text'] );
    774     } else {
    775         // This is the default for when no callback, plural, or argument is passed in.
    776         $translate_nooped_plural = _n_noop( '%s topic', '%s topics' );
    777     }
    778 
    779     /**
    780      * Filter how the items in a tag cloud are sorted.
    781      *
    782      * @since 2.8.0
    783      *
    784      * @param array $tags Ordered array of terms.
    785      * @param array $args An array of tag cloud arguments.
    786      */
    787     $tags_sorted = apply_filters( 'tag_cloud_sort', $tags, $args );
    788     if ( empty( $tags_sorted ) ) {
    789         return $return;
    790     }
    791 
    792     if ( $tags_sorted !== $tags ) {
    793         $tags = $tags_sorted;
    794         unset( $tags_sorted );
    795     } else {
    796         if ( 'RAND' === $args['order'] ) {
    797             shuffle( $tags );
    798         } else {
    799             // SQL cannot save you; this is a second (potentially different) sort on a subset of data.
    800             if ( 'name' === $args['orderby'] ) {
    801                 uasort( $tags, '_wp_object_name_sort_cb' );
    802             } else {
    803                 uasort( $tags, '_wp_object_count_sort_cb' );
    804             }
    805 
    806             if ( 'DESC' === $args['order'] ) {
    807                 $tags = array_reverse( $tags, true );
    808             }
    809         }
    810     }
    811 
    812     if ( $args['number'] > 0 )
    813         $tags = array_slice( $tags, 0, $args['number'] );
    814 
    815     $counts = array();
    816     $real_counts = array(); // For the alt tag
    817     foreach ( (array) $tags as $key => $tag ) {
    818         $real_counts[ $key ] = $tag->count;
    819         $counts[ $key ] = call_user_func( $args['topic_count_scale_callback'], $tag->count );
    820     }
    821 
    822     $min_count = min( $counts );
    823     $spread = max( $counts ) - $min_count;
    824     if ( $spread <= 0 )
    825         $spread = 1;
    826     $font_spread = $args['largest'] - $args['smallest'];
    827     if ( $font_spread < 0 )
    828         $font_spread = 1;
    829     $font_step = $font_spread / $spread;
    830 
    831     // Assemble the data that will be used to generate the tag cloud markup.
    832     $tags_data = array();
    833     foreach ( $tags as $key => $tag ) {
    834         $tag_id = isset( $tag->id ) ? $tag->id : $key;
    835 
    836         $count = $counts[ $key ];
    837         $real_count = $real_counts[ $key ];
    838 
    839         if ( $translate_nooped_plural ) {
    840             $title = sprintf( translate_nooped_plural( $translate_nooped_plural, $real_count ), number_format_i18n( $real_count ) );
    841         } else {
    842             $title = call_user_func( $args['topic_count_text_callback'], $real_count, $tag, $args );
    843         }
    844 
    845         $tags_data[] = array(
    846             'id'         => $tag_id,
    847             'url'        => '#' != $tag->link ? $tag->link : '#',
    848             'name'       => $tag->name,
    849             'title'      => $title,
    850             'slug'       => $tag->slug,
    851             'real_count' => $real_count,
    852             'class'      => 'tag-link-' . $tag_id,
    853             'font_size'  => $args['smallest'] + ( $count - $min_count ) * $font_step,
    854         );
    855     }
    856 
    857     /**
    858      * Filter the data used to generate the tag cloud.
    859      *
    860      * @since 4.3.0
    861      *
    862      * @param array $tags_data An array of term data for term used to generate the tag cloud.
    863      */
    864     $tags_data = apply_filters( 'wp_generate_tag_cloud_data', $tags_data );
    865 
    866     $a = array();
    867 
    868     // generate the output links array
    869     foreach ( $tags_data as $key => $tag_data ) {
    870         $a[] = "<a href='" . esc_url( $tag_data['url'] ) . "' class='" . esc_attr( $tag_data['class'] ) . "' title='" . esc_attr( $tag_data['title'] ) . "' style='font-size: " . esc_attr( str_replace( ',', '.', $tag_data['font_size'] ) . $args['unit'] ) . ";'>" . esc_html( $tag_data['name'] ) . "</a>";
    871     }
    872 
    873     switch ( $args['format'] ) {
    874         case 'array' :
    875             $return =& $a;
    876             break;
    877         case 'list' :
    878             $return = "<ul class='wp-tag-cloud'>\n\t<li>";
    879             $return .= join( "</li>\n\t<li>", $a );
    880             $return .= "</li>\n</ul>\n";
    881             break;
    882         default :
    883             $return = join( $args['separator'], $a );
    884             break;
    885     }
    886 
    887     if ( $args['filter'] ) {
    888         /**
    889          * Filter the generated output of a tag cloud.
    890          *
    891          * The filter is only evaluated if a true value is passed
    892          * to the $filter argument in wp_generate_tag_cloud().
    893          *
    894          * @since 2.3.0
    895          *
    896          * @see wp_generate_tag_cloud()
    897          *
    898          * @param array|string $return String containing the generated HTML tag cloud output
    899          *                             or an array of tag links if the 'format' argument
    900          *                             equals 'array'.
    901          * @param array        $tags   An array of terms used in the tag cloud.
    902          * @param array        $args   An array of wp_generate_tag_cloud() arguments.
    903          */
    904         return apply_filters( 'wp_generate_tag_cloud', $return, $tags, $args );
    905     }
    906 
    907     else
    908         return $return;
    909 }
    910 
    911 /**
    912  * Callback for comparing objects based on name
    913  *
    914  * @since 3.1.0
    915  * @access private
    916  * @return int
    917  */
    918 function _wp_object_name_sort_cb( $a, $b ) {
    919     return strnatcasecmp( $a->name, $b->name );
    920 }
    921 
    922 /**
    923  * Callback for comparing objects based on count
    924  *
    925  * @since 3.1.0
    926  * @access private
    927  * @return bool
    928  */
    929 function _wp_object_count_sort_cb( $a, $b ) {
    930     return ( $a->count > $b->count );
    931 }
    932 
    933 //
    934 // Helper functions
    935 //
    936 
    937 /**
    938  * Retrieve HTML list content for category list.
    939  *
    940  * @uses Walker_Category to create HTML list content.
    941  * @since 2.1.0
    942  * @see Walker_Category::walk() for parameters and return description.
    943  * @return string
    944  */
    945 function walk_category_tree() {
    946     $args = func_get_args();
    947     // the user's options are the third parameter
    948     if ( empty( $args[2]['walker'] ) || ! ( $args[2]['walker'] instanceof Walker ) ) {
    949         $walker = new Walker_Category;
    950     } else {
    951         $walker = $args[2]['walker'];
    952     }
    953     return call_user_func_array( array( $walker, 'walk' ), $args );
    954 }
    955 
    956 /**
    957  * Retrieve HTML dropdown (select) content for category list.
    958  *
    959  * @uses Walker_CategoryDropdown to create HTML dropdown content.
    960  * @since 2.1.0
    961  * @see Walker_CategoryDropdown::walk() for parameters and return description.
    962  * @return string
    963  */
    964 function walk_category_dropdown_tree() {
    965     $args = func_get_args();
    966     // the user's options are the third parameter
    967     if ( empty( $args[2]['walker'] ) || ! ( $args[2]['walker'] instanceof Walker ) ) {
    968         $walker = new Walker_CategoryDropdown;
    969     } else {
    970         $walker = $args[2]['walker'];
    971     }
    972     return call_user_func_array( array( $walker, 'walk' ), $args );
    973 }
    9748
    9759/**
     
    1180214
    1181215}
    1182 
    1183 /**
    1184  * Create HTML dropdown list of Categories.
    1185  *
    1186  * @package WordPress
    1187  * @since 2.1.0
    1188  * @uses Walker
    1189  */
    1190 class Walker_CategoryDropdown extends Walker {
    1191     /**
    1192      * @see Walker::$tree_type
    1193      * @since 2.1.0
    1194      * @var string
    1195      */
    1196     public $tree_type = 'category';
    1197 
    1198     /**
    1199      * @see Walker::$db_fields
    1200      * @since 2.1.0
    1201      * @todo Decouple this
    1202      * @var array
    1203      */
    1204     public $db_fields = array ('parent' => 'parent', 'id' => 'term_id');
    1205 
    1206     /**
    1207      * Start the element output.
    1208      *
    1209      * @see Walker::start_el()
    1210      * @since 2.1.0
    1211      *
    1212      * @param string $output   Passed by reference. Used to append additional content.
    1213      * @param object $category Category data object.
    1214      * @param int    $depth    Depth of category. Used for padding.
    1215      * @param array  $args     Uses 'selected', 'show_count', and 'value_field' keys, if they exist.
    1216      *                         See {@see wp_dropdown_categories()}.
    1217      */
    1218     public function start_el( &$output, $category, $depth = 0, $args = array(), $id = 0 ) {
    1219         $pad = str_repeat('&nbsp;', $depth * 3);
    1220 
    1221         /** This filter is documented in wp-includes/category-template.php */
    1222         $cat_name = apply_filters( 'list_cats', $category->name, $category );
    1223 
    1224         if ( isset( $args['value_field'] ) && isset( $category->{$args['value_field']} ) ) {
    1225             $value_field = $args['value_field'];
    1226         } else {
    1227             $value_field = 'term_id';
    1228         }
    1229 
    1230         $output .= "\t<option class=\"level-$depth\" value=\"" . esc_attr( $category->{$value_field} ) . "\"";
    1231 
    1232         // Type-juggling causes false matches, so we force everything to a string.
    1233         if ( (string) $category->{$value_field} === (string) $args['selected'] )
    1234             $output .= ' selected="selected"';
    1235         $output .= '>';
    1236         $output .= $pad.$cat_name;
    1237         if ( $args['show_count'] )
    1238             $output .= '&nbsp;&nbsp;('. number_format_i18n( $category->count ) .')';
    1239         $output .= "</option>\n";
    1240     }
    1241 }
    1242 
    1243 //
    1244 // Tags
    1245 //
    1246 
    1247 /**
    1248  * Retrieve the link to the tag.
    1249  *
    1250  * @since 2.3.0
    1251  * @see get_term_link()
    1252  *
    1253  * @param int|object $tag Tag ID or object.
    1254  * @return string Link on success, empty string if tag does not exist.
    1255  */
    1256 function get_tag_link( $tag ) {
    1257     if ( ! is_object( $tag ) )
    1258         $tag = (int) $tag;
    1259 
    1260     $tag = get_term_link( $tag, 'post_tag' );
    1261 
    1262     if ( is_wp_error( $tag ) )
    1263         return '';
    1264 
    1265     return $tag;
    1266 }
    1267 
    1268 /**
    1269  * Retrieve the tags for a post.
    1270  *
    1271  * @since 2.3.0
    1272  *
    1273  * @param int $id Post ID.
    1274  * @return array|false|WP_Error Array of tag objects on success, false on failure.
    1275  */
    1276 function get_the_tags( $id = 0 ) {
    1277 
    1278     /**
    1279      * Filter the array of tags for the given post.
    1280      *
    1281      * @since 2.3.0
    1282      *
    1283      * @see get_the_terms()
    1284      *
    1285      * @param array $terms An array of tags for the given post.
    1286      */
    1287     return apply_filters( 'get_the_tags', get_the_terms( $id, 'post_tag' ) );
    1288 }
    1289 
    1290 /**
    1291  * Retrieve the tags for a post formatted as a string.
    1292  *
    1293  * @since 2.3.0
    1294  *
    1295  * @param string $before Optional. Before tags.
    1296  * @param string $sep Optional. Between tags.
    1297  * @param string $after Optional. After tags.
    1298  * @param int $id Optional. Post ID. Defaults to the current post.
    1299  * @return string|false|WP_Error A list of tags on success, false if there are no terms, WP_Error on failure.
    1300  */
    1301 function get_the_tag_list( $before = '', $sep = '', $after = '', $id = 0 ) {
    1302 
    1303     /**
    1304      * Filter the tags list for a given post.
    1305      *
    1306      * @since 2.3.0
    1307      *
    1308      * @param string $tag_list List of tags.
    1309      * @param string $before   String to use before tags.
    1310      * @param string $sep      String to use between the tags.
    1311      * @param string $after    String to use after tags.
    1312      * @param int    $id       Post ID.
    1313      */
    1314     return apply_filters( 'the_tags', get_the_term_list( $id, 'post_tag', $before, $sep, $after ), $before, $sep, $after, $id );
    1315 }
    1316 
    1317 /**
    1318  * Retrieve the tags for a post.
    1319  *
    1320  * @since 2.3.0
    1321  *
    1322  * @param string $before Optional. Before list.
    1323  * @param string $sep Optional. Separate items using this.
    1324  * @param string $after Optional. After list.
    1325  */
    1326 function the_tags( $before = null, $sep = ', ', $after = '' ) {
    1327     if ( null === $before )
    1328         $before = __('Tags: ');
    1329     echo get_the_tag_list($before, $sep, $after);
    1330 }
    1331 
    1332 /**
    1333  * Retrieve tag description.
    1334  *
    1335  * @since 2.8.0
    1336  *
    1337  * @param int $tag Optional. Tag ID. Will use global tag ID by default.
    1338  * @return string Tag description, available.
    1339  */
    1340 function tag_description( $tag = 0 ) {
    1341     return term_description( $tag );
    1342 }
    1343 
    1344 /**
    1345  * Retrieve term description.
    1346  *
    1347  * @since 2.8.0
    1348  *
    1349  * @param int $term Optional. Term ID. Will use global term ID by default.
    1350  * @param string $taxonomy Optional taxonomy name. Defaults to 'post_tag'.
    1351  * @return string Term description, available.
    1352  */
    1353 function term_description( $term = 0, $taxonomy = 'post_tag' ) {
    1354     if ( ! $term && ( is_tax() || is_tag() || is_category() ) ) {
    1355         $term = get_queried_object();
    1356         if ( $term ) {
    1357             $taxonomy = $term->taxonomy;
    1358             $term = $term->term_id;
    1359         }
    1360     }
    1361     $description = get_term_field( 'description', $term, $taxonomy );
    1362     return is_wp_error( $description ) ? '' : $description;
    1363 }
    1364 
    1365 /**
    1366  * Retrieve the terms of the taxonomy that are attached to the post.
    1367  *
    1368  * @since 2.5.0
    1369  *
    1370  * @param int|object $post Post ID or object.
    1371  * @param string $taxonomy Taxonomy name.
    1372  * @return array|false|WP_Error Array of term objects on success, false if there are no terms
    1373  *                              or the post does not exist, WP_Error on failure.
    1374  */
    1375 function get_the_terms( $post, $taxonomy ) {
    1376     if ( ! $post = get_post( $post ) )
    1377         return false;
    1378 
    1379     $terms = get_object_term_cache( $post->ID, $taxonomy );
    1380     if ( false === $terms ) {
    1381         $terms = wp_get_object_terms( $post->ID, $taxonomy );
    1382         wp_cache_add($post->ID, $terms, $taxonomy . '_relationships');
    1383     }
    1384 
    1385     /**
    1386      * Filter the list of terms attached to the given post.
    1387      *
    1388      * @since 3.1.0
    1389      *
    1390      * @param array|WP_Error $terms    List of attached terms, or WP_Error on failure.
    1391      * @param int            $post_id  Post ID.
    1392      * @param string         $taxonomy Name of the taxonomy.
    1393      */
    1394     $terms = apply_filters( 'get_the_terms', $terms, $post->ID, $taxonomy );
    1395 
    1396     if ( empty( $terms ) )
    1397         return false;
    1398 
    1399     return $terms;
    1400 }
    1401 
    1402 /**
    1403  * Retrieve a post's terms as a list with specified format.
    1404  *
    1405  * @since 2.5.0
    1406  *
    1407  * @param int $id Post ID.
    1408  * @param string $taxonomy Taxonomy name.
    1409  * @param string $before Optional. Before list.
    1410  * @param string $sep Optional. Separate items using this.
    1411  * @param string $after Optional. After list.
    1412  * @return string|false|WP_Error A list of terms on success, false if there are no terms, WP_Error on failure.
    1413  */
    1414 function get_the_term_list( $id, $taxonomy, $before = '', $sep = '', $after = '' ) {
    1415     $terms = get_the_terms( $id, $taxonomy );
    1416 
    1417     if ( is_wp_error( $terms ) )
    1418         return $terms;
    1419 
    1420     if ( empty( $terms ) )
    1421         return false;
    1422 
    1423     $links = array();
    1424 
    1425     foreach ( $terms as $term ) {
    1426         $link = get_term_link( $term, $taxonomy );
    1427         if ( is_wp_error( $link ) ) {
    1428             return $link;
    1429         }
    1430         $links[] = '<a href="' . esc_url( $link ) . '" rel="tag">' . $term->name . '</a>';
    1431     }
    1432 
    1433     /**
    1434      * Filter the term links for a given taxonomy.
    1435      *
    1436      * The dynamic portion of the filter name, `$taxonomy`, refers
    1437      * to the taxonomy slug.
    1438      *
    1439      * @since 2.5.0
    1440      *
    1441      * @param array $links An array of term links.
    1442      */
    1443     $term_links = apply_filters( "term_links-$taxonomy", $links );
    1444 
    1445     return $before . join( $sep, $term_links ) . $after;
    1446 }
    1447 
    1448 /**
    1449  * Display the terms in a list.
    1450  *
    1451  * @since 2.5.0
    1452  *
    1453  * @param int $id Post ID.
    1454  * @param string $taxonomy Taxonomy name.
    1455  * @param string $before Optional. Before list.
    1456  * @param string $sep Optional. Separate items using this.
    1457  * @param string $after Optional. After list.
    1458  * @return false|void False on WordPress error.
    1459  */
    1460 function the_terms( $id, $taxonomy, $before = '', $sep = ', ', $after = '' ) {
    1461     $term_list = get_the_term_list( $id, $taxonomy, $before, $sep, $after );
    1462 
    1463     if ( is_wp_error( $term_list ) )
    1464         return false;
    1465 
    1466     /**
    1467      * Filter the list of terms to display.
    1468      *
    1469      * @since 2.9.0
    1470      *
    1471      * @param array  $term_list List of terms to display.
    1472      * @param string $taxonomy  The taxonomy name.
    1473      * @param string $before    String to use before the terms.
    1474      * @param string $sep       String to use between the terms.
    1475      * @param string $after     String to use after the terms.
    1476      */
    1477     echo apply_filters( 'the_terms', $term_list, $taxonomy, $before, $sep, $after );
    1478 }
    1479 
    1480 /**
    1481  * Check if the current post has any of given category.
    1482  *
    1483  * @since 3.1.0
    1484  *
    1485  * @param string|int|array $category Optional. The category name/term_id/slug or array of them to check for.
    1486  * @param int|object $post Optional. Post to check instead of the current post.
    1487  * @return bool True if the current post has any of the given categories (or any category, if no category specified).
    1488  */
    1489 function has_category( $category = '', $post = null ) {
    1490     return has_term( $category, 'category', $post );
    1491 }
    1492 
    1493 /**
    1494  * Check if the current post has any of given tags.
    1495  *
    1496  * The given tags are checked against the post's tags' term_ids, names and slugs.
    1497  * Tags given as integers will only be checked against the post's tags' term_ids.
    1498  * If no tags are given, determines if post has any tags.
    1499  *
    1500  * 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)
    1501  * Prior to v2.7, this function could only be used in the WordPress Loop.
    1502  * As of 2.7, the function can be used anywhere if it is provided a post ID or post object.
    1503  *
    1504  * @since 2.6.0
    1505  *
    1506  * @param string|int|array $tag Optional. The tag name/term_id/slug or array of them to check for.
    1507  * @param int|object $post Optional. Post to check instead of the current post. (since 2.7.0)
    1508  * @return bool True if the current post has any of the given tags (or any tag, if no tag specified).
    1509  */
    1510 function has_tag( $tag = '', $post = null ) {
    1511     return has_term( $tag, 'post_tag', $post );
    1512 }
    1513 
    1514 /**
    1515  * Check if the current post has any of given terms.
    1516  *
    1517  * The given terms are checked against the post's terms' term_ids, names and slugs.
    1518  * Terms given as integers will only be checked against the post's terms' term_ids.
    1519  * If no terms are given, determines if post has any terms.
    1520  *
    1521  * @since 3.1.0
    1522  *
    1523  * @param string|int|array $term Optional. The term name/term_id/slug or array of them to check for.
    1524  * @param string $taxonomy Taxonomy name
    1525  * @param int|object $post Optional. Post to check instead of the current post.
    1526  * @return bool True if the current post has any of the given tags (or any tag, if no tag specified).
    1527  */
    1528 function has_term( $term = '', $taxonomy = '', $post = null ) {
    1529     $post = get_post($post);
    1530 
    1531     if ( !$post )
    1532         return false;
    1533 
    1534     $r = is_object_in_term( $post->ID, $taxonomy, $term );
    1535     if ( is_wp_error( $r ) )
    1536         return false;
    1537 
    1538     return $r;
    1539 }
Note: See TracChangeset for help on using the changeset viewer.