diff --git a/wp-includes/functions.php b/wp-includes/functions.php index 5b838b55b5..14ded2e685 100644 --- a/wp-includes/functions.php +++ b/wp-includes/functions.php @@ -726,32 +726,62 @@ function &get_page(&$page, $output = OBJECT) { } } -function walk_page_tree($pages, $to_depth, $start_element_callback, $end_element_callback = '', $start_level_callback = '', $end_level_callback = '') { - $args = array_slice(func_get_args(), 6); +function walk_tree($tree_type, $elements, $to_depth, $start_element_callback, $end_element_callback = '', $start_level_callback = '', $end_level_callback = '') { + $args = array_slice(func_get_args(), 7); $parents = array(); $depth = 0; - $previous_page = ''; + $previous_element = ''; $output = ''; - $last_page->post_parent = 0; - $last_page->post_id = 0; - $pages[] = $last_page; + $last_element->post_parent = 0; + $last_element->post_id = 0; + $elements[] = $last_element; - foreach ( $pages as $page ) { - if ( !empty($previous_page) && ($page->post_parent == $previous_page->ID) ) { - // Previous page is my parent. Descend a level. - array_unshift($parents, $previous_page); + if ( 'page' == $tree_type ) { + $parent_field = 'post_parent'; + $id_field = 'ID'; + } else { + $parent_field = 'category_parent'; + $id_field = 'cat_ID'; + } + + $flat = false; + if ( $to_depth == -1 ) + $flat = true; + + foreach ( $elements as $element ) { + // If flat, start and end the element and skip the level checks. + if ( $flat) { + // Start the element. + if ( !empty($start_element_callback) && ($element->$id_field != 0) ) { + $cb_args = array_merge( array($output, $element, $depth), $args); + $output = call_user_func_array($start_element_callback, $cb_args); + } + + // End the element. + if ( !empty($end_element_callback) && ($element->$id_field != 0) ) { + $cb_args = array_merge( array($output, $element, $depth), $args); + $output = call_user_func_array($end_element_callback, $cb_args); + } + + continue; + } + + // Walk the tree. + if ( !empty($previous_element) && ($element->$parent_field == $previous_element->$id_field) ) { + // Previous element is my parent. Descend a level. + array_unshift($parents, $previous_element); $depth++; if ( !$to_depth || ($depth < $to_depth) ) if ( !empty($start_level_callback) ) { $cb_args = array_merge( array($output, $depth), $args); $output = call_user_func_array($start_level_callback, $cb_args); } - } else if ( $depth && ($page->post_parent == $previous_page->post_parent) ) { - // On the same level as previous page. + } else if ( $depth && ($element->$parent_field == $previous_element->$parent_field) ) { + // On the same level as previous element. if ( !$to_depth || ($depth < $to_depth) ) { if ( !empty($end_element_callback) ) { - $cb_args = array_merge( array($output, $previous_page, $depth), $args); + $cb_args = array_merge( array($output, $previous_element, $depth), $args); $output = call_user_func_array($end_element_callback, $cb_args); } } @@ -759,7 +789,7 @@ function walk_page_tree($pages, $to_depth, $start_element_callback, $end_element // Ascend one or more levels. if ( !$to_depth || ($depth < $to_depth) ) { if ( !empty($end_element_callback) ) { - $cb_args = array_merge( array($output, $previous_page, $depth), $args); + $cb_args = array_merge( array($output, $previous_element, $depth), $args); $output = call_user_func_array($end_element_callback, $cb_args); } } @@ -776,34 +806,47 @@ function walk_page_tree($pages, $to_depth, $start_element_callback, $end_element $output = call_user_func_array($end_element_callback, $cb_args); } } - if ( $page->post_parent == $parents[0]->ID ) { + if ( $element->$parent_field == $parents[0]->$id_field ) { break; } } - } else if ( !empty($previous_page) ) { - // Close off previous page. + } else if ( !empty($previous_element) ) { + // Close off previous element. if ( !$to_depth || ($depth < $to_depth) ) { if ( !empty($end_element_callback) ) { - $cb_args = array_merge( array($output, $previous_page, $depth), $args); + $cb_args = array_merge( array($output, $previous_element, $depth), $args); $output = call_user_func_array($end_element_callback, $cb_args); } } } - // Start the page. + // Start the element. if ( !$to_depth || ($depth < $to_depth) ) { - if ( !empty($start_element_callback) && ($page->ID != 0) ) { - $cb_args = array_merge( array($output, $page, $depth), $args); + if ( !empty($start_element_callback) && ($element->$id_field != 0) ) { + $cb_args = array_merge( array($output, $element, $depth), $args); $output = call_user_func_array($start_element_callback, $cb_args); } } - $previous_page = $page; + $previous_element = $element; } return $output; } +function walk_page_tree($pages, $to_depth, $start_element_callback, $end_element_callback = '', $start_level_callback = '', $end_level_callback = '') { + $args = array('page', $pages, $to_depth, $start_element_callback, $end_element_callback, $start_level_callback, $end_level_callback); + $extra_args = array_slice(func_get_args(), 6); + + return call_user_func_array('walk_tree', array_merge($args, $extra_args)); +} + +function walk_category_tree($pages, $to_depth, $start_element_callback, $end_element_callback = '', $start_level_callback = '', $end_level_callback = '') { + $args = array('category', $pages, $to_depth, $start_element_callback, $end_element_callback, $start_level_callback, $end_level_callback); + $extra_args = array_slice(func_get_args(), 6); + return call_user_func_array('walk_tree', array_merge($args, $extra_args)); +} + function get_category_by_path($category_path, $full_match = true, $output = OBJECT) { global $wpdb; $category_path = rawurlencode(urldecode($category_path)); diff --git a/wp-includes/template-functions-category.php b/wp-includes/template-functions-category.php index b02a0cb50c..b943361f67 100644 --- a/wp-includes/template-functions-category.php +++ b/wp-includes/template-functions-category.php @@ -252,14 +252,8 @@ function wp_list_cats($args = '') { $r['hide_empty'] = 1; if ( !isset($r['use_desc_for_title']) ) $r['use_desc_for_title'] = 1; - if ( !isset($r['children']) ) - $r['children'] = true; if ( !isset($r['child_of']) ) $r['child_of'] = 0; - if ( !isset($r['categories']) ) - $r['categories'] = 0; - if ( !isset($r['recurse']) ) - $r['recurse'] = 0; if ( !isset($r['feed']) ) $r['feed'] = ''; if ( !isset($r['feed_image']) ) @@ -267,138 +261,132 @@ function wp_list_cats($args = '') { if ( !isset($r['exclude']) ) $r['exclude'] = ''; if ( !isset($r['hierarchical']) ) - $r['hierarchical'] = true; + $r['hierarchical'] = false; + if ( !isset($r['title_li']) ) + $r['title_li'] = ''; - return list_cats($r['optionall'], $r['all'], $r['sort_column'], $r['sort_order'], $r['file'], $r['list'], $r['optiondates'], $r['optioncount'], $r['hide_empty'], $r['use_desc_for_title'], $r['children'], $r['child_of'], $r['categories'], $r['recurse'], $r['feed'], $r['feed_image'], $r['exclude'], $r['hierarchical']); + $q['orderby'] = $r['sort_column']; + $q['order'] = $r['sort_order']; + $q['include_last_update_time'] = $r['optiondates']; + + extract($r); + + $args = add_query_arg($q, $args); + $categories = get_categories($args); + + $output = ''; + if ( $title_li && $list ) + $output = '
  • ' . $r['title_li'] . '
  • '; + + echo apply_filters('list_cats', $output); +} + +function _category_list_level_start($output, $depth, $cat, $args) { + if (! $args['list']) + return $output; + + $indent = str_repeat("\t", $depth); + $output .= "$indent\n"; + return $output; +} + +function _category_list_element_start($output, $category, $depth, $current_category, $args) { + extract($args); + + $link = 'category_description) ) + $link .= 'title="'. sprintf(__("View all posts filed under %s"), wp_specialchars($category->cat_name)) . '"'; + else + $link .= 'title="' . wp_specialchars(apply_filters('category_description',$category->category_description,$category)) . '"'; + $link .= '>'; + $link .= apply_filters('list_cats', $category->cat_name, $category).''; + + if ( (! empty($feed_image)) || (! empty($feed)) ) { + $link .= ' '; + + if ( empty($feed_image) ) + $link .= '('; + + $link .= ''; + else + $link .= $name; + $link .= ''; + if (empty($feed_image)) + $link .= ')'; + } + + if ( intval($optioncount) == 1 ) + $link .= ' ('.intval($category->category_count).')'; + + if ( $optiondates ) { + if ( $optiondates == 1 ) + $optiondates = 'Y-m-d'; + $link .= ' ' . gmdate($optiondates,$category->last_update_timestamp); + } + + if ( $list ) { + $output .= "\tcat_ID == $current_category) && is_category() ) + $output .= ' class="current-cat"'; + $output .= ">$link\n"; + } else { + $output .= "\t$link
    \n"; + } + + return $output; +} + +function _category_list_element_end($output, $category, $depth, $cat, $args) { + if (! $args['list']) + return $output; + + $output .= "\n"; + return $output; } function list_cats($optionall = 1, $all = 'All', $sort_column = 'ID', $sort_order = 'asc', $file = '', $list = true, $optiondates = 0, $optioncount = 0, $hide_empty = 1, $use_desc_for_title = 1, $children=FALSE, $child_of=0, $categories=0, $recurse=0, $feed = '', $feed_image = '', $exclude = '', $hierarchical=FALSE) { - global $wpdb, $wp_query; - // Optiondates now works - if ( '' == $file ) - $file = get_settings('home') . '/'; - - $exclusions = ''; - if ( !empty($exclude) ) { - $excats = preg_split('/[\s,]+/',$exclude); - if ( count($excats) ) { - foreach ( $excats as $excat ) { - $exclusions .= ' AND cat_ID <> ' . intval($excat) . ' '; - } - } - } - - $exclusions = apply_filters('list_cats_exclusions', $exclusions ); - - if ( intval($categories) == 0 ) { - $sort_column = 'cat_'.$sort_column; - - $query = " - SELECT cat_ID, cat_name, category_nicename, category_description, category_parent, category_count - FROM $wpdb->categories - WHERE cat_ID > 0 $exclusions - ORDER BY $sort_column $sort_order"; - - $categories = $wpdb->get_results($query); - } - - if ( $optiondates ) { - $cat_dates = $wpdb->get_results(" SELECT category_id, - UNIX_TIMESTAMP( MAX(post_date) ) AS ts - FROM $wpdb->posts, $wpdb->post2cat, $wpdb->categories - WHERE post_type = 'post' AND post_status = 'publish' AND post_id = ID $exclusions - GROUP BY category_id"); - foreach ( $cat_dates as $cat_date ) { - $category_timestamp["$cat_date->category_id"] = $cat_date->ts; - } - } - - $num_found=0; - $thelist = ""; - - foreach ( $categories as $category ) { - if ( ( intval($hide_empty) == 0 || $category->category_count) && (!$hierarchical || $category->category_parent == $child_of) ) { - $num_found++; - $link = 'category_description) ) - $link .= 'title="'. sprintf(__("View all posts filed under %s"), wp_specialchars($category->cat_name)) . '"'; - else - $link .= 'title="' . wp_specialchars(apply_filters('category_description',$category->category_description,$category)) . '"'; - $link .= '>'; - $link .= apply_filters('list_cats', $category->cat_name, $category).''; - - if ( (! empty($feed_image)) || (! empty($feed)) ) { - - $link .= ' '; - - if ( empty($feed_image) ) - $link .= '('; - - $link .= ''; - else - $link .= $name; - - $link .= ''; - - if (empty($feed_image)) - $link .= ')'; - } - - if ( intval($optioncount) == 1 ) - $link .= ' ('.intval($category->category_count).')'; - - if ( $optiondates ) { - if ( $optiondates == 1 ) - $optiondates = 'Y-m-d'; - $link .= ' ' . gmdate($optiondates, $category_timestamp["$category->cat_ID"]); - } - - if ( $list ) { - $thelist .= "\tcat_ID == $wp_query->get_queried_object_id()) && is_category()) { - $thelist .= ' class="current-cat"'; - } - $thelist .= ">$link\n"; - } else { - $thelist .= "\t$link
    \n"; - } - - if ($hierarchical && $children) - $thelist .= list_cats($optionall, $all, $sort_column, $sort_order, $file, $list, $optiondates, $optioncount, $hide_empty, $use_desc_for_title, $hierarchical, $category->cat_ID, $categories, 1, $feed, $feed_image, $exclude, $hierarchical); - if ($list) - $thelist .= "\n"; - } - } - if ( !$num_found && !$child_of ) { - if ( $list ) { - $before = '
  • '; - $after = '
  • '; - } - echo $before . __("No categories") . $after . "\n"; - return; - } - if ( $list && $child_of && $num_found && $recurse ) { - $pre = "\t\t\n"; - } else { - $pre = $post = ''; - } - $thelist = $pre . $thelist . $post; - if ( $recurse ) - return $thelist; - echo apply_filters('list_cats', $thelist); + $query = "optionall=$optionall&all=$all&sort_column=$sort_column&sort_order=$sort_order&list=$list&optiondates=$optiondates&optioncount=$optioncount&hide_empty=$hide_empty&use_desc_for_title=$use_desc_for_title&child_of=$child_of&feed=$feed&feed_image=$feed_image&exclude=$exclude&hierarchical=$hierarchical"; + return wp_list_cats($query); } function in_category($category) { // Check if the current post is in the given category @@ -410,6 +398,22 @@ function in_category($category) { // Check if the current post is in the given c return false; } +function &_get_cat_children($category_id, $categories) { + if ( empty($categories) ) + return array(); + + $category_list = array(); + foreach ( $categories as $category ) { + if ( $category->category_parent == $category_id ) { + $category_list[] = $category; + if ( $children = _get_cat_children($category->cat_ID, $categories) ) + $category_list = array_merge($category_list, $children); + } + } + + return $category_list; +} + function &get_categories($args = '') { global $wpdb, $category_links; @@ -425,43 +429,60 @@ function &get_categories($args = '') { $r['order'] = 'ASC'; if ( !isset($r['hide_empty']) ) $r['hide_empty'] = true; + if ( !isset($r['include_last_update_time']) ) + $r['include_last_update_time'] = false; + if ( !isset($r['hierarchical']) ) + $r['hierarchical'] = 1; $r['orderby'] = "cat_" . $r['orderby']; + extract($r); + $exclusions = ''; - if ( !empty($r['exclude']) ) { - $excategories = preg_split('/[\s,]+/',$r['exclude']); + $having = ''; + $where = 'cat_ID > 0'; + + $exclusions = ''; + if ( !empty($exclude) ) { + $excategories = preg_split('/[\s,]+/',$exclude); if ( count($excategories) ) { foreach ( $excategories as $excat ) { $exclusions .= ' AND cat_ID <> ' . intval($excat) . ' '; } } } + $exclusions = apply_filters('list_cats_exclusions', $exclusions ); + $where .= $exclusions; - $categories = $wpdb->get_results("SELECT * " . - "FROM $wpdb->categories " . - "$exclusions " . - "ORDER BY " . $r['orderby'] . " " . $r['order']); + if ( $hide_empty ) { + if ( 'link' == $type ) + $having = 'HAVING link_count > 0'; + else + $having = 'HAVING category_count > 0'; + } + + $categories = $wpdb->get_results("SELECT * FROM $wpdb->categories WHERE $where $having ORDER BY $orderby $order"); if ( empty($categories) ) return array(); - if ( $r['hide_empty'] ) { - foreach ( $categories as $category ) { - $count = 0; - if ( 'link' == $r['type'] ) { - $count = $category->link_count; - } else { - $count = $category->category_count; - } - if ( $count ) - $the_categories[] = $category; + if ( $include_last_update_time ) { + $stamps = $wpdb->get_results("SELECT category_id, UNIX_TIMESTAMP( MAX(post_date) ) AS ts FROM $wpdb->posts, $wpdb->post2cat, $wpdb->categories + WHERE post_status = 'publish' AND post_id = ID AND $where GROUP BY category_id"); + global $cat_stamps; + foreach ($stamps as $stamp) + $cat_stamps[$stamp->category_id] = $stamp->ts; + function stamp_cat($cat) { + global $cat_stamps; + $cat->last_update_timestamp = $cat_stamps[$cat->cat_ID]; + return $cat; } - $categories = $the_categories; + $categories = array_map('stamp_cat', $categories); + unset($cat_stamps); } - /* if ( $r['child_of'] ) - $categories = & get_category_children($r['child_of'], $categories); */ + if ( $child_of || $hierarchical ) + $categories = & _get_cat_children($child_of, $categories); return $categories; }