Добавьте все другие таксономии как мета-боксы в пользовательский тип записи.

Вопрос или проблема

У меня есть пользовательский тип записи, который имеет таксономию категории. Эта таксономия отображается как метаблок сбоку. Пока все довольно просто.

Теперь я хочу добавить дополнительные метаблоки под контентом в “нормальной” позиции. Я хочу отображать один метаблок для каждой публичной таксономии в системе. На данный момент я использую этот код для добавления блоков:

public function add_meta_boxes_rfe_taxonomy_related__premium_only($post)
{
    $taxonomies = get_taxonomies(['public' => true], 'objects');
    foreach ($taxonomies as $taxonomy) {

        if ('rfe_taxonomy_related_category' === $taxonomy->name) {
            continue;
        }

        $taxonomy_name = $taxonomy->labels->name;
        $taxonomy_slug = $taxonomy->name;
        $taxonomy_is_hierarchical = $taxonomy->hierarchical;
        $object_type = $taxonomy->object_type;

        $post_type_names = [];

        foreach ($object_type as $post_type) {
            $post_type_name = isset($post_type_names[$post_type]) ? $post_type_names[$post_type] : false;

            if (!$post_type_name) {
                $post_type_name = get_post_type_object($post_type)->label;
                $post_type_names[$post_type] = $post_type_name;
            }

            if ($taxonomy_is_hierarchical) {
                add_meta_box(
                    'rfe_taxonomy_related_meta_box_' . $taxonomy_slug, //ID
                    $taxonomy_name . ' (' . $post_type_name . ')', //Title
                    [$this, 'build_hierarchical_taxonomy_meta_box__premium_only'], //Callback
                    'rfe_taxonomy_related', //Post type to add to
                    'normal',
                    'low'
                );
            } else {
                add_meta_box(
                    'rfe_taxonomy_related_meta_box_' . $taxonomy_slug, //ID
                    $taxonomy_name . ' (' . $post_type_name . ')', //Title
                    [$this, 'build_flat_taxonomy_meta_box__premium_only'], //Callback
                    'rfe_taxonomy_related', //Post type to add to
                    'normal',
                    'low'
                );
            }
        }

    }
}

public function build_hierarchical_taxonomy_meta_box__premium_only($post, $metabox)
{
    $taxonomy_slug = substr($metabox['id'], strlen('rfe_taxonomy_related_meta_box_'));
    $box['args']['taxonomy'] = $taxonomy_slug;
    post_categories_meta_box($post, $box);
}

public function build_flat_taxonomy_meta_box__premium_only($post, $metabox)
{
    $taxonomy_slug = substr($metabox['id'], strlen('rfe_taxonomy_related_meta_box_'));
    $box['args']['taxonomy'] = $taxonomy_slug;
    post_tags_meta_box($post, $box);
}

Этот код уже добавляет мне метаблоки, но метаблоки для плоских таксономий, похоже, не работают. Я не могу добавить новые теги или выбрать из самых популярных.

Вторая проблема заключается в том, что, когда я сохраняю запись, все изменения пропадают. Я задаюсь вопросом, что я упускаю или делаю неправильно.

введите описание изображения здесь

Как предложил LWS-Mo, это можно сделать, используя register_taxonomy_for_object_type() чтобы зарегистрировать мой пользовательский тип записи для всех таксономий в системе, а затем использовать remove_meta_box() и add_meta_box, чтобы перезаписать их в новое место. Я не уверен, правильно ли я использую хуки, но, тем не менее, это работает 🙂

Стоит упомянуть, что все таксономии появляются под моим типом записи как подменю, поэтому мне также пришлось удалить элементы подменю.

Сначала добавьте хуки:

add_action('init', [$this, 'create_taxonomy_related_post_type__premium_only']);
add_action('wp_loaded', [$this, 'add_meta_boxes_rfe_taxonomy_related__premium_only']);
add_action('admin_init', [$this, 'rename_taxonomy_meta_boxes_on_rfe_taxonomy_related__premium_only']);
add_action('admin_menu', [$this, 'remove_taxonomy_menu_from_rfe_taxonomy_related__premium_only']);

Затем добавьте пользовательский тип записи с его собственной таксономией:

