it-swarm-eu.dev

Jak vytvořit návrhy příspěvků nebo příspěvky v přehledu přístupné prostřednictvím úplné adresy URL/slug?

Provozuji webovou stránku s WordPress 4.2 a změnili jste způsob, jakým jsou příspěvky nebo příspěvky ve stavu kontroly zobrazeny nepřihlášeným uživatelům (tyto příspěvky jsou také viditelné pro každého, kdo navštíví webovou stránku).

Toto řešení jsem implementoval zde: https://wordpress.org/support/topic/problem-filtering-query-to-profil-displaying-drafts-even-for-not-logged-users

Zatímco nyní může kdokoliv přistupovat k návrhům příspěvků/čekajících příspěvků, aniž by se musel přihlásit, jsou příspěvky přístupné pouze prostřednictvím post_id:

http://my-domain.com/?p=1234

Nejsou přístupné přes jejich slug/Nice permalink, který býval takový:

http://my-domain.com/2015/12/07/post-with-Nice-slug/

Má někdo nápad, jak "povolit" permalinks pro návrhy příspěvků/čekajících příspěvků?

Děkuji!

AKTUALIZACE 20. února

Odpověď @userabuser funguje jako kouzlo! Vzhledem k tomu, že všechny mé nevyřízené příspěvky byly dříve zveřejněny, nemusel jsem dělat trik, abych je zveřejnil jako první. Myslel jsem, že jsem přišel s pracovním řešením sám - ale: tady je kód, který jsem použil předtím, který nefungoval (a nevím proč to tak je):

function guest_enable_hidden_single_post($query) {
    if(is_user_logged_in()) return $query;
    //user is not logged

    if(!is_single()) return $query;
    //this is a single post

    if(!$query->is_main_query())return $query;
    //this is the main query    

    $query->set('post_status',array('publish', 'pending'));
    //allowed post statuses for guest

    return $query;
}

function guest_reload_hidden_single_post($posts) {
    global $wp_query, $wpdb;

    if(is_user_logged_in()) return $posts;
    //user is not logged

    if(!is_single()) return $posts;
    //this is a single post

    if(!$wp_query->is_main_query()) return $posts;
    //this is the main query

    if($wp_query->post_count) return $posts;
    //no posts were found

    $posts = $wpdb->get_results($wp_query->request);

    return $posts;
}

//allow guests to view single posts even if they have not post_status="publish"
add_filter('pre_get_posts', 'guest_enable_hidden_single_post');

//reload hidden posts
add_filter('the_posts', 'guest_reload_hidden_single_post');

AKTUALIZACE 22. února

Vyskytl se problém se zobrazením soukromých stránek správcům/přihlášeným uživatelům. Opravil jsem to následujícím kódem:

function preview_draft_posts($query) {
    if(is_user_logged_in()) return $query;
    // user is not logged

    if(is_admin()) return $query;
    // user is not admin

    if(is_attachment()) return $query;
    // is not an attachment

    if(get_query_var('suppress_filters')) return $query;
    // no suppressed filters

    if(!is_single()) return $query;
    // query for a single post

    if(!$query->is_main_query()) return $query;
    // this is the main query

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

    return $query;
}
add_filter('pre_get_posts', 'preview_draft_posts');

Nyní čekající příspěvky se zobrazí komukoli a soukromé příspěvky jsou stále viditelné pouze pro administrátory ;-)

2
Sebastian

Caveat: příklady kódů v této odpovědi jsou velmi základní a nemusí nebo nemusí potřebovat další podmíněnou logiku, aby se přizpůsobily vašim přesným potřebám, tato logika je míněna jako příklad, který vás dostane na cestu.

Je třeba mít na paměti dvě skutečnosti:

Úvaha 1:

Pokud přidáte nový příspěvek a uložíte ho s post_status z draft first, příspěvek nebude mít slug v poli post_name v databázi *_posts, dokud nebudete publish alespoň jednou .

Úvaha 2:

Pokud přidáte nový příspěvek, uložte jej pomocí znaku post_status z draft , nebo jednoduše předejte draft stage a jděte rovně na publish a poté příspěvek vložte zpět do draft post_status, pak post bude mít slug vložen do post_name sloupce v tabulce *_posts.

