WordPress hwk Blog Créer des Sous-Pages Dynamiques de Post Type avec des Permaliens Personnalisés

Créer des Sous-Pages Dynamiques de Post Type avec des Permaliens Personnalisés

20 January 2018

Les Custom Post Types permettent de créer, gérer et afficher différents types de contenus tout en gardant un contrôle total sur leurs configurations et affichages. Avec cette fonctionnalité native de WordPress, il est possible de créer une structure de données complexe, avec des permaliens personnalisables. Mais nous pouvons aller encore plus loin, et ajouter un deuxième niveau de sous-pages dynamiques. C’est ce que nous allons découvrir dans ce tutoriel.

Rien de mieux qu’un exemple pour mieux comprendre ce que nous allons achever. Imaginons que nous avons un post type film. L’URL de l’archive est /films et la vue single est /film/interstellar. Maintenant, imaginons que chaque film contient énormément de contenus, si bien qu’il serait judicieux de le découper en différentes sous-parties. Par exemple: /film/interstellar/acteurs ou encore  /film/interstellar/critiques.

En allant plus loin, nous pourrions même configurer des liens de sous-pages avec des mots-clefs dynamiques. Par exemple: /film/interstellar/acteurs-{mot-clef-personnalise}. Le {mot-clef-personnalise} serait alors un post_meta défini manuellement pour chaque post de type film. Avec une telle configuration, les permaliens sont optimisés pour le SEO, avec de nombreuses sous-pages uniques reliés à un parent!

Création d’une de configurations

Afin de gérer nos sous-pages nous allons utiliser notre propre filtre hwk/post_types/subpages. Ci-dessous, deux exemples d’utilisation possibles:

<?php
/**
* Dynamic Post Type Subpages
* Exemple Simple
*/
add_filter('hwk/post_types/subpages', 'hwk_post_type_film_subpages_simple');
function hwk_post_type_film_subpages_simple($settings){
$settings[] = array(
'post_type' => 'film',
'meta_prefix' => 'ptsp_',
'pages' => array(
// Result: /film/interstellar/acteurs
array(
'title' => 'Acteurs', // Titre qui sert à l'administration.
'name' => 'acteurs', // Slug des Query Vars & URL de base de la Sous-Page
'rewrite' => false, // Activation/Désactivation du Permalien dynamique.
'primary' => false, // Remplacer l'URL de base du Post Type. Unique, un seul possible.
'pagination' => false, // Activer la pagination (/page/2/)
'template' => 'single-film-acteurs.php' // Fichier de template. Peut être vide
),
// Result: /film/interstellar/critiques
array(
'title' => 'Critiques',
'name' => 'critiques',
'rewrite' => false,
'primary' => false,
'pagination' => false,
'template' => 'single-film-critiques.php'
),
)
);
return $settings;
}
/**
* Dynamic Post Type Subpages
* Exemple Avancé
*/
add_filter('hwk/post_types/subpages', 'hwk_post_type_film_subpages_advanced');
function hwk_post_type_film_subpages_advanced($settings){
$settings[] = array(
'post_type' => 'film',
'meta_prefix' => 'ptsp_',
'pages' => array(
// Result: /film/interstellar/fiche
// Utilisation de primary = true.
// Fiche devient la nouvelle URL principale de la single 'film'
array(
'title' => 'Fiche',
'name' => 'fiche',
'rewrite' => false,
'primary' => true,
'pagination' => false,
'template' => 'single-film-fiche.php'
),
// Result: /film/interstellar/acteurs-{post_meta:ptsp_acteurs}-liste
array(
'title' => 'Acteurs',
'name' => 'acteurs',
'rewrite' => array(
'prepend' => 'acteurs',
'append' => 'liste',
),
'primary' => false,
'pagination' => true,
'template' => 'single-film-acteurs.php'
),
// Result: /film/interstellar/critiques-{post_meta:ptsp_critiques}
array(
'title' => 'Critiques',
'name' => 'critiques',
'rewrite' => array(
'prepend' => 'critiques',
),
'primary' => false,
'pagination' => true,
'template' => 'single-film-critiques.php'
),
)
);
return $settings;
}

Création des fonctions

Comme d’habitude, nous aurons besoin de différentes fonctions pour nous aider à travailler avec notre configuration.

<?php
// Post Type Subpages: Settings
function hwk_ptsp_settings(){
return apply_filters('hwk/post_types/subpages', array());
}
// Post Type Subpages: Récupération des Post Types
function hwk_ptsp_get_post_types(){
if(!$settings = hwk_ptsp_settings())
return false;
return $settings;
}
// Post Type Subpages: Récupération d'un Post Type en paroculier
function hwk_ptsp_get_post_type($target_post_type){
if(!$post_types = hwk_ptsp_get_post_types())
return false;
foreach($post_types as $post_type){
if($post_type['post_type'] != $target_post_type)
continue;
return $post_type;
}
return false;
}
// Post Type Subpages: Récupération du paramètre 'Rewrite' d'un Post Type particulier
function hwk_ptsp_get_post_type_rewrite($post_type){
if(!($post_type_object = get_post_type_object($post_type)) || !($post_type_object_rewrite = $post_type_object->rewrite))
return false;
return $post_type_object_rewrite['slug'];
}
// Post Type Subpages: Récupération de la sous-page 'primary' si elle existe dans un Post Type particulier
function hwk_ptsp_post_type_has_primary($target_post_type){
if(!$post_types = hwk_ptsp_get_post_types())
return;
foreach($post_types as $post_type){
if($post_type['post_type'] != $target_post_type)
continue;
foreach($post_type['pages'] as $page){
if($page['primary'])
return $page;
}
}
return false;
}
// Post Type Subpages: Récupération d'une sous-page en particulier, dans un Post Type en particulier
function hwk_ptsp_get_page($page_name, $target_post_type){
if( !($post_type = hwk_ptsp_get_post_type($target_post_type)) || !isset($post_type['pages']) || empty($post_type['pages']) )
return false;
foreach($post_type['pages'] as $page){
if($page['name'] != $page_name)
continue;
return $page;
}
return false;
}
// Post Type Subpages: Récupération du paramètre 'rewrite' d'une page en particulier. Permalien dynamique?
function hwk_ptsp_page_has_rewrite($page){
if( isset($page['rewrite']) && (isset($page['rewrite']['prepend']) || isset($page['rewrite']['append'])) )
return $page['rewrite'];
return false;
}
// Post Type Subpages: Récupération de la règle Regex pour le permalien d'une page en particulier
function hwk_ptsp_get_page_rewrite_output($page, $slug){
if(!hwk_ptsp_page_has_rewrite($page))
return $page['name'];
if(isset($page['rewrite']['prepend']) && !empty($page['rewrite']['prepend']))
$slug = $page['rewrite']['prepend'] . '' . $slug;
if(isset($page['rewrite']['append']) && !empty($page['rewrite']['append']))
$slug .= '' . $page['rewrite']['append'];
return $slug;
}
// Post Type Subpages: Création des Règles de Rewrite Rules
add_action('generate_rewrite_rules', 'hwk_ptsp_rewrite_rules');
function hwk_ptsp_rewrite_rules($wp_rewrite){
if(!$post_types = hwk_ptsp_get_post_types())
return;
$wp_rules = $wp_rewrite->rules;
$new_rules = array();
foreach($post_types as $post_type){
if(!$post_type_rewrite = hwk_ptsp_get_post_type_rewrite($post_type['post_type']))
continue;
foreach($post_type['pages'] as $page){
$tag = '([^/]+)';
$prepend = $append = false;
if(hwk_ptsp_page_has_rewrite($page)){
if(isset($page['rewrite']['prepend']) && !empty($page['rewrite']['prepend']))
$tag = $page['rewrite']['prepend'] . '' . $tag;
if(isset($page['rewrite']['append']) && !empty($page['rewrite']['append']))
$tag .= '' . $page['rewrite']['append'];
$match = '&ptsp=$matches[2]';
$paged = '&paged=$matches[3]';
}
else{
$tag = $page['name'];
$match = '&ptsp=' . $page['name'];
$paged = '&paged=$matches[2]';
}
if($page['pagination'])
$new_rules[$post_type_rewrite . '/([^/]+)/' . $tag . '/page/([0-9]{1,})/?$'] = 'index.php?' . $post_type['post_type'] . '=$matches[1]' . $match . $paged;
$new_rules[$post_type_rewrite . '/([^/]+)/' . $tag . '/?$'] = 'index.php?' . $post_type['post_type'] . '=$matches[1]' . $match;
}
}
$wp_rewrite->rules = array_merge($new_rules, $wp_rules);
}
// Post Type Subpages: Ajout des Query Vars
add_filter('query_vars', 'hwk_ptsp_query_vars');
function hwk_ptsp_query_vars($vars){
if(!$post_types = hwk_ptsp_get_post_types())
return $vars;
$vars[] = 'ptsp';
return $vars;
}
// Post Type Subpages: Création des redirections
add_action('template_redirect', 'hwk_ptsp_redirect');
function hwk_ptsp_redirect(){
if( !($post_id = get_the_ID()) || !($post_types = hwk_ptsp_get_post_types()) || !get_query_var('ptsp') )
return;
foreach($post_types as $post_type){
if(!is_singular($post_type['post_type']))
continue;
$query_var = false;
foreach($post_type['pages'] as $page){
if(get_query_var('ptsp') != $page['name'])
continue;
// Si pas de Page Rewrite et Query Var différent de la page OU Page Rewrite activé et Page Meta disponible mais ne correspond pas au Query Var: Redirection
$query_var = true;
$has_rewrite = hwk_ptsp_page_has_rewrite($page);
if( (!$has_rewrite && get_query_var('ptsp') != $page['name']) || ( $has_rewrite && ($slug = get_post_meta($post_id, $post_type['meta_prefix'] . $page['name'], true)) && get_query_var('ptsp') != $slug ) )
return wp_redirect(hwk_ptsp_get_sub_permalink($post_id, $page['name']), 301);
}
// Aucune Query Var et le Post Type a une Page Primaire
if(!$query_var && hwk_ptsp_post_type_has_primary($post_type['post_type']))
return wp_redirect(get_permalink($post_id), 301);
}
}
// Post Type Subpages: Templates
add_filter('template_include', 'hwk_ptsp_template', 9999);
function hwk_ptsp_template($template){
if( !($post_id = get_the_ID()) || !($post_types = hwk_ptsp_get_post_types()) || !get_query_var('ptsp') )
return $template;
foreach($post_types as $post_type){
if(!is_singular($post_type['post_type']))
continue;
foreach($post_type['pages'] as $page){
if(get_query_var('ptsp') != $page['name'] || !isset($page['template']) || empty($page['template']))
continue;
// Template de la Page par défaut
if($new_template = locate_template(array($page['template'])))
return $new_template;
}
}
return $template;
}
// Post Type Subpages: Saubegarde d'un post
add_action('save_post', 'hwk_ptsp_save_post', 10, 2);
function hwk_ptsp_save_post($post_id, $post){
if(!$post_type = hwk_ptsp_get_post_type($post->post_type))
return;
// Aucun Meta Parent: Création du meta par défaut
if(!get_post_meta($post_id, $post_type['meta_prefix'] . 'parent', true))
update_post_meta($post_id, $post_type['meta_prefix'] . 'parent', get_post_field('post_name', $post_id));
// Aucun Meta Page: Création des metas par défaut
foreach($post_type['pages'] as $page){
if( !get_post_meta($post_id, $post_type['meta_prefix'] . $page['name'], true) && hwk_ptsp_page_has_rewrite($page) )
update_post_meta($post_id, $post_type['meta_prefix'] . $page['name'], get_post_field('post_name', $post_id));
}
// Meta Parent: Sanitize & Update du post->name
if( ($new_slug = get_post_meta($post_id, $post_type['meta_prefix'] . 'parent', true)) && $new_slug != $post->post_name){
$new_slug = sanitize_title($new_slug);
wp_update_post(array(
'ID' => $post_id,
'post_name' => $new_slug
));
}
}
// Post Type Subpages: Mise à jour d'un post_meta
add_action('added_post_meta', 'hwk_ptsp_update_meta', 10, 4);
add_action('updated_post_meta', 'hwk_ptsp_update_meta', 10, 4);
function hwk_ptsp_update_meta($meta_id, $post_id, $meta_key, $meta_value){
if(!$post_type = hwk_ptsp_get_post_type(get_post_type($post_id)))
return;
// Meta Parent: Sanitize & Update du post->name
if($meta_key == $post_type['meta_prefix'] . 'parent'){
$new_slug = sanitize_title($meta_value);
update_post_meta($post_id, $post_type['meta_prefix'] . 'parent', $new_slug);
return wp_update_post(array(
'ID' => $post_id,
'post_name' => $new_slug
));
}
foreach($post_type['pages'] as $page){
if($meta_key != $post_type['meta_prefix'] . $page['name'])
continue;
// Meta Page: Sanitize & Update
return update_post_meta($post_id, $post_type['meta_prefix'] . $page['name'], sanitize_title($meta_value));
}
}
// Post Type Subpages: Hook get_permalink()
add_filter('post_link', 'hwk_ptsp_get_permalink', 10, 3);
add_filter('post_type_link', 'hwk_ptsp_get_permalink', 10, 3);
function hwk_ptsp_get_permalink($permalink, $post){
if(!$post_types = hwk_ptsp_get_post_types())
return $permalink;
foreach($post_types as $post_type){
// Mauvais Post Type ou le Post Type n'a pas de Page Primaire ou le Post Type n'a pas de Rewrite configuré
if(!isset($post->post_type) || $post->post_type != $post_type['post_type'] || !hwk_ptsp_post_type_has_primary($post_type['post_type']) || !($post_type_rewrite = hwk_ptsp_get_post_type_rewrite($post_type['post_type'])))
continue;
foreach($post_type['pages'] as $page){
// La Page n'est pas Primaire
if(!$page['primary'])
continue;
// Page Primaire activée – Pas de paramètre Rewrite: Afficher le Page Name de base
if( !hwk_ptsp_page_has_rewrite($page) )
return home_url(user_trailingslashit($post_type_rewrite . '/' . $post->post_name . '/' . $page['name']));
// Page Primaire activée – Paramètre Rewrite: Afficher l'URL dynamique
if( ($slug = get_post_meta($post->ID, $post_type['meta_prefix'] . $page['name'], true)) && !empty($slug) )
return home_url(user_trailingslashit($post_type_rewrite . '/' . $post->post_name . '/' . hwk_ptsp_get_page_rewrite_output($page, $slug) ));
}
}
return $permalink;
}
// Post Type Subpages: Nouvelle fonction pour récupérer le Permalien d'une sous-page
function hwk_ptsp_get_sub_permalink($post_id, $page_name = false){
if( !$page_name || !($post_types = hwk_ptsp_get_post_types()) )
return get_permalink($post_id);
foreach($post_types as $post_type){
// Mauvais Post Type ou le Post Type n'a pas de Rewrite activé
if( get_post_type($post_id) != $post_type['post_type'] || !($post_type_rewrite = hwk_ptsp_get_post_type_rewrite($post_type['post_type'])) )
continue;
// Si la Page n'existe pas, retourner l'URL du parent
if(!$page = hwk_ptsp_get_page($page_name, $post_type['post_type']))
return get_permalink($post_id);
// Si la page n'a pas de paramètre Rewrite: Afficher le Page Name de base
if( !hwk_ptsp_page_has_rewrite($page) )
return home_url(user_trailingslashit($post_type_rewrite . '/' . get_post_field('post_name', $post_id) . '/' . $page['name']));
// Retourner l'URL dynamique
if( ($slug = get_post_meta($post_id, $post_type['meta_prefix'] . $page_name, true)) && !empty($slug) )
return home_url(user_trailingslashit( $post_type_rewrite . '/' . get_post_field('post_name', $post_id) . '/' . hwk_ptsp_get_page_rewrite_output($page, $slug) ));
}
return get_permalink($post_id);
}
// Post Type Subpages: native Canonical
add_filter('get_canonical_url', 'hwk_ptsp_canonical', 10, 2);
function hwk_ptsp_canonical($canonical, $post){
if(!($post_types = hwk_ptsp_get_post_types()) || !get_query_var('ptsp'))
return $canonical;
foreach($post_types as $post_type){
if(!is_singular($post_type['post_type']))
continue;
foreach($post_type['pages'] as $page){
if(get_query_var('ptsp') != $page['name'])
continue;
return hwk_ptsp_get_sub_permalink($post->ID, $page['name']);
}
}
return $canonical;
}
// Post Type Subpages: YOAST Hooks
if(function_exists('wpseo_replace_vars')):
// Post Type Subpages: YOAST Canonical
add_filter('wpseo_canonical', 'hwk_ptsp_yoast_canonical');
function hwk_ptsp_yoast_canonical($canonical){
if( !($post_id = get_the_ID()) || !($post_types = hwk_ptsp_get_post_types()) || !get_query_var('ptsp') )
return $canonical;
foreach($post_types as $post_type){
if(!is_singular($post_type['post_type']))
continue;
foreach($post_type['pages'] as $page){
if(get_query_var('ptsp') != $page['name'])
continue;
return hwk_ptsp_get_sub_permalink($post_id, $page['name']);
}
}
return $canonical;
}
// Post Type Subpages: YOAST Title
add_filter('wpseo_title', 'hwk_ptsp_yoast_title');
function hwk_ptsp_yoast_title($title){
if( !($post_id = get_the_ID()) || !($post_types = hwk_ptsp_get_post_types()) || !get_query_var('ptsp') )
return $title;
foreach($post_types as $post_type){
if(!is_singular($post_type['post_type']))
continue;
foreach($post_type['pages'] as $page){
if(get_query_var('ptsp') != $page['name'])
continue;
// Page Primaire activée: Retourner le titre du meta Yoast
if( $page['primary'] && ($yoast_title = get_post_meta($post_id, '_yoast_wpseo_title', true)) && !empty($yoast_title) )
return $yoast_title;
// Page Primaire activée: Retourner le titre de l'option Yoast
if($page['primary'] && ($yoast_titles = get_option('wpseo_titles')) && isset($yoast_titles['title-' . $post_type['post_type']]) && !empty($yoast_titles['title-' . $post_type['post_type']]) )
return apply_filters('the_title', wpseo_replace_vars($yoast_titles['title-' . $post_type['post_type']], get_post($post_id)));
// Retourner le titre du meta
if($meta_title = get_post_meta($post_id, $post_type['meta_prefix'] . $page['name'] . '_meta_title', true) && !empty($meta_title))
return $meta_title;
// Retourner le titre de l'option Yoast
if( ($yoast_titles = get_option('wpseo_titles')) && isset($yoast_titles['title-' . $post_type['post_type']]) && !empty($yoast_titles['title-' . $post_type['post_type']]) )
return apply_filters('the_title', wpseo_replace_vars($page['title'] . ' ' . $yoast_titles['title-' . $post_type['post_type']], get_post($post_id)));
// Aucune condition remplis, retourner un titre générique
return $page['title'] . ' ' . get_the_title($post_id) . '' . get_bloginfo('name');
}
}
return $title;
}
// Post Type Subpages: YOAST Description
add_filter('wpseo_metadesc', 'hwk_ptsp_yoast_description');
function hwk_ptsp_yoast_description($description){
if( !($post_id = get_the_ID()) || !($post_types = hwk_ptsp_get_post_types()) || !get_query_var('ptsp') )
return $description;
foreach($post_types as $post_type){
if(!is_singular($post_type['post_type']))
continue;
foreach($post_type['pages'] as $page){
if(get_query_var('ptsp') != $page['name'])
continue;
// Page Primaire activée: Retourner la description du meta Yoast
if( $page['primary'] && ($yoast_desc = get_post_meta($post_id, '_yoast_wpseo_desc', true)) && !empty($yoast_desc) )
return $yoast_desc;
// Page Primaire activée: Retourner la description de l'option Yoast
if($page['primary'] && ($yoast_titles = get_option('wpseo_titles')) && isset($yoast_titles['metadesc-' . $post_type['post_type']]) && !empty($yoast_titles['metadesc-' . $post_type['post_type']]) )
return apply_filters('the_title', wpseo_replace_vars($yoast_titles['metadesc-' . $post_type['post_type']], get_post($post_id)));
// Retourner la description du meta
if($meta_desc = get_post_meta($post_id, $post_type['meta_prefix'] . $page['name'] . '_meta_description', true) && !empty($meta_desc))
return $meta_desc;
// Retourner la description de l'option Yoast
if( ($yoast_titles = get_option('wpseo_titles')) && isset($yoast_titles['metadesc-' . $post_type['post_type']]) && !empty($yoast_titles['metadesc-' . $post_type['post_type']]) )
return apply_filters('the_title', wpseo_replace_vars($page['title'] . ' ' . $yoast_titles['metadesc-' . $post_type['post_type']], get_post($post_id)));
// Aucune condition remplis, retourner une description générique
return $page['title'] . ' ' . get_the_title($post_id) . '' . get_bloginfo('name');
}
}
return $description;
}
endif;

