星期四 , 17 4 月 2025

去除所有自定义分类链接中的slug和文章类型的slug版本一

<?php
/**
 * Remove taxonomy base from permalink URLs
 * This file is meant to be included in a theme or plugin
 */

/**
 * Remove taxonomy base from permalink URL for all taxonomies
 *
 * @param string $permalink The full permalink.
 * @param object $term The term object.
 * @param string $taxonomy The taxonomy name.
 * @return string Modified permalink without taxonomy base.
 */
function remove_taxonomy_base($permalink, $term, $taxonomy) {
    // Get all public taxonomies
    $public_taxonomies = get_taxonomies(array('public' => true), 'names');
    
    // Check if current taxonomy is in our list of public taxonomies
    if (in_array($taxonomy, $public_taxonomies)) {
        // Create clean permalink without the taxonomy base
        $permalink = home_url('/' . $term->slug . '/');
    }
    
    return $permalink;
}
add_filter('term_link', 'remove_taxonomy_base', 10, 3);

/**
 * Advanced rewrite rules to prevent 404 errors for all taxonomies
 */
function advanced_taxonomy_rewrite_rules() {
    // Get all public taxonomies
    $public_taxonomies = get_taxonomies(array('public' => true), 'names');
    
    // Process each taxonomy
    foreach ($public_taxonomies as $taxonomy) {
        // Get terms for this taxonomy
        $terms = get_terms(array(
            'taxonomy' => $taxonomy,
            'hide_empty' => false,
        ));
        
        // Create specific rewrite rules for each term
        if (!empty($terms) && !is_wp_error($terms)) {
            foreach ($terms as $term) {
                // Skip if the term slug might conflict with a potential post type or other reserved slugs
                if (is_reserved_term_slug($term->slug)) {
                    continue;
                }
                
                // Basic rule for term archive
                add_rewrite_rule(
                    '^' . $term->slug . '/?$',
                    'index.php?' . $taxonomy . '=' . $term->slug,
                    'top'
                );
                
                // Rule for pagination
                add_rewrite_rule(
                    '^' . $term->slug . '/page/([0-9]{1,})/?$',
                    'index.php?' . $taxonomy . '=' . $term->slug . '&paged=$matches[1]',
                    'top'
                );
                
                // If this is a hierarchical taxonomy, handle child terms too
                if (is_taxonomy_hierarchical($taxonomy) && $term->parent > 0) {
                    // Get the full term ancestry path
                    $ancestors = get_term_parents_list($term->term_id, $taxonomy, array(
                        'format' => 'slug',
                        'separator' => '/',
                        'link' => false,
                        'inclusive' => false
                    ));
                    
                    if (!empty($ancestors)) {
                        // Create rules for hierarchical paths
                        add_rewrite_rule(
                            '^' . trim($ancestors, '/') . '/' . $term->slug . '/?$',
                            'index.php?' . $taxonomy . '=' . $term->slug,
                            'top'
                        );
                        
                        add_rewrite_rule(
                            '^' . trim($ancestors, '/') . '/' . $term->slug . '/page/([0-9]{1,})/?$',
                            'index.php?' . $taxonomy . '=' . $term->slug . '&paged=$matches[1]',
                            'top'
                        );
                    }
                }
            }
        }
    }
}
add_action('init', 'advanced_taxonomy_rewrite_rules', 10);

/**
 * Check if a slug is reserved by WordPress core, plugins, or post types
 *
 * @param string $slug The term slug to check.
 * @return boolean True if the slug is reserved.
 */
function is_reserved_term_slug($slug) {
    // Common reserved WordPress slugs
    $reserved_slugs = array(
        'attachment', 'attachment_id', 'author', 'author_name', 'calendar',
        'cat', 'category', 'category_name', 'cpage', 'day', 'debug', 'error',
        'exact', 'feed', 'hour', 'link_category', 'm', 'minute', 'monthnum',
        'more', 'name', 'nav_menu_item', 'nopaging', 'offset', 'order', 'orderby',
        'p', 'page', 'page_id', 'paged', 'pagename', 'pb', 'post', 'post_type',
        'posts', 'preview', 'robots', 's', 'search', 'second', 'sentence',
        'tag', 'tag_id', 'taxonomy', 'tb', 'term', 'terms', 'theme', 'title',
        'type', 'w', 'year', 'comments_popup', 'admin', 'login', 'wp-admin',
        'wp-content', 'wp-includes', 'wp-json', 'comments', 'shop'
    );
    
    // Get all registered post types
    $post_types = get_post_types(array('public' => true), 'names');
    
    // Merge reserved slugs with post types
    $all_reserved = array_merge($reserved_slugs, $post_types);
    
    return in_array($slug, $all_reserved);
}

/**
 * Helper function to flush rewrite rules when needed
 */
function flush_taxonomy_rules() {
    advanced_taxonomy_rewrite_rules();
    flush_rewrite_rules();
}

/**
 * Add the flush rewrite rules action to admin_init for flushing when needed
 * This is a safer approach than flushing on every page load
 */
function maybe_flush_taxonomy_rules() {
    if (get_option('taxonomy_base_removal_flush_needed', 'yes') === 'yes') {
        flush_taxonomy_rules();
        update_option('taxonomy_base_removal_flush_needed', 'no');
    }
}
add_action('admin_init', 'maybe_flush_taxonomy_rules');

/**
 * Set flush flag when saving permalinks in admin or when a term is added/edited/deleted
 */
function set_taxonomy_flush_needed() {
    update_option('taxonomy_base_removal_flush_needed', 'yes');
}
add_action('created_term', 'set_taxonomy_flush_needed');
add_action('edited_term', 'set_taxonomy_flush_needed');
add_action('delete_term', 'set_taxonomy_flush_needed');
add_action('permalink_structure_changed', 'set_taxonomy_flush_needed');


function remove_cpt_slug($post_link, $post) {
    // Get all custom post types
    $args = array(
        'public'   => true,
        '_builtin' => false // This excludes default post types
    );
    $post_types = array_keys(get_post_types($args, 'names'));

    if (!in_array($post->post_type, $post_types) || 'publish' !== $post->post_status) {
        return $post_link;
    }
    
    //post_type_link 钩子是过滤文章单页的链接
    return str_replace('/' . $post->post_type . '/', '/', $post_link);
}
add_filter('post_type_link', 'remove_cpt_slug', 10, 2);

function parse_request_for_cpt($query) {
    if (!$query->is_main_query() || is_admin()) {
        return;
    }

    if (!isset($query->query['name'])) {
        return;
    }

    $path = trim($query->query['name'], '/');
    
    // Get all custom post types
    $args = array(
        'public'   => true,
        '_builtin' => false
    );
    $post_types = array_keys(get_post_types($args, 'names'));
    
    // Check each custom post type for matching post
    foreach ($post_types as $post_type) {
        $custom_post = get_page_by_path($path, OBJECT, $post_type);
        
        if ($custom_post) {
            $query->set('post_type', array($post_type));
            $query->set('name', $path);
            break;
        }
    }
}
add_action('pre_get_posts', 'parse_request_for_cpt');