18

I am using register_taxonomy_for_object_type() to add the Category taxonomy field to Media uploads (attachments). I'm using this code to do so:

add_action('init', 'reg_tax');
function reg_tax() {
   register_taxonomy_for_object_type('category', 'attachment');
}

This works and adds a simple text field for Category to the Media page when viewing an image. What I really want is to make it display the actual Categories Metabox so that I can choose the Categories I want to use rather than just type them into the plain field. I've also found that putting the slug for a category into this text field such as my-category-name ends up displaying as the actual category name like My Category Name when it's saved, which makes the simple text field even less of a useful option.

I've been looking at the add_post_type_support() function for adding Metaboxes and have seen it used for Custom Post Types, I just can't see if it's possible to add the same for attachments.

6
  • If you wait a day or two before picking a best answer I'll write you a plugin... (I've just got client deadlines and a WordPress meetup to present WordPress Answers to tonight...) Aug 18, 2010 at 20:17
  • @Mike: Thanks, I'm keen to see what solutions there are to this problem. It seems like what I'm after is about 90% there in WordPress as it stands, it just remains to be seen about that last 10%! Aug 19, 2010 at 8:32
  • I've done something very similar with a custom post metabox; i.e. embedding a (basic) category list (i.e. w/o the tabs for all/most popular). It just depends on how 'attachment_fields_to_edit' implements its POST. Anyway, I can't do tonight. Need sleep. Aug 19, 2010 at 8:47
  • Oops, as you've already answered it yourself I'll take off my to-do list. Aug 21, 2010 at 1:17
  • @Mike: Thanks for your help, I'd love some feedback about my solution. I'm glad I found a way to make it work. It'd be great to see adding categories to attachments via the actual category metabox, but my solution works well enough. Aug 21, 2010 at 23:38

5 Answers 5

14

Edit: 12/09/2017 See this answer for a more up to date solution to this: How to use taxonomies on attachments with the new Media Library?

I'm going to answer my own question here as I have managed to figure out a solution to what I've been trying to do. I came to the conclusion that it wasn't possible to get the Category Metabox enabled for attachments. However, I found that it was easy enough to get a basic field for Categories added to the attachments page by using register_taxonomy_for_object_type and add_post_type_support:

add_action('admin_init', 'reg_tax');
function reg_tax() {
   register_taxonomy_for_object_type('category', 'attachment');
   add_post_type_support('attachment', 'category');
}

The field added showed like this:

alt text

It's just a plain text field but what I found was that you could type the name of an existing category in there and it would then be successfully saved when the attachment was updated (The only odd behaviour is that it rendered back the normal version instead of the slug after saving).

Once I realised that I could save categories this way then I figured that I could get a list of all available categories as checkboxes and check the ones that had been selected. I then used a bit of jQuery to grab the values of checked categories and put all the categories' slugs into the Category field. To make this seem even more seamless I then used a simple bit of CSS to hide the table row that contained the Category field, so all you ever see are the checkboxes, like so:

alt text

Now that I can add categories to image attachments I can use something like:

get_posts('post_type=attachment&category_name=timber-fixed-windows')

And pull the categorised images into a page! Exactly what I was hoping to do, I didn't think there was going to be a way to do it but glad I managed to figure something out.

I've turned this into a plugin called WOS Media Categories which I have made available to download from my website, Suburbia.org.uk, I hope it may be of use to somebody else! Thanks again to those who commented on this and other questions I've asked here which helped figure it out!

Update: I've added a fix to enable categories to be added whilst images are uploaded using the Flash bulk uploader.

12
  • I'm a little bothered by using jQuery from something that requires data integrity. I'm pretty sure this can all be done on the server. I'll try to look at it soon. Aug 22, 2010 at 8:31
  • 1
    @Mike: Yep, I'm slightly concerned about that too. However, there's many instances where JavaScript is involved so I decided I was happy enough with that solution. Definitely happy to get some feedback on alternative methods though. When I get a chance I'd like to submit this into the WordPress repository although I may wait and see what you come back with. Thanks! Aug 23, 2010 at 14:26
  • @Mike or @Rick -- Could you possibly provide another example which might automatically assign a post to a specific category when media is added? Category association would be based off the post type he is on or set manually through the code? Oct 19, 2010 at 12:38
  • @NetConstructor.com - Sounds like another question to me... Oct 20, 2010 at 7:22
  • @netconstructor.com: Yep, sounds like another big question to me! Oct 27, 2010 at 14:32
4

just created this, which is a complete workaround to the herky-jerk javascript linkage to the form field. Since the values of your checkboxes are passed along with the $_POST on submit, you can just grab them during the add_image_attachment_fields_to_save filter and set the post object's terms.

