skip to Main Content

I’m trying to write a function that should delete Amazon S3 objects within a designated bucket, when I delete a Woocommerce product(s). But I keep getting an fatal error.

Here’s how I’m trying to accomplish this:

  • The S3 objects (images) are used as Woocommerce downloadable product variations.
  • Using Woocommerce’s before_delete_post I loop through a products variations and trigger $s3->deleteObject.
  • I have a custom field on each variation called s3path. This stores the path of the S3 object eg path/object.jpg.

Here’s my function so far. This is saved in functions.php:

function delete_s3_product_images() {
    global $product;
    
    require ABSPATH . 'vendor/autoload.php';
    $s3 = new AwsS3S3Client([
        'region'  => 'ap-southeast-2',
        'version' => 'latest',
        'credentials' => [
            'key'    => "--Amazon S3 Key--",
            'secret' => "--Amazon S3 Secret--",
        ]
    ]);
    $variations = $product->get_available_variations();
    foreach ( $variations as $key => $value ) {
        $result = $s3->deleteObject([
            'Bucket' => '--Bucket Name--',
            'Key' => $value['s3path'] //value outputs as "path/object.jpg"
        ]);
    }
}
add_action( 'before_delete_post', 'delete_s3_product_images', 10, 1 );

Here’s the error:

Fatal error: Uncaught Error: Call to a member function get_available_variations() on null

I’m assuming it’s throwing the error because it thinks the $product is empty. How can I retrieve the $product correctly?

Edit: Have changed up my original code to use $postid and am not getting any errors any more. However, the image objects within S3 aren’t being deleted. Here’s my updated code:

function delete_s3_product_images($postid) {
    
    require ABSPATH . 'vendor/autoload.php';
    $s3 = new AwsS3S3Client([
        'region'  => 'ap-southeast-2',
        'version' => 'latest',
        'credentials' => [
            'key'    => "--Amazon S3 Key--",
            'secret' => "--Amazon S3 Secret--",
        ]
    ]); 
    
    $args =  array(
        'post_type'      => 'product_variation',
        'post_status'    => 'publish',
        'posts_per_page' => -1,
        'post_parent'    => $postid,
        'meta_query'     => array( 
            array(
                'key' => 's3path',
            ) 
        ),
    );
    $query = new WP_Query( $args );
    
    while( $query->have_posts() ) {
        $query->the_post();

        $s3path = get_post_meta( get_the_id(), 's3path', true );
        
        $result = $s3->deleteObject([
            'Bucket' => '--Bucket Name--',
            'Key' => $s3path
        ]);
    }
    wp_reset_postdata();
}
add_action( 'before_delete_post', 'delete_s3_product_images', 10, 1);

I can confirm that the code works brilliantly when used as a shortcode either within or outside of a Woocommerce page. I’m now assuming it must to do with how before_delete_post handles the while loop?

2

Answers


  1. Try the following

    function delete_s3_product_images($id){
        $product = wc_get_product($id);
    
        if(!$product){
            return;
        }
    
        require ABSPATH ...rest of the function
    }
    
    Login or Signup to reply.
  2. You can create the product object using wc_get_product(). The action [before_delete_post][1] has 2 available parameters: $postid and $post. Use it to create the product object.

    function delete_s3_product_images( $postid ) {
        
        $product = wc_get_product( $postid );
    
        if ( !$product ) { return; }
        
        require ABSPATH . 'vendor/autoload.php';
        $s3 = new AwsS3S3Client([
            'region'  => 'ap-southeast-2',
            'version' => 'latest',
            'credentials' => [
                'key'    => "--Amazon S3 Key--",
                'secret' => "--Amazon S3 Secret--",
            ]
        ]);
        $variations = $product->get_available_variations();
        foreach ( $variations as $key => $value ) {
            $result = $s3->deleteObject([
                'Bucket' => '--Bucket Name--',
                'Key' => $value['s3path'] //value outputs as "path/object.jpg"
            ]);
        }
    }
    add_action( 'before_delete_post', 'delete_s3_product_images', 10, 1 );
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search