Как сделать 301 редирект для приватных записей вместо 404?
Как сделать 301 редирект для приватных страниц вместо отображения ошибки 404? Если запись приватная, WordPress исключает её из SQL-запроса, поэтому нет доступа к переменным $post.
Хотелось бы, чтобы этот код работал, но он не работает:
add_action('wp','redirect_stuffs', 0);
function redirect_stuffs(){
global $post;
if ( $post->post_status == "private" && !is_admin() ):
wp_redirect("http://dangayle.com/",301);
exit();
endif;
}
Я не знаю, где это можно установить раньше, чем в wp
, кроме того факта, что это проблема с ролями пользователей. Если бы я мог дать незалогиненным пользователям соответствующую возможность, это вероятно решило бы проблему:
$publicReader -> add_cap('read_private_posts');
Проблема с add_cap в том, что только авторизованные пользователи имеют возможности.

Извините, ребята, я нашел ответ:
add_action('wp','redirect_stuffs', 0);
function redirect_stuffs(){
global $wpdb;
if ($wpdb->last_result[0]->post_status == "private" && !is_admin() ):
wp_redirect( home_url(), 301 );
exit();
endif;
}
Записи/страницы удаляются из карты сайта, но страница по-прежнему отображается на сайте, чтобы можно было сделать 301 редирект.

Мне кажется, вы не должны возвращать ни 404, ни 301 — вы должны возвращать либо 401 (Unauthorized / требуется аутентификация, хотя вы не будете принимать никакую предложенную аутентификацию), либо 403 (Rejected, то есть "я знаю, что вы просите, но вы этого не получите").
Есть заброшенный плагин Private Page Forbidden, который может быть полезен для изучения, хотя на первый взгляд он пытается преобразовать 404 в 403, что кажется плохой идеей. К сожалению, несмотря на различные обсуждения вариантов (см. https://core.trac.wordpress.org/ticket/10551 и связанные с ним), сроки исправлений постепенно сдвигались до "Future Release".

Во-первых, я должен согласиться с ответом @fencepost. Однако я не смог удержаться от публикации решения, так что вот оно!
function __intercept_private_page( $posts, &$wp_query )
{
// удаляем фильтр сейчас, чтобы при последующих запросах к постам мы не участвовали!
remove_filter( 'the_posts', '__intercept_private_page', 5, 2 );
if ( !( $wp_query->is_page && empty($posts) ) )
return $posts; // выходим, если это не страница без результатов
// если вы хотите явно проверить, что страница *является* приватной, используйте блок кода ниже:
/*
if ( !empty( $wp_query->query['page_id'] ) )
$page = get_page( $wp_query->query['page_id'] );
else
$page = get_page_by_path( $wp_query->query['pagename'] );
if ( $page && $page->post_status == 'private' ) {
// редирект
}
*/
// в противном случае предполагаем, что если запрос был для страницы и страница не найдена, она была приватной
wp_redirect( home_url(), 301 );
exit;
}
is_admin() || add_filter( 'the_posts', '__intercept_private_page', 5, 2 );
Обновление: Пересмотренный код теперь использует фильтр the_posts
вместо posts_results
(который срабатывает до того, как WordPress проверит права доступа, поэтому $posts
ещё не был 'опустошён').
