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 egpath/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
Try the following
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.