Make WordPress Core

Opened 14 years ago

Closed 14 years ago

Last modified 14 years ago

#14329 closed defect (bug) (fixed)

current_page_ancestor not being set because $post->ancestors is not being cached

Reported by: layotte's profile layotte Owned by:
Milestone: 3.1 Priority: normal
Severity: normal Version: 3.0
Component: Cache API Keywords: has-patch needs-testing
Focuses: Cc:

Description

I noticed a weird problem where current_page_ancestor class was not being attached to the appropriate <li> from a wp_list_pages on a WPMS site.

I was running this wp_list_pages query:
$children = wp_list_pages("title_li=&child_of=".$ugce."&echo=0&depth=1&sort_column=menu_order"); $ugce is a dynamic parent ID

the current_page_item and current_page_parent classes are being set. However, when I go to a grandchild, the current_page_ancestor is not being set.

I looked through core and found in classes.php (line 1192 - WP3.0) is calling $_current_page = get_page($current_page) and testing if $_current_page->ancestors is set. It isn't set (for some reason), so it skips to the next test.

I went over to post.php to where get_page merely calls get_post, and noticed that at line 337, get_posts checks to see if the $post_id is already in the wp_cache:
if ( ! $_post = wp_cache_get($post_id, 'posts') )

I assume that the current post would be in the wp_cache, so it merely returns the cached results.

That made me think that perhaps the cache does not have the ancestors in it. So I ran a test to find out more.

I setup my theme to output the post ID, the post ancestors, the array from get_post, the array from wp_cache_get and then I cleared the wp_cache and ran the same output to see how it changed.

before the wp_cache_flush(), the get_post and wp_cache_get does not contain the post->ancestors. After the wp_cache_flush() they both contain the post->ancestors.

I suspect that there is a place where the post is being added to cache without the ancestors and then later when the ancestors are being check from the cache it returns as if there are none.

This is my php code:

<?php echo "<strong>Post ID: </strong>" . $post->ID; ?>
<?php echo '<br><br><strong>$post->ancestors: </strong>'; print_r($post->ancestors); ?>
<?php $page = get_page( $post->ID ); ?>
<?php echo "<br><br><strong>print_r get_page: </strong>"; print_r($page); ?>
<?php $_page = wp_cache_get($post->ID, 'posts'); ?>
<?php echo "<br><br><strong>print_r wp_cache_get: </strong>"; print_r($_page); ?>
<?php echo "<br><br><strong>wp_cache_flush</strong"; wp_cache_flush(); ?>
<?php echo "<br><br><strong>Post ID: </strong>" . $post->ID; ?>
<?php echo '<br><br><strong>$post->ancestors: </strong>'; print_r($post->ancestors); ?>
<?php $page = get_page( $post->ID ); ?>
<?php echo "<br><br><strong>print_r get_page: </strong>"; print_r($page); ?>
<?php $_page = wp_cache_get($post->ID, 'posts'); ?>
<?php echo "<br><br><strong>print_r wp_cache_get: </strong>"; print_r($_page); ?>

And this is the output for my given page:

Post ID: 222

$post->ancestors: Array ( [0] => 216 [1] => 21 [2] => 17 )

