Skip to content

Instantly share code, notes, and snippets.

@ethanclevenger91
Last active October 24, 2023 21:30
Show Gist options
  • Save ethanclevenger91/c8b26b1c7b3bc5d482844913508e4b6e to your computer and use it in GitHub Desktop.
Save ethanclevenger91/c8b26b1c7b3bc5d482844913508e4b6e to your computer and use it in GitHub Desktop.
Add private pages to WordPress menu builder
add_filter('nav_menu_items_page_recent', 'nav_menu_items_page_recent_with_private', 10, 3);
// Update post_status arg to include private pages
function nav_menu_items_page_recent_with_private($most_recent, $args, $box) {
$args['post_status'] = [
'publish',
'private',
];
// Unsure why these aren't passed into the filter already since it's specifically for the Most Recent tab.
// Bug filed: https://core.trac.wordpress.org/ticket/39849#ticket
$recent_args = array_merge( $args, array( 'orderby' => 'post_date', 'order' => 'DESC', 'posts_per_page' => 15 ) );
// @todo transient caching of these results with proper invalidation on updating of a post of this type
$get_posts = new WP_Query;
$most_recent = $get_posts->query( $recent_args );
return $most_recent;
}
add_filter('nav_menu_items_page', 'nav_menu_items_page_with_private', 10, 3);
// Once again, update the args. But we'll have to copy and paste a little extra to be truly seamless.
function nav_menu_items_page_with_private($posts, $args, $post_type) {
global $_nav_menu_placeholder;
$post_type_name = 'page';
$args['post_status'] = [
'publish',
'private',
];
$get_posts = new WP_Query;
$posts = $get_posts->query( $args );
// WP massages the final list to put the site's Front Page page on top. That logic has been copied and pasted here.
if ( 'page' == $post_type_name ) {
$front_page = 'page' == get_option('show_on_front') ? (int) get_option( 'page_on_front' ) : 0;
if ( ! empty( $front_page ) ) {
$front_page_obj = get_post( $front_page );
$front_page_obj->front_or_home = true;
array_unshift( $posts, $front_page_obj );
} else {
$_nav_menu_placeholder = ( 0 > $_nav_menu_placeholder ) ? intval($_nav_menu_placeholder) - 1 : -1;
array_unshift( $posts, (object) array(
'front_or_home' => true,
'ID' => 0,
'object_id' => $_nav_menu_placeholder,
'post_content' => '',
'post_excerpt' => '',
'post_parent' => '',
'post_title' => _x('Home', 'nav menu home label'),
'post_type' => 'nav_menu_item',
'type' => 'custom',
'url' => home_url('/'),
) );
}
}
$post_type = get_post_type_object( $post_type_name );
if ( $post_type->has_archive ) {
$_nav_menu_placeholder = ( 0 > $_nav_menu_placeholder ) ? intval($_nav_menu_placeholder) - 1 : -1;
array_unshift( $posts, (object) array(
'ID' => 0,
'object_id' => $_nav_menu_placeholder,
'object' => $post_type_name,
'post_content' => '',
'post_excerpt' => '',
'post_title' => $post_type->labels->archives,
'post_type' => 'nav_menu_item',
'type' => 'post_type_archive',
'url' => get_post_type_archive_link( $post_type_name ),
) );
}
return $posts;
}
add_filter( 'wp_get_nav_menu_items', 'remove_private_pages_from_menu', null, 3);
// Make sure that only logged in users will see these private pages
function remove_private_pages_from_menu($items, $menu, $args) {
if(!is_user_logged_in() || !current_user_can('read_private_pages')) {
foreach($items as $key => $item) {
if('private' == get_post_status($item->object_id)) {
unset($items[$key]);
}
}
}
return $items;
}
@Fab1en
Copy link

Fab1en commented Aug 7, 2017

there is a simpler way to achieve this :

add_filter( 'nav_menu_meta_box_object', 'show_private_pages_menu_selection' );
/**
* Add query argument for selecting pages to add to a menu
*/
function show_private_pages_menu_selection( $args ){
	if( $args->name == 'page' ) {
		$args->_default_query['post_status'] = array('publish','private');
	}
	return $args;
}

@ethanclevenger91
Copy link
Author

ethanclevenger91 commented Mar 23, 2018

@Fab1en Welp, that's super obvious in retrospect...

@Smittyhead
Copy link

this doesnt seem to work any longer in version 6?

@mattia-beta
Copy link

It's not working in WP v6

@AndreKelling
Copy link

as mentioned here in comment: https://stackoverflow.com/a/42181485/4375061

the filter needs a higher prio.
then it's working for me at WP v 6.1.1.

add_filter( 'nav_menu_meta_box_object', 'show_private_pages_menu_selection', 99 );
/**
* Add query argument for selecting pages to add to a menu
*/
function show_private_pages_menu_selection( $args ){
	if( $args->name == 'page' ) {
		$args->_default_query['post_status'] = array('publish','private');
	}
	return $args;
}

@Smittyhead
Copy link

Thanks @AndreKelling

@bramchi
Copy link

bramchi commented Oct 24, 2023

Thanks for sharing this, it's a very powerful principle 👌

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment