0

After two day of reasearch and questions without answer, today someone has suggested me a way to add a custom metabox field to the wordpress images. My scope is to add an url when the image are uploaded or modified and for now I'm only able to display the input field where user can add the url, but the input will not be saved and I'm unable to get it back on the front-end.

I want to use this custom metabox function with the get_post_gallery() that will output the urls of the images I've added inside a gallery, but I don't know how to combine this, and I need to fix the saving of the inserted url. Can anyone help me or guide trought the implementation?

<?php
 function add_image_link()
 {
   add_meta_box(
     'image_link_box',
     'Link image to url',
     'image_link_field',
     'attachment'
   ); 
 }
 add_action( 'add_meta_boxes_attachment', 'add_image_link' );

 function image_link_field( $post )
 {
   ?>
   <label for="image-link">Link URL</label>
   <input type="text" name="image_link" id="image-link" class="postbox">
   <?php
 }

 function save_image_link( $post_id )
 {
   if( array_key_exists( 'image_link', $_POST ) ){
     update_post_meta(
       $post_id,
       'image_link_url',
       $_POST['image_link']
     );
   }

 }
 add_action( 'save_post_attachment', 'save_image_link' );
?>
3
  • I think the meta/input does get saved, but you should use get_post_meta() in your <input>.
    – Sally CJ
    Nov 5, 2019 at 0:19
  • I've looked to the table, but there is no trace of the key. Also I need toimplement nonces. I've tried with get_post_meta() but the supposed values are not loaded.
    – sialfa
    Nov 5, 2019 at 3:22
  • Have a look at my answer and regarding the nonces, see this.
    – Sally CJ
    Nov 5, 2019 at 4:39

1 Answer 1

1

So actually, for posts of the type attachment, you should use the edit_attachment (action) hook and not save_post_attachment:

add_action( 'edit_attachment', 'save_image_link' );        // use edit_attachment
//add_action( 'save_post_attachment', 'save_image_link' ); // not save_post_attachment

Secondly, your meta box is not currently displaying the meta value, so you should display the value in the input field, and you can use get_post_meta() to retrieve the meta value:

<input type="text" name="image_link" id="image-link" class="postbox" value="<?php // wrapped
    echo esc_attr( get_post_meta( $post->ID, 'image_link_url', true ) ); ?>">

PS: You should always sanitize/escape user-supplied and untrusted data; e.g. above I use esc_attr() to escape the value, and you can use sanitize_text_field() to sanitize the submitted value: sanitize_text_field( $_POST['image_link'] ).

Sample Implementation Using get_post_gallery() (for the [gallery] shortcode)

This is based on the example here. And as I've mentioned before, you can use get_post_meta() to retrieve the custom field's value (which in your case is an URL address).

// Get the gallery data (attachment IDs and URLs).
$gallery = get_post_gallery( get_the_ID(), false );
if ( $gallery ) {
    foreach ( wp_parse_id_list( $gallery['ids'] ) as $i => $att_id ) {
        // Get the custom link URL.
        $url = get_post_meta( $att_id, 'image_link_url', true );

        // Display the image. You can add other attributes later..
        echo '<a href="' . esc_url( $url ) . '"><img src="' . // wrapped
            esc_url( $gallery['src'][ $i ] ). '" alt=""></a> ';
    }
}

UPDATE

A Better (Non-Metabox) Solution

If you want to be able to edit the custom field via the Attachment Details dialog, then you should just forget about using the meta box and instead try the following:

  1. This part adds the custom field to the dialog:

    add_filter( 'attachment_fields_to_edit', function ( $form_fields, $post ) {
        $form_fields['image_link'] = array(
            'label' => 'Link to image URL',
            'value' => get_post_meta( $post->ID, 'image_link_url', true ),
        );
    
        return $form_fields;
    }, 10, 2 );
    
  2. This part saves the field as a meta data:

    add_filter( 'attachment_fields_to_save', function ( $post, $attachment ) {
        if ( isset( $attachment['image_link'] ) ) {
            $meta_input = isset( $post['meta_input'] ) ?
                (array) $post['meta_input'] : [];
    
            $meta_input['image_link_url'] = $attachment['image_link'];
    
            $post['meta_input'] = $meta_input;
        }
    
        return $post;
    }, 10, 2 );
    

Note that image_link is the form field (input) name, whereas image_link_url is the meta key.

And this solution also works well with the standard "Edit Media" page — from the Attachment Details dialog, you can get to that page by clicking on the "Edit more details" link.

Full code I used for testing here.

11
  • It's an url field, and i need to retrive the value on some post/pages where attached post images are used inside an <a> tag.
    – sialfa
    Nov 5, 2019 at 6:30
  • Answer updated. Let me know! :)
    – Sally CJ
    Nov 5, 2019 at 7:49
  • I will try and let you know, thanks for the suggestion!
    – sialfa
    Nov 5, 2019 at 9:57
  • I have updated the question, the data I will add are not saved. I'm still unable to display the images of the gallery with the related links.
    – sialfa
    Nov 5, 2019 at 10:08
  • Ok, look, if you change the add_action( 'save_post_attachment', 'save_image_link' ) to add_action( 'edit_attachment', 'save_image_link' ), the custom field should get saved. And if use the get_post_meta() in the <input>, then the field value would be displayed in the input. You also asked for a sample implementation using the get_post_gallery function which works for the standard [gallery] shortcode, and I've given you a the sample. So referring to the original code, what's your current code now, and have you tried the sample implementation?
    – Sally CJ
    Nov 5, 2019 at 10:50

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.