Skip Navigation

[Resolved] Saving a rating-average score to a parent post, to enable filtering.

This support ticket is created 8 years, 2 months ago. There's a good chance that you are reading advice that it now obsolete.

This is the technical support forum for Toolset - a suite of plugins for developing WordPress sites without writing PHP.

Everyone can read this forum, but only Toolset clients can post in it. Toolset support works 6 days per week, 19 hours per day.

Our next available supporter will start replying to tickets in about 1.89 hours from now. Thank you for your understanding.

Sun Mon Tue Wed Thu Fri Sat
- - 14:00 – 20:00 14:00 – 20:00 14:00 – 20:00 14:00 – 20:00 14:00 – 20:00
- - - - - - -

Supporter timezone: Asia/Ho_Chi_Minh (GMT+07:00)

This topic contains 7 replies, has 4 voices.

Last updated by Beda 8 years, 2 months ago.

Assisted by: Beda.

Author
Posts
#365098

Hello!

I followed this excellent thread to implement a review/ratings system. It all works very well.
https://toolset.com/forums/topic/how-to-get-rating-average-from-cred-for-review/

Then I decided that I wanted to be able to modify my parametric search to include the ability to filter by the average score. I found two useful threads to help achieve this, but I cannot get it to work:
https://toolset.com/forums/topic/passing-custom-field-values-into-another-custom-field-via-cred/
and
https://toolset.com/forums/topic/how-to-save-rating-average-to-a-custom-field-type-on-database-to-sort-it/

I am working within a copy of the "Classifieds" reference site, so the parent post type is "listings", and I've added a custom numerical field called average-rating to hold the average score value.

My child CRED form for adding the review has an ID of 5987.
My "add a new listing" CRED form has ID 5958 - that's the form referenced in the first part of the code below, which is there because of this thread, to get rid of the rich-text editor on the CRED form:
https://toolset.com/forums/topic/how-to-get-rid-of-the-rich-text-editor/

add_action('cred_save_data', 'my_save_data_action',10,2);
function my_save_data_action($post_id, $form_data)
{
    // if a specific form
    if ($form_data['id']==5958) {
        if (isset($_POST['my_post_content'])) {
            // update the standard post content field
            $my_post = array(
                'ID'           => $post_id,
                'post_content' => $_POST['my_post_content']
            );
 
            // Update the post into the database
            wp_update_post( $my_post );
        }
    }
}

//Calculates and displays the Average Rating of a post
add_shortcode('rating_average', 'rating_average_func');
function rating_average_func()
{
    $child_posts = types_child_posts('reviews');
       
    $sum = 0;
    $num = 0;
    foreach ($child_posts as $child_post) {
        if(isset($child_post->fields['stars']))
        {
            $sum += $child_post->fields['stars'];
            $num ++;
        }
    }
    $average = 0;
    if($num>0)
    {
        $average = $sum/$num;
    }
    $res = $average;
    if($average==0) $res = 0;
    if($average>0.001 && $average<0.5)$res = 0.5;
    if($average>0.501 && $average<1) $res = 1;
    if($average>1.001 && $average<1.5) $res = 1.5;
    if($average>1.501 && $average<2) $res = 2;
    if($average>2.001 && $average<2.5) $res = 2.5;
    if($average>2.501 && $average<3) $res = 3;
    if($average>3.001 && $average<3.5) $res = 3.5;
    if($average>3.501 && $average<4) $res = 4;
    if($average>4.001 && $average<4.5) $res = 4.5;
    if($average>4.501 && $average<5) $res = 5;
//... here put more condition ...
    return $res;
}

//Calculates and displays the number of reviews in a post
add_shortcode('reviews_total', 'reviews_total_func');
function reviews_total_func()
{
$child_posts = types_child_posts('reviews');
return count($child_posts);
}

This code above works perfectly for counting the number of ratings and the average scores, and creates the shortcodes to display them in posts.

The two solutions I have looked at for writing the average-rating to the parent post also use a cred_save_data function, and as my code above also uses one, I think this is maybe why the site broke when I tried it.

So I decided to revert back to my working code and ask the experts!

Assuming Luoy's code below works (which I've adapted to fit my slugs and form ID) - how should I integrate it into what I've already got, above?

