4

Please consider the following code in my functions.php file:

add_filter( 'attachment_fields_to_edit', function($form_fields, $post){
    $post_mime_type = (
        get_post_mime_type( $post ) == 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' ||
        get_post_mime_type( $post ) == 'application/msword'
        ) ? 1 : 0;
    if ( $post_mime_type == 1) {
    $ilm = get_post_meta( $post->ID, 'is_latest', true );
    $checked = ($ilm == "1" ? 'checked="checked"' : '');
    $form_fields['is_latest'] = array(
      'label' => '<b">Latest?</b>',
      'input' => 'html',
      'html'  => "<input type=\"checkbox\"
        name=\"attachments[{$post->ID}][is_latest]\"
        id=\"attachments[{$post->ID}][is_latest]\"
        value=\"1\" {$checked}/><br />");
                return $form_fields;
    }
}, null, 2 );

add_filter("attachment_fields_to_save", function($post, $attachment){
  if($attachment['is_latest'] == "1") {
        $args = array( 'post_type' => 'attachment');
    $attachments = get_posts( $args );
    if ( $attachments ) {
      foreach ( $attachments as $a ) {
            update_post_meta($a->ID, 'is_latest', 0);
        }
    }
    update_post_meta($post['ID'], 'is_latest', 1);
  } else {
    update_post_meta($post['ID'], 'is_latest', 0);
  }
}, null , 2);


add_filter("wp_ajax_save-attachment-compat", function(){

    $post_id = $_POST['id'];

    if(($_POST['attachments'][$post_id]['is_latest']) == "1") {
        $args = array( 'post_type' => 'attachment');
        $attachments = get_posts( $args );
        if ( $attachments ) {
          foreach ( $attachments as $a ) {
             update_post_meta($a->ID, 'is_latest', 0);
          }
        }
        update_post_meta($post_id, 'is_latest', 1);
    } else {
        update_post_meta($post_id, 'is_latest', 0);
    }

    clean_post_cache($post_id);

  }, 1, 0);

What I am trying to do is allow multiple Word documents to be uploaded, but for the user to select a "latest" version. This code works fine in achieving that by using a custom meta field on the attachment. However, in the admin interface Wordpress likes to save as it goes along via AJAX, which saves but does not reload other attachment metas, which is the required functionality. So now I effectively want to, at the bottom of my wp_ajax_save-attachment-compat filter, run an AJAX request to update my attachments on view. I have found the AJAX action "query-attachments" which is then used in the JS method Attachments.sync, but I'm really struggling to find a way on how I tie those together?

Cheers

  • 1
    I think you're unnecessarily adding meta. Why not sort by attachment's (post) date ? – Svetoslav Marinov Sep 23 '16 at 13:04
  • I went down this thought process too - I am now using the Enhanced Media Library plugin to categorise the attachments and then use the most recently uploaded one in a particular category to get my desired result. – Ian Sep 23 '16 at 13:36
2

I found a way around this by not using the JS methods themselves but basically listening for their attached AJAX calls and taking it from there. This was my final code. I used the the QueryStringToHash function listed here to parse the data sent in the first place, and use this to determine if I wanted to proceed with refreshing the media frame content view. This was achieved with the help of this post. The one downfall of this method is that once this has been executed, the media library will no longer update with new uploads automatically.

functions.php

add_action('admin_footer-post.php', 'reload_attachments');
add_action('admin_footer-post-new.php', 'reload_attachments');

function reload_attachments() {
    ?>
    <script>
        jQuery(function($) {
            $('#wpcontent').ajaxComplete(function(a,b,c) {
                var input = QueryStringToHash(c.data);
                if (input.action == "save-attachment" || input.action == "save-attachment-compat") {
                     if (wp.media.frame.content.get()!==null) {
                        wp.media.frame.content.get().collection.props.set({ignore: (+ new Date())});
                        wp.media.frame.content.get().options.selection.reset();
                     } else {
                        wp.media.frame.library.props.set({ignore: (+ new Date())});
                     }
                }
            });
        });
    </script>
    <?php
}

There are probably better ways to enqueue this script but actually - as @Svetoslav Marinov comments above - there are perhaps better ways of solving my issue without the inclusion of meta data, so this work is resigned to the cutting room floor. Hopefully someone finds it useful.

| improve this answer | |
  • if you want to display the latest docs first why not check the pre_get_posts filter and make some modifications that way? – Svetoslav Marinov Sep 23 '16 at 14:10

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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