public function create_taxonomy_related_post_type__premium_only()
{
    register_post_type('rfe_taxonomy_related',
        array(
            'labels' => array(
                'name' => 'Taxonomy Related',
                'singular_name' => 'Taxonomy Related',
                'add_new' => 'Add New',
                'add_new_item' => 'Add New Layout',
                'edit' => 'Edit',
                'edit_item' => 'Edit Layout',
                'new_item' => 'New Layout',
                'view' => 'View',
                'view_item' => 'View Layout',
                'search_items' => 'Search Layouts',
                'not_found' => 'No Layouts found',
                'not_found_in_trash' => 'No Layouts found in Trash',
            ),
            'public' => true,
            'exclude_from_search' => true,
            'publicly_queryable' => false,
            'supports' => array('title', 'editor'),
            'taxonomies' => array('rfe_taxonomy_related_category'),
            'menu_icon' => 'dashicons-format-aside',
            'has_archive' => false,
        )
    );

    register_taxonomy(
        'rfe_taxonomy_related_category',
        array('rfe_taxonomy_related'),
        array(
            'hierarchical' => true,
            'labels' => array(
                'name' => __('Categories', 'jt-revolution-for-elementor'),
                'singular_name' => __('Category', 'jt-revolution-for-elementor'),
                'search_items' => __('Search Category', 'jt-revolution-for-elementor'),
                'all_items' => __('All Categories', 'jt-revolution-for-elementor'),
                'parent_item' => __('Parent Category', 'jt-revolution-for-elementor'),
                'parent_item_colon' => __('Parent Category:', 'jt-revolution-for-elementor'),
                'edit_item' => __('Edit Category', 'jt-revolution-for-elementor'),
                'update_item' => __('Update Category', 'jt-revolution-for-elementor'),
                'add_new_item' => __('Add New Category', 'jt-revolution-for-elementor'),
                'new_item_name' => __('New Category Name', 'jt-revolution-for-elementor'),
                'menu_name' => __('Categories', 'jt-revolution-for-elementor'),
            ),
            'show_ui' => true,
            'show_admin_column' => true,
            'query_var' => true,
        )
    );
}

Далее используйте register_taxonomy_for_object_type чтобы добавить каждую таксономию в системе к моему типу записи:

public function add_meta_boxes_rfe_taxonomy_related__premium_only($post)
{
    $args = array('public' => true);
    $output="objects";
    $taxonomies = get_taxonomies($args, $output);
    foreach ($taxonomies as $taxonomy) {
        if ('rfe_taxonomy_related_category' === $taxonomy->name) {
            continue;
        }
        register_taxonomy_for_object_type($taxonomy->name, 'rfe_taxonomy_related');
    }
}

Теперь я могу переместить метаблоки под контент, используя remove_meta_box и add_meta_box:

public function rename_taxonomy_meta_boxes_on_rfe_taxonomy_related__premium_only()
{
    //Сохранит отображаемые названия типов записей, чтобы мы могли их кешировать
    $post_type_names = [];

    $taxonomies = get_taxonomies(['public' => true], 'objects');

    foreach ($taxonomies as $taxonomy) {

        //Пропустить нашу собственную таксономию
        if ('rfe_taxonomy_related_category' === $taxonomy->name) {
            continue;
        }

        $taxonomy_name = $taxonomy->labels->name;
        $taxonomy_slug = $taxonomy->name;
        $taxonomy_post_types = [];

        $object_type = $taxonomy->object_type;
        foreach ($object_type as $post_type) {

            //Пропустить наш собственный тип записи
            if ('rfe_taxonomy_related' === $post_type) {
                continue;
            }

            $post_type_name = isset($post_type_names[$post_type]) ? $post_type_names[$post_type] : false;

            if (!$post_type_name) {
                $post_type_name = get_post_type_object($post_type)->label;
                $post_type_names[$post_type] = $post_type_name;
            }

            $taxonomy_post_types[] = $post_type_name;
        }

        if ($taxonomy->hierarchical) {
            $meta_box_id = $taxonomy_slug . 'div';
            $meta_box_callback = 'post_categories_meta_box';
        } else {
            $meta_box_id = 'tagsdiv-' . $taxonomy_slug;
            $meta_box_callback = 'post_tags_meta_box';
        }

        remove_meta_box($meta_box_id, 'rfe_taxonomy_related', 'side');

        add_meta_box(
            $meta_box_id,
            $taxonomy_name . ' (' . implode(', ', $taxonomy_post_types) . ')',
            $meta_box_callback,
            'rfe_taxonomy_related',
            'normal',
            'low',
            ['taxonomy' => $taxonomy_slug]
        );

    }

}

И, наконец, скрыть страницы подменю для таксономий, кроме той, которую я добавил в свой тип записи сам:

public function remove_taxonomy_menu_from_rfe_taxonomy_related__premium_only()
{
    global $submenu;

    //Получить все таксономии, из которых нужно удалить подменю
    $taxonomies = [];
    foreach (get_taxonomies(['public' => true], 'objects') as $taxonomy) {
        if ('rfe_taxonomy_related_category' === $taxonomy->name) {
            continue;
        }

        $taxonomies[] = $taxonomy->name;
    }

    $post_type="rfe_taxonomy_related";
    if (isset($submenu['edit.php?post_type=" . $post_type])) {
        foreach ($submenu["edit.php?post_type=" . $post_type] as $k => $sub) {
            $should_remove = false;
            foreach ($taxonomies as $taxonomy) {
                if (strpos($sub[2], "taxonomy=' . $taxonomy)) {
                    $should_remove = true;
                    break;
                }
            }
            if ($should_remove) {
                unset($submenu['edit.php?post_type=" . $post_type][$k]);
            }
        }
    }
}

Если у вас есть предложения по улучшению кода, буду рад услышать о них!

Ответ или решение

Чтобы добавить все таксономии как метабоксы к пользовательскому типу записи в WordPress, необходимо выполнить несколько шагов. Нам предстоит убедиться, что для всех таксономий нашего проекта будут встроены метабоксы в нужном расположении, а также корректно сохранять изменения. Давайте подробно рассмотрим, как это сделать.

Шаг 1: Регистрация пользовательского типа записи и таксономии

Сначала создайте пользовательский тип записи и свяжите его с вашей основной таксономией, как показано в коде. Используйте функцию register_post_type() для создания типа записи и register_taxonomy() для создания таксономии. Это позволит вам настроить основной костяк проекта.

public function create_taxonomy_related_post_type__premium_only() {
    register_post_type('rfe_taxonomy_related', array(
        'labels' => array(
            'name' => 'Taxonomy Related',
            'singular_name' => 'Taxonomy Related',
            // другие параметры меток ...
        ),
        'public' => true,
        'exclude_from_search' => true,
        'publicly_queryable' => false,
        'supports' => array('title', 'editor'),
        'taxonomies' => array('rfe_taxonomy_related_category'),
        'menu_icon' => 'dashicons-format-aside',
        'has_archive' => false,
    ));

    register_taxonomy('rfe_taxonomy_related_category', array('rfe_taxonomy_related'), array(
        'hierarchical' => true,
        'labels' => array(
            'name' => __('Categories', 'jt-revolution-for-elementor'),
            // другие параметры меток ...
        ),
        'show_ui' => true,
        'show_admin_column' => true,
        'query_var' => true,
    ));
}

Шаг 2: Подключение существующих таксономий к вашему типу записи

Чтобы все таксономии вместо вашей основной были доступны для вашего типа записи, используйте register_taxonomy_for_object_type():

public function add_meta_boxes_rfe_taxonomy_related__premium_only($post) {
    $taxonomies = get_taxonomies(['public' => true], 'objects');
    foreach ($taxonomies as $taxonomy) {
        if ('rfe_taxonomy_related_category' === $taxonomy->name) {
            continue;
        }
        register_taxonomy_for_object_type($taxonomy->name, 'rfe_taxonomy_related');
    }
}

Шаг 3: Перемещение метабоксов

Чтобы переместить метабоксы под контент, используйте remove_meta_box() и add_meta_box(). Это обеспечит удобное расположение и способствует лучшему пользовательскому опыту.

public function rename_taxonomy_meta_boxes_on_rfe_taxonomy_related__premium_only() {
    $taxonomies = get_taxonomies(['public' => true], 'objects');
    foreach ($taxonomies as $taxonomy) {
        if ('rfe_taxonomy_related_category' === $taxonomy->name) {
            continue;
        }

        $meta_box_id = $taxonomy->hierarchical ? $taxonomy->name . 'div' : 'tagsdiv-' . $taxonomy->name;
        $meta_box_callback = $taxonomy->hierarchical ? 'post_categories_meta_box' : 'post_tags_meta_box';

        remove_meta_box($meta_box_id, 'rfe_taxonomy_related', 'side');
        add_meta_box(
            $meta_box_id,
            __($taxonomy->labels->name),
            $meta_box_callback,
            'rfe_taxonomy_related',
            'normal',
            'low',
            ['taxonomy' => $taxonomy->name]
        );
    }
}

Шаг 4: Удаление ненужных подменю

Чтобы убрать подменю таксономий, которые добавляются по умолчанию, используйте данный код. Это поможет оставить только необходимые элементы управления.

public function remove_taxonomy_menu_from_rfe_taxonomy_related__premium_only() {
    global $submenu;
    $taxonomies = array_filter(get_taxonomies(['public' => true], 'objects'), function($taxonomy) {
        return $taxonomy->name !== 'rfe_taxonomy_related_category';
    });

    foreach ($submenu["edit.php?post_type=rfe_taxonomy_related"] as $k => $sub) {
        foreach ($taxonomies as $taxonomy) {
            if (strpos($sub[2], 'taxonomy=' . $taxonomy->name)) {
                unset($submenu["edit.php?post_type=rfe_taxonomy_related"][$k]);
                break;
            }
        }
    }
}

Оптимизация и завершение

Обратите внимание, что нужно правильно устанавливать хуки, чтобы ваш код выполнялся в нужное время. Это включает в себя использование add_action(), чтобы подключаться на init, wp_loaded, admin_init, и admin_menu.

Эти шаги позволят вам расширять функциональность пользовательского типа записи, обеспечив интеграцию всех публичных таксономий в вашем WordPress проекте. Если у вас есть дополнительные вопросы или нужен совет по улучшению кода, обязательно ищите рекомендации в соответствующем сообществе разработчиков.

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

Капча загружается...