How to tie built in AJAX to an add_action?

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 Answer
1

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.

Leave a Comment