php — Usuń błąd wielu niestandardowych typów postów z hierarchią i bez niej
Mam dwa niestandardowe typy postów o nazwie toplijst i produkt. Próbuję osiągnąć następującą strukturę łącza bezpośredniego:
Toplijst:
website.com/toplijst/parent-toplijst/
website.com/toplijst/parent-toplijst/child-toplijst/
Powinno stać się:
website.com/parent-toplijst/ website.com/parent-toplijst/child-toplijst/
Produkt
website.com/product/product-post
Powinno stać się
strona internetowa.com/product-post
Typ postu produktowego nie jest typem postu hierarchicznego.
Mam zarejestrowany typ postu w następujący sposób:
require_once dirname(__FILE__) . '/../classes/class-slugless-rewrites.php';
// Create toplijst post type
function create_toplijst_post_type()
{
$labels = array(
'name' => _x('Toplijsten', 'post type general name', 'text-domain'),
'singular_name' => _x('Toplijst', 'post type singular name', 'text-domain'),
'menu_name' => _x('Toplijsten', 'admin menu', 'text-domain'),
'name_admin_bar' => _x('Toplijst', 'add new on admin bar', 'text-domain'),
'add_new' => _x('Add New', 'Toplijst', 'text-domain'),
'add_new_item' => __('Add New Toplijst', 'text-domain'),
'new_item' => __('New Toplijst', 'text-domain'),
'edit_item' => __('Edit Toplijst', 'text-domain'),
'view_item' => __('View Toplijst', 'text-domain'),
'all_items' => __('All Toplijsten', 'text-domain'),
'search_items' => __('Search Toplijsten', 'text-domain'),
'parent_item_colon' => __('Parent Toplijsten:', 'text-domain'),
'not_found' => __('No Toplijsten found.', 'text-domain'),
'not_found_in_trash' => __('No Toplijsten found in Trash.', 'text-domain')
);
$args = array(
'labels' => $labels,
'public' => true,
'publicly_queryable' => true,
'show_ui' => true,
'show_in_menu' => true,
'query_var' => true,
'show_in_rest' => true,
'rewrite' => false,
'has_archive' => 'toplijsten',
'capability_type' => 'post',
'hierarchical' => true,
'menu_position' => null,
'menu_icon' => 'dashicons-list-view',
'supports' => array('title', 'author', 'revisions', 'thumbnail', 'custom-fields', 'page-attributes')
);
register_post_type('toplijst', $args);
}
add_action('init', 'create_toplijst_post_type');
// Create producten post type
function create_producten_post_type()
{
$labels = array(
'name' => _x('Producten', 'post type general name', 'text-domain'),
'singular_name' => _x('Product', 'post type singular name', 'text-domain'),
'menu_name' => _x('Producten', 'admin menu', 'text-domain'),
'name_admin_bar' => _x('Product', 'add new on admin bar', 'text-domain'),
'add_new' => _x('Add New', 'Product', 'text-domain'),
'add_new_item' => __('Add New Product', 'text-domain'),
'new_item' => __('New Product', 'text-domain'),
'edit_item' => __('Edit Product', 'text-domain'),
'view_item' => __('View Product', 'text-domain'),
'all_items' => __('All Producten', 'text-domain'),
'search_items' => __('Search Producten', 'text-domain'),
'parent_item_colon' => __('Parent Producten:', 'text-domain'),
'not_found' => __('No Producten found.', 'text-domain'),
'not_found_in_trash' => __('No Producten found in Trash.', 'text-domain')
);
$args = array(
'labels' => $labels,
'public' => true,
'publicly_queryable' => true,
'show_ui' => true,
'show_in_menu' => true,
'query_var' => true,
'rewrite' => false,
'capability_type' => 'post',
'hierarchical' => false,
'menu_position' => null,
'menu_icon' => 'dashicons-star-filled', // Choose an appropriate dashicon
'supports' => array('title', 'author', 'revisions', 'thumbnail', 'custom-fields', 'page-attributes')
);
register_post_type('product', $args);
}
add_action('init', 'create_producten_post_type');
$slugless_rewrite_args = array(
'toplijst' => array(
'hierarchical' => true,
'has_archive' => true,
'archive_feeds' => false,
'archive_slug' => 'toplijsten'
),
'product' => array(
'hierarchical' => false,
'has_archive' => false,
'archive_feeds' => false
)
);
$slugless_rewrites = Slugless_Rewrites::get_instance($slugless_rewrite_args);
Jak widać, skonfigurowałem klasę Slugless_Rewrites do obsługi łączy bezpośrednich. Kod klasy znajduje się tutaj:
class Slugless_Rewrites
{
private $post_types = [];
private static $instance = null;
public static function get_instance($post_types)
{
if (self::$instance === null) {
self::$instance = new self($post_types);
}
return self::$instance;
}
private function __construct($post_types)
{
foreach ($post_types as $post_type => $args) {
$args = wp_parse_args($args, array(
'hierarchical' => false,
'has_archive' => false,
'archive_feeds' => false,
'archive_slug' => $post_type
));
$this->post_types[$post_type] = $args;
add_action('init', function () use ($post_type, $args) {
$this->add_rewrites($post_type, $args);
}, 20);
add_filter('rewrite_rules_array', function ($rules) use ($post_type) {
return $this->inject_rules($rules, $post_type);
});
}
add_filter('request', array($this, 'check_rewrite_conflicts'));
add_filter('query_vars', array($this, 'custom_query_vars'));
add_filter('post_type_link', array($this, 'modify_permalinks'), 10, 3);
add_filter('wp_unique_post_slug', array($this, 'prevent_slug_duplicates'), 10, 6);
}
public function __clone()
{
}
public function __wakeup()
{
}
private function add_rewrites($post_type, $args)
{
add_rewrite_tag("%{$post_type}_type%", '([^&]+)');
if ($args['hierarchical']) {
add_rewrite_rule(
'^' . $post_type . '/(.+)/([^/]+)(?:/([0-9]+))?/?$',
'index.php?post_type=" . $post_type . "&pagename=$matches[1]/$matches[2]&page=$matches[3]',
'top'
);
} else {
add_rewrite_rule(
'^' . $post_type . '/([^/]+)/?$',
'index.php?post_type=" . $post_type . "&name=$matches[1]',
'top'
);
}
}
private function inject_rules($rules, $post_type)
{
$new_rules = [
'^' . $post_type . '/(.+)/([^/]+)(?:/([0-9]+))?/?$' => 'index.php?post_type=" . $post_type . "&pagename=$matches[1]/$matches[2]&page=$matches[3]'
];
return $new_rules + $rules;
}
public function check_rewrite_conflicts($query_vars)
{
if (isset($query_vars['name'])) {
$post_type = $this->determine_post_type($query_vars['name']);
if ($post_type) {
do_action('qm/debug', 'Initial query vars: ' . $post_type);
$query_vars['post_type'] = $post_type;
} else {
foreach ($this->post_types as $type => $args) {
if ($args['hierarchical']) {
$path = $query_vars['pagename'] ?? $query_vars['name'];
$page = get_page_by_path($path, OBJECT, $type);
if ($page) {
$query_vars['post_type'] = $type;
$query_vars['pagename'] = $path;
unset($query_vars['name']);
do_action('qm/debug', 'Final query vars: ' . print_r($query_vars, true));
return $query_vars;
}
}
}
$page = get_page_by_path($query_vars['name']);
if ($page) {
$query_vars['post_type'] = 'page';
$query_vars['pagename'] = $query_vars['name'];
} else {
$query_vars['post_type'] = 'toplijst';
$query_vars['pagename'] = $query_vars['name'];
}
}
}
do_action('qm/debug', 'Final query vars: ' . print_r($query_vars, true));
return $query_vars;
}
private function determine_post_type($slug)
{
$post_types_to_check = array_merge(['page'], array_keys($this->post_types));
foreach ($post_types_to_check as $post_type) {
$posts = get_posts([
'name' => $slug,
'post_type' => $post_type,
'post_status' => 'publish',
'numberposts' => 1
]);
if (!empty($posts)) {
return $post_type;
}
}
return null;
}
public function custom_query_vars($query_vars)
{
foreach (array_keys($this->post_types) as $post_type) {
$query_vars[] = $post_type;
}
return $query_vars;
}
public function modify_permalinks($post_link, $post, $leavename)
{
foreach ($this->post_types as $post_type => $args) {
if ($post->post_type == $post_type) {
$slug = $post->post_name;
$parent_id = $post->post_parent;
while ($parent_id) {
$parent_post = get_post($parent_id);
$slug = $parent_post->post_name . " . $slug;
$parent_id = $parent_post->post_parent;
}
$slug = str_replace("{$post_type}/", '', $slug);
return home_url($slug);
}
}
return $post_link;
}
public function prevent_slug_duplicates($slug, $post_ID, $post_status, $post_type, $post_parent, $original_slug)
{
foreach ($this->post_types as $type => $args) {
if ($post_type != $type && !in_array($post_type, ['post', 'page'])) {
continue;
}
if (get_page_by_path($slug, OBJECT, $type)) {
return $slug . '-duplicate';
}
}
return $slug;
}
}
Klasa pomyślnie tworzy następującą strukturę:
Toplijst:
website.com/parent-toplijst/
Jednak dziecko-toplijst nie działa na:
website.com/parent-toplijst/child-toplijst/
To działa na:
website.com/child-toplijst/
Produkt
Działa zgodnie z oczekiwaniami.
Moje pytanie brzmi: jak mogę uzyskać hierarchiczny niestandardowy typ postu toplijst, aby działał z niestandardową strukturą, którą próbuję skonfigurować.
Zastanawiam się również, czy jest to najlepsza metoda przepisywania niestandardowych łączy bezpośrednich typu post.
Pomoc w tym problemie byłaby bardzo mile widziana!