• Resolved kojaa

    (@kojaa)


    Hello,

    I can’t seem to figure out how wc_update_product_lookup_tables_rating_count() function works.

    I have a cron that inserts new comments/reviews on specific products, which looks something like 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'       => $post->ID,
                    'comment_content'       => $original_comment->comment_content,
                    'comment_karma'         => $original_comment->comment_karma,
                    'comment_approved'      => 1,
                    'comment_agent'         => $original_comment->comment_agent,
                    'comment_type'          => $original_comment->comment_type,
                    'comment_parent'        => $original_comment->comment_parent,
                    'user_id'               => $original_comment->user_id,
                    'comment_meta' => [
                        'rating' => $comment_rating,
                    ]
                ];
    
    wp_insert_comment($commentdata);

    So this is all the necessary data that wp_insert_comment requires for it to be inserted.
    After this function executes, everything is fine, new review is inserted with correct data, but the wc_product_meta_lookup table needs to be updated.

    I tried with this:

     $test = [
                    [
                        'meta_value' =>  $comment_rating,
                        'post_id' => $post->ID 
                    ],
                ];
    
    wc_update_product_lookup_tables_rating_count($test);

    But this doesn’t work. I see that instead of average_rating, rating_count is being updated. I tried various examples with $test array but i can’t find the correct solution for this. Any help is appreciated.

    • This topic was modified 5 years, 2 months ago by kojaa.
Viewing 6 replies - 1 through 6 (of 6 total)
  • I am not getting this function wc_product_meta_lookup() into the WooCommerce plugin.

    Thread Starter kojaa

    (@kojaa)

    Any help on this? I’m trying for 3 days now and can’t get anything to work. I tried updating wc_product_meta_lookup table with a custom sql query, that doesn’t work either, the decimal (3,2) that is assigned to average_rating is not being updated at all. I changed type of average_rating in DB, that didn’t work either. I really don’t know what to do. Literally everything else is updating with no problem , except the average_rating.

    And one more thing, if i run the cron that has a reply to original comment, the wc_product_meta_lookup is updating correctly without any problems.

    https://docs.woocommerce.com/wc-apidocs/source-function-wc_update_product_lookup_tables.html

    • This reply was modified 5 years, 1 month ago by kojaa.
    • This reply was modified 5 years, 1 month ago by kojaa.
    • This reply was modified 5 years, 1 month ago by Steven Stern (sterndata).

    Hey @kojaa,

    This is a fairly complex development topic. I’m going to leave it open for a bit to see if anyone is able to chime in to help you out.

    I would recommend the following places for more development-oriented questions:

    Cheers

    Thread Starter kojaa

    (@kojaa)

    I managed to achieve what i wanted, thanks for reaching out.

    @kojaa how??

    Thread Starter kojaa

    (@kojaa)

    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.

Viewing 6 replies - 1 through 6 (of 6 total)
  • The topic ‘Updating wc_product_meta_lookup after inserting a review with wp_insert_comment’ is closed to new replies.