Jak mogę udostępnić szkicowy post wszystkim?

13

Mam kilka niepublikowanych postów na mojej stronie Wordpress i staram się, aby były one dostępne dla zwykłych użytkowników (którzy nie są zalogowani) przy użyciu normalnych post slugs ( site.com/post-here). Rozumiem, że może nie być to najlepsza praktyka, ale w moim specjalnym celu należy to zrobić.

Próbowałem dodać następujący fragment kodu do mojego functions.phppliku:

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');

Próbowałem też initzamiast haka after_setup_theme. Brak szczęścia.

Rozumiem, że zmiany ról są zapisywane w bazie danych, więc trzeba to zrobić tylko raz. Dlatego używam after_setup_themehooka do wywołania funkcji.

Ale kiedy próbuję uzyskać dostęp do strony jako zwykły użytkownik, wyświetla się strona 404 zamiast treści postu. Próbowałem również załadować podgląd URL ( site.com/?p=212&preview=true), ale to też nie działało.

Oto moje domysły:

  • zwykły użytkownik nie ma wystarczającej ilości, capsaby przeczytać szkic posta.
  • testowanie i przeglądanie wersji roboczych postów na interfejsie nie jest możliwe dla żadnego użytkownika (w tym administratorów).

Jakie zmiany muszę wprowadzić, aby osiągnąć to, co próbuję zrobić? Jeśli nie jest to możliwe, jakie alternatywne rozwiązania sugerujesz?

Uwaga: nie szukam rozwiązań opartych na wtyczkach.

Amal Murali
źródło
2
Myślę, że jest tu trochę zamieszania. Jeśli ktoś nie jest zalogowany, on / ona nie użytkownik, więc on / ona ma nie jakieś czapki. Że abonenci są użytkownicy, więc muszą być zarejestrowane i sprawiają, że logowanie się do uznania za abonentów. Nie możesz dać możliwości komuś, kto się nie zalogował. Jeśli chcesz, aby nikt nie był zalogowany, przeglądaj swoje posty, po prostu nie różnią się niczym od opublikowanych postów. Dlaczego więc nie opublikować? Czy chcesz pokazać wersję roboczą subskrybentom (zalogowanym jako subskrybenci)?
gmazzap
@GM: Staram się, aby niepublikowane posty były dostępne dla wszystkich, którzy znają bezpośredni link do postu. Może się to wydawać dziwnym wymogiem, ale potrzebuję tego do projektu. Jak wspomniałem w moim pytaniu, jeśli nie jest to możliwe - czy możesz zasugerować inne obejścia (jeśli je znasz, oczywiście)?
Amal Murali,
@GM: Czy znasz wtyczkę, która to robi?
Amal Murali,
Czy przeczytałeś odpowiedź poniżej z 3 głosami pozytywnymi? Wyjaśnia, jak to zrobić, a na końcu odpowiedzi znajdziesz link do pobrania pełnej działającej wtyczki z github.
gmazzap
2
Dla późniejszych czytelników: Na GitHub dostępna jest wtyczka Dominika Schillinga .
kaiser

Odpowiedzi:

12

Nie można przypisać funkcji nieznanym użytkownikom. Jeśli chcesz, aby post był widoczny dla wszystkich, utwórz osobny adres URL dla tych postów i dodaj element sterujący do edytora postów, aby włączyć podgląd tylko wybranych postów.
Po wywołaniu takiego adresu URL sprawdź, czy podgląd postu jest dozwolony i czy post nie został jeszcze opublikowany. Upewnij się również, że wyszukiwarki ignorują ten adres URL.

Jako adres URL użyłbym punktu końcowego :

add_rewrite_endpoint( 'post-preview', EP_ROOT );

Teraz możesz tworzyć adresy URL, takie jak…

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

… Gdzie 123jest identyfikator posta.

Następnie użyj modułu obsługi wywołania zwrotnego, aby sprawdzić identyfikator posta, sprawdź, czy jest poprawny, i zastąp główne zapytanie. Jest to prawdopodobnie jedyny dopuszczalny przypadek użycia dla query_posts(). :)

Powiedzmy, że punktem końcowym jest klasa T5_Endpoint(model), a procedura obsługi danych wyjściowych to klasa T5_Render_Endpoint(widok), która wcześniej przekazuje model. Następnie prawdopodobnie jest render()wywoływana metoda 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->metato kolejny model (klasa T5_Post_Meta) dla meta wartości po, który kontroluje, czy podgląd jest dozwolony. Formant jest ustawiony w polu Publikuj ( akcjapost_submitbox_misc_actions ), renderowanym przez inny widok, który otrzymuje tę samą meta klasę.

zrzut ekranu

Więc T5_Post_Metawie, gdzie i kiedy przechowywać wartość meta, widoki coś z tym robią.
Ponadto, hak dotransition_post_status usunięcia pola meta pocztowy gdy post jest opublikowany. Nie chcemy marnować zasobów, prawda?

To tylko zarys. Jest wiele szczegółów do omówienia… Napisałem małą wtyczkę, która pokazuje, jak to zaimplementować: T5 Public Preview .

fuxia
źródło
Dziękuję bardzo. W końcu udało mi się osiągnąć pewien cel. Niesamowite. : D
Amal Murali
6

Rozwiązałem ten problem w sposób, który moim zdaniem był prostszy niż odpowiedź @ toscho powyżej.