Proč je to důležité:

  • V souvislosti s protiplněním 1 ...

WordPress se spoléhá na alespoň jeden identifikační marker, typicky id nebo post_name, které je jedinečné, aby bylo možné získat příspěvek.

Všimněte si, že když vytvoříte návrh příspěvku a pokusíte se jej zobrazit, WordPress vás přivede k náhledové adrese URL podobné:

http://example.com/?p=123&preview=true

Dělá to proto, že jediným způsobem, jak identifikovat a zobrazit náhled daného příspěvku, je udělat to podle ID, ke kterému je v databázi přiřazeno.

  • V souvislosti s protiplněním 2 ...

Pokud zveřejníte příspěvek alespoň jednou, pak jej vrátíte zpět do draft , budete mít přístup k příspěvku, zatímco v draft status pomocí slug ( docela permalink), protože sloupec post_name obsahuje hodnotu slug.

Příklad kódu:

Následující kód vám umožní vrátit příspěvky ve stavu draft nebo pending status pomocí slug, pokud byl příspěvek publikován alespoň jednou předtím (viz bod 2).

function preview_draft_posts($query) {

  if ( is_admin() || get_query_var('suppress_filters') )
    return $query;


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


  return $query;

}

add_filter('pre_get_posts', 'preview_draft_posts');

Výše uvedené bude fungovat pro přihlášené a odhlášené uživatele.

Co se stane, když jste odhlášeni a chcete zobrazit náhled konceptu?

Ok, takže pokud draf nebyl alespoň jednou publikován, jediným způsobem zobrazení náhledu příspěvku je následující formát:

http://example.com/?p=123

WordPress závisí na tomto formátu najít post, kde to nemá slug.

Pokud jste odhlášeni, i když nebudete moci tento příspěvek vidět navzdory logice pre_get_posts jsme použili v příkladu výše.

Místo toho je třeba zavést filtr the_posts a přidat příspěvek zpět do výsledků, které chcete zobrazit, protože WP_Query vyloučí koncept příspěvky ze sady výsledků pro odhlášené uživatele, protože odhlášení uživatelé nemají správných uživatelských schopností.

Pokud se na druhé straně pokusíte (i když jste odhlášeni) o přístup k příspěvku, který je podobný tomu, který je v úvahu 1, je to výchozí náhled URL, jak je uvedeno výše v příkladu http://example.com/?p=123&preview=true (s nebo bez preview=true), pak se setkáte s číslem 404 Oznámení nenalezeno na stránce.

Následující příklady kódu nápravy, které:

function the_posts_preview_draft_posts($posts, $wp_query) {

    //abort if $posts is not empty, this query ain't for us...
    if ( count($posts) ) {
        return $posts;
    }

    $p = get_query_var('p');

    //get our post instead and return it as the result...
    if ( !empty($p) ) {
        return array(get_post($p));
    }
}

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

Skvělé ... ale pověsit, to ještě saje, tak trochu, protože musíte použít URL formát jako http://example.com/?p=123 pro přístup k příspěvku.

Zpět na hlavní problém popsaný v úvaha 1 , jediná řešení, na která si myslím, jsou následující:

Řešení č. 1

  • uložit návrh příspěvek a najít příspěvek je to název převedením slimák na titul.

Příklad...

function the_posts_preview_draft_posts($posts, $wp_query) {

    //abort if $posts is not empty, this query ain't for us...
    if ( count($posts) ) {
        return $posts;
    }

    $id    = get_query_var('p');
    $name = get_query_var('name');

    //this is a bit of a bad idea...
    if ( empty($id) && !empty($name) ) {

        $name = preg_replace('/\W/', ' ', $name);

        global $wpdb;
        $id = $wpdb->get_var( 
            "
            SELECT ID 
            FROM $wpdb->posts 
            WHERE UPPER(post_title) LIKE UPPER('".$name."')
            LIMIT 1" 
        );

    }


    //get our post instead and return it as the result...
    if ( !empty($id) ) {
        return array(get_post($id));
    }

}

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