Règles de ré-écriture

Règle

Commençons par hooker generate_rewrite_rules pour ajouter nos sous-pages pour chaque post_types. Ajout de la pagination dans le cas où le paramètre est défini à true.

<?php
// Post Type Subpages: Création des Règles de Rewrite Rules
add_action('generate_rewrite_rules', 'hwk_ptsp_rewrite_rules');
function hwk_ptsp_rewrite_rules($wp_rewrite){
if(!$post_types = hwk_ptsp_get_post_types())
return;
$wp_rules = $wp_rewrite->rules;
$new_rules = array();
foreach($post_types as $post_type){
if(!$post_type_rewrite = hwk_ptsp_get_post_type_rewrite($post_type['post_type']))
continue;
foreach($post_type['pages'] as $page){
$tag = '([^/]+)';
$prepend = $append = false;
if(hwk_ptsp_page_has_rewrite($page)){
if(isset($page['rewrite']['prepend']) && !empty($page['rewrite']['prepend']))
$tag = $page['rewrite']['prepend'] . '' . $tag;
if(isset($page['rewrite']['append']) && !empty($page['rewrite']['append']))
$tag .= '' . $page['rewrite']['append'];
$match = '&' . $page['name'] . '=$matches[2]';
$paged = '&paged=$matches[3]';
}else{
$tag = $page['name'];
$match = '&' . $page['name'] . '=' . $page['name'];
$paged = '&paged=$matches[2]';
}
if($page['pagination'])
$new_rules[$post_type_rewrite . '/([^/]+)/' . $tag . '/page/([0-9]{1,})/?$'] = 'index.php?' . $post_type['post_type'] . '=$matches[1]' . $match . $paged;
$new_rules[$post_type_rewrite . '/([^/]+)/' . $tag . '/?$'] = 'index.php?' . $post_type['post_type'] . '=$matches[1]' . $match;
}
}
$wp_rewrite->rules = array_merge($new_rules, $wp_rules);
}