print_r get_page: stdClass Object ( [ID] => 222 [post_author] => 1 [post_date] => 2010-07-15 19:09:48 [post_date_gmt] => 2010-07-15 19:09:48 [post_content] => Ed.S. [post_title] => Ed.S. [post_excerpt] => [post_status] => publish [comment_status] => open [ping_status] => open [post_password] => [post_name] => ed-s [to_ping] => [pinged] => [post_modified] => 2010-07-16 12:10:59 [post_modified_gmt] => 2010-07-16 12:10:59 [post_content_filtered] => [post_parent] => 216 [guid] => http://webdev.coe.uga.edu/lle/ [menu_order] => 0 [post_type] => page [post_mime_type] => [comment_count] => 0 [filter] => raw )

print_r wp_cache_get: stdClass Object ( [ID] => 222 [post_author] => 1 [post_date] => 2010-07-15 19:09:48 [post_date_gmt] => 2010-07-15 19:09:48 [post_content] => Ed.S. [post_title] => Ed.S. [post_excerpt] => [post_status] => publish [comment_status] => open [ping_status] => open [post_password] => [post_name] => ed-s [to_ping] => [pinged] => [post_modified] => 2010-07-16 12:10:59 [post_modified_gmt] => 2010-07-16 12:10:59 [post_content_filtered] => [post_parent] => 216 [guid] => http://webdev.coe.uga.edu/lle/ [menu_order] => 0 [post_type] => page [post_mime_type] => [comment_count] => 0 [filter] => raw )

wp_cache_flush

Post ID: 222

$post->ancestors: Array ( [0] => 216 [1] => 21 [2] => 17 )

print_r get_page: stdClass Object ( [ID] => 222 [post_author] => 1 [post_date] => 2010-07-15 19:09:48 [post_date_gmt] => 2010-07-15 19:09:48 [post_content] => Ed.S. [post_title] => Ed.S. [post_excerpt] => [post_status] => publish [comment_status] => open [ping_status] => open [post_password] => [post_name] => ed-s [to_ping] => [pinged] => [post_modified] => 2010-07-16 12:10:59 [post_modified_gmt] => 2010-07-16 12:10:59 [post_content_filtered] => [post_parent] => 216 [guid] => http://webdev.coe.uga.edu/lle/ [menu_order] => 0 [post_type] => page [post_mime_type] => [comment_count] => 0 [ancestors] => Array ( [0] => 216 [1] => 21 [2] => 17 ) [filter] => raw )

print_r wp_cache_get: stdClass Object ( [ID] => 222 [post_author] => 1 [post_date] => 2010-07-15 19:09:48 [post_date_gmt] => 2010-07-15 19:09:48 [post_content] => Ed.S. [post_title] => Ed.S. [post_excerpt] => [post_status] => publish [comment_status] => open [ping_status] => open [post_password] => [post_name] => ed-s [to_ping] => [pinged] => [post_modified] => 2010-07-16 12:10:59 [post_modified_gmt] => 2010-07-16 12:10:59 [post_content_filtered] => [post_parent] => 216 [guid] => http://webdev.coe.uga.edu/lle/ [menu_order] => 0 [post_type] => page [post_mime_type] => [comment_count] => 0 [ancestors] => Array ( [0] => 216 [1] => 21 [2] => 17 ) [filter] => raw ) 

Attachments (1)

classes.php.diff (546 bytes) - added by layotte 14 years ago.
Well, this is my simple fix... I just added _get_post_ancestors($_current_page); into the start_el function of classes, before testing if ancestors.

Download all attachments as: .zip

Change History (11)

#1 @scribu
14 years ago

WP_Query does some up-front caching of posts and ancestors. We really should cache ancestors only when required.

#2 @scribu
14 years ago

  • Keywords needs-patch added; current_page_ancestor $post->ancestors removed
  • Milestone changed from Awaiting Review to 3.1

#3 @layotte
14 years ago

Still testing, I tried wp_cache_flush at the beginning of my template file and it still had the same results as above.

I actually have two wp_list_pages() calls in this template. The first is a left sidebar, with a depth=1, so I can get all the immediate children of a specific page. The second is a depth=2, to get all the children of the ancestor page.

In other words my structure is:

Academic Programs

>Graduate Degrees > Foreign Langauge <= first wp_list_pages to get children of Graduate Degrees > Ed.S. <= second wp_list_pages to get children and grand children degree > How to Apply

I started moving the wp_cache_flush() down until I got to my second wp_list_pages. If I put wp_cache_flush() immediately after the wp_list_pages then the my first two results (above) include the $post->ancestors...

still digging... just reporting as I find stuff.

@layotte
14 years ago

Well, this is my simple fix... I just added _get_post_ancestors($_current_page); into the start_el function of classes, before testing if ancestors.

#4 @layotte
14 years ago

  • Keywords has-patch added; needs-patch removed

#5 @layotte
14 years ago

  • Keywords needs-testing added

#6 @nacin
14 years ago

This looks sane.

#7 @ryan
14 years ago

There are other tickets with patches that fix this down in get_post(), but those are probably too much for 3.1.

#8 @nacin
14 years ago

  • Resolution set to fixed
  • Status changed from new to closed

(In [16834]) _get_post_ancestors() in Walker_Page. props layotte, fixes #14329.

#9 @Denis-de-Bernardy
14 years ago

This ticket would have been fixed automatically by fixing #10381...

#10 @hakre
14 years ago

  • Keywords changed from has-patch, needs-testing to has-patch needs-testing

Related: #14662

Note: See TracTickets for help on using tickets.