The function next_post_link()
allow excludes, with the parameter excluded_terms
. Add a list of the IDs of the password protected posts to this param.
You get a list of all password protected posts with the follow example via DB select.
$password_pages = $wpdb->get_col("SELECT ID FROM $wpdb->posts WHERE post_status="publish" AND post_type="post" AND post_password !=''");
Alternative can you use a hook to filter the password protected post from the loop. Also a example below, that works on the single and page view of the front end.
// Filter to hide protected posts
function exclude_protected($where) {
global $wpdb;
return $where .= " AND {$wpdb->posts}.post_password = '' ";
}
// Decide where to display them
function exclude_protected_action($query) {
if( !is_single() && !is_page() && !is_admin() ) {
add_filter( 'posts_where', 'exclude_protected' );
}
}
// Action to queue the filter at the right time
add_action('pre_get_posts', 'exclude_protected_action');