privatepagesfix I have a few private pages that I use to store random stuff and ideas and private pages (for a reason I don’t understand) don’t show up in the pages widget.

It turns out that WordPress’s get_pages function always filters them out, while get_posts doesn’t (it actually has some logic to figure out whether to show private pages or not).

I’ve decided to fix this. A real fix would probably be merging get_pages and get_posts because both seem to do pretty much the same except that get_posts is a tad bit more advanced, but I’m all for quick fixes at the moment, because I don’t have much time and I don’t want to end up considering myself a PHP developer ;-)

To make get_pages return private pages, too, you have to open the file wp-includes/post.php and change the following lines near the bottom of the get_pages function:

$query = "SELECT * FROM $wpdb->posts $join WHERE (post_type = 'page' AND post_status = 'publish') $where ";
$query .= $author_query;
$query .= " ORDER BY " . $sort_column . " " . $sort_order ;

to:

$private_pages_inclusion_where = ";
if ( is_user_logged_in() ) {
    $private_pages_inclusion_where  = current_user_can( "read_private_pages" ) ? " OR post_status = 'private'" : " OR post_author = $user_ID AND post_status = 'private'";
}

$query = "SELECT * FROM $wpdb->posts $join WHERE (post_type = 'page' AND (post_status = 'publish' $private_pages_inclusion_where)) $where ";
$query .= $author_query;
$query .= " ORDER BY " . $sort_column . " " . $sort_order ;

If you also want to make it easier to distinguish private pages from normal ones, you can also change the following bits in wp-includes/classes.php in the method Walker_Page::start_el:

$output .= $indent . '<li class="' . $css_class . '"><a href="' . get_page_link($page->ID) .
    '" title="' . attribute_escape(apply_filters('the_title', $page->post_title)) . '">' .
    $link_before . apply_filters('the_title', $page->post_title) . $link_after . '</a>';

to:

$output .= $indent . '<li class="' . $css_class . '"><a href="' . get_page_link($page->ID) .
    '" title="' . attribute_escape(apply_filters('the_title', $page->post_title)) . '">' .
    $link_before . apply_filters('the_title', $page->post_title) . ($page->post_status == 'private' ? " (Private)" : ") . $link_after . '</a>';