PLEASE NOTE: These forums are no longer utilized and are provided as an archive for informational purposes only. All support issues will be handled via email using our support ticket system. For more detailed information on this change, please see this blog post.

Updating an existing lead

  1. Lowtone

    I'm looking for a way to update an existing lead instead of creating a new one on each submission.

    Using existing action hooks I figured this would be possible using the "gform_after_submission" action since this is the first hook with access to the lead used for the submission. This would however require a new lead to be created (by GFFormDisplay::handle_submission()) and then using the hook to either remove the earlier lead and update the new one with the ID from the earlier lead or update the values for the earlier lead with the new ones and remove the newly created lead. Besides being a bit complicated I could imagine that the lead ID jugling might cause other problems.

    Another solution would require the ability to access the lead data before a new one is created. I couldn't find such a hook so I've tried it by creating my own filter in GFFormsModel::save_lead() by adding this line after line 996:

    $lead = apply_filters("gform_pre_save_lead", $lead);

    Using this filter to inject the lead ID for an existing lead into the lead data worked perfectly.

    Since I'm not a supporter of making modifications to existing plugins I am still wondering if I missed something and that there might be a better solution to the problem.

    Any suggestions?

    Posted 10 years ago on Monday July 8, 2013 | Permalink
  2. David Peralty

    I have asked our developers to take a look at this and give any suggestions or opinions they may have. You are right though that updating core files is not the way to go.

    Posted 10 years ago on Monday July 8, 2013 | Permalink
  3. Thanks for the suggestion. Would you mind sending me the entire save_lead() function so that I can look into adding this hook for you?

    Posted 10 years ago on Monday July 8, 2013 | Permalink
  4. Lowtone

    Hi Alex,
    I've added the code below. The original method comes from Gravity Forms v1.7.6. I made two other modifications in this version to prevent problems with the value returned by the filter.

    Instead of checking the $lead value to be NULL I've made it to check if the $lead value has an ID. To do so I had to cast $lead to an array (isset($lead["id"]) would have worked on any type except for objects which would have caused a fatal error for using them as an array).

    public static function save_lead($form, &$lead){
        global $wpdb;
        GFCommon::log_debug("Saving entry.");
        if(IS_ADMIN && !GFCommon::current_user_can_any("gravityforms_edit_entries"))
            die(__("You don't have adequate permission to edit entries.", "gravityforms"));
        $lead = apply_filters("gform_pre_save_lead", $lead);
        $lead_detail_table = self::get_lead_details_table_name();
        $lead = (array) $lead;
        //Inserting lead if null
        if(!isset($lead["id"])) {
            global $current_user;
            $user_id = $current_user && $current_user->ID ? $current_user->ID : 'NULL';
            $lead_table = RGFormsModel::get_lead_table_name();
            $user_agent = strlen($_SERVER["HTTP_USER_AGENT"]) > 250 ? substr($_SERVER["HTTP_USER_AGENT"], 0, 250) : $_SERVER["HTTP_USER_AGENT"];
            $currency = GFCommon::get_currency();
            $wpdb->query($wpdb->prepare("INSERT INTO $lead_table(form_id, ip, source_url, date_created, user_agent, currency, created_by) VALUES(%d, %s, %s, utc_timestamp(), %s, %s, {$user_id})", $form["id"], self::get_ip(), self::get_current_page_url(), $user_agent, $currency));
            //reading newly created lead id
            $lead_id = $wpdb->insert_id;
            $lead = array("id" => $lead_id);
            GFCommon::log_debug("Entry record created in the database. ID: {$lead_id}");
        $current_fields = $wpdb->get_results($wpdb->prepare("SELECT id, field_number FROM $lead_detail_table WHERE lead_id=%d", $lead["id"]));
        $original_post_id = rgget("post_id", $lead);
        $total_field = null;
        $calculation_fields = array();
        $recalculate_total = false;
        GFCommon::log_debug("Saving entry fields.");
        foreach($form["fields"] as $field){
            //Ignore fields that are marked as display only
            if(rgget("displayOnly", $field) && $field["type"] != "password"){
            //ignore pricing fields in the entry detail
            if(RG_CURRENT_VIEW == "entry" && GFCommon::is_pricing_field($field["type"])){
            //process total field after all fields have been saved
            if($field["type"] == "total"){
                $total_field = $field;
            //only save fields that are not hidden (except on entry screen)
            if(RG_CURRENT_VIEW == "entry" || !RGFormsModel::is_field_hidden($form, $field, array()) ){
                // process calculation fields after all fields have been saved (moved after the is hidden check)
                if( GFCommon::has_field_calculation($field) ) {
                    $calculation_fields[] = $field;
                GFCommon::log_debug("Saving field {$field["label"]}");
                if($field['type'] == 'post_category')
                    $field = GFCommon::add_categories_as_choices($field, '');
                if(isset($field["inputs"]) && is_array($field["inputs"])){
                    foreach($field["inputs"] as $input)
                        self::save_input($form, $field, $lead, $current_fields, $input["id"]);
                    self::save_input($form, $field, $lead, $current_fields, $field["id"]);
        if(!empty($calculation_fields)) {
            foreach($calculation_fields as $calculation_field) {
                GFCommon::log_debug("Saving calculated field {$calculation_field["label"]}");
                if(isset($calculation_field["inputs"]) && is_array($calculation_field["inputs"])){
                    foreach($calculation_field["inputs"] as $input) {
                        self::save_input($form, $calculation_field, $lead, $current_fields, $input["id"]);
                        self::refresh_lead_field_value($lead["id"], $input["id"]);
                    self::save_input($form, $calculation_field, $lead, $current_fields, $calculation_field["id"]);
                    self::refresh_lead_field_value($lead["id"], $calculation_field["id"]);
            self::refresh_product_cache($form, $lead = RGFormsModel::get_lead($lead['id']));
        //saving total field as the last field of the form.
        if($total_field) {
            GFCommon::log_debug("Saving total field.");
            self::save_input($form, $total_field, $lead, $current_fields, $total_field["id"]);
    Posted 10 years ago on Tuesday July 9, 2013 | Permalink
  5. Thanks for the code. The issue I have with this hook is that it kind of implies that you would be able to change the $lead array and your data would be saved. I think it would create some confusion.
    How about something more specific to your scenario? Something like "gform_lead_id_pre_save", which would filter just the lead id?

    As you know, we are in the process of closing this forum for support, so can you please reply by submitting the support form? Please add a link to this topic.


    Posted 10 years ago on Thursday July 25, 2013 | Permalink

This topic has been resolved and has been closed to new replies.