El desafío que intentamos asumir aquí es cómo:
Suponemos que estamos en la pantalla de edición de una sola página y queremos agregar el tipo de publicación event
al page
menú desplegable principal .
La lista desplegable se muestra mediante la función wp_dropdown_pages()
, que llama a la función get_pages()
. Solo soporta un único tipo de publicación.
Aquí hay dos formas de hacer esto:
Método # 1 - Modificar SQL
Esta es una forma experimental, ya que trata con las modificaciones de SQL.
Ya que no hay una forma obvia de filtrar la consulta SQL generada en get_pages()
, podemos usar el filtro general query
para nuestras necesidades.
Para hacer que el menú desplegable sea más fácil de usar, cuando contiene títulos de varios tipos de publicaciones, usamos el filtro list_pages
, para anteponer la información del tipo de publicación.
Ejemplo :
Entonces, en lugar de mostrar las opciones como:
"(no parent)"
"About the Music Hall"
"History"
"Location"
"Concerts"
"Of Monsters and Men"
"Vienna Philharmonic Orchestra"
"Tickets"
obtenemos:
"(no parent)"
"page - About the Music Hall"
"page - History"
"page - Location"
"event - Concerts"
"event - Of Monsters and Men"
"event - Vienna Philharmonic Orchestra"
"page - Tickets"
Complemento de demostración:
Aquí está el fragmento de código que se podría colocar en un complemento para la prueba:
/**
* 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 );
donde:
function wpse_add_post_type_info_in_options ( $title, $page )
{
return $page->post_type . ' - ' . $title;
}
y un poco de limpieza:
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;
} );
Método # 2: solo usa wp_dropdown_pages()
Aquí dejamos que wp_dropdown_pages()
se ejecute dos veces y luego lo combinamos en un solo desplegable; una vez para el tipo de publicación page
y otra vez para el tipo de publicación 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;
}
Aquí, los dos menús desplegables jerárquicos están separados por la opción vacía === Seleccionar eventos a continuación: === .
Ejemplo :
"(no parent)"
"About the Music Hall"
"History"
"Location"
"Tickets"
"=== Select Events here below: ==="
"Concerts"
"Of Monsters and Men"
"Vienna Philharmonic Orchestra"
Ajustando la consulta principal
Supongamos ahora que creamos una página llamada Of Monsters And Men - Info con el slug omam-info
y seleccionamos el evento Of Monsters And Men como padre, con el omam
slug.
Entonces el camino sería
example.tld/omam/omam-info
pero esto da un error 404. La razón es que la comprobación get_page_path()
dentro de la clase \WP_Query
, para la consulta principal, falla:
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);
Esto se debe a que aquí get_page_by_path()
solo verifica los tipos de publicación page
y attachment
, no el tipo de publicación event
. Desafortunadamente no hay un filtro explícito para cambiar eso.
Por supuesto, podríamos usar el filtro query
, como hicimos anteriormente, pero intentemos otra solución.
Podemos intentar ajustar las propiedades no asignadas queried_object_id
y queried_object_id
del objeto \WP_Query
con:
/**
* 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;
}
}
} );
Esto también debería admitir cualquier cantidad de padres de eventos, como la siguiente jerarquía:
ecample.tld/event-grandparent/event-parent/event-child/page-slug
Nota
Para los desplegables principales en la pantalla edit.php
, podríamos usar el filtro quick_edit_dropdown_pages_args
, en lugar del filtro page_attributes_dropdown_pages_args
que usamos anteriormente.