Создание рубрик из набора рубрик и меток

Рейтинг: 0Ответов: 2Опубликовано: 15.03.2023

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

Например:

Рубрика - Происшествия

Метка - Париж

Новая рубрика - Происшествия в Париже

Сюда выведутся все записи из рубрики Происшествия и метки Париж.

Какими хуками воспользоваться, чтобы создать новую рубрику и вывести туда соответствующие записи?

Ответы

▲ 0Принят
// Регистрируем новую таксономию
function custom_taxonomy()
{
  $labels = array(
    'name'              => __('Категории'),
    'singular_name'     => __('map'),
  );

  $args = array(
    'hierarchical'      => true,
    'labels'            => $labels,
    'show_ui'           => true,
    'show_admin_column' => true,
    'query_var'         => true,
    'rewrite'           => array('slug' => 'map'),
  );

  register_taxonomy('map', array('post'), $args);
}

add_action('init', 'custom_taxonomy');


// Декартово произведение, формируем массив из пересечения Рубрика + Метка
function array_cartesian()
{
  $_ = func_get_args();
  if (count($_) == 0)
    return array(array());
  $a = array_shift($_);
  $c = call_user_func_array(__FUNCTION__, $_);
  $r = array();
  foreach ($a as $v)
    foreach ($c as $p)
      $r[] = array_merge(array($v), $p);
  return $r;
}

// Генерация новых элементов Категории на основе массивов Рубрик и Меток
function add_tax()
{
  // Получаем все элементы рубрики
  $categories = get_categories([
    'orderby' => 'name',
    'order' => 'ASC',
    'hide_empty' => false,
    'exclude' => 1 //исключаем термин Без рубрики
  ]);
  $ar_cat = array();
  foreach ($categories as $category) {
    $ar_cat[] = $category->slug;
  }

  // Получаем все элементы метки
  $tags = get_tags();
  $ar_tag = array();
  foreach ($tags as $tag) {
    $ar_tag[] = $tag->slug;
  }

  $cross = array_cartesian($ar_cat, $ar_tag);

  foreach ($cross as $cr) {
    print_r($cr[0].' - '.$cr[1].'<br>');

    // Генерируем новые элементы Категорий
    $name = get_term_by('slug', $cr[0], 'category')->name . ' ' . get_term_by('slug', $cr[1], 'post_tag')->name;
    $taxonomy = 'map';

    // сначала нам нужно проверить, что термина не существует
    if (!term_exists($name, $taxonomy)) {

      // окей, пробуем добавить рубрику
      $cat = wp_insert_term($name, $taxonomy);
      if (!is_wp_error($cat)) {
        echo '<script>console.log("Рубрика добавлена, её ID=' . $cat['term_id'] . '")</script>';
      } else {
        echo $cat->get_error_message();
      }
    }

// присваиваем к терминам новой таксономии записи, у которых есть рубрика и метка, состоящие в основе термина новой таксономии
    $ida = get_term_by('slug', $cr[0], 'category')->term_id;
    $idb = get_term_by('slug', $cr[1], 'post_tag')->term_id;
    
    $post_idc = get_objects_in_term( $ida, 'category' );
    $post_idt = get_objects_in_term( $idb, 'post_tag' );
    
    foreach ($post_idc as $idc) {
        foreach ($post_idt as $idt) {
            if (has_category( $cr[0], $idt ) && has_tag( $cr[1], $idt ) && has_category( $cr[0], $idc ) && has_tag( $cr[1], $idc ) && $cr[0].'-'.$cr[1] == get_term_by('slug', $cr[0].'-'.$cr[1], 'map')->slug) {
            wp_set_object_terms( $idc, $name, $taxonomy, true );
            wp_set_object_terms( $idt, $name, $taxonomy, true );
            }
        }
    }
  }
}
add_action('init', 'add_tax');
▲ 0

Хук init - для создания кастомной таксономии (рубрики и/или метки)

Пример:

function custom_taxonomy() {
    $labels = array(
        'name'              => __( 'Incident in Paris' ),
        'singular_name'     => __( 'Incident in Paris' ),
        'search_items'      => __( 'Search Incident in Paris' ),
        'all_items'         => __( 'All Incident in Paris' ),
        'parent_item'       => __( 'Parent Incident in Paris' ),
        'parent_item_colon' => __( 'Parent Incident in Paris:' ),
        'edit_item'         => __( 'Edit Incident in Paris' ),
        'update_item'       => __( 'Update Incident in Paris' ),
        'add_new_item'      => __( 'Add New Incident in Paris' ),
        'new_item_name'     => __( 'New Incident in Paris' ),
        'menu_name'         => __( 'Incident in Paris' ),
    );

    $args = array(
        'hierarchical'      => true,
        'labels'            => $labels,
        'show_ui'           => true,
        'show_admin_column' => true,
        'query_var'         => true,
        'rewrite'           => array( 'slug' => 'incidents-in-paris' ),
    );

    register_taxonomy( 'incidents-in-paris', array( 'post' ), $args );
}

add_action( 'init', 'custom_taxonomy' );

Хук pre_get_posts - для вывода постов из пересечения рубрик и меток

Пример:

function custom_filter_by_taxonomy( $query ) {
  if ( $query->is_main_query() && $query->is_tax( 'incidents-in-paris' ) ) {
    $tax_query = array(
      'relation' => 'AND',
      array(
        'taxonomy' => 'category',
        'field' => 'slug',
        'terms' => 'incidents',
      ),
      array(
        'taxonomy' => 'post_tag',
        'field' => 'slug',
        'terms' => 'paris',
      ),
    );
    $query->set( 'tax_query', $tax_query );
  }
}
add_action( 'pre_get_posts', 'custom_filter_by_taxonomy' );