Site icon WP Smith

Filter Pages by Post Parent and Filter Pages/Posts by Pages/Posts Per on WordPress Edit Pages

Recently I migrated a site that had hundreds of pages, which made page management a potential nightmare. Seeing this potential, I developed a filter that would enable me to see various parts of the pages tree as well as allow me to set the number of pages I wanted to see.

To add a filter on the edit page, you must hook into 'restrict_manage_posts'. The function below will add 2 filters: pages_per filter and a post_parent page filter. The pages_per filter is something that can be used on all post types; however, the post_parent filter should only be used on pages (or other hierarchical post types--but for this tutorial, we will only do pages).

So here's what I did:
[php]
add_action ( 'restrict_manage_posts' , 'wps_restrict_manage_posts' );
function wps_restrict_manage_posts() {
global $typenow;

// only run this filter on page post type
if ( $typenow == 'page' ) {

// Parent Page Filter (HTML)
$args = array(
'child_of' => 0,
'show_option_none' => 'Show all pages',
'depth' => 2, //change this to whatever you want
'name' => 'wps_page_filter',
'selected' => $_GET['wps_page_filter'],
);
$dropdown = wp_dropdown_pages( $args );
}

// Per Page Filter (HTML)
global $wps_per_page;
$wps_per_page = isset( $_GET['wps_per_page'] ) ? (int) $_GET['wps_per_page'] : $wps_per_page;
?>
<select name="wps_per_page" style="width: 110px;">
<option <?php selected( $wps_per_page, 9999 ); ?> value="9999"><?php _e( 'Show all', FDA_DOMAIN ); ?></option>
<?php for( $i=10; $i<=100; $i+=10 ) : ?>
<option <?php selected( $wps_per_page, $i ); ?> value="<?php echo $i; ?>"><?php echo $i; ?> <?php _e( 'per page', FDA_DOMAIN ); ?></option>
<?php endfor; ?>
<?php if ( $wps_per_page != -1 && $wps_per_page != 9999 && ( $wps_per_page%10 != 0 || $wps_per_page > 100 ) ) : ?>
<option <?php selected( true ); ?> value="<?php echo (int) $wps_per_page; ?>"><?php echo (int) $wps_per_page; ?> <?php _e( 'per page', FDA_DOMAIN ); ?></option>
<?php endif; ?>
</select>
<?php
}
[/php]

Now, I wanted to add an option to show only top level pages only. This has to be done manually, darn WordPress for having no good filters in wp_dropdown_pages().
[php]
// Add an option to show top level pages only
add_filter ( 'wp_dropdown_pages' , 'wps_insert_option_in_dropdown' );
function wps_insert_option_in_dropdown ( $output ) {
$filter = $_GET['wps_page_filter'];
if ( $filter == 'parent' )
$selected = ' selected="selected"';
else
$selected = '';
$second_option = 'Show all pages</option><option value="parent"' . $selected . '>Parent Pages Only</option>';
return preg_replace( '#Show all pages</option>#' , $second_option , $output );
}
[/php]

Now, WordPress won't execute the filter for us, so we have to make sure this happens. This can be done in two separate functions; however, since it really doesn't matter pragmatically, we will keep with one function.
[php]
add_filter ( 'parse_query', 'wps_admin_posts_filter' );
function wps_admin_posts_filter( $query ) {
global $pagenow;

// Update pages_per (just because we are here, we do it in this function)
$wps_per_page = $_GET['wps_per_page'];
if ( isset( $wps_per_page ) && ( $wps_per_page == 9999 || ( $wps_per_page % 10 ) == 0 ) )
update_user_option( get_current_user_id(), 'edit_page_per_page', (int) $wps_per_page );

// Change query based on post_parent
$wps_page_filter = $_GET['wps_page_filter'];
if ( is_admin() && $pagenow == 'edit.php' && !empty( $wps_page_filter ) ) {
if ( $wps_page_filter == 'parent' )
$query->query_vars['post_parent'] = 0;
else
$query->query_vars['post_parent'] = $wps_page_filter;
}
}
[/php]