How can I add a URL field to the attachments window?

For example…

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

Adds a “Category” input field to the media manager and attachments editor. I’d like to know if its possible to alter this function to capture a “link destination” URL instead. The URL would be executed when the image is clicked.

Read More

Also need to know how to retrieve the value for this new field.

UPDATE: Thanks to Thomas Answer below, here is my final solution…

function my_image_attachment_fields_to_edit($form_fields, $post) {  
    $form_fields["custom1"] = array(  
        "label" => __("Image Links To"),  
        "input" => "text",
        "value" => get_post_meta($post->ID, "_custom1", true)  
    );        
    return $form_fields;  
}  

function my_image_attachment_fields_to_save($post, $attachment) {    
    if( isset($attachment['custom1']) ){  
        update_post_meta($post['ID'], '_custom1', $attachment['custom1']);  
    }  
    return $post;  
}  

add_filter("attachment_fields_to_edit", "my_image_attachment_fields_to_edit", null, 2); 
add_filter("attachment_fields_to_save", "my_image_attachment_fields_to_save", null, 2); 

Related posts

Leave a Reply

2 comments

  1. I use a very rough plugin to add information about the artist and a URL to media files. It needs some tweaking (and I need the time), but it works and may demonstrate how add the extra fields and how to use them in your theme:

    <?php
    /*
    Plugin Name: Media Artist Field
    Description: Adds two field to attachments – Artist and Artist URL – and adds this information to captions.
    Version:     0.1
    Author:      Fuxia Scholz
    Created:     19.09.2010
    */
    $Media_Artist = new Media_Artist(
        array (
            'artist_name' => array (
                'public' => 'artist_name'
            ,   'hidden' => '_artist_name'
            ,   'label'  => 'Fotograf (Name)'
            )
        ,   'artist_url' => array (
                'public' => 'artist_url'
            ,   'hidden' => '_artist_url'
            ,   'label'  => 'Fotograf (URL)'
            )
        )
    ,   'Foto: '
    );
    /**
     * Adds two fields for credits to any media file: name and URL.
     *
     * Based on the clear tutorial by Andy Blackwell:
     * @link http://net.tutsplus.com/?p=13076
     */
    class Media_Artist
    {
        public
            $fields = array (
                'artist_name' => array (
                    'public' => 'artist_name'
                ,   'hidden' => '_artist_name'
                ,   'label'  => 'Artist Name'
                )
            ,   'artist_url' => array (
                    'public' => 'artist_url'
                ,   'hidden' => '_artist_url'
                ,   'label'  => 'Artist URL'
                )
            )
            // Maybe its own field?
        ,   $caption_prefix
        ,   $br_before = TRUE;
    
        public function __construct(
            $fields         = array()
        ,   $caption_prefix = 'Source: '
        ,   $br_before      = TRUE
        )
        {
            $this->fields         = array_merge($this->fields, $fields);
            $this->caption_prefix = $caption_prefix;
            $this->br_before      = (bool) $br_before;
    
            $this->set_filter();
        }
    
        public function set_filter()
        {
            add_filter(
                'attachment_fields_to_edit'
            ,   array ( $this, 'add_fields' )
            ,   15
            ,   2
            );
            add_filter(
                'attachment_fields_to_save'
            ,   array ( $this, 'save_fields' )
            ,   10
            ,   2
            );
            add_filter(
                'img_caption_shortcode'
            ,   array ( $this, 'caption_filter' )
            ,   1
            ,   3
            );
        }
    
        public function add_fields($form_fields, $post)
        {
            foreach ( $this->fields as $field)
            {
                $form_fields[ $field['public'] ]['label'] = $field['label'];
                $form_fields[ $field['public'] ]['input'] = 'text';
                $form_fields[ $field['public'] ]['value'] = get_post_meta(
                    $post->ID
                ,   $field['hidden']
                ,   TRUE
                );
            }
            return $form_fields;
        }
    
        public function save_fields($post, $attachment)
        {
            foreach ( $this->fields as $field)
            {
                if ( isset ( $attachment[ $field['public'] ]) )
                {
                    update_post_meta(
                        $post['ID']
                    ,   $field['hidden']
                    ,   $attachment[ $field['public'] ]
                    );
                }
            }
    
            return $post;
        }
    
        public function caption_filter($empty, $attr, $content = '')
        {
            /* Typical input:
             * [caption id="attachment_525" align="aligncenter"
             * width="300" caption="The caption."]
             * <a href="http://example.com/2008/images-test/albeo-screengrab/"
             * rel="attachment wp-att-525"><img
             * src="http://example.com/uploads/2010/08/albeo-screengrab4.jpg?w=300"
             * alt="" title="albeo-screengrab" width="300" height="276"
             * class="size-medium wp-image-525" /></a>[/caption]
             */
            extract(
                shortcode_atts(
                    array (
                        'id'        => ''
                    ,   'align'     => 'alignnone'
                    ,   'width'     => ''
                    ,   'caption'   => ''
                    ,   'nocredits' => '0'
                    )
                ,   $attr
                )
            );
    
            // Let WP handle these cases.
            if ( empty ($id ) or 1 == $nocredits )
            {
                return '';
            }
    
            if ( 1 > (int) $width || empty ( $caption ) )
            {
                return $content;
            }
    
            if ( ! empty ( $id ) )
            {
                // Example: attachment_525
                $html_id     = 'id="' . esc_attr($id) . '" ';
                $tmp         = explode('_', $id);
                $id          = end($tmp);
    
                $sub_caption = '';
                $artist_name = get_post_meta($id, $this->fields['artist_name']['hidden'], TRUE);
                $artist_url  = get_post_meta($id, $this->fields['artist_url']['hidden'], TRUE);
    
                // Okay, at least one value.
                if ( '' != $artist_name . $artist_url )
                {
                    $sub_caption .= $this->br_before ? '<br />' : '';
                    $sub_caption .= '<span class="media-artist">' . $this->caption_prefix;
    
                    // No name given. We use the shortened URL.
                    if ( '' == $artist_name )
                    {
                        $sub_caption .= '<a rel="author" href="'
                            . $artist_url . '">'
                            . $this->short_url($artist_url)
                            . '</a>';
                    } // We have just the name.
                    elseif ( '' == $artist_url )
                    {
                        $sub_caption .= $artist_name;
                    } // We have both.
                    else
                    {
                        $sub_caption .= '<a rel="author" href="'
                            . $artist_url . '">'
                            . $artist_name
                            . '</a>';
                    }
    
                    $sub_caption .= '</span>';
                }
    
                $caption .= $sub_caption;
            }
    
            return '<div ' . $html_id . 'class="wp-caption ' . esc_attr($align)
            . '" style="width: ' . (10 + (int) $width) . 'px">'
            . do_shortcode( $content ) . '<p class="wp-caption-text">'
            . $caption . '</p></div>';
        }
    
        public function short_url($url, $max_length=20)
        {
            $real_length = mb_strlen($url, 'UTF-8');
    
            if ( $real_length <= $max_length )
            {
                return $url;
            }
    
            $keep = round( $max_length / 2 ) - 1;
    
            return mb_substr($url, 0, $keep, 'UTF-8') . '…'
                . mb_substr($url, -$keep, $real_length, 'UTF-8');
        }
        # @todo uninstall
    }
    
  2. Responding to Drew’s question in the comments, you can customize the HTML for the field by setting the input to a new string, and then adding that same string as a key to the $form_fields array.

    By default, WordPress will only accept text and textarea for the input type. Anything else will have to be defined in a custom way as below. I haven’t tried actually persisting form fields this way so in order to make another input type, like a radio button, might take a little extra finesse.

    add_filter( 'attachment_fields_to_edit', 'change_fields', 10, 2 );
    function change_fields( $form_fields, $post ) {
    
        $form_fields["some_new_field"] = array(  
                "label" => __("Type something"),
                "input" => "arbitrary_value",
                "value" => get_post_meta($post->ID, "some_new_field", true),
                "arbitrary_value" => "hello world!"
            );
    }