Workflow for attachments in WordPress

Here is how I realized a simple media workflow. Security checking and sanitizing is up to everyone.

Based on WordPress version: 4.9.8

Create Attachment Post | Handle Media

if (!empty($_FILES) && isset($_POST['postid'])) {
  media_handle_upload("attachments", $_POST['postid']);
}

Post status pending is not possible for attachments when using media_handle_upload. For this case a filter needs to be used. This Filter should be added before using media_handle_upload.

add_filter('wp_insert_attachment_data', 'SetAttachmentStatusPending', '99');

function SetAttachmentStatusPending($data) {
  if ($data['post_type'] == 'attachment') {
    $data['post_status'] = 'pending';
  }

  return $data;
}

Now the attachment post is added with pending post_status.

Show pending posts in media library

Worpress Media Library shows only posts with private or inherit post_status. To show posts with pending status we can hook in

add_action('pre_get_posts', array($this, 'QueryAddPendingMedia'));

function QueryAddPendingMedia($query)
{
  // Change query only for admin media page
  if (!is_admin() || get_current_screen()->base !== 'upload') {
    return;
  }

  $arr = explode(',', $query->query["post_status"]);
  $arr[] = 'pending';
  $query->set('post_status', implode(',', $arr));
}

Actions and Bulk Actions

To complete the workflow we need something to publish pending media. To do this we can add (bulk) actions to the media library.

Add Bulk Action

add_filter('bulk_actions-upload', 'BulkActionPublish');

function BulkActionPublish($bulk_actions)
{
  $bulk_actions['publish'] = __('Publish');

  return $bulk_actions;
}

Add Row Action

To add a link to the row actions this code is useful

add_filter('media_row_actions', 'AddMediaPublishLink', 10, 3);

function AddMediaPublishLink(array $actions, WP_Post $post, bool $detached)
{
  if ($post->post_status === 'pending') {
    $link = wp_nonce_url(add_query_arg(array('act' => 'publish', 'itm' => $post->ID), 'upload.php'), 'publish_media_nonce');
    $actions['publish'] = sprintf('<a href="https://wordpress.stackexchange.com/questions/316238/%s">%s</a>', $link, __("Publish"));
  }

  return $actions;
}

Handle Actions

add_action('load-upload.php', 'RowActionPublishHandle');
add_filter('handle_bulk_actions-upload', 'BulkActionPublishHandler', 10, 3);

function BulkActionPublishHandler($redirect_to, $doaction, $post_ids)
{
  if ($doaction !== 'publish') {
    return $redirect_to;
  }

  foreach ($post_ids as $post_id) {
    wp_update_post(array(
      'ID' => $post_id,
      'post_status' => 'publish'
    ));
  }

  return $redirect_to;
}

function RowActionPublishHandle()
{
  // Handle publishing only for admin media page
  if (!is_admin() || get_current_screen()->base !== 'upload') {
    return;
  }

  if (isset($_GET['_wpnonce']) && wp_verify_nonce($_GET['_wpnonce'], 'publish_media_nonce')) {
    if (isset($_GET['act']) && $_GET['act'] === 'publish') {
      wp_update_post(array(
        'ID' => $_GET['itm'],
        'post_status' => 'publish'
      ));
    }
  }
}