GravityView  1.19.4
The best, easiest way to display Gravity Forms entries on your website.
class-edit-entry-render.php
Go to the documentation of this file.
1 <?php
2 /**
3  * GravityView Edit Entry - render frontend
4  *
5  * @package GravityView
6  * @license GPL2+
7  * @author Katz Web Services, Inc.
8  * @link http://gravityview.co
9  * @copyright Copyright 2014, Katz Web Services, Inc.
10  */
11 
12 if ( ! defined( 'WPINC' ) ) {
13  die;
14 }
15 
16 
18 
19  /**
20  * @var GravityView_Edit_Entry
21  */
22  protected $loader;
23 
24  /**
25  * @var string String used to generate unique nonce for the entry/form/view combination. Allows access to edit page.
26  */
27  static $nonce_key;
28 
29  /**
30  * @since 1.9
31  * @var string String used for check valid edit entry form submission. Allows saving edit form values.
32  */
33  private static $nonce_field = 'is_gv_edit_entry';
34 
35  /**
36  * @since 1.9
37  * @var bool Whether to allow save and continue functionality
38  */
39  private static $supports_save_and_continue = false;
40 
41  /**
42  * @since 1.9
43  * @var bool Whether to allow editing product fields
44  */
45  private static $supports_product_fields = false;
46 
47  /**
48  * Gravity Forms entry array
49  *
50  * @var array
51  */
52  public $entry;
53 
54  /**
55  * Gravity Forms entry array (it won't get changed during this class lifecycle)
56  * @since 1.17.2
57  * @var array
58  */
59  private static $original_entry = array();
60 
61  /**
62  * Gravity Forms form array (GravityView modifies the content through this class lifecycle)
63  *
64  * @var array
65  */
66  public $form;
67 
68  /**
69  * Gravity Forms form array (it won't get changed during this class lifecycle)
70  * @since 1.16.2.1
71  * @var array
72  */
73  private static $original_form;
74 
75  /**
76  * Gravity Forms form array after the form validation process
77  * @since 1.13
78  * @var array
79  */
80  public $form_after_validation = null;
81 
82  /**
83  * Hold an array of GF field objects that have calculation rules
84  * @var array
85  */
86  public $fields_with_calculation = array();
87 
88  /**
89  * Hold an array of GF field objects with type 'total'
90  * @var array
91  */
92  public $total_fields = array();
93 
94  /**
95  * Gravity Forms form id
96  *
97  * @var int
98  */
99  public $form_id;
100 
101  /**
102  * ID of the current view
103  *
104  * @var int
105  */
106  public $view_id;
107 
108  /**
109  * Updated entry is valid (GF Validation object)
110  *
111  * @var array
112  */
113  public $is_valid = NULL;
114 
116  $this->loader = $loader;
117  }
118 
119  function load() {
120 
121  /** @define "GRAVITYVIEW_DIR" "../../../" */
122  include_once( GRAVITYVIEW_DIR .'includes/class-admin-approve-entries.php' );
123 
124  // Don't display an embedded form when editing an entry
125  add_action( 'wp_head', array( $this, 'prevent_render_form' ) );
126  add_action( 'wp_footer', array( $this, 'prevent_render_form' ) );
127 
128  // Stop Gravity Forms processing what is ours!
129  add_filter( 'wp', array( $this, 'prevent_maybe_process_form'), 8 );
130 
131  add_filter( 'gravityview_is_edit_entry', array( $this, 'is_edit_entry') );
132 
133  add_action( 'gravityview_edit_entry', array( $this, 'init' ) );
134 
135  // Disable conditional logic if needed (since 1.9)
136  add_filter( 'gform_has_conditional_logic', array( $this, 'manage_conditional_logic' ), 10, 2 );
137 
138  // Make sure GF doesn't validate max files (since 1.9)
139  add_filter( 'gform_plupload_settings', array( $this, 'modify_fileupload_settings' ), 10, 3 );
140 
141  // Add fields expected by GFFormDisplay::validate()
142  add_filter( 'gform_pre_validation', array( $this, 'gform_pre_validation') );
143 
144  }
145 
146  /**
147  * Don't show any forms embedded on a page when GravityView is in Edit Entry mode
148  *
149  * Adds a `__return_empty_string` filter on the Gravity Forms shortcode on the `wp_head` action
150  * And then removes it on the `wp_footer` action
151  *
152  * @since 1.16.1
153  *
154  * @return void
155  */
156  public function prevent_render_form() {
157  if( $this->is_edit_entry() ) {
158  if( 'wp_head' === current_filter() ) {
159  add_filter( 'gform_shortcode_form', '__return_empty_string' );
160  } else {
161  remove_filter( 'gform_shortcode_form', '__return_empty_string' );
162  }
163  }
164  }
165 
166  /**
167  * Because we're mimicking being a front-end Gravity Forms form while using a Gravity Forms
168  * backend form, we need to prevent them from saving twice.
169  * @return void
170  */
171  public function prevent_maybe_process_form() {
172 
173  do_action('gravityview_log_debug', 'GravityView_Edit_Entry[prevent_maybe_process_form] $_POSTed data (sanitized): ', esc_html( print_r( $_POST, true ) ) );
174 
175  if( $this->is_edit_entry_submission() && $this->verify_nonce() ) {
176  remove_action( 'wp', array( 'RGForms', 'maybe_process_form'), 9 );
177  }
178  }
179 
180  /**
181  * Is the current page an Edit Entry page?
182  * @return boolean
183  */
184  public function is_edit_entry() {
185 
186  $is_edit_entry = GravityView_frontend::is_single_entry() && ! empty( $_GET['edit'] );
187 
188  return ( $is_edit_entry || $this->is_edit_entry_submission() );
189  }
190 
191  /**
192  * Is the current page an Edit Entry page?
193  * @since 1.9
194  * @return boolean
195  */
196  public function is_edit_entry_submission() {
197  return !empty( $_POST[ self::$nonce_field ] );
198  }
199 
200  /**
201  * When Edit entry view is requested setup the vars
202  */
203  private function setup_vars() {
205 
206 
207  $entries = $gravityview_view->getEntries();
208  self::$original_entry = $entries[0];
209  $this->entry = $entries[0];
210 
211  self::$original_form = $gravityview_view->getForm();
212  $this->form = $gravityview_view->getForm();
213  $this->form_id = $gravityview_view->getFormId();
214  $this->view_id = $gravityview_view->getViewId();
215 
216  self::$nonce_key = GravityView_Edit_Entry::get_nonce_key( $this->view_id, $this->form_id, $this->entry['id'] );
217  }
218 
219 
220  /**
221  * Load required files and trigger edit flow
222  *
223  * Run when the is_edit_entry returns true.
224  *
225  * @param GravityView_View_Data $gv_data GravityView Data object
226  * @return void
227  */
228  public function init( $gv_data ) {
229 
230  require_once( GFCommon::get_base_path() . '/form_display.php' );
231  require_once( GFCommon::get_base_path() . '/entry_detail.php' );
232 
233  $this->setup_vars();
234 
235  // Multiple Views embedded, don't proceed if nonce fails
236  if( $gv_data->has_multiple_views() && ! wp_verify_nonce( $_GET['edit'], self::$nonce_key ) ) {
237  do_action('gravityview_log_error', __METHOD__ . ': Nonce validation failed for the Edit Entry request; returning' );
238  return;
239  }
240 
241  // Sorry, you're not allowed here.
242  if( false === $this->user_can_edit_entry( true ) ) {
243  do_action('gravityview_log_error', __METHOD__ . ': User is not allowed to edit this entry; returning', $this->entry );
244  return;
245  }
246 
247  $this->print_scripts();
248 
249  $this->process_save();
250 
251  $this->edit_entry_form();
252 
253  }
254 
255 
256  /**
257  * Force Gravity Forms to output scripts as if it were in the admin
258  * @return void
259  */
260  private function print_scripts() {
262 
263  wp_register_script( 'gform_gravityforms', GFCommon::get_base_url().'/js/gravityforms.js', array( 'jquery', 'gform_json', 'gform_placeholder', 'sack', 'plupload-all', 'gravityview-fe-view' ) );
264 
265  GFFormDisplay::enqueue_form_scripts($gravityview_view->getForm(), false);
266 
267  // Sack is required for images
268  wp_print_scripts( array( 'sack', 'gform_gravityforms' ) );
269  }
270 
271 
272  /**
273  * Process edit entry form save
274  */
275  private function process_save() {
276 
277  if( empty( $_POST ) || ! isset( $_POST['lid'] ) ) {
278  return;
279  }
280 
281  // Make sure the entry, view, and form IDs are all correct
282  $valid = $this->verify_nonce();
283 
284  if( !$valid ) {
285  do_action('gravityview_log_error', __METHOD__ . ' Nonce validation failed.' );
286  return;
287  }
288 
289  if( $this->entry['id'] !== $_POST['lid'] ) {
290  do_action('gravityview_log_error', __METHOD__ . ' Entry ID did not match posted entry ID.' );
291  return;
292  }
293 
294  do_action('gravityview_log_debug', __METHOD__ . ': $_POSTed data (sanitized): ', esc_html( print_r( $_POST, true ) ) );
295 
296  $this->process_save_process_files( $this->form_id );
297 
298  $this->validate();
299 
300  if( $this->is_valid ) {
301 
302  do_action('gravityview_log_debug', __METHOD__ . ': Submission is valid.' );
303 
304  /**
305  * @hack This step is needed to unset the adminOnly from form fields, to add the calculation fields
306  */
307  $form = $this->form_prepare_for_save();
308 
309  /**
310  * @hack to avoid the capability validation of the method save_lead for GF 1.9+
311  */
312  unset( $_GET['page'] );
313 
314  $date_created = $this->entry['date_created'];
315 
316  /**
317  * @hack to force Gravity Forms to use $read_value_from_post in GFFormsModel::save_lead()
318  * @since 1.17.2
319  */
320  unset( $this->entry['date_created'] );
321 
322  GFFormsModel::save_lead( $form, $this->entry );
323 
324  // Delete the values for hidden inputs
325  $this->unset_hidden_field_values();
326 
327  $this->entry['date_created'] = $date_created;
328 
329  // Process calculation fields
330  $this->update_calculation_fields();
331 
332  // Perform actions normally performed after updating a lead
333  $this->after_update();
334 
335  /**
336  * Must be AFTER after_update()!
337  * @see https://github.com/gravityview/GravityView/issues/764
338  */
340 
341  /**
342  * @action `gravityview/edit_entry/after_update` Perform an action after the entry has been updated using Edit Entry
343  * @param array $form Gravity Forms form array
344  * @param string $entry_id Numeric ID of the entry that was updated
345  */
346  do_action( 'gravityview/edit_entry/after_update', $this->form, $this->entry['id'] );
347 
348  } else {
349  do_action('gravityview_log_error', __METHOD__ . ': Submission is NOT valid.', $this->entry );
350  }
351 
352  } // process_save
353 
354  /**
355  * Delete the value of fields hidden by conditional logic when the entry is edited
356  *
357  * @uses GFFormsModel::update_lead_field_value()
358  *
359  * @since 1.17.4
360  *
361  * @return void
362  */
363  private function unset_hidden_field_values() {
364  global $wpdb;
365 
366  $lead_detail_table = GFFormsModel::get_lead_details_table_name();
367  $current_fields = $wpdb->get_results( $wpdb->prepare( "SELECT id, field_number FROM $lead_detail_table WHERE lead_id=%d", $this->entry['id'] ) );
368 
369  foreach ( $this->entry as $input_id => $field_value ) {
370 
371  $field = RGFormsModel::get_field( $this->form, $input_id );
372 
373  // Reset fields that are hidden
374  // Don't pass $entry as fourth parameter; force using $_POST values to calculate conditional logic
375  if ( GFFormsModel::is_field_hidden( $this->form, $field, array(), NULL ) ) {
376 
377  // List fields are stored as empty arrays when empty
378  $empty_value = $this->is_field_json_encoded( $field ) ? '[]' : '';
379 
380  $lead_detail_id = GFFormsModel::get_lead_detail_id( $current_fields, $input_id );
381 
382  GFFormsModel::update_lead_field_value( $this->form, $this->entry, $field, $lead_detail_id, $input_id, $empty_value );
383 
384  // Prevent the $_POST values of hidden fields from being used as default values when rendering the form
385  // after submission
386  $post_input_id = 'input_' . str_replace( '.', '_', $input_id );
387  $_POST[ $post_input_id ] = '';
388  }
389  }
390  }
391 
392  /**
393  * Have GF handle file uploads
394  *
395  * Copy of code from GFFormDisplay::process_form()
396  *
397  * @param int $form_id
398  */
399  private function process_save_process_files( $form_id ) {
400 
401  //Loading files that have been uploaded to temp folder
402  $files = GFCommon::json_decode( stripslashes( RGForms::post( 'gform_uploaded_files' ) ) );
403  if ( ! is_array( $files ) ) {
404  $files = array();
405  }
406 
407  RGFormsModel::$uploaded_files[ $form_id ] = $files;
408  }
409 
410  /**
411  * Remove max_files validation (done on gravityforms.js) to avoid conflicts with GravityView
412  * Late validation done on self::custom_validation
413  *
414  * @param $plupload_init array Plupload settings
415  * @param $form_id
416  * @param $instance
417  * @return mixed
418  */
419  public function modify_fileupload_settings( $plupload_init, $form_id, $instance ) {
420  if( ! $this->is_edit_entry() ) {
421  return $plupload_init;
422  }
423 
424  $plupload_init['gf_vars']['max_files'] = 0;
425 
426  return $plupload_init;
427  }
428 
429 
430  /**
431  * Unset adminOnly and convert field input key to string
432  * @return array $form
433  */
434  private function form_prepare_for_save() {
435 
436  $form = $this->form;
437 
438  /** @var GF_Field $field */
439  foreach( $form['fields'] as $k => &$field ) {
440 
441  /**
442  * Remove the fields with calculation formulas before save to avoid conflicts with GF logic
443  * @since 1.16.3
444  * @var GF_Field $field
445  */
446  if( $field->has_calculation() ) {
447  unset( $form['fields'][ $k ] );
448  }
449 
450  $field->adminOnly = false;
451 
452  if( isset( $field->inputs ) && is_array( $field->inputs ) ) {
453  foreach( $field->inputs as $key => $input ) {
454  $field->inputs[ $key ][ 'id' ] = (string)$input['id'];
455  }
456  }
457  }
458 
459  return $form;
460  }
461 
462  private function update_calculation_fields() {
463 
464  $form = self::$original_form;
465  $update = false;
466 
467  // get the most up to date entry values
468  $entry = GFAPI::get_entry( $this->entry['id'] );
469 
470  if( !empty( $this->fields_with_calculation ) ) {
471  $update = true;
472  foreach ( $this->fields_with_calculation as $calc_field ) {
473  $inputs = $calc_field->get_entry_inputs();
474  if ( is_array( $inputs ) ) {
475  foreach ( $inputs as $input ) {
476  $input_name = 'input_' . str_replace( '.', '_', $input['id'] );
477  $entry[ strval( $input['id'] ) ] = RGFormsModel::prepare_value( $form, $calc_field, '', $input_name, $entry['id'], $entry );
478  }
479  } else {
480  $input_name = 'input_' . str_replace( '.', '_', $calc_field->id);
481  $entry[ strval( $calc_field->id ) ] = RGFormsModel::prepare_value( $form, $calc_field, '', $input_name, $entry['id'], $entry );
482  }
483  }
484 
485  }
486 
487  //saving total field as the last field of the form.
488  if ( ! empty( $this->total_fields ) ) {
489  $update = true;
490  foreach ( $this->total_fields as $total_field ) {
491  $input_name = 'input_' . str_replace( '.', '_', $total_field->id);
492  $entry[ strval( $total_field->id ) ] = RGFormsModel::prepare_value( $form, $total_field, '', $input_name, $entry['id'], $entry );
493  }
494  }
495 
496  if( $update ) {
497 
498  $return_entry = GFAPI::update_entry( $entry );
499 
500  if( is_wp_error( $return_entry ) ) {
501  do_action( 'gravityview_log_error', 'Updating the entry calculation and total fields failed', $return_entry );
502  } else {
503  do_action( 'gravityview_log_debug', 'Updating the entry calculation and total fields succeeded' );
504  }
505  }
506  }
507 
508  /**
509  * Handle updating the Post Image field
510  *
511  * Sets a new Featured Image if configured in Gravity Forms; otherwise uploads/updates media
512  *
513  * @since 1.17
514  *
515  * @uses GFFormsModel::media_handle_upload
516  * @uses set_post_thumbnail
517  *
518  * @param array $form GF Form array
519  * @param GF_Field $field GF Field
520  * @param string $field_id Numeric ID of the field
521  * @param string $value
522  * @param array $entry GF Entry currently being edited
523  * @param int $post_id ID of the Post being edited
524  *
525  * @return mixed|string
526  */
527  private function update_post_image( $form, $field, $field_id, $value, $entry, $post_id ) {
528 
529  $input_name = 'input_' . $field_id;
530 
531  if ( !empty( $_FILES[ $input_name ]['name'] ) ) {
532 
533  // We have a new image
534 
535  $value = RGFormsModel::prepare_value( $form, $field, $value, $input_name, $entry['id'] );
536 
537  $ary = ! empty( $value ) ? explode( '|:|', $value ) : array();
538  $img_url = rgar( $ary, 0 );
539 
540  $img_title = count( $ary ) > 1 ? $ary[1] : '';
541  $img_caption = count( $ary ) > 2 ? $ary[2] : '';
542  $img_description = count( $ary ) > 3 ? $ary[3] : '';
543 
544  $image_meta = array(
545  'post_excerpt' => $img_caption,
546  'post_content' => $img_description,
547  );
548 
549  //adding title only if it is not empty. It will default to the file name if it is not in the array
550  if ( ! empty( $img_title ) ) {
551  $image_meta['post_title'] = $img_title;
552  }
553 
554  /**
555  * todo: As soon as \GFFormsModel::media_handle_upload becomes a public method, move this call to \GFFormsModel::media_handle_upload and remove the hack from this class.
556  * Note: the method became public in GF 1.9.17.7, but we don't require that version yet.
557  */
558  require_once GRAVITYVIEW_DIR . 'includes/class-gravityview-gfformsmodel.php';
559  $media_id = GravityView_GFFormsModel::media_handle_upload( $img_url, $post_id, $image_meta );
560 
561  // is this field set as featured image?
562  if ( $media_id && $field->postFeaturedImage ) {
563  set_post_thumbnail( $post_id, $media_id );
564  }
565 
566  } elseif ( !empty( $_POST[ $input_name ] ) && is_array( $value ) ) {
567 
568  // Same image although the image title, caption or description might have changed
569 
570  $ary = array();
571  if( ! empty( $entry[ $field_id ] ) ) {
572  $ary = is_array( $entry[ $field_id ] ) ? $entry[ $field_id ] : explode( '|:|', $entry[ $field_id ] );
573  }
574  $img_url = rgar( $ary, 0 );
575 
576  // is this really the same image or something went wrong ?
577  if( $img_url === $_POST[ $input_name ] ) {
578 
579  $img_title = rgar( $value, $field_id .'.1' );
580  $img_caption = rgar( $value, $field_id .'.4' );
581  $img_description = rgar( $value, $field_id .'.7' );
582 
583  $value = ! empty( $img_url ) ? $img_url . "|:|" . $img_title . "|:|" . $img_caption . "|:|" . $img_description : '';
584 
585  if ( $field->postFeaturedImage ) {
586 
587  $image_meta = array(
588  'ID' => get_post_thumbnail_id( $post_id ),
589  'post_title' => $img_title,
590  'post_excerpt' => $img_caption,
591  'post_content' => $img_description,
592  );
593 
594  // update image title, caption or description
595  wp_update_post( $image_meta );
596  }
597  }
598 
599  } else {
600 
601  // if we get here, image was removed or not set.
602  $value = '';
603 
604  if ( $field->postFeaturedImage ) {
605  delete_post_thumbnail( $post_id );
606  }
607  }
608 
609  return $value;
610  }
611 
612  /**
613  * Loop through the fields being edited and if they include Post fields, update the Entry's post object
614  *
615  * @param array $form Gravity Forms form
616  *
617  * @return void
618  */
619  private function maybe_update_post_fields( $form ) {
620 
621  if( empty( $this->entry['post_id'] ) ) {
622  do_action( 'gravityview_log_debug', __METHOD__ . ': This entry has no post fields. Continuing...' );
623  return;
624  }
625 
626  $post_id = $this->entry['post_id'];
627 
628  // Security check
629  if( false === GVCommon::has_cap( 'edit_post', $post_id ) ) {
630  do_action( 'gravityview_log_error', 'The current user does not have the ability to edit Post #'.$post_id );
631  return;
632  }
633 
634  $update_entry = false;
635 
636  $updated_post = $original_post = get_post( $post_id );
637 
638  foreach ( $this->entry as $field_id => $value ) {
639 
640  $field = RGFormsModel::get_field( $form, $field_id );
641 
642  if( ! $field ) {
643  continue;
644  }
645 
646  if( GFCommon::is_post_field( $field ) && 'post_category' !== $field->type ) {
647 
648  // Get the value of the field, including $_POSTed value
649  $value = RGFormsModel::get_field_value( $field );
650 
651  // Use temporary entry variable, to make values available to fill_post_template() and update_post_image()
652  $entry_tmp = $this->entry;
653  $entry_tmp["{$field_id}"] = $value;
654 
655  switch( $field->type ) {
656 
657  case 'post_title':
658  $post_title = $value;
659  if( rgar( $form, 'postTitleTemplateEnabled' ) ) {
660  $post_title = $this->fill_post_template( $form['postTitleTemplate'], $form, $entry_tmp );
661  }
662  $updated_post->post_title = $post_title;
663  $updated_post->post_name = $post_title;
664  unset( $post_title );
665  break;
666 
667  case 'post_content':
668  $post_content = $value;
669  if( rgar( $form, 'postContentTemplateEnabled' ) ) {
670  $post_content = $this->fill_post_template( $form['postContentTemplate'], $form, $entry_tmp, true );
671  }
672  $updated_post->post_content = $post_content;
673  unset( $post_content );
674  break;
675  case 'post_excerpt':
676  $updated_post->post_excerpt = $value;
677  break;
678  case 'post_tags':
679  wp_set_post_tags( $post_id, $value, false );
680  break;
681  case 'post_category':
682  break;
683  case 'post_custom_field':
684  if( ! empty( $field->customFieldTemplateEnabled ) ) {
685  $value = $this->fill_post_template( $field->customFieldTemplate, $form, $entry_tmp, true );
686  }
687 
688  if ( $this->is_field_json_encoded( $field ) && ! is_string( $value ) ) {
689  $value = function_exists('wp_json_encode') ? wp_json_encode( $value ) : json_encode( $value );
690  }
691 
692  update_post_meta( $post_id, $field->postCustomFieldName, $value );
693  break;
694 
695  case 'post_image':
696  $value = $this->update_post_image( $form, $field, $field_id, $value, $this->entry, $post_id );
697  break;
698 
699  }
700 
701  // update entry after
702  $this->entry["{$field_id}"] = $value;
703 
704  $update_entry = true;
705 
706  unset( $entry_tmp );
707  }
708 
709  }
710 
711  if( $update_entry ) {
712 
713  $return_entry = GFAPI::update_entry( $this->entry );
714 
715  if( is_wp_error( $return_entry ) ) {
716  do_action( 'gravityview_log_error', 'Updating the entry post fields failed', array( '$this->entry' => $this->entry, '$return_entry' => $return_entry ) );
717  } else {
718  do_action( 'gravityview_log_debug', 'Updating the entry post fields for post #'.$post_id.' succeeded' );
719  }
720 
721  }
722 
723  $return_post = wp_update_post( $updated_post, true );
724 
725  if( is_wp_error( $return_post ) ) {
726  $return_post->add_data( $updated_post, '$updated_post' );
727  do_action( 'gravityview_log_error', 'Updating the post content failed', compact( 'updated_post', 'return_post' ) );
728  } else {
729  do_action( 'gravityview_log_debug', 'Updating the post content for post #'.$post_id.' succeeded', $updated_post );
730  }
731  }
732 
733  /**
734  * Is the field stored in a JSON-encoded manner?
735  *
736  * @param GF_Field $field
737  *
738  * @return bool True: stored in DB json_encode()'d; False: not encoded
739  */
740  private function is_field_json_encoded( $field ) {
741 
742  $json_encoded = false;
743 
744  $input_type = RGFormsModel::get_input_type( $field );
745 
746  // Only certain custom field types are supported
747  switch( $input_type ) {
748  case 'fileupload':
749  case 'list':
750  case 'multiselect':
751  $json_encoded = true;
752  break;
753  }
754 
755  return $json_encoded;
756  }
757 
758  /**
759  * Convert a field content template into prepared output
760  *
761  * @uses GravityView_GFFormsModel::get_post_field_images()
762  *
763  * @since 1.17
764  *
765  * @param string $template The content template for the field
766  * @param array $form Gravity Forms form
767  * @param bool $do_shortcode Whether to process shortcode inside content. In GF, only run on Custom Field and Post Content fields
768  *
769  * @return mixed|string|void
770  */
771  private function fill_post_template( $template, $form, $entry, $do_shortcode = false ) {
772 
773  require_once GRAVITYVIEW_DIR . 'includes/class-gravityview-gfformsmodel.php';
774 
776 
777  //replacing post image variables
778  $output = GFCommon::replace_variables_post_image( $template, $post_images, $entry );
779 
780  //replacing all other variables
781  $output = GFCommon::replace_variables( $output, $form, $entry, false, false, false );
782 
783  // replace conditional shortcodes
784  if( $do_shortcode ) {
785  $output = do_shortcode( $output );
786  }
787 
788  return $output;
789  }
790 
791 
792  /**
793  * Perform actions normally performed after updating a lead
794  *
795  * @since 1.8
796  *
797  * @see GFEntryDetail::lead_detail_page()
798  *
799  * @return void
800  */
801  private function after_update() {
802 
803  do_action( 'gform_after_update_entry', $this->form, $this->entry['id'], self::$original_entry );
804  do_action( "gform_after_update_entry_{$this->form['id']}", $this->form, $this->entry['id'] );
805 
806  // Re-define the entry now that we've updated it.
807  $entry = RGFormsModel::get_lead( $this->entry['id'] );
808 
809  $entry = GFFormsModel::set_entry_meta( $entry, $this->form );
810 
811  // We need to clear the cache because Gravity Forms caches the field values, which
812  // we have just updated.
813  foreach ($this->form['fields'] as $key => $field) {
814  GFFormsModel::refresh_lead_field_value( $entry['id'], $field->id );
815  }
816 
817  $this->entry = $entry;
818  }
819 
820 
821  /**
822  * Display the Edit Entry form
823  *
824  * @return void
825  */
826  public function edit_entry_form() {
827 
828  ?>
829 
830  <div class="gv-edit-entry-wrapper"><?php
831 
832  $javascript = gravityview_ob_include( GravityView_Edit_Entry::$file .'/partials/inline-javascript.php', $this );
833 
834  /**
835  * Fixes weird wpautop() issue
836  * @see https://github.com/katzwebservices/GravityView/issues/451
837  */
838  echo gravityview_strip_whitespace( $javascript );
839 
840  ?><h2 class="gv-edit-entry-title">
841  <span><?php
842 
843  /**
844  * @filter `gravityview_edit_entry_title` Modify the edit entry title
845  * @param string $edit_entry_title Modify the "Edit Entry" title
846  * @param GravityView_Edit_Entry_Render $this This object
847  */
848  $edit_entry_title = apply_filters('gravityview_edit_entry_title', __('Edit Entry', 'gravityview'), $this );
849 
850  echo esc_attr( $edit_entry_title );
851  ?></span>
852  </h2>
853 
854  <?php $this->maybe_print_message(); ?>
855 
856  <?php // The ID of the form needs to be `gform_{form_id}` for the pluploader ?>
857 
858  <form method="post" id="gform_<?php echo $this->form_id; ?>" enctype="multipart/form-data">
859 
860  <?php
861 
862  wp_nonce_field( self::$nonce_key, self::$nonce_key );
863 
864  wp_nonce_field( self::$nonce_field, self::$nonce_field, false );
865 
866  // Print the actual form HTML
867  $this->render_edit_form();
868 
869  ?>
870  </form>
871 
872  <script>
873  gform.addFilter('gform_reset_pre_conditional_logic_field_action', function ( reset, formId, targetId, defaultValues, isInit ) {
874  return false;
875  });
876  </script>
877 
878  </div>
879 
880  <?php
881  }
882 
883  /**
884  * Display success or error message if the form has been submitted
885  *
886  * @uses GVCommon::generate_notice
887  *
888  * @since 1.16.2.2
889  *
890  * @return void
891  */
892  private function maybe_print_message() {
893 
894  if( rgpost('action') === 'update' ) {
895 
896  $back_link = esc_url( remove_query_arg( array( 'page', 'view', 'edit' ) ) );
897 
898  if( ! $this->is_valid ){
899 
900  // Keeping this compatible with Gravity Forms.
901  $validation_message = "<div class='validation_error'>" . __('There was a problem with your submission.', 'gravityview') . " " . __('Errors have been highlighted below.', 'gravityview') . "</div>";
902  $message = apply_filters("gform_validation_message_{$this->form['id']}", apply_filters("gform_validation_message", $validation_message, $this->form), $this->form);
903 
904  echo GVCommon::generate_notice( $message , 'gv-error' );
905 
906  } else {
907  $entry_updated_message = sprintf( esc_attr__('Entry Updated. %sReturn to Entry%s', 'gravityview'), '<a href="'. $back_link .'">', '</a>' );
908 
909  /**
910  * @filter `gravityview/edit_entry/success` Modify the edit entry success message (including the anchor link)
911  * @since 1.5.4
912  * @param string $entry_updated_message Existing message
913  * @param int $view_id View ID
914  * @param array $entry Gravity Forms entry array
915  * @param string $back_link URL to return to the original entry. @since 1.6
916  */
917  $message = apply_filters( 'gravityview/edit_entry/success', $entry_updated_message , $this->view_id, $this->entry, $back_link );
918 
919  echo GVCommon::generate_notice( $message );
920  }
921 
922  }
923  }
924 
925  /**
926  * Display the Edit Entry form in the original Gravity Forms format
927  *
928  * @since 1.9
929  *
930  * @return void
931  */
932  private function render_edit_form() {
933 
934  /**
935  * @action `gravityview/edit-entry/render/before` Before rendering the Edit Entry form
936  * @since 1.17
937  * @param GravityView_Edit_Entry_Render $this
938  */
939  do_action( 'gravityview/edit-entry/render/before', $this );
940 
941  add_filter( 'gform_pre_render', array( $this, 'filter_modify_form_fields'), 5000, 3 );
942  add_filter( 'gform_submit_button', array( $this, 'render_form_buttons') );
943  add_filter( 'gform_disable_view_counter', '__return_true' );
944 
945  add_filter( 'gform_field_input', array( $this, 'verify_user_can_edit_post' ), 5, 5 );
946  add_filter( 'gform_field_input', array( $this, 'modify_edit_field_input' ), 10, 5 );
947 
948  // We need to remove the fake $_GET['page'] arg to avoid rendering form as if in admin.
949  unset( $_GET['page'] );
950 
951  // TODO: Verify multiple-page forms
952  // TODO: Product fields are not editable
953 
954  ob_start(); // Prevent PHP warnings possibly caused by prefilling list fields for conditional logic
955 
956  $html = GFFormDisplay::get_form( $this->form['id'], false, false, true, $this->entry );
957 
958  ob_get_clean();
959 
960  remove_filter( 'gform_pre_render', array( $this, 'filter_modify_form_fields' ), 5000 );
961  remove_filter( 'gform_submit_button', array( $this, 'render_form_buttons' ) );
962  remove_filter( 'gform_disable_view_counter', '__return_true' );
963  remove_filter( 'gform_field_input', array( $this, 'verify_user_can_edit_post' ), 5 );
964  remove_filter( 'gform_field_input', array( $this, 'modify_edit_field_input' ), 10 );
965 
966  echo $html;
967 
968  /**
969  * @action `gravityview/edit-entry/render/after` After rendering the Edit Entry form
970  * @since 1.17
971  * @param GravityView_Edit_Entry_Render $this
972  */
973  do_action( 'gravityview/edit-entry/render/after', $this );
974  }
975 
976  /**
977  * Display the Update/Cancel/Delete buttons for the Edit Entry form
978  * @since 1.8
979  * @return string
980  */
981  public function render_form_buttons() {
982  return gravityview_ob_include( GravityView_Edit_Entry::$file .'/partials/form-buttons.php', $this );
983  }
984 
985 
986  /**
987  * Modify the form fields that are shown when using GFFormDisplay::get_form()
988  *
989  * By default, all fields will be shown. We only want the Edit Tab configured fields to be shown.
990  *
991  * @param array $form
992  * @param boolean $ajax Whether in AJAX mode
993  * @param array|string $field_values Passed parameters to the form
994  *
995  * @since 1.9
996  *
997  * @return array Modified form array
998  */
999  public function filter_modify_form_fields( $form, $ajax = false, $field_values = '' ) {
1000 
1001  // In case we have validated the form, use it to inject the validation results into the form render
1002  if( isset( $this->form_after_validation ) ) {
1004  } else {
1005  $form['fields'] = $this->get_configured_edit_fields( $form, $this->view_id );
1006  }
1007 
1008  $form = $this->filter_conditional_logic( $form );
1009 
1010  $form = $this->prefill_conditional_logic( $form );
1011 
1012  // for now we don't support Save and Continue feature.
1013  if( ! self::$supports_save_and_continue ) {
1014  unset( $form['save'] );
1015  }
1016 
1017  return $form;
1018  }
1019 
1020  /**
1021  * When displaying a field, check if it's a Post Field, and if so, make sure the post exists and current user has edit rights.
1022  *
1023  * @since 1.16.2.2
1024  *
1025  * @param string $field_content Always empty. Returning not-empty overrides the input.
1026  * @param GF_Field $field
1027  * @param string|array $value If array, it's a field with multiple inputs. If string, single input.
1028  * @param int $lead_id Lead ID. Always 0 for the `gform_field_input` filter.
1029  * @param int $form_id Form ID
1030  *
1031  * @return string If error, the error message. If no error, blank string (modify_edit_field_input() runs next)
1032  */
1033  public function verify_user_can_edit_post( $field_content = '', $field, $value, $lead_id = 0, $form_id ) {
1034 
1035  if( GFCommon::is_post_field( $field ) ) {
1036 
1037  $message = null;
1038 
1039  // First, make sure they have the capability to edit the post.
1040  if( false === current_user_can( 'edit_post', $this->entry['post_id'] ) ) {
1041 
1042  /**
1043  * @filter `gravityview/edit_entry/unsupported_post_field_text` Modify the message when someone isn't able to edit a post
1044  * @param string $message The existing "You don't have permission..." text
1045  */
1046  $message = apply_filters('gravityview/edit_entry/unsupported_post_field_text', __('You don&rsquo;t have permission to edit this post.', 'gravityview') );
1047 
1048  } elseif( null === get_post( $this->entry['post_id'] ) ) {
1049  /**
1050  * @filter `gravityview/edit_entry/no_post_text` Modify the message when someone is editing an entry attached to a post that no longer exists
1051  * @param string $message The existing "This field is not editable; the post no longer exists." text
1052  */
1053  $message = apply_filters('gravityview/edit_entry/no_post_text', __('This field is not editable; the post no longer exists.', 'gravityview' ) );
1054  }
1055 
1056  if( $message ) {
1057  $field_content = sprintf('<div class="ginput_container ginput_container_' . $field->type . '">%s</div>', wpautop( $message ) );
1058  }
1059  }
1060 
1061  return $field_content;
1062  }
1063 
1064  /**
1065  *
1066  * Fill-in the saved values into the form inputs
1067  *
1068  * @param string $field_content Always empty. Returning not-empty overrides the input.
1069  * @param GF_Field $field
1070  * @param string|array $value If array, it's a field with multiple inputs. If string, single input.
1071  * @param int $lead_id Lead ID. Always 0 for the `gform_field_input` filter.
1072  * @param int $form_id Form ID
1073  *
1074  * @return mixed
1075  */
1076  public function modify_edit_field_input( $field_content = '', $field, $value, $lead_id = 0, $form_id ) {
1077 
1079 
1080  // If the form has been submitted, then we don't need to pre-fill the values,
1081  // Except for fileupload type and when a field input is overridden- run always!!
1082  if(
1083  ( $this->is_edit_entry_submission() && !in_array( $field->type, array( 'fileupload', 'post_image' ) ) )
1084  && false === ( $gv_field && is_callable( array( $gv_field, 'get_field_input' ) ) )
1085  || ! empty( $field_content )
1086  || in_array( $field->type, array( 'honeypot' ) )
1087  || GFCommon::is_product_field( $field->type ) // Prevent product fields from appearing editable
1088  ) {
1089  return $field_content;
1090  }
1091 
1092  // Turn on Admin-style display for file upload fields only
1093  if( 'fileupload' === $field->type ) {
1094  $_GET['page'] = 'gf_entries';
1095  }
1096 
1097  // SET SOME FIELD DEFAULTS TO PREVENT ISSUES
1098  $field->adminOnly = false; /** @see GFFormDisplay::get_counter_init_script() need to prevent adminOnly */
1099 
1100  // add categories as choices for Post Category field
1101  if ( 'post_category' === $field->type ) {
1102  $field = GFCommon::add_categories_as_choices( $field, $value );
1103  }
1104 
1105  $field_value = $this->get_field_value( $field );
1106 
1107  /**
1108  * @filter `gravityview/edit_entry/field_value` Change the value of an Edit Entry field, if needed
1109  * @since 1.11
1110  * @param mixed $field_value field value used to populate the input
1111  * @param object $field Gravity Forms field object ( Class GF_Field )
1112  */
1113  $field_value = apply_filters( 'gravityview/edit_entry/field_value', $field_value, $field );
1114 
1115  /**
1116  * @filter `gravityview/edit_entry/field_value_{field_type}` Change the value of an Edit Entry field for a specific field type
1117  * @since 1.17
1118  * @param mixed $field_value field value used to populate the input
1119  * @param GF_Field $field Gravity Forms field object
1120  */
1121  $field_value = apply_filters( 'gravityview/edit_entry/field_value_' . $field->type , $field_value, $field );
1122 
1123  // Prevent any PHP warnings, like undefined index
1124  ob_start();
1125 
1126  /** @var GravityView_Field $gv_field */
1127  if( $gv_field && is_callable( array( $gv_field, 'get_field_input' ) ) ) {
1128  $return = $gv_field->get_field_input( $this->form, $field_value, $this->entry, $field );
1129  } else {
1130  $return = $field->get_field_input( $this->form, $field_value, $this->entry );
1131  }
1132 
1133 
1134  // If there was output, it's an error
1135  $warnings = ob_get_clean();
1136 
1137  if( !empty( $warnings ) ) {
1138  do_action( 'gravityview_log_error', __METHOD__ . $warnings, $field_value );
1139  }
1140 
1141  /**
1142  * Unset hack $_GET['page'] = 'gf_entries'
1143  * We need the fileupload html field to render with the proper id
1144  * ( <li id="field_80_16" ... > )
1145  */
1146  unset( $_GET['page'] );
1147 
1148  return $return;
1149  }
1150 
1151  /**
1152  * Modify the value for the current field input
1153  *
1154  * @param GF_Field $field
1155  *
1156  * @return array|mixed|string|void
1157  */
1158  private function get_field_value( $field ) {
1159 
1160  /**
1161  * @filter `gravityview/edit_entry/pre_populate/override` Allow the pre-populated value to override saved value in Edit Entry form. By default, pre-populate mechanism only kicks on empty fields.
1162  * @param boolean True: override saved values; False: don't override (default)
1163  * @param $field GF_Field object Gravity Forms field object
1164  * @since 1.13
1165  */
1166  $override_saved_value = apply_filters( 'gravityview/edit_entry/pre_populate/override', false, $field );
1167 
1168  // We're dealing with multiple inputs (e.g. checkbox) but not time or date (as it doesn't store data in input IDs)
1169  if( isset( $field->inputs ) && is_array( $field->inputs ) && !in_array( $field->type, array( 'time', 'date' ) ) ) {
1170 
1171  $field_value = array();
1172 
1173  // only accept pre-populated values if the field doesn't have any choice selected.
1174  $allow_pre_populated = $field->allowsPrepopulate;
1175 
1176  foreach ( (array)$field->inputs as $input ) {
1177 
1178  $input_id = strval( $input['id'] );
1179 
1180  if ( isset( $this->entry[ $input_id ] ) && ! gv_empty( $this->entry[ $input_id ], false, false ) ) {
1181  $field_value[ $input_id ] = 'post_category' === $field->type ? GFCommon::format_post_category( $this->entry[ $input_id ], true ) : $this->entry[ $input_id ];
1182  $allow_pre_populated = false;
1183  }
1184 
1185  }
1186 
1187  $pre_value = $field->get_value_submission( array(), false );
1188 
1189  $field_value = ! $allow_pre_populated && ! ( $override_saved_value && !gv_empty( $pre_value, false, false ) ) ? $field_value : $pre_value;
1190 
1191  } else {
1192 
1193  $id = intval( $field->id );
1194 
1195  // get pre-populated value if exists
1196  $pre_value = $field->allowsPrepopulate ? GFFormsModel::get_parameter_value( $field->inputName, array(), $field ) : '';
1197 
1198  // saved field entry value (if empty, fallback to the pre-populated value, if exists)
1199  // or pre-populated value if not empty and set to override saved value
1200  $field_value = !gv_empty( $this->entry[ $id ], false, false ) && ! ( $override_saved_value && !gv_empty( $pre_value, false, false ) ) ? $this->entry[ $id ] : $pre_value;
1201 
1202  // in case field is post_category but inputType is select, multi-select or radio, convert value into array of category IDs.
1203  if ( 'post_category' === $field->type && !gv_empty( $field_value, false, false ) ) {
1204  $categories = array();
1205  foreach ( explode( ',', $field_value ) as $cat_string ) {
1206  $categories[] = GFCommon::format_post_category( $cat_string, true );
1207  }
1208  $field_value = 'multiselect' === $field->get_input_type() ? $categories : implode( '', $categories );
1209  }
1210 
1211  }
1212 
1213  // if value is empty get the default value if defined
1214  $field_value = $field->get_value_default_if_empty( $field_value );
1215 
1216  return $field_value;
1217  }
1218 
1219 
1220  // ---- Entry validation
1221 
1222  /**
1223  * Add field keys that Gravity Forms expects.
1224  *
1225  * @see GFFormDisplay::validate()
1226  * @param array $form GF Form
1227  * @return array Modified GF Form
1228  */
1229  public function gform_pre_validation( $form ) {
1230 
1231  if( ! $this->verify_nonce() ) {
1232  return $form;
1233  }
1234 
1235  // Fix PHP warning regarding undefined index.
1236  foreach ( $form['fields'] as &$field) {
1237 
1238  // This is because we're doing admin form pretending to be front-end, so Gravity Forms
1239  // expects certain field array items to be set.
1240  foreach ( array( 'noDuplicates', 'adminOnly', 'inputType', 'isRequired', 'enablePrice', 'inputs', 'allowedExtensions' ) as $key ) {
1241  $field->{$key} = isset( $field->{$key} ) ? $field->{$key} : NULL;
1242  }
1243 
1244  // unset emailConfirmEnabled for email type fields
1245  /* if( 'email' === $field['type'] && !empty( $field['emailConfirmEnabled'] ) ) {
1246  $field['emailConfirmEnabled'] = '';
1247  }*/
1248 
1249  switch( RGFormsModel::get_input_type( $field ) ) {
1250 
1251  /**
1252  * this whole fileupload hack is because in the admin, Gravity Forms simply doesn't update any fileupload field if it's empty, but it DOES in the frontend.
1253  *
1254  * What we have to do is set the value so that it doesn't get overwritten as empty on save and appears immediately in the Edit Entry screen again.
1255  *
1256  * @hack
1257  */
1258  case 'fileupload':
1259 
1260  // Set the previous value
1261  $entry = $this->get_entry();
1262 
1263  $input_name = 'input_'.$field->id;
1264  $form_id = $form['id'];
1265 
1266  $value = NULL;
1267 
1268  // Use the previous entry value as the default.
1269  if( isset( $entry[ $field->id ] ) ) {
1270  $value = $entry[ $field->id ];
1271  }
1272 
1273  // If this is a single upload file
1274  if( !empty( $_FILES[ $input_name ] ) && !empty( $_FILES[ $input_name ]['name'] ) ) {
1275  $file_path = GFFormsModel::get_file_upload_path( $form['id'], $_FILES[ $input_name ]['name'] );
1276  $value = $file_path['url'];
1277 
1278  } else {
1279 
1280  // Fix PHP warning on line 1498 of form_display.php for post_image fields
1281  // Fix PHP Notice: Undefined index: size in form_display.php on line 1511
1282  $_FILES[ $input_name ] = array('name' => '', 'size' => '' );
1283 
1284  }
1285 
1286  if( rgar($field, "multipleFiles") ) {
1287 
1288  // If there are fresh uploads, process and merge them.
1289  // Otherwise, use the passed values, which should be json-encoded array of URLs
1290  if( isset( GFFormsModel::$uploaded_files[$form_id][$input_name] ) ) {
1291  $value = empty( $value ) ? '[]' : $value;
1292  $value = stripslashes_deep( $value );
1293  $value = GFFormsModel::prepare_value( $form, $field, $value, $input_name, $entry['id'], array());
1294  }
1295 
1296  } else {
1297 
1298  // A file already exists when editing an entry
1299  // We set this to solve issue when file upload fields are required.
1300  GFFormsModel::$uploaded_files[ $form_id ][ $input_name ] = $value;
1301 
1302  }
1303 
1304  $this->entry[ $input_name ] = $value;
1305  $_POST[ $input_name ] = $value;
1306 
1307  break;
1308 
1309  case 'number':
1310  // Fix "undefined index" issue at line 1286 in form_display.php
1311  if( !isset( $_POST['input_'.$field->id ] ) ) {
1312  $_POST['input_'.$field->id ] = NULL;
1313  }
1314  break;
1315  case 'captcha':
1316  // Fix issue with recaptcha_check_answer() on line 1458 in form_display.php
1317  $_POST['recaptcha_challenge_field'] = NULL;
1318  $_POST['recaptcha_response_field'] = NULL;
1319  break;
1320  }
1321 
1322  }
1323 
1324  return $form;
1325  }
1326 
1327 
1328  /**
1329  * Process validation for a edit entry submission
1330  *
1331  * Sets the `is_valid` object var
1332  *
1333  * @return void
1334  */
1335  private function validate() {
1336 
1337  /**
1338  * If using GF User Registration Add-on, remove the validation step, otherwise generates error when updating the entry
1339  * GF User Registration Add-on version > 3.x has a different class name
1340  * @since 1.16.2
1341  */
1342  if ( class_exists( 'GF_User_Registration' ) ) {
1343  remove_filter( 'gform_validation', array( GF_User_Registration::get_instance(), 'validate' ) );
1344  } else if ( class_exists( 'GFUser' ) ) {
1345  remove_filter( 'gform_validation', array( 'GFUser', 'user_registration_validation' ) );
1346  }
1347 
1348 
1349  /**
1350  * For some crazy reason, Gravity Forms doesn't validate Edit Entry form submissions.
1351  * You can enter whatever you want!
1352  * We try validating, and customize the results using `self::custom_validation()`
1353  */
1354  add_filter( 'gform_validation_'. $this->form_id, array( $this, 'custom_validation' ), 10, 4);
1355 
1356  // Needed by the validate funtion
1357  $failed_validation_page = NULL;
1358  $field_values = RGForms::post( 'gform_field_values' );
1359 
1360  // Prevent entry limit from running when editing an entry, also
1361  // prevent form scheduling from preventing editing
1362  unset( $this->form['limitEntries'], $this->form['scheduleForm'] );
1363 
1364  // Hide fields depending on Edit Entry settings
1365  $this->form['fields'] = $this->get_configured_edit_fields( $this->form, $this->view_id );
1366 
1367  $this->is_valid = GFFormDisplay::validate( $this->form, $field_values, 1, $failed_validation_page );
1368 
1369  remove_filter( 'gform_validation_'. $this->form_id, array( $this, 'custom_validation' ), 10 );
1370  }
1371 
1372 
1373  /**
1374  * Make validation work for Edit Entry
1375  *
1376  * Because we're calling the GFFormDisplay::validate() in an unusual way (as a front-end
1377  * form pretending to be a back-end form), validate() doesn't know we _can't_ edit post
1378  * fields. This goes through all the fields and if they're an invalid post field, we
1379  * set them as valid. If there are still issues, we'll return false.
1380  *
1381  * @param [type] $validation_results [description]
1382  * @return [type] [description]
1383  */
1384  public function custom_validation( $validation_results ) {
1385 
1386  do_action('gravityview_log_debug', 'GravityView_Edit_Entry[custom_validation] Validation results: ', $validation_results );
1387 
1388  do_action('gravityview_log_debug', 'GravityView_Edit_Entry[custom_validation] $_POSTed data (sanitized): ', esc_html( print_r( $_POST, true ) ) );
1389 
1390  $gv_valid = true;
1391 
1392  foreach ( $validation_results['form']['fields'] as $key => &$field ) {
1393 
1394  $value = RGFormsModel::get_field_value( $field );
1395  $field_type = RGFormsModel::get_input_type( $field );
1396 
1397  // Validate always
1398  switch ( $field_type ) {
1399 
1400 
1401  case 'fileupload' :
1402  case 'post_image':
1403 
1404  // in case nothing is uploaded but there are already files saved
1405  if( !empty( $field->failed_validation ) && !empty( $field->isRequired ) && !empty( $value ) ) {
1406  $field->failed_validation = false;
1407  unset( $field->validation_message );
1408  }
1409 
1410  // validate if multi file upload reached max number of files [maxFiles] => 2
1411  if( rgobj( $field, 'maxFiles') && rgobj( $field, 'multipleFiles') ) {
1412 
1413  $input_name = 'input_' . $field->id;
1414  //uploaded
1415  $file_names = isset( GFFormsModel::$uploaded_files[ $validation_results['form']['id'] ][ $input_name ] ) ? GFFormsModel::$uploaded_files[ $validation_results['form']['id'] ][ $input_name ] : array();
1416 
1417  //existent
1418  $entry = $this->get_entry();
1419  $value = NULL;
1420  if( isset( $entry[ $field->id ] ) ) {
1421  $value = json_decode( $entry[ $field->id ], true );
1422  }
1423 
1424  // count uploaded files and existent entry files
1425  $count_files = count( $file_names ) + count( $value );
1426 
1427  if( $count_files > $field->maxFiles ) {
1428  $field->validation_message = __( 'Maximum number of files reached', 'gravityview' );
1429  $field->failed_validation = 1;
1430  $gv_valid = false;
1431 
1432  // in case of error make sure the newest upload files are removed from the upload input
1433  GFFormsModel::$uploaded_files[ $validation_results['form']['id'] ] = null;
1434  }
1435 
1436  }
1437 
1438 
1439  break;
1440 
1441  }
1442 
1443  // This field has failed validation.
1444  if( !empty( $field->failed_validation ) ) {
1445 
1446  do_action( 'gravityview_log_debug', 'GravityView_Edit_Entry[custom_validation] Field is invalid.', array( 'field' => $field, 'value' => $value ) );
1447 
1448  switch ( $field_type ) {
1449 
1450  // Captchas don't need to be re-entered.
1451  case 'captcha':
1452 
1453  // Post Image fields aren't editable, so we un-fail them.
1454  case 'post_image':
1455  $field->failed_validation = false;
1456  unset( $field->validation_message );
1457  break;
1458 
1459  }
1460 
1461  // You can't continue inside a switch, so we do it after.
1462  if( empty( $field->failed_validation ) ) {
1463  continue;
1464  }
1465 
1466  // checks if the No Duplicates option is not validating entry against itself, since
1467  // we're editing a stored entry, it would also assume it's a duplicate.
1468  if( !empty( $field->noDuplicates ) ) {
1469 
1470  $entry = $this->get_entry();
1471 
1472  // If the value of the entry is the same as the stored value
1473  // Then we can assume it's not a duplicate, it's the same.
1474  if( !empty( $entry ) && $value == $entry[ $field->id ] ) {
1475  //if value submitted was not changed, then don't validate
1476  $field->failed_validation = false;
1477 
1478  unset( $field->validation_message );
1479 
1480  do_action('gravityview_log_debug', 'GravityView_Edit_Entry[custom_validation] Field not a duplicate; it is the same entry.', $entry );
1481 
1482  continue;
1483  }
1484  }
1485 
1486  // if here then probably we are facing the validation 'At least one field must be filled out'
1487  if( GFFormDisplay::is_empty( $field, $this->form_id ) && empty( $field->isRequired ) ) {
1488  unset( $field->validation_message );
1489  $field->validation_message = false;
1490  continue;
1491  }
1492 
1493  $gv_valid = false;
1494 
1495  }
1496 
1497  }
1498 
1499  $validation_results['is_valid'] = $gv_valid;
1500 
1501  do_action('gravityview_log_debug', 'GravityView_Edit_Entry[custom_validation] Validation results.', $validation_results );
1502 
1503  // We'll need this result when rendering the form ( on GFFormDisplay::get_form )
1504  $this->form_after_validation = $validation_results['form'];
1505 
1506  return $validation_results;
1507  }
1508 
1509 
1510  /**
1511  * TODO: This seems to be hacky... we should remove it. Entry is set when updating the form using setup_vars()!
1512  * Get the current entry and set it if it's not yet set.
1513  * @return array Gravity Forms entry array
1514  */
1515  public function get_entry() {
1516 
1517  if( empty( $this->entry ) ) {
1518  // Get the database value of the entry that's being edited
1520  }
1521 
1522  return $this->entry;
1523  }
1524 
1525 
1526 
1527  // --- Filters
1528 
1529  /**
1530  * Get the Edit Entry fields as configured in the View
1531  *
1532  * @since 1.8
1533  *
1534  * @param int $view_id
1535  *
1536  * @return array Array of fields that are configured in the Edit tab in the Admin
1537  */
1539 
1540  // Get all fields for form
1541  $properties = GravityView_View_Data::getInstance()->get_fields( $view_id );
1542 
1543  // If edit tab not yet configured, show all fields
1544  $edit_fields = !empty( $properties['edit_edit-fields'] ) ? $properties['edit_edit-fields'] : NULL;
1545 
1546  // Hide fields depending on admin settings
1547  $fields = $this->filter_fields( $form['fields'], $edit_fields );
1548 
1549  // If Edit Entry fields are configured, remove adminOnly field settings. Otherwise, don't.
1550  $fields = $this->filter_admin_only_fields( $fields, $edit_fields, $form, $view_id );
1551 
1552  /**
1553  * @filter `gravityview/edit_entry/form_fields` Modify the fields displayed in Edit Entry form
1554  * @since 1.17
1555  * @param GF_Field[] $fields Gravity Forms form fields
1556  * @param array|null $edit_fields Fields for the Edit Entry tab configured in the View Configuration
1557  * @param array $form GF Form array (`fields` key modified to have only fields configured to show in Edit Entry)
1558  * @param int $view_id View ID
1559  */
1560  $fields = apply_filters( 'gravityview/edit_entry/form_fields', $fields, $edit_fields, $form, $view_id );
1561 
1562  return $fields;
1563  }
1564 
1565 
1566  /**
1567  * Filter area fields based on specified conditions
1568  * - This filter removes the fields that have calculation configured
1569  *
1570  * @uses GravityView_Edit_Entry::user_can_edit_field() Check caps
1571  * @access private
1572  * @param GF_Field[] $fields
1573  * @param array $configured_fields
1574  * @since 1.5
1575  * @return array $fields
1576  */
1577  private function filter_fields( $fields, $configured_fields ) {
1578 
1579  if( empty( $fields ) || !is_array( $fields ) ) {
1580  return $fields;
1581  }
1582 
1583  $edit_fields = array();
1584 
1585  $field_type_blacklist = array(
1586  'page',
1587  );
1588 
1589  /**
1590  * @filter `gravityview/edit_entry/hide-product-fields` Hide product fields from being editable.
1591  * @since 1.9.1
1592  * @param boolean $hide_product_fields Whether to hide product fields in the editor. Default: false
1593  */
1594  $hide_product_fields = apply_filters( 'gravityview/edit_entry/hide-product-fields', empty( self::$supports_product_fields ) );
1595 
1596  if( $hide_product_fields ) {
1597  $field_type_blacklist[] = 'option';
1598  $field_type_blacklist[] = 'quantity';
1599  $field_type_blacklist[] = 'product';
1600  $field_type_blacklist[] = 'total';
1601  $field_type_blacklist[] = 'shipping';
1602  $field_type_blacklist[] = 'calculation';
1603  }
1604 
1605  // First, remove blacklist or calculation fields
1606  foreach ( $fields as $key => $field ) {
1607 
1608  // Remove the fields that have calculation properties and keep them to be used later
1609  // @since 1.16.2
1610  if( $field->has_calculation() ) {
1611  $this->fields_with_calculation[] = $field;
1612  // don't remove the calculation fields on form render.
1613  }
1614 
1615  // process total field after all fields have been saved
1616  if ( $field->type == 'total' ) {
1617  $this->total_fields[] = $field;
1618  unset( $fields[ $key ] );
1619  }
1620 
1621  if( in_array( $field->type, $field_type_blacklist ) ) {
1622  unset( $fields[ $key ] );
1623  }
1624  }
1625 
1626  // The Edit tab has not been configured, so we return all fields by default.
1627  if( empty( $configured_fields ) ) {
1628  return $fields;
1629  }
1630 
1631  // The edit tab has been configured, so we loop through to configured settings
1632  foreach ( $configured_fields as $configured_field ) {
1633 
1634  /** @var GF_Field $field */
1635  foreach ( $fields as $field ) {
1636 
1637  if( intval( $configured_field['id'] ) === intval( $field->id ) && $this->user_can_edit_field( $configured_field, false ) ) {
1638  $edit_fields[] = $this->merge_field_properties( $field, $configured_field );
1639  break;
1640  }
1641 
1642  }
1643 
1644  }
1645 
1646  return $edit_fields;
1647 
1648  }
1649 
1650  /**
1651  * Override GF Form field properties with the ones defined on the View
1652  * @param GF_Field $field GF Form field object
1653  * @param array $field_setting GV field options
1654  * @since 1.5
1655  * @return array|GF_Field
1656  */
1657  private function merge_field_properties( $field, $field_setting ) {
1658 
1659  $return_field = $field;
1660 
1661  if( empty( $field_setting['show_label'] ) ) {
1662  $return_field->label = '';
1663  } elseif ( !empty( $field_setting['custom_label'] ) ) {
1664  $return_field->label = $field_setting['custom_label'];
1665  }
1666 
1667  if( !empty( $field_setting['custom_class'] ) ) {
1668  $return_field->cssClass .= ' '. gravityview_sanitize_html_class( $field_setting['custom_class'] );
1669  }
1670 
1671  /**
1672  * Normalize page numbers - avoid conflicts with page validation
1673  * @since 1.6
1674  */
1675  $return_field->pageNumber = 1;
1676 
1677  return $return_field;
1678 
1679  }
1680 
1681  /**
1682  * Remove fields that shouldn't be visible based on the Gravity Forms adminOnly field property
1683  *
1684  * @since 1.9.1
1685  *
1686  * @param array|GF_Field[] $fields Gravity Forms form fields
1687  * @param array|null $edit_fields Fields for the Edit Entry tab configured in the View Configuration
1688  * @param array $form GF Form array
1689  * @param int $view_id View ID
1690  *
1691  * @return array Possibly modified form array
1692  */
1693  private function filter_admin_only_fields( $fields = array(), $edit_fields = null, $form = array(), $view_id = 0 ) {
1694 
1695  /**
1696  * @filter `gravityview/edit_entry/use_gf_admin_only_setting` When Edit tab isn't configured, should the Gravity Forms "Admin Only" field settings be used to control field display to non-admins? Default: true
1697  * If the Edit Entry tab is not configured, adminOnly fields will not be shown to non-administrators.
1698  * If the Edit Entry tab *is* configured, adminOnly fields will be shown to non-administrators, using the configured GV permissions
1699  * @since 1.9.1
1700  * @param boolean $use_gf_adminonly_setting True: Hide field if set to Admin Only in GF and the user is not an admin. False: show field based on GV permissions, ignoring GF permissions.
1701  * @param array $form GF Form array
1702  * @param int $view_id View ID
1703  */
1704  $use_gf_adminonly_setting = apply_filters( 'gravityview/edit_entry/use_gf_admin_only_setting', empty( $edit_fields ), $form, $view_id );
1705 
1706  if( $use_gf_adminonly_setting && false === GVCommon::has_cap( 'gravityforms_edit_entries', $this->entry['id'] ) ) {
1707  foreach( $fields as $k => $field ) {
1708  if( $field->adminOnly ) {
1709  unset( $fields[ $k ] );
1710  }
1711  }
1712  return $fields;
1713  }
1714 
1715  foreach( $fields as &$field ) {
1716  $field->adminOnly = false;
1717  }
1718 
1719  return $fields;
1720  }
1721 
1722  // --- Conditional Logic
1723 
1724  /**
1725  * Conditional logic isn't designed to work with forms that already have content. When switching input values,
1726  * the dependent fields will be blank.
1727  *
1728  * Note: This is because GF populates a JavaScript variable with the input values. This is tough to filter at the input level;
1729  * via the `gform_field_value` filter; it requires lots of legwork. Doing it at the form level is easier.
1730  *
1731  * @since 1.17.4
1732  *
1733  * @param array $form Gravity Forms array object
1734  *
1735  * @return array $form, modified to fix conditional
1736  */
1737  function prefill_conditional_logic( $form ) {
1738 
1739  if( ! GFFormDisplay::has_conditional_logic( $form ) ) {
1740  return $form;
1741  }
1742 
1743  // Have Conditional Logic pre-fill fields as if the data were default values
1744  /** @var GF_Field $field */
1745  foreach ( $form['fields'] as &$field ) {
1746 
1747  if( 'checkbox' === $field->type ) {
1748  foreach ( $field->get_entry_inputs() as $key => $input ) {
1749  $input_id = $input['id'];
1750  $choice = $field->choices[ $key ];
1751  $value = rgar( $this->entry, $input_id );
1752  $match = RGFormsModel::choice_value_match( $field, $choice, $value );
1753  if( $match ) {
1754  $field->choices[ $key ]['isSelected'] = true;
1755  }
1756  }
1757  } else {
1758 
1759  // We need to run through each field to set the default values
1760  foreach ( $this->entry as $field_id => $field_value ) {
1761 
1762  if( floatval( $field_id ) === floatval( $field->id ) ) {
1763 
1764  if( 'list' === $field->type ) {
1765  $list_rows = maybe_unserialize( $field_value );
1766 
1767  $list_field_value = array();
1768  foreach ( (array) $list_rows as $row ) {
1769  foreach ( (array) $row as $column ) {
1770  $list_field_value[] = $column;
1771  }
1772  }
1773 
1774  $field->defaultValue = serialize( $list_field_value );
1775  } else {
1776  $field->defaultValue = $field_value;
1777  }
1778  }
1779  }
1780  }
1781  }
1782 
1783  return $form;
1784  }
1785 
1786  /**
1787  * Remove the conditional logic rules from the form button and the form fields, if needed.
1788  *
1789  * @todo Merge with caller method
1790  * @since 1.9
1791  *
1792  * @param array $form Gravity Forms form
1793  * @return array Modified form, if not using Conditional Logic
1794  */
1795  private function filter_conditional_logic( $form ) {
1796 
1797  /**
1798  * @filter `gravityview/edit_entry/conditional_logic` Should the Edit Entry form use Gravity Forms conditional logic showing/hiding of fields?
1799  * @since 1.9
1800  * @param bool $use_conditional_logic True: Gravity Forms will show/hide fields just like in the original form; False: conditional logic will be disabled and fields will be shown based on configuration. Default: true
1801  * @param array $form Gravity Forms form
1802  */
1803  $use_conditional_logic = apply_filters( 'gravityview/edit_entry/conditional_logic', true, $form );
1804 
1805  if( $use_conditional_logic ) {
1806  return $form;
1807  }
1808 
1809  foreach( $form['fields'] as &$field ) {
1810  /* @var GF_Field $field */
1811  $field->conditionalLogic = null;
1812  }
1813 
1814  unset( $form['button']['conditionalLogic'] );
1815 
1816  return $form;
1817 
1818  }
1819 
1820  /**
1821  * Disable the Gravity Forms conditional logic script and features on the Edit Entry screen
1822  *
1823  * @since 1.9
1824  *
1825  * @param $has_conditional_logic
1826  * @param $form
1827  * @return mixed|void
1828  */
1829  public function manage_conditional_logic( $has_conditional_logic, $form ) {
1830 
1831  if( ! $this->is_edit_entry() ) {
1832  return $has_conditional_logic;
1833  }
1834 
1835  /** @see GravityView_Edit_Entry_Render::filter_conditional_logic for filter documentation */
1836  return apply_filters( 'gravityview/edit_entry/conditional_logic', $has_conditional_logic, $form );
1837  }
1838 
1839 
1840  // --- User checks and nonces
1841 
1842  /**
1843  * Check if the user can edit the entry
1844  *
1845  * - Is the nonce valid?
1846  * - Does the user have the right caps for the entry
1847  * - Is the entry in the trash?
1848  *
1849  * @todo Move to GVCommon
1850  *
1851  * @param boolean $echo Show error messages in the form?
1852  * @return boolean True: can edit form. False: nope.
1853  */
1854  private function user_can_edit_entry( $echo = false ) {
1855 
1856  $error = NULL;
1857 
1858  /**
1859  * 1. Permalinks are turned off
1860  * 2. There are two entries embedded using oEmbed
1861  * 3. One of the entries has just been saved
1862  */
1863  if( !empty( $_POST['lid'] ) && !empty( $_GET['entry'] ) && ( $_POST['lid'] !== $_GET['entry'] ) ) {
1864 
1865  $error = true;
1866 
1867  }
1868 
1869  if( !empty( $_GET['entry'] ) && (string)$this->entry['id'] !== $_GET['entry'] ) {
1870 
1871  $error = true;
1872 
1873  } elseif( ! $this->verify_nonce() ) {
1874 
1875  /**
1876  * If the Entry is embedded, there may be two entries on the same page.
1877  * If that's the case, and one is being edited, the other should fail gracefully and not display an error.
1878  */
1879  if( GravityView_oEmbed::getInstance()->get_entry_id() ) {
1880  $error = true;
1881  } else {
1882  $error = __( 'The link to edit this entry is not valid; it may have expired.', 'gravityview');
1883  }
1884 
1885  }
1886 
1887  if( ! GravityView_Edit_Entry::check_user_cap_edit_entry( $this->entry ) ) {
1888  $error = __( 'You do not have permission to edit this entry.', 'gravityview');
1889  }
1890 
1891  if( $this->entry['status'] === 'trash' ) {
1892  $error = __('You cannot edit the entry; it is in the trash.', 'gravityview' );
1893  }
1894 
1895  // No errors; everything's fine here!
1896  if( empty( $error ) ) {
1897  return true;
1898  }
1899 
1900  if( $echo && $error !== true ) {
1901 
1902  $error = esc_html( $error );
1903 
1904  /**
1905  * @since 1.9
1906  */
1907  if ( ! empty( $this->entry ) ) {
1908  $error .= ' ' . gravityview_get_link( '#', _x('Go back.', 'Link shown when invalid Edit Entry link is clicked', 'gravityview' ), array( 'onclick' => "window.history.go(-1); return false;" ) );
1909  }
1910 
1911  echo GVCommon::generate_notice( wpautop( $error ), 'gv-error error');
1912  }
1913 
1914  do_action('gravityview_log_error', 'GravityView_Edit_Entry[user_can_edit_entry]' . $error );
1915 
1916  return false;
1917  }
1918 
1919 
1920  /**
1921  * Check whether a field is editable by the current user, and optionally display an error message
1922  * @uses GravityView_Edit_Entry->check_user_cap_edit_field() Check user capabilities
1923  * @param array $field Field or field settings array
1924  * @param boolean $echo Whether to show error message telling user they aren't allowed
1925  * @return boolean True: user can edit the current field; False: nope, they can't.
1926  */
1927  private function user_can_edit_field( $field, $echo = false ) {
1928 
1929  $error = NULL;
1930 
1931  if( ! $this->check_user_cap_edit_field( $field ) ) {
1932  $error = __( 'You do not have permission to edit this field.', 'gravityview');
1933  }
1934 
1935  // No errors; everything's fine here!
1936  if( empty( $error ) ) {
1937  return true;
1938  }
1939 
1940  if( $echo ) {
1941  echo GVCommon::generate_notice( wpautop( esc_html( $error ) ), 'gv-error error');
1942  }
1943 
1944  do_action('gravityview_log_error', 'GravityView_Edit_Entry[user_can_edit_field]' . $error );
1945 
1946  return false;
1947 
1948  }
1949 
1950 
1951  /**
1952  * checks if user has permissions to edit a specific field
1953  *
1954  * Needs to be used combined with GravityView_Edit_Entry::user_can_edit_field for maximum security!!
1955  *
1956  * @param [type] $field [description]
1957  * @return bool
1958  */
1959  private function check_user_cap_edit_field( $field ) {
1960 
1961  // If they can edit any entries (as defined in Gravity Forms), we're good.
1962  if( GVCommon::has_cap( array( 'gravityforms_edit_entries', 'gravityview_edit_others_entries' ) ) ) {
1963  return true;
1964  }
1965 
1966  $field_cap = isset( $field['allow_edit_cap'] ) ? $field['allow_edit_cap'] : false;
1967 
1968  // If the field has custom editing capaibilities set, check those
1969  if( $field_cap ) {
1970  return GVCommon::has_cap( $field['allow_edit_cap'] );
1971  }
1972 
1973  return false;
1974  }
1975 
1976 
1977  /**
1978  * Is the current nonce valid for editing the entry?
1979  * @return boolean
1980  */
1981  public function verify_nonce() {
1982 
1983  // Verify form submitted for editing single
1984  if( $this->is_edit_entry_submission() ) {
1985  $valid = wp_verify_nonce( $_POST[ self::$nonce_field ], self::$nonce_field );
1986  }
1987 
1988  // Verify
1989  else if( ! $this->is_edit_entry() ) {
1990  $valid = false;
1991  }
1992 
1993  else {
1994  $valid = wp_verify_nonce( $_GET['edit'], self::$nonce_key );
1995  }
1996 
1997  /**
1998  * @filter `gravityview/edit_entry/verify_nonce` Override Edit Entry nonce validation. Return true to declare nonce valid.
1999  * @since 1.13
2000  * @param int|boolean $valid False if invalid; 1 or 2 when nonce was generated
2001  * @param string $nonce_field Key used when validating submissions. Default: is_gv_edit_entry
2002  */
2003  $valid = apply_filters( 'gravityview/edit_entry/verify_nonce', $valid, self::$nonce_field );
2004 
2005  return $valid;
2006  }
2007 
2008 
2009 
2010 } //end class
const GRAVITYVIEW_DIR
"GRAVITYVIEW_DIR" "./" The absolute path to the plugin directory
Definition: gravityview.php:35
modify_fileupload_settings($plupload_init, $form_id, $instance)
Remove max_files validation (done on gravityforms.js) to avoid conflicts with GravityView Late valida...
$entry
filter_admin_only_fields($fields=array(), $edit_fields=null, $form=array(), $view_id=0)
Remove fields that shouldn&#39;t be visible based on the Gravity Forms adminOnly field property...
is_field_json_encoded($field)
Is the field stored in a JSON-encoded manner?
edit_entry_form()
Display the Edit Entry form.
gv_empty($value, $zero_is_empty=true, $allow_string_booleans=true)
Is the value empty?
$fields_with_calculation
static $supports_product_fields
manage_conditional_logic($has_conditional_logic, $form)
Disable the Gravity Forms conditional logic script and features on the Edit Entry screen...
$image_meta
Definition: post_image.php:106
$back_link
load()
$total_fields
update_calculation_fields()
$is_valid
is_edit_entry()
Is the current page an Edit Entry page?
static media_handle_upload($url, $post_id, $post_data=array())
Copied function from Gravity Forms plugin ::media_handle_upload since the method is private...
$ary
Definition: post_image.php:24
user_can_edit_entry($echo=false)
Check if the user can edit the entry.
render_edit_form()
Display the Edit Entry form in the original Gravity Forms format.
static has_cap($caps= '', $object_id=null, $user_id=null)
Alias of GravityView_Roles_Capabilities::has_cap()
get_configured_edit_fields($form, $view_id)
Get the Edit Entry fields as configured in the View.
$entries
after_update()
Perform actions normally performed after updating a lead.
init($gv_data)
Load required files and trigger edit flow.
user_can_edit_field($field, $echo=false)
Check whether a field is editable by the current user, and optionally display an error message Gravi...
static $nonce_field
$html
Definition: demo.php:7
maybe_print_message()
Display success or error message if the form has been submitted.
setup_vars()
When Edit entry view is requested setup the vars.
filter_conditional_logic($form)
Remove the conditional logic rules from the form button and the form fields, if needed.
static check_user_cap_edit_entry($entry, $view_id=0)
checks if user has permissions to edit a specific entry
unset_hidden_field_values()
Delete the value of fields hidden by conditional logic when the entry is edited.
process_save_process_files($form_id)
Have GF handle file uploads.
$view_id
merge_field_properties($field, $field_setting)
Override GF Form field properties with the ones defined on the View.
static $nonce_key
get_field_value($field)
Modify the value for the current field input.
print_scripts()
Force Gravity Forms to output scripts as if it were in the admin.
static getInstance($passed_post=NULL)
Definition: class-data.php:119
$form_id
verify_user_can_edit_post($field_content= '', $field, $value, $lead_id=0, $form_id)
When displaying a field, check if it&#39;s a Post Field, and if so, make sure the post exists and current...
$gv_field
Definition: time.php:11
maybe_update_post_fields($form)
Loop through the fields being edited and if they include Post fields, update the Entry&#39;s post object...
__construct(GravityView_Edit_Entry $loader)
static get_associated_field($gf_field)
Alias for get_instance()
static generate_notice($notice, $class= '', $cap= '', $object_id=null)
Display updated/error notice.
static $original_form
gravityview_get_link($href= '', $anchor_text= '', $atts=array())
Generate an HTML anchor tag with a list of supported attributes.
prevent_maybe_process_form()
Because we&#39;re mimicking being a front-end Gravity Forms form while using a Gravity Forms backend form...
static $file
static get_post_field_images($form, $entry)
Given information provided in an entry, get array of media IDs.
filter_modify_form_fields($form, $ajax=false, $field_values= '')
Modify the form fields that are shown when using GFFormDisplay::get_form()
static is_single_entry()
Verify if user requested a single entry view.
gravityview_ob_include($file_path, $object=NULL)
Get the contents of a file using include() and ob_start()
$field_id
Definition: time.php:17
if(!function_exists( 'gravityview_sanitize_html_class')) gravityview_strip_whitespace($string)
Replace multiple newlines, tabs, and spaces with a single space.
process_save()
Process edit entry form save.
static $original_entry
gravityview_get_entry($entry_slug, $force_allow_ids=false, $check_entry_display=true)
Return a single entry object.
static $supports_save_and_continue
static get_nonce_key($view_id, $form_id, $entry_id)
Return a well formatted nonce key according to GravityView Edit Entry protocol.
validate()
Process validation for a edit entry submission.
verify_nonce()
Is the current nonce valid for editing the entry?
get_entry()
TODO: This seems to be hacky...
render_form_buttons()
Display the Update/Cancel/Delete buttons for the Edit Entry form.
check_user_cap_edit_field($field)
checks if user has permissions to edit a specific field
update_post_image($form, $field, $field_id, $value, $entry, $post_id)
Handle updating the Post Image field.
is_edit_entry_submission()
Is the current page an Edit Entry page?
static getInstance($passed_post=NULL)
$form_after_validation
$loader
gform_pre_validation($form)
Add field keys that Gravity Forms expects.
$form
fill_post_template($template, $form, $entry, $do_shortcode=false)
Convert a field content template into prepared output.
prevent_render_form()
Don&#39;t show any forms embedded on a page when GravityView is in Edit Entry mode.
$field_value
Definition: checkbox.php:24
$field
Definition: gquiz_grade.php:11
custom_validation($validation_results)
Make validation work for Edit Entry.