Query Vars

Afin que WordPress utilise nos nouvelles query_vars, nous les ajoutons en hookant query_vars.

<?php
// Post Type Subpages: Ajout des Query Vars
add_filter('query_vars', 'hwk_ptsp_query_vars');
function hwk_ptsp_query_vars($vars){
if(!$post_types = hwk_ptsp_get_post_types())
return $vars;
foreach($post_types as $post_type){
foreach($post_type['pages'] as $page){
$vars[] = $page['name'];
}
}
return $vars;
}

Redirections

<?php
// Post Type Subpages: Création des redirections
add_action('template_redirect', 'hwk_ptsp_redirect');
function hwk_ptsp_redirect(){
if( !($post_id = get_the_ID()) || !($post_types = hwk_ptsp_get_post_types()) )
return;
foreach($post_types as $post_type){
if(!is_singular($post_type['post_type']))
continue;
$query_var = false;
foreach($post_type['pages'] as $page){
if(get_query_var($page['name'])){
$query_var = true;
// Si pas de Page Rewrite et Query Var différent de la page OU Page Rewrite activé et Page Meta disponible mais ne correspond pas au Query Var: Redirection
$has_rewrite = hwk_ptsp_page_has_rewrite($page);
if( (!$has_rewrite && get_query_var($page['name']) != $page['name']) || ( $has_rewrite && ($slug = get_post_meta($post_id, $post_type['meta_prefix'] . $page['name'], true)) && get_query_var($page['name']) != $slug ) )
return wp_redirect(hwk_ptsp_get_sub_permalink($post_id, $page['name']), 301);
}
}
// Aucune Query Var et le Post Type a une Page Primaire
if(!$query_var && hwk_ptsp_post_type_has_primary($post_type['post_type']))
return wp_redirect(get_permalink($post_id), 301);
}
}