Nahoře ... ↑ ... je špatný nápad, ale jen příklad délky, kterou potřebujete jít. Proč je to špatný nápad, je jednoduché, musíte zajistit, že nemáte žádné duplicitní post tituly v databázi a musíte zajistit, že neupravujete slug tak, že je odlišný od názvu při uložení jako koncept .

Máte problémy, jak vidíte.

Řešení č. 2

Pravděpodobně lepší způsob, jak to zvládnout, by bylo nastavit post_status příspěvku na publish tak, aby sloupec post_name dostal hodnotu slug a pak ihned umístil příspěvek zpět do draft status .

Tímto způsobem ručně sát, takže je zde nějaký kód:

function allow_draft_public_preview( ) {

        global $post;

        if ( !empty($post->post_name) )
            return;

        $html =<<<DOC
        <div class="misc-pub-section">
            <label>
                <input type="checkbox" id="_allow_public_preview" name="_allow_public_preview" value="1" />
                Allow public preview
            </label>
        </div>
DOC;

echo $html;

}

add_action('post_submitbox_misc_actions', 'allow_draft_public_preview');

function update_post_status( $post_id, $post, $update ) {

    if ( !empty($_POST['_allow_public_preview']) ) {

        //un-hook to prevent infinite loop
        remove_action( 'save_post', 'update_post_status', 13, 2 );

        //set the post to publish so it gets the slug is saved to post_name
        wp_update_post( array( 'ID' => $post_id, 'post_status' => 'publish' ) );

        //immediately put it back to draft status
        wp_update_post( array( 'ID' => $post_id, 'post_status' => 'draft' ) );

        //re-hool
        add_action( 'save_post', 'update_post_status', 13, 2 );
    }

}

add_action('save_post', 'update_post_status', 13, 2);

První zpětné volání připojené k akci post_submitbox_misc_actions přidá zaškrtávací políčko na obrazovku Upravit příspěvek "Povolit veřejný náhled" ...

 enter image description here 

... když toto zaškrtávací políčko označíte, bude rozpoznáno druhým zpětným volaním vyvolaným akcí save_post.

V akci save_post kontrolujeme existenci našeho zaškrtávacího políčka v souboru $_POST superglobal a pokud je přítomen, nastavíme stav postu na publish pak jej ihned nastavíme zpět na draft .

Nyní můžete přistupovat k návrhům příspěvků, přihlášených nebo odhlášených, jejich slugs/pretty permalinks.

Teď všichni společně:

function preview_draft_posts($query) {

  if ( is_admin() || get_query_var('suppress_filters') )
    return $query;


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


  return $query;

}

add_filter('pre_get_posts', 'preview_draft_posts');

function the_posts_preview_draft_posts($posts, $wp_query) {

    //abort if $posts is not empty, this query ain't for us...
    if ( count($posts) ) {
        return $posts;
    }

    $p = get_query_var('p');

    //get our post instead and return it as the result...
    if ( !empty($p) ) {
        return array(get_post($p));
    }
}

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

function allow_draft_public_preview( ) {

        global $post;

        if ( !empty($post->post_name) )
            return;

        $html =<<<DOC
        <div class="misc-pub-section">
            <label>
                <input type="checkbox" id="_allow_public_preview" name="_allow_public_preview" value="1" />
                Allow public preview
            </label>
        </div>
DOC;

echo $html;

}

add_action('post_submitbox_misc_actions', 'allow_draft_public_preview');

function update_post_status( $post_id, $post, $update ) {

    if ( !empty($_POST['_allow_public_preview']) ) {

        //un-hook to prevent infinite loop
        remove_action( 'save_post', 'update_post_status', 13, 2 );

        //set the post to publish so it gets the slug is saved to post_name
        wp_update_post( array( 'ID' => $post_id, 'post_status' => 'publish' ) );

        //immediately put it back to draft status
        wp_update_post( array( 'ID' => $post_id, 'post_status' => 'draft' ) );

        //re-hool
        add_action( 'save_post', 'update_post_status', 13, 2 );
    }

}

add_action('save_post', 'update_post_status', 13, 2);
3
userabuser