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'] . '';
+
+ if ( empty($categories) ) {
+ if ( $list)
+ $output .= '- ' . __("No categories") . '
';
+ 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);
+ }
+
+ if ( $title_li && $list )
+ $output .= '
';
+
+ 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_level_end($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;
}