Templates

<?php
// Post Type Subpages: Templates
add_filter('template_include', 'hwk_ptsp_template');
function hwk_ptsp_template($template){
if( !($post_id = get_the_ID()) || !($post_types = hwk_ptsp_get_post_types()) )
return $template;
foreach($post_types as $post_type){
if(!is_singular($post_type['post_type']))
continue;
foreach($post_type['pages'] as $page){
// Template de la Page par défaut
if( get_query_var($page['name']) && ($new_template = locate_template(array($page['template']))) )
return $new_template;
}
}
return $template;
}

Les Post Meta

<?php
// Post Type Subpages: Saubegarde d'un post
add_action('save_post', 'hwk_ptsp_save_post', 10, 2);
function hwk_ptsp_save_post($post_id, $post){
if(!$post_type = hwk_ptsp_get_post_type($post->post_type))
return;
// Aucun Meta Parent: Création du meta par défaut
if(!get_post_meta($post_id, $post_type['meta_prefix'] . 'parent', true))
update_post_meta($post_id, $post_type['meta_prefix'] . 'parent', get_post_field('post_name', $post_id));
// Aucun Meta Page: Création des metas par défaut
foreach($post_type['pages'] as $page){
if( !get_post_meta($post_id, $post_type['meta_prefix'] . $page['name'], true) && hwk_ptsp_page_has_rewrite($page) )
update_post_meta($post_id, $post_type['meta_prefix'] . $page['name'], get_post_field('post_name', $post_id));
}
// Meta Parent: Sanitize & Update du post->name
if( ($new_slug = get_post_meta($post_id, $post_type['meta_prefix'] . 'parent', true)) && $new_slug != $post->post_name){
$new_slug = sanitize_title($new_slug);
wp_update_post(array(
'ID' => $post_id,
'post_name' => $new_slug
));
}
}
// Post Type Subpages: Mise à jour d'un post_meta
add_action('added_post_meta', 'hwk_ptsp_update_meta', 10, 4);
add_action('updated_post_meta', 'hwk_ptsp_update_meta', 10, 4);
function hwk_ptsp_update_meta($meta_id, $post_id, $meta_key, $meta_value){
if(!$post_type = hwk_ptsp_get_post_type(get_post_type($post_id)))
return;
// Meta Parent: Sanitize & Update du post->name
if($meta_key == $post_type['meta_prefix'] . 'parent'){
$new_slug = sanitize_title($meta_value);
update_post_meta($post_id, $post_type['meta_prefix'] . 'parent', $new_slug);
return wp_update_post(array(
'ID' => $post_id,
'post_name' => $new_slug
));
}
foreach($post_type['pages'] as $page){
if($meta_key != $post_type['meta_prefix'] . $page['name'])
continue;
// Meta Page: Sanitize & Update
return update_post_meta($post_id, $post_type['meta_prefix'] . $page['name'], sanitize_title($meta_value));
}
}

