Last active
February 17, 2025 02:53
-
-
Save RadGH/2e419f7b67974f969e55fa3556f652fc to your computer and use it in GitHub Desktop.
Revisions
-
RadGH revised this gist
May 16, 2022 . 1 changed file with 5 additions and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -127,7 +127,11 @@ public function get_edited_entry_id() { $entry_id = (int) rgar( $_GET, $this->query_arg ); if ( !$entry_id ) $entry_id = false; if ( $this->can_user_edit_entry( get_current_user_id(), $entry_id ) ) { return $entry_id; }else{ return false; } } /** -
RadGH revised this gist
May 16, 2022 . 1 changed file with 323 additions and 130 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,86 +1,330 @@ <?php /* Plugin Name: GF Editable by Radley Description: Example classes to make a particular gravity form editable on the front-end. Author: Radley Sustaire Author URI: https://radleysustaire.com/ Version: 1.0.0 */ // QUICK TEST INSTRUCTIONS: // 1. Import this example form in Gravity Forms (download as json): // https://gist.github.com/RadGH/afb032d642515aedbb068f6b5990b668 // // 2. Modify "GF_Form_12" below to be your own form ID after import. // * If you change the class, make sure to replace "new GF_Form_12()" below too. // // 3. Submit an entry on the form. // 4. Go back to the form and add ?edited_entry_id=100 (where 100 is your entry id) // 5. Field values should populate, allowing to edit the same entry. // RECOMMENDED AFTER TESTING: // // 1. Put the "abstract" class Editable_GF_Form into a separate file. // 2. Create a copy of GF_Form_12 for any of your forms. // 3. Include the abstract class, and your custom classes, then instantiate your custom classes like: new GF_Form_12() // Extending "Editable_GF_Form" gives the ability to edit entries. You only need to supply $form_id and $query_arg /** * @class GF_Form_12 * @version 1.0 */ class GF_Form_12 extends Editable_GF_Form { // Each form should have its own class. public $form_id = 12; public $query_arg = 'edited_entry_id'; public function __construct() { // Add essential hooks from the parent Editable_GF_Form class parent::__construct(); // Register actions or filters for the form here. // EXAMPLE: Add a key when the form gets saved // add_filter( 'gform_entry_post_save', array($this, 'fill_random_key'), 30, 2 ); } // EXAMPLE: The function to add a key when the form gets saved /* public function fill_random_key( $entry, $form ) { if ( $this->form_id != $form['id'] ) return $entry; // Some form of key $key = uniqid(); // Save to the database gform_update_meta( $entry['id'], 'secret_key', $key ); // Add to current entry too $entry['secret_key'] = $key; return $entry; } */ } // Remember to instantiate your class, or else it won't do anything. new GF_Form_12(); /** * This class is used to make a gravity form entry editable. * Do not edit below, create your own object that extends this class. * An example is above "GF_Form_12" */ abstract class Editable_GF_Form { /** * Form ID that will allow editing entries. * * @var int */ public $form_id = null; // Internal variables protected $uploads = array(); protected $sub_inputs = array(); public function __construct() { if ( $this->form_id === null ) { _doing_it_wrong(__FUNCTION__, '$this->form_id must be an integer', '1.0'); exit; } // When editing an entry, change the entry ID to the edited entry instead of creating a new entry add_filter( "gform_entry_id_pre_save_lead_{$this->form_id}", array($this, 'change_saved_entry_id'), 50, 2 ); // Prepare the form to be editable on a very early hook add_filter( 'gform_form_args', array( $this, 'prepare_editable_form' ), 20 ); // Insert field values for most fields add_filter( "gform_field_value", array($this, 'load_regular_field_value'), 20, 3 ); // Keeps file uploads unless the user actually deletes or replaces them add_filter( "gform_pre_process", array( $this, 'pre_restore_existing_uploads' ), 20, 1 ); } /** * Get the entry id that is being edited from the url ?entry_id=100 * * @return int|false */ public function get_edited_entry_id() { $entry_id = (int) rgar( $_GET, $this->query_arg ); if ( !$entry_id ) $entry_id = false; return $entry_id; } /** * Keeps file uploads unless the user actually deletes or replaces them. * Gravity forms seems to do this, but fails at it. * To make this work we capture values before (here) and restore them after the entry is saved. * * @param $form * * @return mixed */ public function pre_restore_existing_uploads( $form ) { if ( $form['id'] != $this->form_id ) return $form; $entry_id = $this->get_edited_entry_id(); // Get uploads from $_POST, served as JSON string, which has file upload info $uploads = rgpost( 'gform_uploaded_files' ); if ( !$uploads ) return $form; // Decode the json $uploads = json_decode( $uploads ); // Each file upload field will have the previous filename, or NULL if removing that file. if ( $uploads ) foreach( $uploads as $input_name => $file ) { // If file was removed by user, or replaced with new file if ( ! $file ) continue; // File should be kept. $field_id = (int) str_replace('input_', '', $input_name ); $url = gform_get_meta( $entry_id, $field_id ); $this->uploads[ $input_name ] = array( 'entry_id' => $entry_id, 'input_name' => $input_name, 'field_id' => $field_id, 'url' => $url ); } add_filter( "gform_after_submission_{$form['id']}", array( $this, 'restore_existing_uploads' ), 10, 2 ); return $form; } /** * Restore files preserved by pre_restore_existing_uploads() after the entry has been saved * * @param $entry * @param $form * * @return mixed */ public function restore_existing_uploads( $entry, $form ) { if ( $form['id'] != $this->form_id ) return $entry; if ( $this->uploads ) foreach( $this->uploads as $u ) { if ( $entry['id'] != $u['entry_id'] ) continue; // Get the field ID and URL of the file that should be preserved $field_id = $u['field_id']; // 13 $url = $u['url']; // https://example.com/.../icon-zm3.png // Restore the URL to the entry $entry[ $field_id ] = $url; // Update the entry GFAPI::update_entry( $entry ); } return $entry; } /** * Make all fields on the form editable (allowPrepopulate) and add names if not already given. * * @param $form * * @return mixed */ public function add_form_prepopulate_names( $form ) { // Modify every field and add a name if needed. // Names added manually work too, by enabling "Allow field to be populated dynamically" on the field. if ( $form['fields'] ) foreach( $form['fields'] as &$field ) { if ( !($field instanceof GF_Field) ) continue; // Don't affect display fields (like html) if ( $field->displayOnly ) continue; // Enable pre-populate $field->allowsPrepopulate = true; // Get regular field name $inputName = $field->inputName; if ( $inputName ) continue; // Check if we need a regular field name, or if we need sub fields with names. if ( empty( $field->inputs ) ) { // Regular field // 1st and 2nd are form ID ($form['id']), and field ID ($form->fields[0]->id) // field_12_4_value $field->inputName = "field_{$field['formId']}_{$field['id']}_value"; }else{ // Sub fields // Loop through sub fields and add names to any that are missing foreach( $field->inputs as $key => &$input ) { if ( empty($input['name']) ) { // 3rd number is the sub field ID: ($form->fields[0]->inputs[0]->id) // input name="field_12_4_1_value" $input['name'] = "sub_field_" . $field['formId'] . '_' . $field['id'] . '_'. $key .'_value'; } } } } return $form; } /** * Fill the value on our form using the existing entry's data * * @param $value * @param GF_Field|null $field * @param $name * * @return array */ public function load_regular_field_value( $value = null, GF_Field $field = null, $name = null ) { if ( ! ($field instanceof GF_Field) ) return $value; if ( $field->formId != $this->form_id ) return $value; $existing_entry_id = $this->get_edited_entry_id(); if ( !$existing_entry_id ) return $value; $existing_entry = GFAPI::get_entry( $existing_entry_id ); if ( !$existing_entry ) return $value; $value = GFFormsModel::get_lead_field_value( $existing_entry, $field ); // If no sub fields just return value if ( empty($field->inputs) ) return $value; // Checkboxes work with the given value if ( $field->type == 'checkbox' ) return $value; // Names do not seem to work. return $value; } /** * Add certain hooks only when the form is going to be displayed (based on shortcode usage) * * $args = array(7) { * "form_id" => "12" * "display_title" => true * "display_description" => true * "force_display" => false * "field_values" => array() (empty) * "ajax" => false * "tabindex" => "0" * } * * @param $args * @return array */ public function prepare_editable_form( $args ) { // Only for this form if ( $this->form_id !== (int) $args['form_id'] ) return $args; // Add saved files to edited entry when the form started to be rendered add_filter( "gform_pre_render_{$this->form_id}", array($this, 'prepare_previously_uploaded_files'), 20, 3 ); // Fill in the value of all fields that have a name. The name must match the "autofill parameter name" in the field's settings. $form = GFAPI::get_form( $this->form_id ); $form = $this->add_form_prepopulate_names( $form ); foreach( $form['fields'] as $field ) { if ( !($field instanceof GF_Field) ) continue; $sub_inputs = rgobj($field, 'inputs'); // Advanced inputs like Name and Address have multiple sub inputs, each with their own name and values // They are tricky to fill because Gravity Forms doesn't give you the key with this filter. if ( $sub_inputs ) { foreach( $sub_inputs as $sub_input ) { if ( !is_array($sub_input) ) continue; @@ -89,11 +333,11 @@ public function add_hooks_on_display( $args ) { $name = rgar($sub_input, 'name' ); if ( !$name ) continue; // Store the sub input field assigned to the name (first_name) so we can get field data later $this->sub_inputs[ $name ] = $sub_input; // Use a special filter for sub inputs add_filter( "gform_field_value_{$name}", array( $this, 'fill_sub_input_value' ), 20, 3 ); } continue; } @@ -102,18 +346,6 @@ public function add_hooks_on_display( $args ) { return $args; } /** * Return true if the given user is able to make edits to the entry. * @@ -126,21 +358,26 @@ public function can_user_edit_entry( $user_id, $entry ) { if ( is_numeric($entry) ) $entry = GFAPI::get_entry( $entry ); if ( !$entry || is_wp_error( $entry ) ) return false; // Must be an entry belonging to this form if ( $entry['form_id'] != $this->form_id ) return false; // The user ID must match the owner of the entry if ( (int) $entry['created_by'] != (int) $user_id ) return false; return true; } /** * Set up "uploaded_files" using values from the previous entry. Allows you to keep your previous upload, or remove it and start over. * * If file is kept, form submits: * gform_uploaded_files: {"input_13":"icon-aa3.png"} * * If file is removed, form submits: * gform_uploaded_files: {"input_13":null} * * * * @param $form * @param $ajax * @param $field_values @@ -153,6 +390,8 @@ public function prepare_previously_uploaded_files( $form, $ajax, $field_values ) // Get the edited entry $entry_id = $this->get_edited_entry_id(); if ( !$entry_id ) return $form; // Check permissions if ( !$this->can_user_edit_entry( $user_id, $entry_id ) ) return $form; // Check if any field is a file upload. If not, we can ignore this function @@ -181,18 +420,20 @@ public function prepare_previously_uploaded_files( $form, $ajax, $field_values ) $value = rgar( $entry, $field->id ); GFFormsModel::$uploaded_files[ $form['id'] ]["input_{$field->id}"] = basename( $value ); } return $form; } /** * Make Gravity Forms edit an existing entry ($entry_id = int), instead of creating a new one ($entry_id = null). * * @param $entry_id null|int * @param $form array * * @return null|int */ public function change_saved_entry_id( $entry_id, $form ) { if ( $entry_id !== null ) return $entry_id; @@ -203,78 +444,30 @@ public function change_saved_entry_id( $entry_id, $form ) { $existing_entry_id = $this->get_edited_entry_id(); if ( !$existing_entry_id ) return $entry_id; // Check access, if user can edit then return the previous entry ID, instead of creating a new one (null). if ( $this->can_user_edit_entry( $user_id, $existing_entry_id ) ) { // Edit previous entry return $existing_entry_id; }else{ // Create a new entry return null; } } /** * Get text used for sub inputs * * @param null $value * @param GF_Field|null $field * @param null $name * * @return string */ public function fill_sub_input_value( $value = null, GF_Field $field = null, $name = null ) { if ( $field->formId != $this->form_id ) return $value; // Name must be defined in $this->sub_inputs so we know what sub field this hook relates to. -
RadGH revised this gist
Mar 31, 2021 . 1 changed file with 2 additions and 18 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -105,28 +105,12 @@ public function add_hooks_on_display( $args ) { /** * Get the entry id that is being edited * * @return int|false */ public function get_edited_entry_id() { $entry_id = (int) rgar( $_GET, 'entry_id' ); if ( !$entry_id ) $entry_id = false; return $entry_id; } -
RadGH revised this gist
Jul 14, 2020 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -11,7 +11,7 @@ // * This is a dumb restriction by GF as without a name, there is no filter to set the value. // * File inputs do not need a name though (they don't support one anyway). // 3. This is only for the front-end. I don't know why GF doesn't let you edit entries on the backend. abstract class Editable_GF_Form { // Form ID that will allow editing entries public $form_id = null; -
RadGH revised this gist
Jul 14, 2020 . 1 changed file with 142 additions and 25 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -10,55 +10,96 @@ // 1. All fields must have a unique name set for "allow to be pre-populated". // * This is a dumb restriction by GF as without a name, there is no filter to set the value. // * File inputs do not need a name though (they don't support one anyway). // 3. This is only for the front-end. I don't know why GF doesn't let you edit entries on the backend. abstract class Evaluation_Form_GF_Editable { // Form ID that will allow editing entries public $form_id = null; public $initialized = false; public $sub_inputs = array(); public function __construct() {; // Add other hooks on every page load -- for things like saving data add_action( 'after_setup_theme', array( $this, 'add_hooks_on_every_load' ) ); // Add certain hooks only when the form is going to be displayed (based on shortcode usage) add_filter( 'gform_form_args', array( $this, 'add_hooks_on_display' ), 20 ); } /** * Add hooks so that entry can save. This can happen on submit or ajax, the shortcode will not be processed so it needs a separate hook. */ public function add_hooks_on_every_load() { // Only for this form if ( $this->form_id === null ) return; // Allow editing previous insurance entry, if reinstatement needed and admin reinstatement tracking allows for it add_filter( "gform_entry_id_pre_save_lead_{$this->form_id}", array($this, 'change_saved_entry_id'), 50, 2 ); } /** * Add certain hooks only when the form is going to be displayed (based on shortcode usage) * * @param $args * @return array */ public function add_hooks_on_display( $args ) { // Only for this form if ( $this->form_id !== (int) $args['form_id'] ) return $args; // Add saved files to edited entry when the form started to be rendered add_filter( "gform_pre_render_{$this->form_id}", array($this, 'prepare_previously_uploaded_files'), 20, 3 ); // Fill in the value of all fields that have a name. The name must match the "autofill parameter name" in the field's settings. $form = GFAPI::get_form( $this->form_id ); $ignored_field_types = array('html', 'section', 'page'); $compound_field_types = array('checkbox'); foreach( $form['fields'] as $field ) { if ( !($field instanceof GF_Field) ) continue; $name = rgobj( $field, 'inputName' ); $type = rgobj( $field, 'type' ); $sub_inputs = rgobj($field, 'inputs'); // Always ignore certain field types if ( !$type ) continue; if ( in_array($type, $ignored_field_types) ) continue; // Compound inputs have just one name, but have multiple inputs with their own values. if ( in_array($type, $compound_field_types) ) { add_filter( "gform_field_value_{$name}", array( $this, 'fill_field_value_compound' ), 20, 3 ); continue; } // Standard inputs like text and selects have just one input name for the field with a single value. // And some like the Date field have one name with multiple inputs, but still just a single value. if ( $name ) { add_filter( "gform_field_value_{$name}", array( $this, 'fill_field_value_text' ), 20, 3 ); continue; } // Advanced inputs like Name and Address have multiple sub inputs, each with their own name and values if ( $sub_inputs ) { foreach( $sub_inputs as $sub_input ) { if ( !is_array($sub_input) ) continue; // Get the name, if any $name = rgar($sub_input, 'name' ); if ( !$name ) continue; // Store the sub input, particularly so we can get the ID later $this->sub_inputs[ $name ] = $sub_input; // Use a special filter for sub inputs add_filter( "gform_field_value_{$name}", array( $this, 'fill_sub_input_value_text' ), 20, 3 ); } continue; } } return $args; } /** @@ -67,8 +108,24 @@ public function add_gravityform_editable_hooks() { * @return bool|int|mixed */ public function get_edited_entry_id() { $evaluation_id = (int) rgar( $_GET, 'evaluation_id' ); if ( !$evaluation_id ) return false; // Cache the entry_id for this evaluation for the session. static $cached_entry_ids = null; if ( $cached_entry_ids === null ) $cached_entry_ids = array(); // Return from cache if set if ( isset($cached_entry_ids[$evaluation_id]) ) { return $cached_entry_ids[$evaluation_id]; } // Get entry id from evaluation $entry_id = (int) get_field( 'entry_id', $evaluation_id ); if ( !$entry_id ) $entry_id = false; // Cache the entry id for next occurrence $cached_entry_ids[$evaluation_id] = $entry_id; return $entry_id; } @@ -89,7 +146,7 @@ public function can_user_edit_entry( $user_id, $entry ) { if ( $entry['form_id'] != $this->form_id ) return false; // Check if user is owner of the entry if ( (int)$entry['created_by'] != (int)$user_id ) return false; // Check if status of entry is no longer "active". Only active entries can be edited if ( $entry['status'] !== 'active' ) return false; @@ -191,4 +248,64 @@ public function fill_field_value_text( $value = null, GF_Field $field = null, $n return $value; } /** * Fill text fields with the value of an existing entry * * @param null $value * @param GF_Field|null $field * @param null $name * * @return array */ public function fill_field_value_compound( $value = null, GF_Field $field = null, $name = null ) { if ( $field->formId != $this->form_id ) return $value; $sub_inputs = rgobj($field, 'inputs'); if ( !$sub_inputs ) return $value; $existing_entry_id = $this->get_edited_entry_id(); $value = array(); if ( $existing_entry_id ) { foreach( $sub_inputs as $sub_input ) { if ( !is_array($sub_input) ) continue; $sub_input_id = $sub_input['id']; $v = gform_get_meta( $existing_entry_id, $sub_input_id ); if ( $v ) $value[] = $v; } } return $value; } /** * Same as fill_field_value_text, but for sub inputs which are recorded in $this->sub_inputs * * @param null $value * @param GF_Field|null $field * @param null $name * * @return string */ public function fill_sub_input_value_text( $value = null, GF_Field $field = null, $name = null ) { if ( $field->formId != $this->form_id ) return $value; // Name must be defined in $this->sub_inputs so we know what sub field this hook relates to. if ( !isset($this->sub_inputs[$name]) ) return $value; $id = rgar( $this->sub_inputs[$name], 'id' ); if ( !$id ) return $value; $existing_entry_id = $this->get_edited_entry_id(); if ( $existing_entry_id ) { $value = gform_get_meta( $existing_entry_id, $id ); } return $value; } } -
RadGH revised this gist
Jul 14, 2020 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -55,7 +55,7 @@ public function add_gravityform_editable_hooks() { $hook = 'fill_field_value_text'; } if ( $hook && $name ) { add_filter( "gform_field_value_{$name}", array($this, $hook), 20, 3 ); } } -
RadGH revised this gist
Jun 25, 2020 . 1 changed file with 1 addition and 0 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -12,6 +12,7 @@ // * File inputs do not need a name though (they don't support one anyway). // 2. Advanced fields or fields with more than one option may need their own hook set up in add_gravityform_editable_hooks(). // * I added an example if statement for "type = text". Replace that with other field types and build your own hook to get the value. // 3. This is only for the front-end. I don't know why GF doesn't let you edit entries on the backend. abstract class Editable_GF_Form { // Form ID that will allow editing entries -
RadGH revised this gist
Jun 25, 2020 . 1 changed file with 100 additions and 155 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,114 +1,99 @@ <?php if ( !defined( 'ABSPATH' ) ) exit; // How to use: // 1. Create your own class that extends this one, such as: class Amazing_Quiz extends Editable_GF_Form {...} // 2. Set the $form_id in your class (Amazing_Quiz). *Note: This code is designed for a single form per class but could easily be adapted to support any form. // 3. Edit an entry by visiting your form normally but with ?entry_id=123 in the URL. If your user account created the entry, you can edit it. // Requirements: // 1. All fields must have a unique name set for "allow to be pre-populated". // * This is a dumb restriction by GF as without a name, there is no filter to set the value. // * File inputs do not need a name though (they don't support one anyway). // 2. Advanced fields or fields with more than one option may need their own hook set up in add_gravityform_editable_hooks(). // * I added an example if statement for "type = text". Replace that with other field types and build your own hook to get the value. abstract class Editable_GF_Form { // Form ID that will allow editing entries public $form_id = null; public function __construct() { // Certain functions needed when adding hooks are loaded elsewhere in the theme. Hook at init to fix this. add_action( 'after_setup_theme', array( $this, 'add_gravityform_editable_hooks' ) ); } /** * Add hooks so that this form can be modified */ public function add_gravityform_editable_hooks() { // Form id must be specified if ( $this->form_id === null ) return; // Allow editing previous insurance entry, if reinstatement needed and admin reinstatement tracking allows for it add_filter( "gform_entry_id_pre_save_lead_{$this->form_id}", array($this, 'change_saved_entry_id'), 50, 2 ); // Add saved files to edited entry when the form started to be rendered add_filter( "gform_pre_render_{$this->form_id}", array($this, 'prepare_previously_uploaded_files'), 20, 3 ); // Fill in the value of all fields that have a name. The name must match the "autofill parameter name" in the field's settings. $form = GFAPI::get_form( $this->form_id ); foreach( $form['fields'] as $i => $field ) { if ( !($field instanceof GF_Field) ) continue; $name = rgobj( $field, 'inputName' ); // "evaluation_id" $type = rgobj( $field, 'type' ); // "hidden" $hook = false; if ( $type == 'text' ) { $hook = 'fill_field_value_text'; // some other condition can be used here if text doesn't work }else{ $hook = 'fill_field_value_text'; } if ( $hook ) { add_filter( "gform_field_value_{$name}", array($this, $hook), 20, 3 ); } } } /** * Get the entry id that is being edited * * @return bool|int|mixed */ public function get_edited_entry_id() { $entry_id = (int) rgar( $_GET, 'entry_id' ); if ( !$entry_id ) return false; return $entry_id; } /** * Return true if the given user is able to make edits to the entry. * * @param int $user_id * @param array|int $entry * * @return bool */ public function can_user_edit_entry( $user_id, $entry ) { if ( is_numeric($entry) ) $entry = GFAPI::get_entry( $entry ); if ( !$entry || is_wp_error( $entry ) ) return false; // Must be an entry belonging to this renewal form if ( $entry['form_id'] != $this->form_id ) return false; // Check if user is owner of the entry if ( (int) $entry['created_by'] != (int) $user_id ) return false; // Check if status of entry is no longer "active". Only active entries can be edited if ( $entry['status'] !== 'active' ) return false; return true; } /** @@ -123,56 +108,42 @@ public function add_gravityform_editable_hooks() { public function prepare_previously_uploaded_files( $form, $ajax, $field_values ) { $user_id = get_current_user_id(); // Get the edited entry $entry_id = $this->get_edited_entry_id(); if ( !$entry_id ) return $form; if ( !$this->can_user_edit_entry( $user_id, $entry_id ) ) return $form; // Check if any field is a file upload. If not, we can ignore this function do { foreach( $form['fields'] as $field ) { if ( $field instanceof GF_Field_FileUpload ) { // File upload found. Abort the do{} loop and proceed with the function break 2; } } // No file uploads found return $form; } while(false); // Get the entry object $entry = GFAPI::get_entry( $entry_id ); if ( !isset( GFFormsModel::$uploaded_files[ $form['id'] ] ) ) { GFFormsModel::$uploaded_files[ $form['id'] ] = array(); } // Loop through each file upload and put the basename as an uploaded file foreach( $form['fields'] as $field ) { if ( !$field instanceof GF_Field_FileUpload ) continue; $value = rgar( $entry, $field->id ); GFFormsModel::$uploaded_files[ $form['id'] ]["input_{$field->id}"] = basename( $value ); } return $form; } /** * Allow editing previous form entry * @@ -181,20 +152,16 @@ public function get_field_definition_by_field_name( $value ) { * * @return mixed */ public function change_saved_entry_id( $entry_id, $form ) { if ( $entry_id !== null ) return $entry_id; $user_id = get_current_user_id(); // Get the entry being edited $existing_entry_id = $this->get_edited_entry_id(); if ( !$existing_entry_id ) return $entry_id; // Use the edited entry if the user is permitted to edit it if ( $this->can_user_edit_entry( $user_id, $existing_entry_id ) ) { return $existing_entry_id; } @@ -212,34 +179,12 @@ public function edit_existing_entry( $entry_id, $form ) { * @return string */ public function fill_field_value_text( $value = null, GF_Field $field = null, $name = null ) { if ( $field->formId != $this->form_id ) return $value; $existing_entry_id = $this->get_edited_entry_id(); if ( $existing_entry_id ) { $value = gform_get_meta( $existing_entry_id, $field['id'] ); } return $value; -
RadGH revised this gist
Apr 7, 2020 . 1 changed file with 6 additions and 2 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,10 +1,14 @@ <?php if ( !defined( 'ABSPATH' ) ) exit; // This is an example for a specific form type. // You must also call new Renewal(); somewhere. // Alternatively this class can be used as an abstract class (inherit-only) and then you can extend this class for multiple forms. class Renewal { // Gravity Forms settings use during submission and to edit existing entries. public $form_id = 1; // You must put all fields with values (except for file inputs) into this array. This allows them to be given values. // You may need to add your own function for certain field types. -
RadGH revised this gist
Apr 7, 2020 . 1 changed file with 4 additions and 4 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -6,10 +6,10 @@ abstract class Renewal { // Gravity Forms settings use during submission and to edit existing entries. public $form_id = null; // You must put all fields with values (except for file inputs) into this array. This allows them to be given values. // You may need to add your own function for certain field types. // Each field needs to have the "Allow populate from URL" option enabled and given a name that you use as the "name" parameter here. // Gravity Forms has WILDLY INCONSISTENT hooks for filtering the field value otherwise. public $fields = array( // key // gravity form details // 'user_id' => array( 'field_id' => 1, 'name' => false, 'type' => 'text' ), -
RadGH created this gist
Apr 7, 2020 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,244 @@ <?php if ( !defined( 'ABSPATH' ) ) exit; abstract class Renewal { // Gravity Forms settings use during submission and to edit existing entries. public $form_id = null; // You must put all fields with values (except for file inputs) into this array. This allows them to be given values. // You may need to add your own function for certain field types. // Each field needs to have the "Allow populate from URL" option enabled and given a name that you use as the "name" parameter here. // Gravity Forms has WILDLY INCONSISTENT hooks for filtering the field value otherwise. public $fields = array( // key // gravity form details // 'user_id' => array( 'field_id' => 1, 'name' => false, 'type' => 'text' ), ); public function __construct() { // Certain functions needed when adding hooks are loaded elsewhere in the theme. Hook at init to fix this. add_action( 'after_setup_theme', array( $this, 'add_gravityform_editable_hooks' ) ); } /** * Return true if the given user is able to make edits to the entry. * * @param $user_id * @param $entry_id * * @return bool */ public function can_user_edit_entry( $user_id, $entry_id ) { $entry = GFAPI::get_entry( $entry_id ); if ( !$entry || is_wp_error($entry) ) return false; // Must be an entry belonging to this renewal form if ( $entry['form_id'] != $this->form_id ) return false; // Check if user is owner of the entry if ( (int) $entry['created_by'] != (int) $user_id ) return false; // Check if status of entry is no longer "active". Only active entries can be edited if ( $entry['status'] !== 'active' ) return false; return true; } /** * Get the user's current inactive pli renewal entry * - Must be active (not trashed) * - Must be created by the user_id * * @param $user_id * * @return int|false */ public function get_user_active_entry( $user_id = null ) { if ( $user_id === null ) $user_id = get_current_user_id(); // Get entries by this user from this form in the last year, where reinstatement required = 1 $search_args = array( 'status' => 'active', 'field_filters' => array( array( 'key' => 'created_by', 'value' => $user_id ), ), ); $existing_entry_ids = GFAPI::get_entry_ids( $this->form_id, $search_args ); if ( $existing_entry_ids ) { return (int) $existing_entry_ids[0]; }else{ return false; } } /** * Add hooks so that this form can be modified */ public function add_gravityform_editable_hooks() { // Form id must be specified if ( $this->form_id === null ) return; // Allow editing previous insurance entry, if reinstatement needed and admin reinstatement tracking allows for it add_filter( "gform_entry_id_pre_save_lead_{$this->form_id}", array( $this, 'edit_existing_entry' ), 50, 2 ); // Add saved files to edited entry when the form started to be rendered add_filter( "gform_pre_render_{$this->form_id}", array( $this, 'prepare_previously_uploaded_files' ), 20, 3 ); // Fill in the value of all fields that have a name. The name must match the "autofill parameter name" in the field's settings. foreach( $this->fields as $key => $field ) { if ( $field['name'] ) switch( $field['type'] ) { case 'text': // Fill text field add_filter( "gform_field_value_{$field['name']}", array( $this, 'fill_field_value_text' ), 20, 3 ); break; case 'sub_field_text': // Fill sub_field_text field add_filter( "gform_field_value_{$field['name']}", array( $this, 'fill_field_value_sub_field_text' ), 20, 3 ); break; } } } /** * Set up "uploaded_files" using values from the previous entry. Allows you to keep your previous upload, or remove it and start over. * * @param $form * @param $ajax * @param $field_values * * @return mixed */ public function prepare_previously_uploaded_files( $form, $ajax, $field_values ) { $user_id = get_current_user_id(); $entry_id = $this->get_user_active_entry( $user_id ); if ( ! $this->can_user_edit_entry( $user_id, $entry_id ) ) return $form; $entry = GFAPI::get_entry( $entry_id ); if ( !isset(GFFormsModel::$uploaded_files[$form['id']]) ) { GFFormsModel::$uploaded_files[$form['id']] = array(); } foreach( $form['fields'] as $field ) { if ( ! $field instanceof GF_Field_FileUpload ) continue; $value = rgar( $entry, $field->id ); GFFormsModel::$uploaded_files[$form['id']]["input_{$field->id}"] = basename($value); } return $form; } /** * Gets a field from $this->fields based on field_id instead of name * * @param $value * * @return bool|mixed */ public function get_field_definition_by_field_id( $value ) { foreach( $this->fields as $key => $f ) { if ( $f['field_id'] == $value ) return $f; } return false; } /** * Gets a field from $this->fields based on pre-populate name instead of key * * @param $value * * @return bool|mixed */ public function get_field_definition_by_field_name( $value ) { foreach( $this->fields as $key => $f ) { if ( $f['name'] == $value ) return $f; } return false; } /** * Allow editing previous form entry * * @param $entry_id * @param $form * * @return mixed */ public function edit_existing_entry( $entry_id, $form ) { if ( $entry_id !== null ) return $entry_id; $user_id = get_current_user_id(); // Get the user's existing entry $existing_entry_id = $this->get_user_active_entry( $user_id ); // If they have not previously submitted an entry, use the new one. if ( !$existing_entry_id ) { return $entry_id; } // If the user is permitted to edit an existing entry, return that entry ID to be updated instead of the new one. if ( $this->can_user_edit_entry( $user_id, $existing_entry_id ) ) { return $existing_entry_id; } return $entry_id; } /** * Fill text fields with the value of an existing entry * * @param null $value * @param GF_Field|null $field * @param null $name * * @return string */ public function fill_field_value_text( $value = null, GF_Field $field = null, $name = null ) { $existing_entry_id = $this->get_user_active_entry(); if ( $existing_entry_id ) { $value = gform_get_meta( $existing_entry_id, $field['id'] ); } return $value; } /** * Fill text fields for sub-fields from an existing entry. These fields use meta keys like "15.3" for "Address -> City". * * @param null $value * @param GF_Field|null $field * @param null $name * * @return bool|mixed|null */ public function fill_field_value_sub_field_text( $value = null, GF_Field $field = null, $name = null ) { $existing_entry_id = $this->get_user_active_entry(); if ( $existing_entry_id ) { $field_definition = $this->get_field_definition_by_field_name( $name ); if ( $field_definition ) { $meta_key = $field['id'] . '.' . $field_definition['sub_field_index']; // 15.3 = Address[city] $value = gform_get_meta( $existing_entry_id, $meta_key ); } } return $value; } }