Как сделать черновик сообщения доступным для всех?

13

У меня есть несколько неопубликованных постов на моем веб-сайте Wordpress, и я пытаюсь сделать его доступным для обычных пользователей (которые не вошли в систему) с помощью обычных пост-слагов ( site.com/post-here). Я понимаю, что это не лучшая практика, но для моей особой цели это нужно сделать.

Я попытался добавить следующий фрагмент кода в мой functions.phpфайл:

function enable_view_drafts() {
$role = get_role( 'subscriber' ); 
$role->add_cap( 'read_private_posts' ); 
$role->add_cap( 'edit_posts' );
}
add_action( 'after_setup_theme', 'enable_view_drafts');

Я также попробовал initкрюк вместо after_setup_theme. Неудачно.

Насколько я понимаю, изменения ролей сохраняются в базе данных, поэтому их нужно выполнить только один раз. Вот почему я использую after_setup_themeкрючок для вызова функции.

Но когда я пытаюсь получить доступ к странице как обычный пользователь, мне показывают страницу 404 вместо того, чтобы показывать содержание сообщения. Я также попытался загрузить URL предварительного просмотра ( site.com/?p=212&preview=true), но это тоже не сработало.

Это мои догадки:

  • обычному пользователю не хватает capsчитать черновик.
  • Тестирование и просмотр черновиков сообщений во внешнем интерфейсе невозможны ни для каких пользователей (включая администраторов).

Какие изменения я должен сделать, чтобы выполнить то, что я пытаюсь сделать? Если это невозможно, какие альтернативные решения вы предлагаете?

Примечание: я не ищу решения на основе плагинов.

Амаль Мурали
источник
2
Я думаю, что здесь есть небольшая путаница. Если кто-то не вошел в систему, он / она не пользователь, поэтому у него / нее нет никаких заглавных букв. Эти абоненты являются пользователями, поэтому они должны быть зарегистрированы и сделать Войти , чтобы быть признанными в качестве абонентов. Вы не можете предоставлять возможности тому, кто не вошел в систему. Если вы хотите, чтобы кто-то не вошел в систему, просмотрите ваши сообщения, они ничем не отличаются от опубликованных. Так почему бы не опубликовать это? Или вы хотите показать черновик подписчикам (вошли как подписчики)?
gmazzap
@GM: я пытаюсь сделать неопубликованные посты доступными для всех, кто знает прямую постоянную ссылку на пост. Это может показаться странным требованием, но мне это нужно для проекта. Как я уже упоминал в своем вопросе, если это невозможно - можете ли вы предложить другие способы обхода (если вы знаете один, конечно)?
Амаль Мурали
@GM: Вы знаете о плагине, который делает это?
Амаль Мурали
Вы читали ответ чуть ниже с 3 ответами? В нем объясняется, как это сделать, и в конце ответа вы найдете ссылку для загрузки полного рабочего плагина с github.
gmazzap
2
Для более поздних читателей: этот плагин от Dominik Schilling доступен на GitHub.
Кайзер

Ответы:

12

Вы не можете назначать возможности неизвестным пользователям. Если вы хотите сделать сообщение видимым для всех, создайте отдельный URL для этих сообщений и добавьте элемент управления в редактор сообщений, чтобы включить предварительный просмотр только для выбранных сообщений.
Когда вызывается такой URL-адрес, проверьте, разрешен ли предварительный просмотр для сообщения, и не было ли оно уже опубликовано. Также убедитесь, что поисковые системы игнорируют этот URL.

Для URL я бы использовал конечную точку :

add_rewrite_endpoint( 'post-preview', EP_ROOT );

Теперь вы можете создавать URL-адреса, как ...

http://example.com/post-preview/123

… Где 123идентификатор сообщения.

Затем используйте обработчик обратного вызова, чтобы проверить идентификатор сообщения, проверить его действительность и переписать основной запрос. Это, вероятно, единственный приемлемый вариант использования для query_posts(). :)