Les Permaliens

<?php
// Post Type Subpages: Hook get_permalink()
add_filter('post_link', 'hwk_ptsp_get_permalink', 10, 3);
add_filter('post_type_link', 'hwk_ptsp_get_permalink', 10, 3);
function hwk_ptsp_get_permalink($permalink, $post){
if(!$post_types = hwk_ptsp_get_post_types())
return $permalink;
foreach($post_types as $post_type){
// Mauvais Post Type ou le Post Type n'a pas de Page Primaire ou le Post Type n'a pas de Rewrite configuré
if(!isset($post->post_type) || $post->post_type != $post_type['post_type'] || !hwk_ptsp_post_type_has_primary($post_type['post_type']) || !($post_type_rewrite = hwk_ptsp_get_post_type_rewrite($post_type['post_type'])))
continue;
foreach($post_type['pages'] as $page){
// La Page n'est pas Primaire
if(!$page['primary'])
continue;
// Page Primaire activée – Pas de paramètre Rewrite: Afficher le Page Name de base
if( !hwk_ptsp_page_has_rewrite($page) )
return home_url(user_trailingslashit($post_type_rewrite . '/' . $post->post_name . '/' . $page['name']));
// Page Primaire activée – Paramètre Rewrite: Afficher l'URL dynamique
if( ($slug = get_post_meta($post->ID, $post_type['meta_prefix'] . $page['name'], true)) && !empty($slug) )
return home_url(user_trailingslashit($post_type_rewrite . '/' . $post->post_name . '/' . hwk_ptsp_get_page_rewrite_output($page, $slug) ));
}
}
return $permalink;
}
// Post Type Subpages: Nouvelle fonction pour récupérer le Permalien d'une sous-page
function hwk_ptsp_get_sub_permalink($post_id, $page_name = false){
if( !$page_name || !($post_types = hwk_ptsp_get_post_types()) )
return get_permalink($post_id);
foreach($post_types as $post_type){
// Mauvais Post Type ou le Post Type n'a pas de Rewrite activé
if( get_post_type($post_id) != $post_type['post_type'] || !($post_type_rewrite = hwk_ptsp_get_post_type_rewrite($post_type['post_type'])) )
continue;
// Si la Page n'existe pas, retourner l'URL du parent
if(!$page = hwk_ptsp_get_page($page_name, $post_type['post_type']))
return get_permalink($post_id);
// Si la page n'a pas de paramètre Rewrite: Afficher le Page Name de base
if( !hwk_ptsp_page_has_rewrite($page) )
return home_url(user_trailingslashit($post_type_rewrite . '/' . get_post_field('post_name', $post_id) . '/' . $page['name']));
// Retourner l'URL dynamique
if( ($slug = get_post_meta($post_id, $post_type['meta_prefix'] . $page_name, true)) && !empty($slug) )
return home_url(user_trailingslashit( $post_type_rewrite . '/' . get_post_field('post_name', $post_id) . '/' . hwk_ptsp_get_page_rewrite_output($page, $slug) ));
}
return get_permalink($post_id);
}

