Удаляем тип поста Magic Fields из url

Плагин Magic Fields практически полностью игнорируют настройки ЧПУ, устанавливаемые в панели управления WordPress. Он использует свои собственные, генерируя достаточно простые ЧПУ, которыми, к сожалению, нельзя управлять. В основе всегда лежит тип записи (это требование WP). Затем следует имя таксономии и имя самой записи или имя страницы, если за основу была взята модель страниц (capability type page). На форумах очень часто встречается вопрос о том, как убрать тип записи из ссылок.

Проблему рождает не особенность работы Magic Fields 2, а роутинг WordPress, который обязывает передавать значение post type, иначе поиск запрошенной записи будет производиться среди стандартных типов.

Рассмотрю ситуацию на живом примере.




Допустим, ссылка выглядит следующим образом:
/firearms/огнестрельное-оружие/снайперские-винтовки/

При этом имеем дерево страниц вида:

  • огнестрельное-оружие
    • снайперские-винтовки
    • штурмовые винтовки
    • ручные пулеметы

Если обратиться по адресу /firearms/, то получим 404 ошибку, так как ничего, кроме типа записи (post type) мы в таком случае не передаем. Но необходимо, чтобы по этому url отображался, например, рубрикатор или вводный материал.

firearms, в данном конкретном случае, дублирует сегмент «огнестрельное-оружие» (страница) и от него требуется избавиться. В url он присутствует только для того, чтобы за него могли зацепиться rewrite правила, которые создает Magic Fields при добавление нового типа.

Для начала пример того, как относительно безопасно вырезать из permalink тип записи. Это решение «в лоб», поэтому можете поискать более оптимальный вариант.

add_filter('post_link', 'rebuild_links', 10, 3);
add_filter('post_type_link', 'rebuild_links', 10, 3);

function rebuild_links($permalink, $post_id, $leavename) {
    global $catalog_post_types;

    preg_match_all('#/((' . implode('|', array_keys($catalog_post_types)) . ')/)#uim', $permalink, $custom_tax_slug);

    if (empty($custom_tax_slug) || !array_key_exists(1, $custom_tax_slug)) {
        return $permalink;
    } else {
        $start = mb_strpos($permalink, $custom_tax_slug[1][0]);
        $finish = mb_strlen($custom_tax_slug[1][0]);

        $permalink = substr_replace($permalink, '', $start, $finish);
    }

    return $permalink;
}

Массив $catalog_post_types имеет следующий вид:

$catalog_post_types = array(
    'firearms' => 'огнестрельное-оружие',
    'designers' => 'конструкторы'
);

Самый простой и удобный способ убедить WordPress воспринимать новые урлы – создать дополнительные правила роутинга, добавив их в числе первых. За основу я взял набор правил, добавляемых самим Magic Fields.

С задачей справляется следующий код:

if (!function_exists('myadd_rules')) {
    add_action('init', 'myadd_rules');

    function myadd_rules() {
        global $catalog_post_types;
    
        foreach ($catalog_post_types as $pt => $r) {
            add_rewrite_rule( $r . '$', 'index.php?' . $pt . '=' . $r, 'top');
            add_rewrite_rule( $r . '/.+?/attachment/([^/]+)/?$', 'index.php?attachment=$matches[1]', 'top');
            add_rewrite_rule( $r . '/.+?/attachment/([^/]+)/trackback/?$', 'index.php?attachment=$matches[1]&tb=1', 'top');
            add_rewrite_rule( $r . '/.+?/attachment/([^/]+)/feed/(feed|rdf|rss|rss2|atom)/?$', 'index.php?attachment=$matches[1]&feed=$matches[2]', 'top');
            add_rewrite_rule( $r . '/.+?/attachment/([^/]+)/(feed|rdf|rss|rss2|atom)/?$', 'index.php?attachment=$matches[1]&feed=$matches[2]', 'top');
            add_rewrite_rule( $r . '/.+?/attachment/([^/]+)/comment-page-([0-9]{1,})/?$', 'index.php?attachment=$matches[1]&cpage=$matches[2]', 'top');
            add_rewrite_rule( $r . '/(.+?)/trackback/?$', 'index.php?' . $pt . '=' . $r . '/$matches[1]&tb=1', 'top');
            add_rewrite_rule( $r . '/(.+?)/feed/(feed|rdf|rss|rss2|atom)/?$', 'index.php?' . $pt . '=' . $r . '/$matches[1]&feed=$matches[2]', 'top');
            add_rewrite_rule( $r . '/(.+?)/(feed|rdf|rss|rss2|atom)/?$', 'index.php?' . $pt . '=' . $r . '/$matches[1]&feed=$matches[2]', 'top');
            add_rewrite_rule( $r . '/(.+?)/page/?([0-9]{1,})/?$', 'index.php?' . $pt . '=' . $r . '/$matches[1]&paged=$matches[2]', 'top');
            add_rewrite_rule( $r . '/(.+?)/comment-page-([0-9]{1,})/?$', 'index.php?' . $pt . '=' . $r . '/$matches[1]&cpage=$matches[2]', 'top');
            add_rewrite_rule( $r . '/(.+?)(/[0-9]+)?/?$', 'index.php?' . $pt . '=' . $r . '/$matches[1]&page=$matches[2]', 'top');
        }
    
        flush_rewrite_rules();
    }
}

В продакшен такой код пропускать нельзя из-за неограниченного использования функции сброса кэша правил flush_rewrite_rules(). При каждом обновлении страницы правила будут перезаписываться в базе, что лишено всякого смысла и генерирует лишний запрос на запись.

Сбрасывайте правила либо вручную, либо можно завернуть все это в плагин со страницей персональных настроек.

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *