我们在这里所面临的挑战是如何:
不要删除或替换当前的页面属性元框
在下拉列表中保留层次结构信息。
我们假设我们在单页编辑屏幕上,并希望添加event
将类型发布到page
父级下拉列表。
使用显示下拉列表wp_dropdown_pages()
函数,调用get_pages()
作用它只支持单个post类型。
有两种方法可以做到这一点:
方法#1-修改SQL这是一种实验方法,因为它处理SQL修改
因为没有明显的方法来过滤生成的SQL查询get_pages()
, 我们可以使用generalquery
根据我们的需要进行筛选。
为了使下拉列表更加用户友好,当它包含来自多个帖子类型的标题时,我们使用list_pages
过滤器,用于前置帖子类型信息。
Example:
因此,不要显示以下选项:
"(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"
Demo plugin:
以下是可以放在插件中进行测试的代码片段:
/**
* 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;
} );
方法#2-仅限使用wp_dropdown_pages()
我们让
wp_dropdown_pages()
运行两次,然后将其合并到一个下拉列表中;一次用于
page
发布类型和
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;
}
在这里,两个层次下拉列表由下面的空选择事件选项分隔开来。
一
/**
* 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 );
调整主查询假设现在我们创建了一个名为怪物和男人信息的页面omam-info
使用omam
鼻涕虫那么路径就是
example.tld/omam/omam-info
但这会产生404错误。原因是get_page_path()
检查内部\\WP_Query
类的主查询失败: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
我们在上面使用的过滤器。