function register_custom_taxonomies() {
    $labels = array(
        'name' => _x( 'Image Formats', 'taxonomy general name' ),
        'singular_name' => _x( 'Image Format', 'taxonomy singular name' ),
        'search_items' =>  __( 'Search Formats' ),
        'all_items' => __( 'All Formats' ),
        'parent_item' => __( 'Parent Format' ),
        'parent_item_colon' => __( 'Parent Format:' ),
        'edit_item' => __( 'Edit Format' ), 
        'update_item' => __( 'Update Format' ),
        'add_new_item' => __( 'Add New Format' ),
        'new_item_name' => __( 'New Format Name' ),
        'menu_name' => __( 'Image Format' )
    );
    $capabilities = array(
        'manage_terms' => 'nobody',
        'edit_terms' => 'nobody',
        'delete_terms' => 'nobody'
    );
    $args = array(
        'public' => false,
        'hierarchical' => true,
        'labels' => $labels,
        'capabilities' => $capabilities,
        'show_ui' => false,
        'query_var' => 'image-format',
        'rewrite' => false
    );
    register_taxonomy('image-format', array('attachment'), $args);
}
add_action( 'init', 'register_custom_taxonomies', 1);

function add_media_categories($fields, $post) {
    $categories = get_categories(array('taxonomy' => 'image-format', 'hide_empty' => 0));
    $post_categories = wp_get_object_terms($post->ID, 'image-format', array('fields' => 'ids'));
    $all_cats .= '<ul id="media-categories-list" style="width:500px;">'; 
    foreach ($categories as $category) {
        if (in_array($category->term_id, $post_categories)) {
            $checked = ' checked="checked"';
        } else {
            $checked = '';  
        }
        $option = '<li style="width:240px;float:left;"><input type="checkbox" value="'.$category->category_nicename.'" id="'.$post->ID.'-'.$category->category_nicename.'" name="'.$post->ID.'-'.$category->category_nicename.'"'.$checked.'> ';
        $option .= '<label for="'.$post->ID.'-'.$category->category_nicename.'">'.$category->cat_name.'</label>';
        $option .= '</li>';
        $all_cats .= $option;
    }
    $all_cats .= '</ul>';

    $categories = array('all_categories' => array (
            'label' => __('Image Formats'),
            'input' => 'html',
            'html' => $all_cats
    ));
    return array_merge($fields, $categories);
}
add_filter('attachment_fields_to_edit', 'add_media_categories', null, 2);

function add_image_attachment_fields_to_save($post, $attachment) {
    $categories = get_categories(array('taxonomy' => 'image-format', 'hide_empty' => 0));
    $terms = array();
    foreach($categories as $category) {
        if (isset($_POST[$post['ID'].'-'.$category->category_nicename])) {
            $terms[] = $_POST[$post['ID'].'-'.$category->category_nicename];        
        }
    }
    wp_set_object_terms( $post['ID'], $terms, 'image-format' );
    return $post;
}
add_filter('attachment_fields_to_save', 'add_image_attachment_fields_to_save', null , 2);

(note that I am using a custom taxonomy, and not categories, so you'll have to change the $categories array to match the same array as you use when you set up your checkboxes)

Shabam, shabozzle. Enjoy.

2
  • Your add_image_attachment_fields_to_save function needs to return $post at the end. wp_set_object_terms( $post['ID'], $terms, 'image-format' ); return $post;. And the script you posted doesn't execute register_custom_taxonomies. But anyway nice script. Will definitely use this in the future! Jan 12, 2012 at 16:49
  • Oh oops, I cobbled it together thinking I was being convenient. I'll fix it here in a sec. Good point on the return, though, I wasn't having any trouble with it. Jan 12, 2012 at 18:50
1

This is difficult/complicated if you want to use WordPress' default category box. For one thing, the metabox doesn't return the output, it just echoes it. On top of that, it wouldn't give you the correct input field name, so it wouldn't save. One idea might be to use a jQuery UI Autocomplete to replicate the tags box's functionality.

However, if you want to play around with the media editor's fields, you can hook into 'attachment_fields_to_edit' and edit the array of fields. The filter passes two arguments to the callback: first argument is the array of fields, second is the attachment post object. See here for more details:

http://phpxref.ftwr.co.uk/wordpress/nav.html?wp-admin/includes/media.php.source.html#l1025

1
  • Thanks, I'll take a look at attachment_fields_to_edit and see how that goes. Aug 19, 2010 at 8:37
1

I've created a plugin using @RickCurran's WOS Media Categories as a starting point. However, WOS Media Categories, like other plugins that add category support to media, doesnt actually add a metabox, I've done just that.

overall view

Its necessarily simplified form the metaboxes on posts and pages, but I did include a filtering ability that makes it easy to use.

filterable categories

I am actually generating the entire category metabox that you see on pages and posts, but hiding the bits that dont work on the media page because of both a lack of styling and the missing javascript.

I welcome any thoughts anyone might have as to how to make the metabox fully functional - something I intend to do in a later version.

0

Great plugin Rick - very helpful.

If you move the onclick trigger inline instead of binding it to onload (and make a few other minor tweaks), it'll work on the Flash bulk uploader as well. With the current version the Flash loads after the jQuery load event so the objects don't exist yet.

revised js:

 function wos_category_click(cat){
    var container = jQuery(cat).closest("tbody");
    var cat_checked = jQuery(container).find("tr.all_categories input:checked");
    var cat_arr = jQuery(cat_checked).map(function() {
        return jQuery(this).val();
    }).get().join();
    jQuery(container).find("tr.category > td.field > input.text").val(cat_arr);
}

add onclick to input in php file:

<input type="checkbox" onclick="wos_category_click(this)" class="wos-categories-cb"....

add bulk uploader form id to css file:

form#media-single-form tr.category,form#file-form tr.category {
display:none; 

}

1

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.