Допустим, конечная точка - это класс T5_Endpoint(модель), а обработчик вывода - это класс T5_Render_Endpoint(представление), который получает модель, переданную ранее. Тогда, вероятно, есть метод, который вызывается render()на template_redirect:

public function render()
{
    $post_id = $this->endpoint->get_value();

    if ( ! $post_id )
        return;

    if ( 1 !== $this->meta->get_value( $post_id )
        or 'publish' === get_post_status( $post_id )
        )
    {
        wp_redirect( get_permalink( $post_id ) );
        exit;
    }

    $query = array (
        'suppress_filters' => TRUE,
        'p'                => $post_id,
        'post_type'        => 'any'
    );

    query_posts( $query );

    add_action( 'wp_head', 'wp_no_robots' );
}

$this->metaявляется другой моделью (классом T5_Post_Meta) для мета-значения post, которое контролирует, разрешен ли предварительный просмотр. Элемент управления устанавливается в поле « Публикация» ( действиеpost_submitbox_misc_actions ), отображаемое другим представлением, которое получает тот же мета-класс.

Скриншот

Так что T5_Post_Metaзнает, где и когда хранить мета-значение, представления с ним что-то делают.
Кроме того, подключитесь,transition_post_status чтобы удалить мета-поле сообщения при публикации сообщения. Мы не хотим тратить ресурсы, верно?

Это всего лишь набросок. Есть много деталей для рассмотрения ... Я написал небольшой плагин, который показывает, как реализовать это: T5 Public Preview .

Фуксия
источник
Огромное спасибо. Я наконец достиг своей цели с некоторыми изменениями. Потрясающие. : D
Амаль Мурали
6

Я решил эту проблему более простым способом, чем ответ @ toscho выше.

В моем случае я использую одну и ту же базу данных для внутреннего промежуточного сайта интрасети и общедоступного сайта, и рабочий процесс заключается в том, что авторы пишут черновики и делятся ими с другими пользователями, которые просматривают эти черновики на сайте интрасети перед публикацией. Я специально не хотел требовать, чтобы рецензенты входили в систему, чтобы видеть черновики, поэтому я просто зависел от константы, ENV_PRODUCTIONкоторая задается в файле wp-config на основе имени хоста в $_SERVER['SERVER_NAME']. Вот что делают чеки ENV_PRODUCTIONздесь; просто отключив все эти фильтры, если производственный сайт просматривается.

Это немного странно, потому что вам нужно подключиться после того, как WP_Query удалит все записи из массива $ wp_query-> posts, но мне он кажется стабильным и безопасным.

/*
 * On staging site home and archives, drafts should be visible.
 */
function show_drafts_in_staging_archives( $query ) {
    if ( ENV_PRODUCTION )
        return;

    if ( is_admin() || is_feed() )
        return;

    $query->set( 'post_status', array( 'publish', 'draft' ) );
}

add_action( 'pre_get_posts', 'show_drafts_in_staging_archives' );


/*
 * Make drafts visible on staging site single views.
 *
 * (Because on single views, WP_Query goes through logic to make sure the 
 * current user can edit the post before displaying a draft.)
 */
function show_single_drafts_on_staging( $posts, $wp_query ) {
    if ( ENV_PRODUCTION )
        return $posts;

    //making sure the post is a preview to avoid showing published private posts
    if ( ! is_preview() )        
        return $posts;

    if ( count( $posts ) )
        return $posts;

    if ( !empty( $wp_query->query['p'] ) ) {
        return array ( get_post( $wp_query->query['p'] ) );
    }
}

add_filter( 'the_posts', 'show_single_drafts_on_staging', 10, 2 );

В фильтрах есть две отдельные части.

  • Фильтр на хуке «pre_get_posts» устанавливает для post_status по умолчанию значение «publish, draft» на промежуточном сайте. Это вернет черновики сообщений в списках архивов.
  • Для отдельных представлений необходим отдельный фильтр, поскольку в классе WP_Query есть некоторая неприятная логика для удаления черновиков сообщений из результатов запроса, если только текущий пользователь не сможет их редактировать. Я справился с этим, отфильтровав «the_posts» и добавив нужную запись прямо к результатам.
