Eliminar páginas padre de los enlaces permanentes
Preguntas similares se han hecho antes, pero ninguna respuesta se adapta bien.
Tengo: site.com/pagina-padre/pagina-hija
y me gustaría tener: site.com/pagina-hija
Quiero tener exclusivamente enlaces permanentes con profundidad 1, sin usar el menú personalizado pero manteniendo la jerarquía de páginas en la vista de administrador y con los atributos de página padre/orden.
La solución también debe funcionar automáticamente, sin cambiar manualmente los permalinks en cada página con plugins como "Custom Permalinks".
Esto es lo que necesito, y estoy seguro que es posible con unas pocas líneas de código en el functions.php
, que he encontrado en otros lugares pero solo para posts (para eliminar categorías), pero no funciona para páginas para eliminar el padre.
Este es el código, ¿quizás se pueda modificar para que funcione con páginas?
add_filter( 'post_link', 'remove_parent_cats_from_link', 10, 3 );
function remove_parent_cats_from_link( $permalink, $post, $leavename ) {
$cats = get_the_category( $post->ID );
if ( $cats ) {
// Asegurarse de usar la misma categoría inicial que el generador de permalinks
usort( $cats, '_usort_terms_by_ID' ); // ordenar por ID
$category = $cats[0]->slug;
if ( $parent = $cats[0]->parent ) {
// Si hay categorías padre, recolectarlas y reemplazarlas en el enlace
$parentcats = get_category_parents( $parent, false, '/', true );
// str_replace() no es la mejor solución si puede haber duplicados:
// ejemplo.com/luxemburgo/luxemburgo/ se reducirá a ejemplo.com/
// Pero si no esperas eso, debería funcionar
$permalink = str_replace( $parentcats, '', $permalink );
}
}
return $permalink;
}

Una búsqueda rápida muestra otro tema en StackExchange sobre esto, que utilizó este código para limpiar el enlace permanente de padres/ancestros:
function wpse_101072_flatten_hierarchies( $post_link, $post ) {
if ( 'page' != $post->post_type )
return $post_link;
$uri = '';
foreach ( $post->ancestors as $parent ) {
$uri = get_post( $parent )->post_name . "/" . $uri;
}
return str_replace( $uri, '', $post_link );
}
add_filter( 'post_type_link', 'wpse_101072_flatten_hierarchies', 10, 2 );
Puedes encontrar esa discusión aquí: Eliminar el slug del padre de la URL en tipos de contenido personalizados

Esto hace cosas divertidas :) Los que tienen un padre todavía se muestran con los padres, pero los que no tienen padre llevan a un 404 :D Y también se habla de tipos de posts personalizados, y Sebastián al final hace la misma pregunta que yo, cómo hacer que funcione para páginas, que quedó sin respuesta. Así que todavía espero que encuentre una respuesta.

tl;dr = Instala el plugin gratuito "Permalinks Customizer". Configura "PostTypes Settings" para Páginas como '%postname%' y luego edita las páginas para modificar los Permalinks respectivos. He probado esto con un escenario de páginas jerárquicas y no jerárquicas, y funciona sin dificultad.
La respuesta más extensa
El escenario planteado por el OP se basa en una página genérica y, en mi opinión, esto presenta un desafío significativo, posiblemente imposible, ya que la solución debe aplicarse de forma anónima. Es decir, no hay un "disparador" o "manejo" predecible que se pueda usar para crear una reescritura que genere una solicitud válida. Un tipo de entrada personalizada podría funcionar (o no), pero el OP ha descartado esta opción. El enfoque propuesto por el OP también conlleva el riesgo de páginas duplicadas. Teniendo esto en cuenta, uno podría sugerir que el enfoque propuesto por el OP no vale la pena ni es sabio, pero dejaré que el OP lo juzgue por sí mismo.
El OP tiene razón; la respuesta propuesta por Nicu no funciona porque esta línea tiene el efecto de construir el URI a partir de la jerarquía original.
$uri = get_post( $parent )->post_name . "/" . $uri;
He trabajado (sin éxito) en un filtro que cumpla con los requisitos del OP. Lo ofrezco aquí por si pudiera ser útil para alguien más. Para referencia, todas mis pruebas se realizaron con Permalinks configurados como "Nombre de la entrada", y cada vez que ajustaba un filtro, actualizaba la página de Permalinks. Creé cuatro páginas. Ancestros, Padres (padre = 'Ancestros'), Hijos (padre = 'Padres') y Transporte (sin padre).
Descubrí que crear el URI es la parte fácil, o al menos parece fácil. Esta alternativa (en functions.php) funciona:
function wpse_182006_pages_permalink( $link, $post_id) {
// obtiene el post_type y evalúa
$posttype = get_post_field( 'post_type', $post_id, 'display' );
if ($posttype !== 'page'){
return link;
}
// construye el URI a partir del slug
$slugname = get_post_field( 'post_name', $post_id, 'display' );
$slugname = $slugname."/";
$link = home_url($slugname);
return $link;
}
add_filter( 'page_link', 'wpse_182006_pages_permalink', 10, 3 );
Tanto las páginas "Ancestros" como "Transporte" se abren normalmente.
Las páginas "Padres" e "Hijos" (cada una con una página 'padre') generan errores 404.
Si observas la Consulta de Solicitud (ver más abajo), es evidente que el 404 se genera porque WordPress interpreta la "página" como una "entrada", y no existe tal entrada. Ten en cuenta que el ID de la entrada no se usa en las consultas fallidas. Quizás esta sea la clave para una reescritura exitosa, pero estaba más allá de mis habilidades.
Como referencia, estos son los detalles de "solicitud" para "Ancestros":
Consulta Coincidente = 'pagename=ancestory&page='
Regla Coincidente = '(.?.+?)(?:/([0-9]+))?/?$'
Consulta principal = SELECT wp_posts.* FROM wp_posts WHERE 1=1 AND (wp_posts.ID = '46') AND wp_posts.post_type = 'page' ORDER BY
wp_posts.post_date DESC
En comparación, estos son los detalles de "solicitud" para "Hijos":
Consulta Coincidente = 'name=children&page='
Regla Coincidente = '([^/]+)(?:/([0-9]+))?/?$'
Consulta principal = SELECT wp_posts.* FROM wp_posts WHERE 1=1 AND wp_posts.post_name = 'parents' AND wp_posts.post_type = 'post' ORDER BY wp_posts.post_date DESC
Por si acaso, al configurar el permalink de esta manera, el permalink no es editable. Antes:
Después:
