wp_list_cats() rework. Add walk_tree() and walk_category_tree(). Use get_categories() for query.

git-svn-id: http://svn.automattic.com/wordpress/trunk@3582 1a063a9b-81f0-0310-95a4-ce76da25c4cd
This commit is contained in:
ryan 2006-03-01 13:30:19 +00:00
parent 6452ec1bbc
commit 459c030ef3
2 changed files with 239 additions and 175 deletions

View File

@ -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 = '') { 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(), 6); $args = array_slice(func_get_args(), 7);
$parents = array(); $parents = array();
$depth = 0; $depth = 0;
$previous_page = ''; $previous_element = '';
$output = ''; $output = '';
$last_page->post_parent = 0; $last_element->post_parent = 0;
$last_page->post_id = 0; $last_element->post_id = 0;
$pages[] = $last_page; $elements[] = $last_element;
foreach ( $pages as $page ) { if ( 'page' == $tree_type ) {
if ( !empty($previous_page) && ($page->post_parent == $previous_page->ID) ) { $parent_field = 'post_parent';
// Previous page is my parent. Descend a level. $id_field = 'ID';
array_unshift($parents, $previous_page); } 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++; $depth++;
if ( !$to_depth || ($depth < $to_depth) ) if ( !$to_depth || ($depth < $to_depth) )
if ( !empty($start_level_callback) ) { if ( !empty($start_level_callback) ) {
$cb_args = array_merge( array($output, $depth), $args); $cb_args = array_merge( array($output, $depth), $args);
$output = call_user_func_array($start_level_callback, $cb_args); $output = call_user_func_array($start_level_callback, $cb_args);
} }
} else if ( $depth && ($page->post_parent == $previous_page->post_parent) ) { } else if ( $depth && ($element->$parent_field == $previous_element->$parent_field) ) {
// On the same level as previous page. // On the same level as previous element.
if ( !$to_depth || ($depth < $to_depth) ) { if ( !$to_depth || ($depth < $to_depth) ) {
if ( !empty($end_element_callback) ) { 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); $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. // Ascend one or more levels.
if ( !$to_depth || ($depth < $to_depth) ) { if ( !$to_depth || ($depth < $to_depth) ) {
if ( !empty($end_element_callback) ) { 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); $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); $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; break;
} }
} }
} else if ( !empty($previous_page) ) { } else if ( !empty($previous_element) ) {
// Close off previous page. // Close off previous element.
if ( !$to_depth || ($depth < $to_depth) ) { if ( !$to_depth || ($depth < $to_depth) ) {
if ( !empty($end_element_callback) ) { 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); $output = call_user_func_array($end_element_callback, $cb_args);
} }
} }
} }
// Start the page. // Start the element.
if ( !$to_depth || ($depth < $to_depth) ) { if ( !$to_depth || ($depth < $to_depth) ) {
if ( !empty($start_element_callback) && ($page->ID != 0) ) { if ( !empty($start_element_callback) && ($element->$id_field != 0) ) {
$cb_args = array_merge( array($output, $page, $depth), $args); $cb_args = array_merge( array($output, $element, $depth), $args);
$output = call_user_func_array($start_element_callback, $cb_args); $output = call_user_func_array($start_element_callback, $cb_args);
} }
} }
$previous_page = $page; $previous_element = $element;
} }
return $output; 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) { function get_category_by_path($category_path, $full_match = true, $output = OBJECT) {
global $wpdb; global $wpdb;
$category_path = rawurlencode(urldecode($category_path)); $category_path = rawurlencode(urldecode($category_path));

View File

@ -252,14 +252,8 @@ function wp_list_cats($args = '') {
$r['hide_empty'] = 1; $r['hide_empty'] = 1;
if ( !isset($r['use_desc_for_title']) ) if ( !isset($r['use_desc_for_title']) )
$r['use_desc_for_title'] = 1; $r['use_desc_for_title'] = 1;
if ( !isset($r['children']) )
$r['children'] = true;
if ( !isset($r['child_of']) ) if ( !isset($r['child_of']) )
$r['child_of'] = 0; $r['child_of'] = 0;
if ( !isset($r['categories']) )
$r['categories'] = 0;
if ( !isset($r['recurse']) )
$r['recurse'] = 0;
if ( !isset($r['feed']) ) if ( !isset($r['feed']) )
$r['feed'] = ''; $r['feed'] = '';
if ( !isset($r['feed_image']) ) if ( !isset($r['feed_image']) )
@ -267,58 +261,66 @@ function wp_list_cats($args = '') {
if ( !isset($r['exclude']) ) if ( !isset($r['exclude']) )
$r['exclude'] = ''; $r['exclude'] = '';
if ( !isset($r['hierarchical']) ) 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 = '<li class="categories">' . $r['title_li'] . '<ul>';
if ( empty($categories) ) {
if ( $list)
$output .= '<li>' . __("No categories") . '</li>';
else
$output .= __("No categories");
} else {
global $wp_query;
$current_category = $wp_query->get_queried_object_id();
if ( $hierarchical )
$depth = 0; // Walk the full depth.
else
$depth = -1; // Flat.
$output .= walk_category_tree($categories, $depth, '_category_list_element_start', '_category_list_element_end', '_category_list_level_start', '_category_list_level_end', $current_category, $r);
} }
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) { if ( $title_li && $list )
global $wpdb, $wp_query; $output .= '</ul></li>';
// Optiondates now works
if ( '' == $file )
$file = get_settings('home') . '/';
$exclusions = ''; echo apply_filters('list_cats', $output);
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 ); function _category_list_level_start($output, $depth, $cat, $args) {
if (! $args['list'])
return $output;
if ( intval($categories) == 0 ) { $indent = str_repeat("\t", $depth);
$sort_column = 'cat_'.$sort_column; $output .= "$indent<ul class='children'>\n";
return $output;
$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 ) { function _category_list_level_end($output, $depth, $cat, $args) {
$cat_dates = $wpdb->get_results(" SELECT category_id, if (! $args['list'])
UNIX_TIMESTAMP( MAX(post_date) ) AS ts return $output;
FROM $wpdb->posts, $wpdb->post2cat, $wpdb->categories
WHERE post_type = 'post' AND post_status = 'publish' AND post_id = ID $exclusions $indent = str_repeat("\t", $depth);
GROUP BY category_id"); $output .= "$indent</ul>\n";
foreach ( $cat_dates as $cat_date ) { return $output;
$category_timestamp["$cat_date->category_id"] = $cat_date->ts;
}
} }
$num_found=0; function _category_list_element_start($output, $category, $depth, $current_category, $args) {
$thelist = ""; extract($args);
foreach ( $categories as $category ) {
if ( ( intval($hide_empty) == 0 || $category->category_count) && (!$hierarchical || $category->category_parent == $child_of) ) {
$num_found++;
$link = '<a href="' . get_category_link($category->cat_ID) . '" '; $link = '<a href="' . get_category_link($category->cat_ID) . '" ';
if ( $use_desc_for_title == 0 || empty($category->category_description) ) if ( $use_desc_for_title == 0 || empty($category->category_description) )
$link .= 'title="'. sprintf(__("View all posts filed under %s"), wp_specialchars($category->cat_name)) . '"'; $link .= 'title="'. sprintf(__("View all posts filed under %s"), wp_specialchars($category->cat_name)) . '"';
@ -328,7 +330,6 @@ function list_cats($optionall = 1, $all = 'All', $sort_column = 'ID', $sort_orde
$link .= apply_filters('list_cats', $category->cat_name, $category).'</a>'; $link .= apply_filters('list_cats', $category->cat_name, $category).'</a>';
if ( (! empty($feed_image)) || (! empty($feed)) ) { if ( (! empty($feed_image)) || (! empty($feed)) ) {
$link .= ' '; $link .= ' ';
if ( empty($feed_image) ) if ( empty($feed_image) )
@ -349,9 +350,7 @@ function list_cats($optionall = 1, $all = 'All', $sort_column = 'ID', $sort_orde
$link .= "<img src='$feed_image' $alt$title" . ' />'; $link .= "<img src='$feed_image' $alt$title" . ' />';
else else
$link .= $name; $link .= $name;
$link .= '</a>'; $link .= '</a>';
if (empty($feed_image)) if (empty($feed_image))
$link .= ')'; $link .= ')';
} }
@ -362,43 +361,32 @@ function list_cats($optionall = 1, $all = 'All', $sort_column = 'ID', $sort_orde
if ( $optiondates ) { if ( $optiondates ) {
if ( $optiondates == 1 ) if ( $optiondates == 1 )
$optiondates = 'Y-m-d'; $optiondates = 'Y-m-d';
$link .= ' ' . gmdate($optiondates, $category_timestamp["$category->cat_ID"]); $link .= ' ' . gmdate($optiondates,$category->last_update_timestamp);
} }
if ( $list ) { if ( $list ) {
$thelist .= "\t<li"; $output .= "\t<li";
if (($category->cat_ID == $wp_query->get_queried_object_id()) && is_category()) { if ( ($category->cat_ID == $current_category) && is_category() )
$thelist .= ' class="current-cat"'; $output .= ' class="current-cat"';
} $output .= ">$link\n";
$thelist .= ">$link\n";
} else { } else {
$thelist .= "\t$link<br />\n"; $output .= "\t$link<br />\n";
} }
if ($hierarchical && $children) return $output;
$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 .= "</li>\n";
} }
function _category_list_element_end($output, $category, $depth, $cat, $args) {
if (! $args['list'])
return $output;
$output .= "</li>\n";
return $output;
} }
if ( !$num_found && !$child_of ) {
if ( $list ) { 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) {
$before = '<li>'; $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";
$after = '</li>'; return wp_list_cats($query);
}
echo $before . __("No categories") . $after . "\n";
return;
}
if ( $list && $child_of && $num_found && $recurse ) {
$pre = "\t\t<ul class='children'>";
$post = "\t\t</ul>\n";
} else {
$pre = $post = '';
}
$thelist = $pre . $thelist . $post;
if ( $recurse )
return $thelist;
echo apply_filters('list_cats', $thelist);
} }
function in_category($category) { // Check if the current post is in the given category 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; 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 = '') { function &get_categories($args = '') {
global $wpdb, $category_links; global $wpdb, $category_links;
@ -425,43 +429,60 @@ function &get_categories($args = '') {
$r['order'] = 'ASC'; $r['order'] = 'ASC';
if ( !isset($r['hide_empty']) ) if ( !isset($r['hide_empty']) )
$r['hide_empty'] = true; $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']; $r['orderby'] = "cat_" . $r['orderby'];
extract($r);
$exclusions = ''; $exclusions = '';
if ( !empty($r['exclude']) ) { $having = '';
$excategories = preg_split('/[\s,]+/',$r['exclude']); $where = 'cat_ID > 0';
$exclusions = '';
if ( !empty($exclude) ) {
$excategories = preg_split('/[\s,]+/',$exclude);
if ( count($excategories) ) { if ( count($excategories) ) {
foreach ( $excategories as $excat ) { foreach ( $excategories as $excat ) {
$exclusions .= ' AND cat_ID <> ' . intval($excat) . ' '; $exclusions .= ' AND cat_ID <> ' . intval($excat) . ' ';
} }
} }
} }
$exclusions = apply_filters('list_cats_exclusions', $exclusions );
$where .= $exclusions;
$categories = $wpdb->get_results("SELECT * " . if ( $hide_empty ) {
"FROM $wpdb->categories " . if ( 'link' == $type )
"$exclusions " . $having = 'HAVING link_count > 0';
"ORDER BY " . $r['orderby'] . " " . $r['order']); else
$having = 'HAVING category_count > 0';
}
$categories = $wpdb->get_results("SELECT * FROM $wpdb->categories WHERE $where $having ORDER BY $orderby $order");
if ( empty($categories) ) if ( empty($categories) )
return array(); return array();
if ( $r['hide_empty'] ) { if ( $include_last_update_time ) {
foreach ( $categories as $category ) { $stamps = $wpdb->get_results("SELECT category_id, UNIX_TIMESTAMP( MAX(post_date) ) AS ts FROM $wpdb->posts, $wpdb->post2cat, $wpdb->categories
$count = 0; WHERE post_status = 'publish' AND post_id = ID AND $where GROUP BY category_id");
if ( 'link' == $r['type'] ) { global $cat_stamps;
$count = $category->link_count; foreach ($stamps as $stamp)
} else { $cat_stamps[$stamp->category_id] = $stamp->ts;
$count = $category->category_count; function stamp_cat($cat) {
global $cat_stamps;
$cat->last_update_timestamp = $cat_stamps[$cat->cat_ID];
return $cat;
} }
if ( $count ) $categories = array_map('stamp_cat', $categories);
$the_categories[] = $category; unset($cat_stamps);
}
$categories = $the_categories;
} }
/* if ( $r['child_of'] ) if ( $child_of || $hierarchical )
$categories = & get_category_children($r['child_of'], $categories); */ $categories = & _get_cat_children($child_of, $categories);
return $categories; return $categories;
} }