Fix orphan image attachments in wordpress/woocommerce

I ended up with a load of orphan image attachments. By which i mean the post_parent of the image attachment was 0. This is bad in one particular situation. Although all the images were in use on posts, Google has a habit of indexing the attachment pages as well and often these are not themed and do not contain the info you want end users to see, For example http://example.org/product/attachment/1234/. Its possible to use plugins to add no-index no-follow meta tags to the attachment pages that will remove them from search. But this seemed a bit half-arsed. Plugins such as Yoast SEO have options to redirect attachment pages back to the parent post. But this is useless if the post_parent is 0.

So i came up with the following quick hack to run on the server from a ssh prompt.


<?php 
$sapi_type = php_sapi_name(); 
if (substr($sapi_type, 0, 3) == 'cgi') 
{ die("You are using CGI PHP\n"); } 

require('wp-blog-header.php'); 
require ( ABSPATH . 'wp-admin/includes/image.php' ); 

$args = array( 'posts_per_page' => 1000,
        'offset'           => 0,
        'category'         => '',
        'category_name'    => '',
        'orderby'          => 'date',
        'order'            => 'DESC',
        'include'          => '',
        'exclude'          => '',
        'meta_key'         => '',
        'meta_value'       => '',
        'post_type'        => 'product',
        'post_mime_type'   => '',
        'post_parent'      => '',
        'author'           => '',
        'post_status'      => 'publish',
        'suppress_filters' => true
);

$posts = get_posts($args);


foreach ($posts as $post) {
   // Get post title
   $post_thumbnail_id = get_post_thumbnail_id( $post->ID );
   $parentid = wp_get_post_parent_id( $post_thumbnail_id );
   if($parentid == 0)
   {
        wp_update_post(
                array(
                        'ID' =>  $post_thumbnail_id,
                        'post_parent' =>  $post->ID
                )
        );
   }

}

?>


This script finds each post of post_type, gets the featured image ID, then looks up this to see if the post_parent is 0. If it is 0 it sets the post_parent of the image to the post ID determined before. The first few lines ensure that this script is only executable from the command line/ssh prompt so that if you leave this on your web-server it cannot be executed by the http process. However i would encourage removing it directly after use.

The things to note with this are:-

  1. This will run on the first 1000 posts, if you need more, probably best to create an outer loop and use that offset parameter
  2. post_type is set to “product” this is good for woocommerce product posts, for regular posts make this “post”

Leave a Reply