add_action('cred_save_data', 'my_save_data_action',10,2);
function my_save_data_action($post_id, $form_data) {
    if ($form_data['id']==5987) {
        $parent_slug = 'listing'; // parent post type slug
        $child_slug = 'reviews'; // child post type slug
        $rating_field_slug = 'stars'; // the rating field slug in child post
        $average_field_slug = 'average-rating'; // the average rating field slug in parent post
        $parent_id = get_post_meta($post_id, '_wpcf_belongs_' . $parent_slug . '_id');
        $child_posts = types_child_posts($child_slug, array('post_id' => $parent_id));
        $sum = 0;
        $num = 0;
        foreach ($child_posts as $child_post) {
            if(isset($child_post->fields[$rating_field_slug]))
            {
                $sum += $child_post->fields[$rating_field_slug];
                $num ++;
            }
        }
        if($num>0)
        {
            $average = $sum/$num;
        }
        update_post_meta($parent_id, 'wpcf-' . $average_field_slug, $average);
    }
};
#365100

Thank you for contacting Toolset support, I'd be delighted to assist!

Custom development projects and code is handled on a best effort basis on the Toolset Forums. Personally, do not have the skill level in PHP to assist with this request and have left it in our support queue so that another supporter can take a look at it. Technically it's out of our scope of support however we do realize that Toolset is a complex suite of tools and some supporters may take it on themselves to help when possible.

I just didn't want to leave you hanging without an explanation of why other tickets are being answered and this one not. I appreciate your understanding!

#365104

Thanks Ross, that's the fastest response I've ever had on this forum.

From reading the other threads, I know that they got it working, so I can't help feeling that for someone like Luoy, Waqas or Beda, the solution would be obvious.

Toolset was attractive to me in the first place because I'm not a programmer but ironically, has led me to start getting to grips with more css, js and php but I still feel hopeless!
thanks

#365135

Yeah totally I can understand the feeling of having an answer so close but not yet all there can be both exciting and aggravating all the at same time 🙂 Thanks on the feedback for the quick reply, it means a lot!

I did want to provide one last note, I'm just about the last Toolset supporter here for the rest of the weekend as I am in the US and my shift ends at 6pm (one hour from now). Some may log in on Sundays though, don't loose hope! I'll ping Beda and Louy to take a look at this in my daily report to see if they can snag it though the next time they are on. Beda is sometimes around Sundays, tell him hello for me!

#365212

Hello Alan, Beda here.

1. Then I decided that I wanted to be able to modify my parametric search to include the ability to filter by the average score. I found two useful threads to help achieve this, but I cannot get it to work:
https://toolset.com/forums/topic/passing-custom-field-values-into-another-custom-field-via-cred/
and
https://toolset.com/forums/topic/how-to-save-rating-average-to-a-custom-field-type-on-database-to-sort-it/

I don't see how those posts are related to a parametric Search.
Can you elaborate?

2. I assume you want to filter by Rating Average.
So probably you want a Filter that lets you filter Posts by "rating average [value here]"

3. The Code you use never updates a Field with the total of reviews.

4. Actually I am not even sure how you related Reviews to the Posts.
==> In your first CRED form you just create a Review, that's all. No Parent is set for the Review post, unless you do out in your CRED Form as a "Create Child Post" link of CRED.

5. The ShortCode you use to display ratings just gets some Posts, it's feels values and Displays them in a sum.
It doesn't update anything with that final Summed Up value.

Can you confirm you have a Parent Post set for each review, and that you want to search those Parent Posts by Reviews Averages?

Then you need to store a Field in the parent Posts with a Total of Review.
You can add a Update Post Meta in the "Create Review" code, which gets the total of already stores reviews, sums the new to it and saves it to another field "total reviews"
(as your second code section in the first post)

That code can go to the same CRED Code for when you submit Reviews (Child of a given parent)

It just needs to be after you created the current Review, so that means after you update the Review Post in the DDBB.

There you can use a get_posts of all Child (Reviews) of the given parent and sum them up, then update that value to a custom field in the same post and later you can create a Parametric Search out of this field.

Note that all Fields must be numeric.

Please let me know if you have further questions regarding the issue mentioned in this Thread

Thank you for your patience.

#365268

Hi Beda

Thanks so much for looking at this for me.

Yes, you are correct - my REVIEWS post type is set up as a child of the LISTING post type, and I am using the "Create Child Post" link from the listing post, so that the review gets created under the appropriate listing.

