How can I set status=’publish’ for all featured images?

Background:

I’ve come accross this WP issue: https://core.trac.wordpress.org/ticket/41445

In short: when you make a request to a post over the REST API, if the featured image was originally uploaded to a different post and this post is not accessible via the REST API (eg. the original post is trashed, is a draft, etc), you get a 403 error.

This is a bug in the WordPress API and it has not been fixed yet.

Apparently, this is happening because all attachments inherit the status from their parent post (in the database, post_status="inherit")

Possible Workarounds:

  • Following this suggestion, I’ve updated the status of all the images I currently have in the DB:
UPDATE wp_posts
SET post_status="publish"
WHERE post_type="attachment"
AND post_mime_type LIKE 'image/%';

This fixes the issue for all the images I currently have… but it obviously doesn’t fix any images that will be uploaded in the future.

  • I can grant extra capabilities to my users.

In my case, it worked by adding edit_posts, edit_private_posts and edit_others_posts.

Solves the problem but it’s definitely not ideal…

Permanent Solution?

I wonder what’s the best way to get a permanent fix for this. Maybe creating a hook with add_attachment and changing the status right after an image is uploaded to WP?

Am I missing something here? Is there a better approach?


UPDATE (june 2019)

As stated in the comments, @cjbj’s answer does exactly what I was asking for (when a new attachment is uploaded, it sets the status of this attachment to ‘publish’). Unfortunately, it seems that this solution will break the Media Library, as it does not display images/attachments with post_status=”publish”.

For anyone facing this same issue, I recommend taking the route of adding extra capabilities to users.

1 Answer
1

If I understand you correctly, you want all attachment status set to ‘publish’ on upload in stead of ‘inherit’ to prevent that status changing when the parent post status changes. Let’s take a look at wp_insert_post if it offers any possibilities.

First on line 3483 (current version) the post status is set to ‘inherit’ in case of attachment posts:

if ( 'attachment' === $post_type && ! in_array( $post_status, array( 'inherit', 'private', 'trash', 'auto-draft' ), true ) ) {
    $post_status="inherit";

Later on (line 3683) all post parameters are compacted into an array called data:

$data = compact( 'post_author', 'post_date', 'post_date_gmt', 'post_content', 'post_content_filtered', 'post_title', 'post_excerpt', 'post_status', 'post_type', 'comment_status', 'ping_status', 'post_password', 'post_name', 'to_ping', 'pinged', 'post_modified', 'post_modified_gmt', 'post_parent', 'menu_order', 'post_mime_type', 'guid' );

Then further on (line 3703) there is this filter:

$data = apply_filters( 'wp_insert_attachment_data', $data, $postarr );

So there you have it, a filter that allows you to change the attachment data right before it is actually stored into the database. You may exploit it like this:

add_filter ('wp_insert_attachment_data','wpse448037_force_attachment_publish', 10, 2)
function wpse448037_force_attachment_publish ($data, $postarr) {
  $data['post_status'] = 'publish';
  return $data;
  }

Note that I didn’t test this code, so some debugging may be necessary.

Leave a Comment