goldenapples
источник
2
Это невероятно , большое спасибо за то, что поделились этим. Абсолютно идеально и именно то, что мне нужно.
Кристиан Варга
Где я могу разместить этот код? (какие файлы?)
Joelio
@Joelio Можете ли вы быть конкретным о проблеме, которую вы решаете? В качестве простого подхода я просто добавил этот код в мой functions.php и добавил простое определение в мой wp-config.php, в котором константе ENV_PRODUCTION присвоено значение true или false в зависимости от домена запроса.
Золотые яблоки
@goldenapples Я добавил этот кусок кода в свой function.php, что мне добавить в wp-config? Спасибо за вашу помощь
Грэм Слик
@MatthiasGrahamSlick - Вам просто нужно что-то, что установит ENV_PRODUCTIONконстанту, если вы находитесь на производстве. Я использовал domain.com для производства и staging.domain.com для подготовки, поэтому моя линия была « define( 'ENV_PRODUCTION', false === stripos( $_SERVER['HTTP_HOST'], 'staging' ) );Помогает ли это?
Золотые яблоки
0

Я думаю, что плагин «User Role Editor», доступный на веб-сайте WordPress.org, может быть тем, что вы ищете. Кстати, почему ты хочешь дать доступ к своим черновикам всем? Лично я не могу вспомнить случай, когда это потребуется.

Георгий Демирев
источник
Нет, как уже упоминалось в вопросе, я не ищу решения на основе плагинов. Вариант использования немного сложен, но я уверен, что это лучшее решение для этой конкретной задачи, которую я пытаюсь выполнить. :-)
Амаль Мурали
Я также озадачен причиной. Если вы хотите, чтобы все увидели сообщение, почему бы просто не опубликовать его? Вы можете использовать настраиваемые поля в сообщении для отслеживания любого особого состояния, которое вы можете захотеть определить.
KenB
Я разрешаю пользователям просматривать контент, но по какой-то конкретной причине я не хочу, чтобы посты публиковались.
Амаль Мурали
0

Вы можете просто изменить видимость на странице / посте на «Приватный», который виден только редакторам и администраторам, а не публичным посетителям, поисковым системам, RSS-каналам и т. Д.

NickJAB
источник
0

Я думаю, что комментарий GM является лучшим здесь. Я предполагаю, что вы пытаетесь сделать следующее:

  1. Написать сообщение
  2. Сохранить как черновик
  3. Разрешить внешнему (не зарегистрированному) пользователю просматривать черновик для утверждения
  4. Публиковать

Это верно?

К сожалению, я не могу придумать простой способ сделать это. Вы можете опубликовать это как личное сообщение, чтобы им нужно было ввести пароль для просмотра, но для этого вам необходимо войти в систему. Вы также можете защитить его паролем, но тогда он все равно будет отображаться в вашем фиде и списке последних сообщений и т. Д. Не могли бы вы создать гостевую учетную запись пользователя и дать им имя пользователя / пароль, когда вы дадите им URL?

Читайте здесь для получения дополнительной информации: http://codex.wordpress.org/Content_Visibility

Кроме того, есть плагин, который может удовлетворить ваши потребности: http://wordpress.org/extend/plugins/shareadraft/ Я быстро просмотрел код, и оказалось, что разработчик изменяет значение, возвращаемое get_post_status, так что вы можете в состоянии поиграть с этим:

http://codex.wordpress.org/Function_Reference/get_post_status

НТН

TomC
источник
0

Если вам все равно, опубликовано ли это сообщение или нет, просто хотите, чтобы оно было доступно любому по обычному опубликованному URL-адресу и не отображалось на главной странице / результатах поиска / RSS-каналах и т. Д., Этот плагин работает с WP 4.6. 1 и позволяет вам точно настроить место появления сообщения:

https://wordpress.org/plugins/wp-hide-post/

Сара Нортвей
источник