Créer des Sous-Pages Dynamiques de Post Type avec des Permaliens Personnalisés
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; |