Administration WordPress

<?php
// Post Type Subpages: Ajout permaliens sous le titre du Post dans l'Admin
add_action('edit_form_after_title', 'hwk_ptsp_edit_after_title');
function hwk_ptsp_edit_after_title($post){
if(!$post_types = hwk_ptsp_get_post_types())
return;
foreach($post_types as $post_type){
if(get_post_type() != $post_type['post_type'])
continue;
foreach($post_type['pages'] as $page){
if($page['primary'])
continue;
// Si la page a un paramètre Rewrite et qu'un Post Meta est défini avec un slug: Afficher l'URL
if( hwk_ptsp_page_has_rewrite($page) && ($slug = get_post_meta($post->ID, $post_type['meta_prefix'] . $page['name'], true)) && !empty($slug) ){
?>
<div id="edit-slug-box">
<strong>Permalien <?php echo $page['title']; ?> :</strong>
<a href="<?php echo hwk_ptsp_get_sub_permalink($post->ID, $page['name']); ?>"><?php echo hwk_ptsp_get_sub_permalink($post->ID, $page['name']); ?></a>
</div>
<?php
}
}
}
}

Compatibilité: YOAST

<?php
// Post Type Subpages: YOAST Hooks
if(function_exists('wpseo_replace_vars')):
// Post Type Subpages: YOAST Canonical
add_filter('wpseo_canonical', 'hwk_ptsp_yoast_canonical');
function hwk_ptsp_yoast_canonical($canonical){
if( !($post_id = get_the_ID()) || !($post_types = hwk_ptsp_get_post_types()) )
return $canonical;
foreach($post_types as $post_type){
if(!is_singular($post_type['post_type']))
continue;
foreach($post_type['pages'] as $page){
if(!get_query_var($page['name']))
continue;
return hwk_ptsp_get_sub_permalink($post_id, $page['name']);
}
}
return $canonical;
}
// Post Type Subpages: YOAST Title
add_filter('wpseo_title', 'hwk_ptsp_yoast_title');
function hwk_ptsp_yoast_title($title){
if( !($post_id = get_the_ID()) || !($post_types = hwk_ptsp_get_post_types()) )
return $title;
foreach($post_types as $post_type){
if(!is_singular($post_type['post_type']))
continue;
foreach($post_type['pages'] as $page){
if(!get_query_var($page['name']))
continue;
// Page Primaire activée: Retourner le titre du meta Yoast
if( $page['primary'] && ($yoast_title = get_post_meta($post_id, '_yoast_wpseo_title', true)) && !empty($yoast_title) )
return $yoast_title;
// Page Primaire activée: Retourner le titre de l'option Yoast
if($page['primary'] && ($yoast_titles = get_option('wpseo_titles')) && isset($yoast_titles['title-' . $post_type['post_type']]) && !empty($yoast_titles['title-' . $post_type['post_type']]) )
return apply_filters('the_title', wpseo_replace_vars($yoast_titles['title-' . $post_type['post_type']], get_post($post_id)));
// Retourner le titre du meta
if($meta_title = get_post_meta($post_id, $post_type['meta_prefix'] . $page['name'] . '_meta_title', true) && !empty($meta_title))
return $meta_title;
// Retourner le titre de l'option Yoast
if( ($yoast_titles = get_option('wpseo_titles')) && isset($yoast_titles['title-' . $post_type['post_type']]) && !empty($yoast_titles['title-' . $post_type['post_type']]) )
return apply_filters('the_title', wpseo_replace_vars($page['title'] . ' ' . $yoast_titles['title-' . $post_type['post_type']], get_post($post_id)));
// Aucune condition remplis, retourner un titre générique
return $page['title'] . ' ' . get_the_title($post_id) . '' . get_bloginfo('name');
}
}
return $title;
}
// Post Type Subpages: YOAST Description
add_filter('wpseo_metadesc', 'hwk_ptsp_yoast_description');
function hwk_ptsp_yoast_description($description){
if( !($post_id = get_the_ID()) || !($post_types = hwk_ptsp_get_post_types()) )
return $description;
foreach($post_types as $post_type){
if(!is_singular($post_type['post_type']))
continue;
foreach($post_type['pages'] as $page){
if(!get_query_var($page['name']))
continue;
// Page Primaire activée: Retourner la description du meta Yoast
if( $page['primary'] && ($yoast_desc = get_post_meta($post_id, '_yoast_wpseo_desc', true)) && !empty($yoast_desc) )
return $yoast_desc;
// Page Primaire activée: Retourner la description de l'option Yoast
if($page['primary'] && ($yoast_titles = get_option('wpseo_titles')) && isset($yoast_titles['metadesc-' . $post_type['post_type']]) && !empty($yoast_titles['metadesc-' . $post_type['post_type']]) )
return apply_filters('the_title', wpseo_replace_vars($yoast_titles['metadesc-' . $post_type['post_type']], get_post($post_id)));
// Retourner la description du meta
if($meta_desc = get_post_meta($post_id, $post_type['meta_prefix'] . $page['name'] . '_meta_description', true) && !empty($meta_desc))
return $meta_desc;
// Retourner la description de l'option Yoast
if( ($yoast_titles = get_option('wpseo_titles')) && isset($yoast_titles['metadesc-' . $post_type['post_type']]) && !empty($yoast_titles['metadesc-' . $post_type['post_type']]) )
return apply_filters('the_title', wpseo_replace_vars($page['title'] . ' ' . $yoast_titles['metadesc-' . $post_type['post_type']], get_post($post_id)));
// Aucune condition remplis, retourner une description générique
return $page['title'] . ' ' . get_the_title($post_id) . '' . get_bloginfo('name');
}
}
return $description;
}
endif;