Mój przypadek użycia polega na tym, że używam tej samej bazy danych dla wewnętrznej witryny pośredniej i wewnętrznej witryny intranetowej, a przepływ pracy polega na tym, że autorzy piszą wersje robocze i udostępniają je innym użytkownikom, którzy przeglądają te wersje robocze w witrynie intranetowej, przed opublikowaniem. W szczególności nie chciałem wymagać od recenzentów, aby logowali się, aby zobaczyć wersje robocze, więc po prostu polegam na stałej, ENV_PRODUCTIONktóra jest ustawiona w pliku wp-config na podstawie nazwy hosta w $_SERVER['SERVER_NAME']. To właśnie ENV_PRODUCTIONrobią tutaj kontrole ; po prostu zewrzyj wszystkie te filtry, jeśli przeglądana jest strona produkcyjna.

Jest to trochę dziwne, ponieważ musisz podłączyć się po tym, jak WP_Query usuwa wszystkie posty z tablicy $ wp_query-> posts, ale wydaje mi się to stabilne i bezpieczne.

/*
 * 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 );

Filtry składają się z dwóch oddzielnych części.

  • Filtr na haku „pre_get_posts” ustawia domyślny stan post_status na „publikuj, szkic” na stronie pomostowej. Spowoduje to zwrócenie wersji roboczych postów na listach archiwów.
  • Oddzielny filtr jest potrzebny dla pojedynczych widoków, ponieważ w klasie WP_Query istnieje nieprzyjemna logika do usuwania szkiców z wyników zapytania, chyba że bieżący cuser może je edytować. Obejrzałem to, filtrując „the_posts” i dodając post, który chciałem z powrotem do wyników.
Złote Jabłka
źródło
2
To niesamowite , dziękuję bardzo za udostępnienie tego. Absolutnie idealny i dokładnie to, czego potrzebowałem.
Christian Varga,
Gdzie mam umieścić ten kod? (które pliki?)
Joelio
@Joelio Czy możesz szczegółowo określić problem, który rozwiązujesz? Jako proste podejście, właśnie dodałem ten kod do funkcji.php i dodałem prostą definicję do mojego wp-config.php, które ustawiają stałą ENV_PRODUCTION na true lub false w zależności od domeny żądania.
goldenapples
@goldenapples Dodałem ten fragment kodu do funkcji.php, co powinienem dodać do wp-config? Dzięki za pomoc
Graham Slick,
@MatthiasGrahamSlick - Potrzebujesz tylko czegoś, co ustawi ENV_PRODUCTIONstałą, jeśli jesteś w produkcji. Użyłem domain.com do produkcji i staging.domain.com do inscenizacji, więc moja linia brzmiała: define( 'ENV_PRODUCTION', false === stripos( $_SERVER['HTTP_HOST'], 'staging' ) );Czy to pomaga?
goldenapples
0

Myślę, że wtyczka „User Role Editor” dostępna na stronie WordPress.org może być tym, czego szukasz. Nawiasem mówiąc, dlaczego chcesz wszystkim udostępnić swoje projekty? Osobiście nie mogę wymyślić przypadku, w którym byłoby to wymagane.

Georgi Demirev
źródło
Nie, jak wspomniano w pytaniu, nie szukam rozwiązań opartych na wtyczkach. Przypadek użycia jest nieco skomplikowany, ale jestem pewien, że jest to najlepsze rozwiązanie dla tego konkretnego zadania, które próbuję wykonać. :-)
Amal Murali,
Niepokoi mnie również powód. Jeśli chcesz, aby wszyscy widzieli post, dlaczego po prostu go nie opublikować? Możesz użyć niestandardowych pól w poście, aby śledzić dowolny stan specjalny, który chcesz zdefiniować.
KenB
Pozwalam użytkownikom zobaczyć treść, ale z jakiegoś konkretnego powodu nie chcę, aby posty były publikowane.
Amal Murali,
0

Możesz po prostu zmienić widoczność strony / postu na „Prywatna”, która jest widoczna tylko dla redaktorów i administratorów, a nie dla odwiedzających publicznych, wyszukiwarek, kanałów rss itp.

NickJAB
źródło
0

Myślę, że komentarz GM jest tutaj najlepszy. Zakładam, że próbujesz wykonać następujące czynności:

  1. Napisz post
  2. Zapisz jako szkic
  3. Zezwól zewnętrznemu (niezalogowanemu) użytkownikowi zobaczyć wersję roboczą do zatwierdzenia
  4. Publikować

Czy to jest poprawne?

Niestety nie mogę wymyślić żadnego prostego sposobu na zrobienie tego. Możesz opublikować go jako post prywatny, aby musiał wprowadzić hasło, aby je wyświetlić, ale musisz być zalogowany. Możesz także zabezpieczyć hasłem, ale nadal będzie pojawiać się w Twoim kanale i liście ostatnich postów itp. Czy nie możesz utworzyć konta użytkownika-gościa i podać mu nazwę użytkownika / hasło, podając im adres URL?

Przeczytaj tutaj, aby uzyskać więcej informacji: http://codex.wordpress.org/Content_Visibility

Alternatywnie istnieje wtyczka, która może odpowiadać Twoim potrzebom: http://wordpress.org/extend/plugins/shareadraft/ Rzuciłem okiem na kod i wygląda na to, że programista modyfikuje wartość zwracaną przez get_post_status, więc możesz być w stanie się z tym bawić:

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

HTH

TomC
źródło
0

Jeśli nie obchodzi Cię, czy post jest „opublikowany”, czy nie, po prostu chcę, aby był dostępny dla każdego pod zwykłym opublikowanym adresem URL i nie pojawiał się na stronie głównej / wynikach wyszukiwania / kanałach RSS itp., Ta wtyczka działała z WP 4.6. 1 i pozwala dostosować, gdzie pojawia się post:

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

Sarah Northway
źródło