I will try to help. My specific task was to copy the original review to 2 more products. So i will try my best to explain and show the code that managed to do it (but the code i will show here is going to copy it to only 1 product).
Note: This might not be the best solution but it works.
First of all i had to get the $original_comment
from database by querying a custom table, now this might not be the case in your situation, however this is the query.
$original_comment = $wpdb->get_row("SELECT * FROM {$prefix}comments WHERE
comment_post_ID = '{$comment_post_id}' AND
user_id = '{$comment_user_id}' AND
comment_author = '{$comment_author}' AND
comment_author_IP = '{$comment_author_ip}' AND
comment_author_email = '{$comment_author_email}' AND
comment_content = '{$comment_content}' AND
comment_agent = '{$comment_agent}' AND
comment_approved = '1' AND
comment_date BETWEEN '{$last_30_days}' AND '{$today}'");
The data that is being compared in this query is from the custom table keep that in mind.
Now i had to check whenever that comment is a reply or an actual review.
By doing this $no_reply = get_comment($comment->comment_parent);
i have variable which will give me either the comment or it will return me NULL
if the comment is NOT reply.
Continuing with the comment (which is not reply) I’m checking if the comment is approved or not by doing if($original_comment->comment_approved == '1')
.
The data for the wp_insert_comment()
function is this:
$commentdata = [
'comment_author' => $original_comment->comment_author,
'comment_author_email' => $original_comment->comment_author_email,
'comment_author_url' => $original_comment->comment_author_url,
'comment_author_IP' => $original_comment->comment_author_IP,
'comment_date' => $original_comment->comment_date,
'comment_date_gmt' => $original_comment->comment_date_gmt,
'comment_post_ID' => $hardcover->ID,
'comment_content' => $original_comment->comment_content,
'comment_karma' => $original_comment->comment_karma,
'comment_approved' => 1,
'comment_agent' => $original_comment->comment_agent,
'comment_type' => $comment_type,
'comment_parent' => 0,
'user_id' => $original_comment->user_id,
'comment_meta' => [ 'rating' => $comment_rating ]
];
NOTE: Keep in mind that this $comment_rating
is coming from the custom table.
Now for all the calculations and inserting data first i had to get the comment_post_ID
of original comment by doing this $og_com_id = $original_comment->comment_post_ID;
So by having comment_post_ID
i can query the commentmeta
table which will be used to calculate average rating and rating counts.
$comment_ids = $wpdb->get_results("SELECT * FROM {$wpdb->prefix}comments WHERE comment_post_ID = '{$og_com_id}' AND comment_approved = '1'");
$ratings = [];
foreach($comment_ids as $comment_id) {
$res = $wpdb->get_results("SELECT meta_value FROM {$wpdb->prefix}commentmeta WHERE comment_id = '{$comment_id->comment_ID}' AND meta_key = 'rating'");
if(empty($res)) continue;
$ratings[] = $res[0]->meta_value;
}
By having the $ratings array
i now have all the ratings that will be calculated for later inserting.
I made a helper function called calculate_average_for_comment_duplicating
(i know it’s long name)
By doing this:
$final_rating_array = calculate_average_for_comment_duplicating($ratings);
I have all data i need.
How function looks like:
function calculate_average_for_comment_duplicating(array $ratings){
$count = count($ratings);
$all_ratings = 0;
foreach($ratings as $rating){
$all_ratings += (int)$rating;
}
return ['count' => $count, 'average_rating' => round($all_ratings / $count, 2)];
}
Now i insert the comment in the database with:
wp_insert_comment($commentdata);
And i query the postmeta
table like this:
$pm_prefix = $wpdb->prefix . 'postmeta';
$_wc_average_rating = $wpdb->get_row(" SELECT meta_value
FROM {$pm_prefix}
WHERE meta_key = '_wc_average_rating'
AND post_id = '{$og_com_id}'");
$_wc_rating_count = $wpdb->get_row(" SELECT meta_value
FROM {$pm_prefix}
WHERE meta_key = '_wc_rating_count'
AND post_id = '{$og_com_id}'");
By having this data, i can query the postmeta
table like this:
$wpdb->query("UPDATE {$pm_prefix} SET
meta_value = '{$_wc_average_rating->meta_value}'
WHERE meta_key = '_wc_average_rating'
AND post_id = {POST_ID_YOU_WANT_TO_CHANGE_RATING_AND_COUNT} ");
$wpdb->query(" UPDATE {$pm_prefix} SET
meta_value = '{$_wc_rating_count->meta_value}'
WHERE meta_key = '_wc_rating_count'
AND post_id = {POST_ID_YOU_WANT_TO_CHANGE_RATING_AND_COUNT} ");
And the final part of this mess is:
$meta_prefix = $wpdb->prefix . 'wc_product_meta_lookup';
$rc_query = $final_rating_array['count'];
$ar_query = $final_rating_array['average_rating'];
$wpdb->query(" UPDATE {$meta_prefix}
SET rating_count = {$rc_query}, average_rating = {$ar_query}
WHERE product_id = '{YOUR_PRODUCT_ID}'");
$wpdb->query(" UPDATE {$meta_prefix}
SET rating_count = {$rc_query}, average_rating = {$ar_query}
WHERE product_id = '{YOUR_PRODUCT_ID}'");
I hope you get the idea what needs to be done here. I understand this is a complete mess but this was the solution that worked for that. Please keep in mind that this is probably not the best solution and you might need to have different data and other stuff but i hope this will help.