If a post password is applied and the user is not logged in, the post will not show up in search results. This is the expected behavior of WP_Query
:
// If a search pattern is specified, load the posts that match
if ( !empty($q['s']) ) {
// added slashes screw with quote grouping when done early, so done later
$q['s'] = stripslashes($q['s']);
if ( !empty($q['sentence']) ) {
$q['search_terms'] = array($q['s']);
} else {
preg_match_all('/".*?("|$)|((?<=[\r\n\t ",+])|^)[^\r\n\t ",+]+/', $q['s'], $matches);
$q['search_terms'] = array_map('_search_terms_tidy', $matches[0]);
}
$n = !empty($q['exact']) ? '' : '%';
$searchand = '';
foreach( (array) $q['search_terms'] as $term ) {
$term = esc_sql( like_escape( $term ) );
$search .= "{$searchand}(($wpdb->posts.post_title LIKE '{$n}{$term}{$n}') OR ($wpdb->posts.post_content LIKE '{$n}{$term}{$n}'))";
$searchand = ' AND ';
}
if ( !empty($search) ) {
$search = " AND ({$search}) ";
if ( !is_user_logged_in() )
$search .= " AND ($wpdb->posts.post_password = '') ";
}
}
See the bottom part? if ( !empty($search) ) {
checks to see if we’re queuing up a search and, if the user isn’t logged in, explicitly searches only for posts that have no password set.
If you need to password protect content anyway, I recommend one of two routes:
1 Require an account
You can easily require users to log in before viewing content – either password-protected or private posts. This gives you complete control over who can see content.
2 Build your own widget
You’re trying to include a link to this password-protected content in a dynamic widget. Either use a static list instead (hand-edit the text to include the link) or build your own dynamic widget that does include password-protected posts.