Как использовать таксономии для вложений с новой Медиабиблиотекой?
В WordPress 3.5 изменили управление медиафайлами, и теперь экран редактирования Медиабиблиотеки использует стандартный интерфейс типа записи. Таксономии очень полезны для WordPress-установок с разными пользователями и вложениями, предоставляя больше возможностей для поиска вложений и/или добавления классификации.
Я видел Можно ли добавить метабокс категорий к вложениям? на WPSE, но это не идеально для использования с WP 3.5 и также нет информации об использовании пользовательских категорий для вложений, а не только категорий записей.
Короче: можно ли добавить пользовательские категории/теги к вложениям для использования в Медиабиблиотеке с WP 3.5?

Для добавления таксономий из типа записи post (по умолчанию), можно легко добавить таксономии 'category' и 'tags' с помощью небольшого плагина, как в примере ниже.
<?php
/**
* Plugin Name: Attachment Taxonomies
* Plugin URI:
* Text Domain: attachment_taxonomies
* Domain Path: /languages
* Description:
* Version: 1.0.0
* Author: Frank Bültge
* Author URI: http://bueltge.de
* License: GPLv3
*/
add_action( 'init', 'fb_attachment_taxonomies' );
function fb_attachment_taxonomies() {
$taxonomies = array( 'category', 'post_tag' ); // добавляем 2 таксономии ...
foreach ( $taxonomies as $tax ) {
register_taxonomy_for_object_type( $tax, 'attachment' ); // добавляем к типу записи attachment
}
}
Для использования пользовательских таксономий для вложений важно сначала создать пользовательскую таксономию и привязать её к типу записи attachment
, как в следующем плагине.
<?php
/**
* Plugin Name: Attachment Taxonomies
* Plugin URI:
* Text Domain: attachment_taxonomies
* Domain Path: /languages
* Description:
* Version: 1.0.0
* Author: Frank Bültge
* Author URI: http://bueltge.de
* License: GPLv3
*/
if ( function_exists( 'add_filter' ) )
add_action( 'plugins_loaded', array( 'Fb_Attachment_Taxonomies', 'get_object' ) );
/**
* Добавляет таксономии Tags и Categories к Attachment в WP 3.5
*/
class Fb_Attachment_Taxonomies {
static private $classobj;
/**
* Конструктор, инициализирует функции внутри WP
*
* @since 1.0.0
* @return void
*/
public function __construct() {
// загрузка файлов перевода
add_action( 'admin_init', array( $this, 'localize_plugin' ) );
// добавление таксономий
add_action( 'init', array( $this, 'setup_taxonomies' ) );
}
/**
* Обработчик действия 'init'. Создает экземпляр этого класса.
*
* @since 1.0.0
* @access public
* @return $classobj
*/
public function get_object() {
if ( NULL === self::$classobj ) {
self::$classobj = new self;
}
return self::$classobj;
}
/**
* Локализация плагина.
*
* @uses load_plugin_textdomain, plugin_basename
* @since 2.0.0
* @return void
*/
public function localize_plugin() {
load_plugin_textdomain(
'attachment_taxonomies',
FALSE,
dirname( plugin_basename( __FILE__ ) ) . '/languages/'
);
}
/**
* Настройка таксономий
* Создает таксономии 'attachment_tag' и 'attachment_category'.
* Расширяется через фильтр `fb_attachment_taxonomies`
*
* @uses register_taxonomy, apply_filters
* @since 1.0.0
* @return void
*/
public function setup_taxonomies() {
$attachment_taxonomies = array();
// Теги
$labels = array(
'name' => _x( 'Метки медиафайлов', 'taxonomy general name', 'attachment_taxonomies' ),
'singular_name' => _x( 'Метка медиафайла', 'taxonomy singular name', 'attachment_taxonomies' ),
'search_items' => __( 'Искать метки медиафайлов', 'attachment_taxonomies' ),
'all_items' => __( 'Все метки медиафайлов', 'attachment_taxonomies' ),
'parent_item' => __( 'Родительская метка медиафайла', 'attachment_taxonomies' ),
'parent_item_colon' => __( 'Родительская метка медиафайла:', 'attachment_taxonomies' ),
'edit_item' => __( 'Редактировать метку медиафайла', 'attachment_taxonomies' ),
'update_item' => __( 'Обновить метку медиафайла', 'attachment_taxonomies' ),
'add_new_item' => __( 'Добавить новую метку медиафайла', 'attachment_taxonomies' ),
'new_item_name' => __( 'Новое имя метки медиафайла', 'attachment_taxonomies' ),
'menu_name' => __( 'Метки медиафайлов', 'attachment_taxonomies' ),
);
$args = array(
'hierarchical' => FALSE,
'labels' => $labels,
'show_ui' => TRUE,
'show_admin_column' => TRUE,
'query_var' => TRUE,
'rewrite' => TRUE,
);
$attachment_taxonomies[] = array(
'taxonomy' => 'attachment_tag',
'post_type' => 'attachment',
'args' => $args
);
// Категории
$labels = array(
'name' => _x( 'Категории медиафайлов', 'taxonomy general name', 'attachment_taxonomies' ),
'singular_name' => _x( 'Категория медиафайла', 'taxonomy singular name', 'attachment_taxonomies' ),
'search_items' => __( 'Искать категории медиафайлов', 'attachment_taxonomies' ),
'all_items' => __( 'Все категории медиафайлов', 'attachment_taxonomies' ),
'parent_item' => __( 'Родительская категория медиафайла', 'attachment_taxonomies' ),
'parent_item_colon' => __( 'Родительская категория медиафайла:', 'attachment_taxonomies' ),
'edit_item' => __( 'Редактировать категорию медиафайла', 'attachment_taxonomies' ),
'update_item' => __( 'Обновить категорию медиафайла', 'attachment_taxonomies' ),
'add_new_item' => __( 'Добавить новую категорию медиафайла', 'attachment_taxonomies' ),
'new_item_name' => __( 'Новое имя категории медиафайла', 'attachment_taxonomies' ),
'menu_name' => __( 'Категории медиафайлов', 'attachment_taxonomies' ),
);
$args = array(
'hierarchical' => TRUE,
'labels' => $labels,
'show_ui' => TRUE,
'query_var' => TRUE,
'rewrite' => TRUE,
);
$attachment_taxonomies[] = array(
'taxonomy' => 'attachment_category',
'post_type' => 'attachment',
'args' => $args
);
$attachment_taxonomies = apply_filters( 'fb_attachment_taxonomies', $attachment_taxonomies );
foreach ( $attachment_taxonomies as $attachment_taxonomy ) {
register_taxonomy(
$attachment_taxonomy['taxonomy'],
$attachment_taxonomy['post_type'],
$attachment_taxonomy['args']
);
}
}
} // конец класса
Результат можно увидеть на следующем скриншоте, который лучше иллюстрирует разницу, чем мои слова. (Изображение в примере скриншота не относится к исходному коду ;)
Небольшие подсказки: интерфейс модального окна для добавления медиа в типе записи немного отличается от экрана редактирования типа записи attachment. Иерархические таксономии имеют древовидную структуру только на экране редактирования. В модальном окне это поле ввода, а таксономии работают с разделителем в виде запятой. Смотрите также эту статью от Helen в блоге WP Core. Но пользовательские таксономии для 'tags' и 'categories' также можно увидеть на скриншоте.

