In my plugin, I’m creating a custom post type that has an archive and uses the rewrite parameter to choose a slug:
$args = array (
'public' => true,
'has_archive' => true,
'rewrite' => array('slug' => 'lessons', 'with_front' => false)
);
register_post_type ('my_plugin_lesson', $args);
With this code, I get an archive of the ‘my_plugin_lesson’ posts at example.com/lessons/
.
However, I can also create a Page with the title “Lessons”, and WordPress will assign it the slug ‘lessons’. The View Page link on the admin panel for this page will be example.com/lessons/
, but the page is inaccessible because WordPress shows the archive for my custom post type.
Is there a way to prevent WordPress from choosing a slug for pages or posts that interfere with the slug of my custom post types?
2 Answers
I know you already find the solution, because you figured out this question was already asked and answered…
However, once this question is a bounty one and cannot be closed as duplicate, I want to make sense to this, and add (a bit of) additional value on the answers already posted.
What is done in those answers (the one by @RachelCarden and the one posted here by @matthew-boynes) is what you need, but it is hardcoded, i.e. you have to manually add the cpt archive slug in the filter function.
What I want to obtain is a filter that works in the same way, but dinamically, something like:
add_filter('wp_unique_post_slug_is_bad_hierarchical_slug', 'prevent_slug_override', 99, 3);
add_filter('wp_unique_post_slug_is_bad_flat_slug', 'prevent_slug_override', 99, 3);
function prevent_slug_override( $now, $slug, $type ) {
if ( in_array($type, array('nav_menu_item', 'revision', 'attachment') ) )
return $now;
$cpts = get_post_types( array('_builtin' => false), 'objects' );
$check_bad = array();
foreach ( $cpts as $cpt => $object ) {
if ( $object->has_archive ) {
if (
! empty($object->rewrite) && isset($object->rewrite['slug']) &&
! empty($object->rewrite['slug']) && ($object->rewrite['slug'] != $cpt)
) {
$check_bad[] = $object->rewrite['slug'];
} else {
$check_bad[] = is_string($object->has_archive) ? $object->has_archive : $cpt;
}
}
}
if ( in_array($slug, $check_bad) ) return true;
return $now;
}