問題描述
我的 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 頁面,而不是顯示該帖子內容。我也嘗試載入預覽網址 (site.com/?p=212&preview=true),但也沒有。
這些是我的猜測:
-
普通使用者沒有足夠的
caps來閱讀釋出的草稿。 -
對於任何使用者 (包括管理員),都不可能對 front-end 進行測試和檢視草稿。
為了完成我要做的工作,我必須做些什麼改變?如果不可能,你建議什麼替代解決方案?
注意:我不是在尋找 plugin-based 解決方案。
最佳解決方案
您不能向未知使用者分配功能。如果您想為每個人顯示一個帖子,請為這些帖子建立一個單獨的 URL,並將一個控制元素新增到帖子編輯器中,以便僅在選定的帖子上啟用預覽。呼叫這樣的 URL 時,請檢查是否允許該帖子預覽,以及該帖子是否尚未被髮布。還要確保搜尋引擎忽略此 URL 。
對於 URL,我將使用 endpoint:
add_rewrite_endpoint( 'post-preview', EP_ROOT );
現在您可以建立…
http://example.com/post-preview/123
… 123 是帖子 ID 。
然後使用回撥處理程序來檢查帖子 ID,檢查它是否有效並覆蓋主查詢。這可能是 query_posts()唯一可接受的用例。 🙂
假設端點是一個類 T5_Endpoint(一個模型),並且輸出處理程序是一個類 T5_Render_Endpoint(一個檢視),它獲取了較早傳遞的模型。那麼在 template_redirect 上呼叫 render()可能有一個方法:
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_submitbox_misc_actions) 中,由另一個獲取相同元類的檢視呈現。
所以 T5_Post_Meta 知道在哪裡和什麼時候儲存元值,這些檢視用它做一些事情。此外,掛鉤到 transition_post_status 刪除釋出後的帖子元欄位。我們不想浪費資源,對吧?
這只是一個大綱。有很多細節要覆蓋… 我寫了一個小外掛,顯示如何實現:T5 Public Preview 。
次佳解決方案
我解決了這個問題,我以為比 @ toscho 上面的答案更簡單一些。
我的用例是使用相同的資料庫進行內部 Intranet 分段站點和 public-facing 站點,工作流程是作者撰寫草稿並與釋出之前在內部網站上檢視這些草稿的其他使用者共享。我特意不要求審閱者登入檢視草稿,所以我只是依賴於一個常數 ENV_PRODUCTION,它是根據 $_SERVER['SERVER_NAME']中的主機名在 wp-config 檔案中設定的。這是 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;
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 類中有一些令人討厭的邏輯從查詢結果中刪除草稿檔案,除非當前的 cuser 可以編輯它們。我透過過濾’the_posts’ 來解決這個問題,並將我想要的帖子新增到結果中。
參考文獻
注:本文內容整合自 Google/Baidu/Bing 輔助翻譯的英文資料結果。如果您對結果不滿意,可以加入我們改善翻譯效果:薇曉朵技術論壇。