+1+ Ещё один шаг в изучении Media Library 3.5, великой неизвестности 2012 года!

Да, вы правы. Мне нравится этот параметр в WP 3.6; я часто использую его с небольшим вспомогательным классом, если работаю с множественными таксономиями: https://github.com/bueltge/WP-Control-Taxonomy

Фрэнк, не забудь, что для таксономий вложений, скорее всего, нужно установить update_count_callback
в значение _update_generic_term_count
. Обновленная запись в Codex объясняет почему: http://codex.wordpress.org/Function_Reference/register_taxonomy#Arguments

Я расширю ответ Фрэнка с помощью Добавления фильтра таксономии в админ-список для пользовательского типа записи?
Ища обе вещи, категории медиа и фильтр таксономии, я объединил код Фрэнка с ответом Кайзера в этом посте. Также добавил свою доработку, чтобы добавить тип записи, куда было загружено вложение, в качестве категории.
Получается вот так:
add_action(
'plugins_loaded',
array ( WPSE76720_Attachment_Taxonomies::get_object(), 'plugin_setup' )
);
// BUELTGE/KAISER/RUDOLF
class WPSE76720_Attachment_Taxonomies
{
protected static $instance = NULL;
public $post_type;
public $taxonomies;
/**
* Используется для регулярной работы плагина.
*
* @wp-hook plugins_loaded
* @return void
*/
public function plugin_setup()
{
// Фильтр таксономий
add_action( 'load-upload.php', array( $this, 'setup' ) );
// добавление таксономий
add_action( 'init', array( $this, 'setup_taxonomies' ) );
add_action( 'add_attachment', array( $this, 'auto_tax' ), 10, 2 );
}
/**
* Конструктор, инициализирует функции внутри WP
*
* @since 1.0.0
* @return void
*/
public function __construct() {}
/**
* Обработчик действия 'init'. Создает экземпляр этого класса.
*
* @since 1.0.0
* @access public
* @return $instance
*/
public function get_object()
{
NULL === self::$instance and self::$instance = new self;
return self::$instance;
}
/**
* Настройка таксономий
* Создает таксономии 'attachment_tag' и 'attachment_category'.
* Расширяется через фильтр `fb_attachment_taxonomies`
*
* @uses register_taxonomy, apply_filters
* @since 1.0.0
* @return void
*/
public function setup_taxonomies()
{
$attachment_taxonomies = array();
// Категории
$labels = array(
'name' => __( 'Категории медиа', 'b5f-mc' ),
'singular_name' => __( 'Категория медиа', 'b5f-mc' ),
'search_items' => __( 'Поиск категорий медиа', 'b5f-mc' ),
'all_items' => __( 'Все категории медиа', 'b5f-mc' ),
'parent_item' => __( 'Родительская категория медиа', 'b5f-mc' ),
'parent_item_colon' => __( 'Родительская категория медиа:', 'b5f-mc' ),
'edit_item' => __( 'Редактировать категорию медиа', 'b5f-mc' ),
'update_item' => __( 'Обновить категорию медиа', 'b5f-mc' ),
'add_new_item' => __( 'Добавить новую категорию медиа', 'b5f-mc' ),
'new_item_name' => __( 'Название новой категории медиа', 'b5f-mc' ),
'menu_name' => __( 'Категории медиа', 'b5f-mc' ),
);
$args = array(
'hierarchical' => TRUE,
'labels' => $labels,
'show_admin_column' => TRUE,
'show_ui' => TRUE,
'query_var' => TRUE,
'rewrite' => TRUE,
);
$attachment_taxonomies[] = array(
'taxonomy' => 'attachment_category',
'post_type' => 'attachment',
'args' => $args
);
$attachment_taxonomies = apply_filters( 'fb_attachment_taxonomies', $attachment_taxonomies );
foreach ( $attachment_taxonomies as $attachment_taxonomy ) {
register_taxonomy(
$attachment_taxonomy['taxonomy'],
$attachment_taxonomy['post_type'],
$attachment_taxonomy['args']
);
}
}
public function setup()
{
add_action( current_filter(), array( $this, 'setup_vars' ), 20 );
add_action( 'restrict_manage_posts', array( $this, 'get_select' ) );
add_filter( "manage_taxonomies_for_attachment_columns", array( $this, 'add_columns' ) );
}
public function setup_vars()
{
$this->post_type = 'attachment';
$this->taxonomies = get_object_taxonomies( $this->post_type );
}
public function add_columns( $taxonomies )
{
return array_merge(
$taxonomies
,$this->taxonomies
);
}
public function get_select()
{
$walker = new WCMF_walker;
foreach ( $this->taxonomies as $tax )
{
wp_dropdown_categories( array(
'taxonomy' => $tax
,'hide_if_empty' => false
,'show_option_all' => sprintf(
get_taxonomy( $tax )->labels->all_items
)
,'hide_empty' => false
,'hierarchical' => is_taxonomy_hierarchical( $tax )
,'show_count' => false
,'orderby' => 'name'
,'selected' => '0' !== get_query_var( $tax )
? get_query_var( $tax )
: false
,'name' => $tax
,'id' => $tax
,'walker' => $walker
) );
}
}
/**
* Добавляет родительский тип записи как категорию вложения
*
* @author Rodolfo Buaiz
*/
public function auto_tax( $post_id )
{
$the_p = get_post( $post_id );
if( $the_p->post_parent > 0 )
{
$cpt = get_post_type( $the_p->post_parent );
$term = term_exists( $cpt, 'attachment_category' );
if( !$term )
$term = wp_insert_term( $cpt, 'attachment_category' );
wp_set_post_terms( $post_id, $term['term_id'], 'attachment_category', true );
}
}
} // end BUELTGE/KAISER/RUDOLF
// KAISER
class WCMF_walker extends Walker_CategoryDropdown
{
var $tree_type = 'category';
var $db_fields = array(
'parent' => 'parent'
,'id' => 'term_id'
);
public $tax_name;
/**
* @see Walker::start_el()
* @param string $output Передается по ссылке. Используется для добавления дополнительного содержимого.
* @param object $term Объект данных таксономии.
* @param int $depth Глубина категории. Используется для отступов.
* @param array $args Использует ключи 'selected' и 'show_count', если они существуют.
* @param int $id
* @return void
*/
function start_el( &$output, $term, $depth, $args, $id = 0 )
{
$pad = str_repeat( ' ', $depth * 3 );
$cat_name = apply_filters( 'list_cats', $term->name, $term );
$output .= sprintf(
'<option class="level-%s" value="%s" %s>%s%s</option>'
,$depth
,$term->slug
,selected(
$args['selected']
,$term->slug
,false
)
,"{$pad}{$cat_name}"
,$args['show_count']
? " ({$term->count})"
: ''
);
}
}
// end KAISER

Мой плагин Media Categories сделает это за вас — он даже упрощает интерфейс в медиа-модальном окне, так что вы по-прежнему получаете список чекбоксов, тогда как по умолчанию доступны только текстовые поля.
