WordPress.org

Make WordPress Core

Opened 7 years ago

Closed 5 years ago

#3566 closed enhancement (invalid)

Request for new function get_page_parents

Reported by: snakefoot Owned by:
Milestone: Priority: normal
Severity: normal Version: 2.1
Component: Template Keywords: has-patch 2nd-opinion
Focuses: Cc:

Description

Like there is a get_category_parents, then it would be nice with a get_page_parents:

function get_page_parents($id, $link = FALSE, $separator = '/', $nicename = FALSE){
	$chain = '';
	$parent = &get_page($id);

	if ( $nicename )
		$name = $parent->post_title;
	else
		$name = $parent->post_name;	

	if ( $parent->post_parent )
		$chain .= get_page_parents($parent->post_parent, $link, $separator, $nicename);

	if ( $link )
		$chain .= '<a href="' . get_page_link($parent->ID) . '" title="' . $parent->post_title . '">'.$name.'</a>' . $separator;
	else
		$chain .= $name.$separator;
	return $chain;
}

Attachments (1)

post.php.diff (1.6 KB) - added by Huskey 5 years ago.

Download all attachments as: .zip

Change History (17)

comment:1 snakefoot7 years ago

  • Milestone changed from 2.2 to 2.1

comment:2 Viper007Bond7 years ago

  • Keywords has-patch added; get_category_parents get_page_parents wp_list_pages wp_list_cats removed
  • Version changed from 2.0 to 2.1

comment:3 ryan7 years ago

  • Milestone changed from 2.1 to 2.2

comment:4 foolswisdom7 years ago

  • Milestone changed from 2.2 to 2.3

comment:5 ryan7 years ago

  • Milestone changed from 2.3 to 2.4 (next)

comment:6 Huskey6 years ago

Your solution has a bug and returns the page title for $nicename = TRUE and vice-versa, which is wrong. Also, it lacks the check for a valid page object returned. Here's the updated code:

function get_page_parents($id, $link = FALSE, $separator = '/', $nicename = FALSE) {
	$chain = '';
	$parent = &get_page($id);
	if ( is_wp_error( $parent ) )
		return $parent;

	if ( $nicename )
		$name = $parent->post_name;
	else
		$name = $parent->post_title;

	if ( $parent->post_parent )
		$chain .= get_page_parents($parent->post_parent, $link, $separator, $nicename);

	if ( $link )
		$chain .= '<a href="' . get_page_link($parent->ID) . '" title="' . $parent->post_title . '">'.$name.'</a>' . $separator;
	else
		$chain .= $name.$separator;
	return $chain;
}

comment:7 Huskey6 years ago

  • Cc Huskey added

comment:8 santosj6 years ago

  • Component changed from General to Template

comment:9 westi6 years ago

  • Keywords needs-patch added; has-patch removed
  • Milestone changed from 2.5 to 2.6

Enhancement, no patch, feature freeze ==> 2.6

Huskey5 years ago

comment:10 Huskey5 years ago

  • Keywords has-patch added; needs-patch removed
  • Milestone changed from 2.9 to 2.8

comment:11 Denis-de-Bernardy5 years ago

Isn't there a walker method or something like that allows to get a page's ancestors as objects?

comment:12 Denis-de-Bernardy5 years ago

  • Keywords 2nd-opinion added
  • Milestone changed from 2.8 to Future Release

dumping to Future, due to apparent lack of interest

comment:13 exavolt5 years ago

I don't really know about the walker. Isn't it just to walk downward? lists children?

and I think this implementation is much simpler (and faster).

it will be useful for wordpress as CMS that utilizes pages (rather than posts + categories) to create structured site.

comment:14 dd325 years ago

Isn't there a walker method or something like that allows to get a page's ancestors as objects?

You'd be thinking of _get_post_ancestors() and get_post_ancestors() in http://core.trac.wordpress.org/browser/trunk/wp-includes/post.php

comment:15 Denis-de-Bernardy5 years ago

I use the following code in a few of my plugins, in case there is any interest:

	function cache_pages() {
		if ( is_page() ) {
			global $wp_the_query;
			$page_id = (int) $wp_the_query->get_queried_object_id();
			$page = get_page($page_id);
		} elseif ( get_option('show_on_front') == 'page' ) {
			$page_id = (int) get_option('page_for_posts');
			$page = get_page($page_id);
		} else {
			$page_id = 0;
			$page = null;
		}
		
		$ancestors = wp_cache_get($page_id, 'page_ancestors');
		if ( $ancestors === false ) {
			$ancestors = array();
			while ( $page && $page->post_parent != 0 ) {
				$ancestors[] = (int) $page->post_parent;
				$page = get_page($page->post_parent);
			}
			$ancestors = array_reverse($ancestors);
			wp_cache_set($page_id, $ancestors, 'page_ancestors');
		}
		
		$parent_ids = $ancestors;
		array_unshift($parent_ids, 0);
		if ( $page_id )
			$parent_ids[] = $page_id;
		
		$cached = true;
		foreach ( $parent_ids as $parent_id ) {
			$cached = is_array(wp_cache_get($parent_id, 'page_children'));
			if ( $cached === false )
				break;
		}
		
		if ( $cached )
			return;
		
		global $wpdb;
		
		$roots = (array) $wpdb->get_col("
			SELECT	posts.ID
			FROM	$wpdb->posts as posts
			WHERE	posts.post_type = 'page'
			AND		posts.post_parent IN ( 0, $page_id )
			");
		
		$parent_ids = array_merge($parent_ids, $roots, array($page_id));
		$parent_ids = array_unique($parent_ids);
		$parent_ids = array_map('intval', $parent_ids);
		
		$pages = (array) $wpdb->get_results("
			SELECT	posts.*
			FROM	$wpdb->posts as posts
			WHERE	posts.post_type = 'page'
			AND		posts.post_status = 'publish'
			AND		posts.post_parent IN ( " . implode(',', $parent_ids) . " )
			ORDER BY posts.menu_order, posts.post_title
			");
		update_post_cache($pages);
		
		$children = array();
		$to_cache = array();
		
		foreach ( $parent_ids as $parent_id )
			$children[$parent_id] = array();
		
		foreach ( $pages as $page ) {
			$children[$page->post_parent][] = $page->ID;
			$to_cache[] = $page->ID;
		}

		update_postmeta_cache($to_cache);
		
		$all_ancestors = array();
		
		foreach ( $children as $parent => $child_ids ) {
			foreach ( $child_ids as $key => $child_id ) {
				$all_ancestors[$child_id][] = $parent;
				if ( get_post_meta($child_id, '_widgets_exclude', true) )
					unset($child_ids[$key]);
			}
			
			wp_cache_set($parent, $child_ids, 'page_children');
		}
		
		foreach ( $all_ancestors as $child_id => $parent_ids ) {
			while ( $parent_ids[0] )
				$parent_ids = array_merge($all_ancestors[$parent_ids[0]], $parent_ids);
			wp_cache_set($child_id, $parent_ids, 'page_ancestors');
		}
	} # cache_pages()

It's meant to cache parents and children of a static page, and all of its ancestors sibblings.

comment:16 Denis-de-Bernardy5 years ago

  • Milestone Future Release deleted
  • Resolution set to invalid
  • Status changed from new to closed

get_post_ancestors() does the trick. but the ticket was really about adding a breadcrumb. there are a few plugins that do this well already.

Note: See TracTickets for help on using tickets.