このように登録されているEvent
というカスタム投稿タイプがあります。
add_action('init', 'register_custom_post_types');
function register_custom_post_types() {
$event_capabilities = array(
'publish_posts' => 'publish_events',
'edit_posts' => 'edit_events',
'edit_others_posts' => 'edit_others_event',
'delete_posts' => 'delete_events',
'delete_published_posts' => 'delete_published_events',
'delete_others_posts' => 'delete_others_events',
'read_private_posts' => 'read_private_events',
'edit_post' => 'edit_event',
'delete_post' => 'delete_event',
'read_post' => 'read_event',
);
register_post_type('event',
array(
'labels' => array(
'name' => __( 'Event' )
),
'rewrite' => 'event',
'public' => true,
'has_archive' => true,
'show_ui' => true,
'menu_position' => 8,
'capability_type' => array('event', 'events'),
'capabilities' => $event_capabilities,
'supports' => array('title', 'thumbnail', 'page-attributes'),
'map_meta_cap' => true,
'hierarchical' => true,
)
);
}
イベントを通常のページの親として設定できるようにしたいです。言い換えれば、私はすべてのイベントをPage Attributes
の下のParent
select要素に表示したいと思います。
CPTをページの子として設定する方法についての記事をたくさん読んだことがありますが、その逆はできません。
私たちがここで取り組もうとしている挑戦は、以下の方法です。
現在の ページ属性 メタボックスを削除または置換しない
階層情報をドロップダウンのままにします。
単一ページの編集画面を表示していて、event
parentドロップダウン にpage
投稿タイプを追加したいとします。
ドロップダウンは、wp_dropdown_pages()
関数を呼び出すget_pages()
関数を使用して表示されます。単一の投稿タイプのみをサポートします。
これをする2つの方法はここにあります:
これは実験的な方法です、なぜならそれはSQLの修正を扱うからです。
生成されたSQLクエリをget_pages()
でフィルタリングする明白な方法がないので、私達は私達のニーズに一般的なquery
フィルタを使うことができます。
ドロップダウンをより使いやすくするために、複数の投稿タイプのタイトルが含まれている場合は、投稿タイプ情報の先頭にlist_pages
フィルタを使用します。
例:
そのため、代わりに次のようなオプションを表示します。
"(no parent)"
"About the Music Hall"
"History"
"Location"
"Concerts"
"Of Monsters and Men"
"Vienna Philharmonic Orchestra"
"Tickets"
我々が得る:
"(no parent)"
"page - About the Music Hall"
"page - History"
"page - Location"
"event - Concerts"
"event - Of Monsters and Men"
"event - Vienna Philharmonic Orchestra"
"page - Tickets"
デモプラグイン:
テストのためにプラグインに配置できるコードスニペットは次のとおりです。
/**
* Add the hierarchical 'event' post type, to the 'page' parent drop-down.
*
* @link http://wordpress.stackexchange.com/a/204439/26350
*/
is_admin() && add_filter( 'page_attributes_dropdown_pages_args', function( $dropdown_args, $post )
{
// Only do this for the 'page' post type on the single edit 'page' screen
if( 'page' === get_current_screen()->id && 'page' === $post->post_type )
{
// Modify the options' titles
add_filter( 'list_pages', 'wpse_add_post_type_info_in_options', 10, 2 );
// Modify the get_pages() query
add_filter( 'query', function( $sql )
{
// Only run this once
if( ! did_action( 'wpse_change_cpt' ) )
{
do_action( 'wpse_change_cpt' );
// Adjust the post type part of the query - add the 'event' post type
$sql = str_replace(
"post_type = 'page' ",
"post_type IN ( 'event', 'page' ) ",
$sql
);
}
return $sql;
} );
}
return $dropdown_args;
}, 10, 2 );
ここで、
function wpse_add_post_type_info_in_options ( $title, $page )
{
return $page->post_type . ' - ' . $title;
}
そして少しのクリーンアップ:
add_filter( 'wp_dropdown_pages', function( $output )
{
if( did_action( 'wpse_change_cpt' ) )
remove_filter( 'list_pages', 'wpse_add_post_type_info_in_options', 10, 2 );
return $output;
} );
wp_dropdown_pages()
だけを使うここではwp_dropdown_pages()
を2回実行してからそれを1つのドロップダウンにマージします。投稿タイプがpage
の場合は1回、投稿タイプがevent
の場合はもう一度
/**
* Add the hierarchical 'event' post type, to the 'page' parent drop-down.
*
* @link http://wordpress.stackexchange.com/a/204439/26350
*/
is_admin() && add_filter( 'page_attributes_dropdown_pages_args', 'wpse_attributes', 99, 2 );
function wpse_attributes( $dropdown_args, $post )
{
// Run this filter callback only once
remove_filter( current_filter(), __FUNCTION__, 99 );
// Only do this for the 'page' post type on the edit page screen
if( 'page' === get_current_screen()->id && 'page' === $post->post_type )
{
// Modify the input arguments, for the 'event' drop-down
$modified_args = $dropdown_args;
$modified_args['post_type'] = 'page';
$modified_args['show_option_no_change'] = __( '=== Select Events here below: ===' );
$modified_args['show_option_none'] = false;
// Add the 'event' drop-down
add_filter( 'wp_dropdown_pages', function( $output ) use ( $modified_args )
{
// Only run it once
if( ! did_action( 'wpse_dropdown' ) )
{
do_action( 'wpse_dropdown' );
// Create our second drop-down for events
$output .= wp_dropdown_pages( $modified_args );
// Adjust the output, so we only got a single drop-down
$output = str_replace(
[ "<select name='parent_id' id='parent_id'>", "</select>"],
'',
$output
);
$output = "<select name='parent_id' id='parent_id'>" . $output . "</select>";
}
return $output;
} );
}
return $dropdown_args;
}
ここでは、2つの階層型ドロップダウンは、空の ===下のSelect Eventsの下にある:=== オプションで区切られています。
例:
"(no parent)"
"About the Music Hall"
"History"
"Location"
"Tickets"
"=== Select Events here below: ==="
"Concerts"
"Of Monsters and Men"
"Vienna Philharmonic Orchestra"
omam-info
slugを使用して Of Monsters And Men - Info というページを作成し、omam
slugを使用してイベントとして Of Monsters And Men を選択したとします。
それからパスは
example.tld/omam/omam-info
しかし、これは404エラーになります。これは、メインクエリに対する\WP_Query
クラス内のget_page_path()
チェックが失敗するためです。
if ( '' != $qv['pagename'] ) {
$this->queried_object = get_page_by_path($qv['pagename']);
if ( !empty($this->queried_object) )
$this->queried_object_id = (int) $this->queried_object->ID;
else
unset($this->queried_object);
これは、ここでget_page_by_path()
がpage
とattachment
の投稿タイプのみをチェックし、event
の投稿タイプはチェックしないためです。残念ながら、それを変更するための明示的なフィルタはありません。
もちろん、上記のようにquery
フィルタを使用することもできますが、別の回避策を試してみましょう。
queried_object_id
オブジェクトの割り当てられていないプロパティqueried_object_id
と\WP_Query
を調整することができます。
/**
* Support for page slugs with any kind event parent hierarchy
*
* @link http://wordpress.stackexchange.com/a/204439/26350
*/
add_action( 'pre_get_posts', function( \WP_Query $q )
{
if(
! is_admin() // Front-end only
&& $q->is_main_query() // Target the main query
&& $q->get( 'pagename' ) // Check for pagename query variable
&& ! $q->get( 'post_type' ) // Target the 'page' post type
&& $page = get_page_by_path( $q->get( 'pagename' ), OBJECT, [ 'page', 'event', 'attachment' ] )
) {
if( is_a( $page, '\WP_Post' ) )
{
$q->queried_object_id = $page->ID;
$q->queried_object = $page;
}
}
} );
これはまた、次のような任意の数のイベント親をサポートするはずです。
ecample.tld/event-grandparent/event-parent/event-child/page-slug
edit.php
画面の親ドロップダウンには、上で使用したquick_edit_dropdown_pages_args
フィルタの代わりにpage_attributes_dropdown_pages_args
フィルタを使用することができます。
まず、コア ページ属性 メタボックスを削除してから、親投稿タイプを変更する以外はすべてをそのままの状態に保って自分で追加します。これが私のコードです。あなたのevents
投稿タイプで動作するように調整されています。コピー/貼り付けの準備をしましたが、エラーが発生した場合はお知らせください。
/* Remove the core Page Attribute Metabox */
function event_remove_pa_meta_boxes() {
remove_meta_box( 'pageparentdiv', 'page', 'side' );
}
add_action( 'do_meta_boxes', 'event_remove_pa_meta_boxes' );
/* Set the Page Attribute Metabox again*/
function events_pa_meta_box( $post ) {
add_meta_box(
'event-select',
__( 'Page Attributes', 'textdomain' ),
'events_selectors_box',
'page',
'side',
'core'
);
}
add_action( 'add_meta_boxes_page', 'events_pa_meta_box' );
/* Recreate the meta box. */
function events_selectors_box( $post ) {
/* Set Events as Post Parent */
$parents = get_posts(
array(
'post_type' => 'event',
'orderby' => 'title',
'order' => 'ASC',
'numberposts' => -1
)
);
echo '<p><strong>Parent</strong></p><label class="screen-reader-text" for="parent_id">Parent</label>';
if ( !empty( $parents ) ) {
echo '<select id="parent_id" name="parent_id">';
foreach ( $parents as $parent ) {
printf( '<option value="%s"%s>%s</option>', esc_attr( $parent->ID ), selected( $parent->ID, $post->post_parent, false ), esc_html( $parent->post_title ) );
}
echo '</select>';
} else {
echo '<p>Please <a href="' . admin_url( "post-new.php?post_type=event" ) . '">create an event first</a>.</p>';
}
/* Page Templates */
if ( 'page' == $post->post_type && 0 != count( get_page_templates( $post ) ) && get_option( 'page_for_posts' ) != $post->ID ) {
$template = !empty($post->page_template) ? $post->page_template : false;
echo '<p><strong>Template</strong></p><label class="screen-reader-text" for="page_template">Page Template</label>';
echo '<select id="page_template" name="page_template">';
$default_title = apply_filters( 'default_page_template_title', __( 'Default Template' ), 'meta-box' );
echo '<option value="default">' . esc_html( $default_title ) . '</option>'
page_template_dropdown($template);
echo '</select>';
}
/* Page Order */
echo '<p><strong>' . _e('Order') .'</strong></p>';
echo '<label class="screen-reader-text" for="menu_order">'. _e('Order') . '</label><input name="menu_order" type="text" size="4" id="menu_order" value="'. esc_attr($post->menu_order) .'" />';
/* Help Paragraph */
if ( 'page' == $post->post_type && get_current_screen()->get_help_tabs() ) { ?>
echo '<p>' . _e( 'Need help? Use the Help tab in the upper right of your screen.' ) . '</p>';
}
}
編集: ページ属性メタボックスのデフォルトの引数を変更するために利用可能なフィルタがあることに気付いた:
$dropdown_args = array(
'post_type' => $post->post_type,
'exclude_tree' => $post->ID,
'selected' => $post->post_parent,
'name' => 'parent_id',
'show_option_none' => __('(no parent)'),
'sort_column' => 'menu_order, post_title',
'echo' => 0,
);
$dropdown_args = apply_filters( 'page_attributes_dropdown_pages_args', $dropdown_args, $post );
だから、あなたが望むことをするための超簡単な方法があるかもしれません。