You're also correct (I think, in terms of my limited understanding of what the code is doing...) that the shortcodes generate the figures "on the fly" as it were, and do not ever save a value to the parent listing post.

Ideally I would like to be able to include the "average-rating" score as a saved field, so that it can be included in a parametric search. (I'm not so interested in creating a field to record the number of the reviews - just the average scores.)

I have created a numeric custom field in the LISTING post type, to contain this data. It's called average-rating. My question boils down to a) how to calculate the score and b) how to store the data in the custom field.

I have tried the code originally supplied by Luoy to do this (copied from another thread, the bottom section of code in my first post above) but it's not working for me, for some reason.

Really appreciate your time, and grateful if you can provide any further help.
Thanks
Alan

#365705

Minesh
Supporter

Languages: English (English )

Timezone: Asia/Kolkata (GMT+05:30)

Beda on his national holiday. He will be back tomorrow and get in touch with you as soon as possible.

#365808

I apologize the delay here

1. Yes, you are correct - my REVIEWS post type is set up as a child of the LISTING post type, and I am using the "Create Child Post" link from the listing post, so that the review gets created under the appropriate listing.

OK great. So we have many reviews, being Child of a Listing.

2. You're also correct (I think, in terms of my limited understanding of what the code is doing...) that the shortcodes generate the figures "on the fly" as it were, and do not ever save a value to the parent listing post.

Yes, I'm pretty sure here, as I don't see any Updates to the DDBB in that code, but only a return value of a types_child_posts();

3. Ideally I would like to be able to include the "average-rating" score as a saved field, so that it can be included in a parametric search. (I'm not so interested in creating a field to record the number of the reviews - just the average scores.)

==> You want to search the parent Listing by Scores.
==> So you need a Field saved in that Parent Post Type (average-rating)
==> You update that Field with the total count of reviews which currently is returned by rating_average ShortCode.
==> You can use that same code, in a update_post_meta function.
==> Ideally that update action happens when a new Review is submitted, that means, you integrate the code in your CRED API function "my_save_data_action" (which BTW i would recommend to re-name to a unique identifier)

So your CRED API function is triggered when a Review is submitted.

Below a code example, and here the logic process:

1. Review is submitted
2. It gets the value of currently submitted star-field value
3. Sum it to the already existing average value of the parent Listing
5. Update the Listing (parent) field average-score with this value.

The problem is, you already have many reviews stored, right?
You need to populate your parent Post Listing at least once so to populate the average listing amount with the total of reviews you already have.
After, every listing review (new review) will just sum the new value to it.

To update with what you already have, either do that manually or create a Custom PHP Script (can be in a CRED from) that you trigger ONCE.

To then update the review-average field each time in your Review CRED API code, go with so,thing like this:
(read comments inline for study purposes)

function my_save_data_action($post_id, $form_data)
{
    // if a specific form
    if ($form_data['id']==5958) {
        if (isset($_POST['my_post_content'])) {
            // update the standard post content field
            $my_post = array(
                'ID'           => $post_id,
                'post_content' => $_POST['my_post_content']
            );
  
            // Update the post into the database
            wp_update_post( $my_post );
        }

        //Get the curretn reveiw star value
        $star_value_this_review = get_post_meta($post_id, 'wpcf-your-star-value-field', true);

        //Get the parent post ID of this post (listing)
        $parent_post_id = get_post_meta($post_id, '_wpcf_belongs_your-parent-post-type-slug_id');

        //get the listings average reveiw value
        $listing_parent_total_stars = get_post_meta($parent_post_id, 'wpcf-average-rating', true);

        //Sum the current lsitings total reveiw to the new review
        $total = $star_value_this_review + $listing_parent_total_stars;

        //Update the avergae reveiw of the parent listing
        update_post_meta($parent_post_id, 'wpcf-average-rating', $total);

    }
}

add_action('cred_save_data', 'my_save_data_action',10,2);

Please also refer to the WordPress Codex and PHP Codex to understand the process better:
https://codex.wordpress.org/Function_Reference/update_post_meta
https://developer.wordpress.org/reference/functions/get_post_meta/
hidden link

Please do not hesitate to open a new thread if other issues or problems arise

Thank you for your patience.

This ticket is now closed. If you're a WPML client and need related help, please open a new support ticket.