Completed
Push — develop ( ea9883...4778e3 )
by Gennady
20:37 queued 40s
created

GravityView_Edit_Entry_Render   F

Complexity

Total Complexity 268

Size/Duplication

Total Lines 2099
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 11

Test Coverage

Coverage 68.3%

Importance

Changes 0
Metric Value
dl 0
loc 2099
ccs 461
cts 675
cp 0.683
rs 0.8
c 0
b 0
f 0
wmc 268
lcom 1
cbo 11

46 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 3 1
A load() 0 28 1
A prevent_render_form() 0 9 3
A is_edit_entry() 0 6 3
A is_edit_entry_submission() 0 3 1
A setup_vars() 0 18 1
A init() 0 30 5
A print_scripts() 0 12 1
A prevent_maybe_process_form() 0 11 3
B process_save() 0 81 6
B unset_hidden_field_values() 0 45 7
A process_save_process_files() 0 16 2
B save_field_value() 0 23 6
A modify_fileupload_settings() 0 9 2
B form_prepare_for_save() 0 29 6
B update_calculation_fields() 0 36 8
C update_post_image() 0 73 14
F maybe_update_post_fields() 0 117 24
A is_field_json_encoded() 0 17 4
A fill_post_template() 0 19 2
A after_update() 0 20 3
B edit_entry_form() 0 56 1
B maybe_print_message() 0 62 8
A render_edit_form() 0 42 1
A render_form_buttons() 0 3 1
A filter_modify_form_fields() 0 22 3
A verify_user_can_edit_post() 0 31 5
B modify_edit_field_input() 0 42 11
D get_field_value() 0 80 20
C gform_pre_validation() 0 87 14
A validate() 0 36 3
F custom_validation() 0 124 21
A get_entry() 0 9 2
A get_configured_edit_fields() 0 31 4
B filter_fields() 0 47 11
A merge_field_properties() 0 23 4
B filter_admin_only_fields() 0 28 6
A unselect_default_values() 0 17 5
B prefill_conditional_logic() 0 48 11
A filter_conditional_logic() 0 24 3
A manage_conditional_logic() 0 9 2
C user_can_edit_entry() 0 64 14
A user_can_edit_field() 0 22 4
A check_user_cap_edit_field() 0 15 4
A verify_nonce() 0 26 3
A fix_multiselect_value_serialization() 0 13 4

How to fix   Complexity   

Complex Class

Complex classes like GravityView_Edit_Entry_Render often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use GravityView_Edit_Entry_Render, and based on these observations, apply Extract Interface, too.

1
<?php
0 ignored issues
show
Coding Style Compatibility introduced by
For compatibility and reusability of your code, PSR1 recommends that a file should introduce either new symbols (like classes, functions, etc.) or have side-effects (like outputting something, or including other files), but not both at the same time. The first symbol is defined on line 16 and the first side effect is on line 13.

The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.

The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.

To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.

Loading history...
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
class GravityView_Edit_Entry_Render {
17
18
	/**
19
	 * @var GravityView_Edit_Entry
20
	 */
21
	protected $loader;
22
23
	/**
24
	 * @var string String used to generate unique nonce for the entry/form/view combination. Allows access to edit page.
25
	 */
26
	static $nonce_key;
0 ignored issues
show
Coding Style introduced by
The visibility should be declared for property $nonce_key.

The PSR-2 coding standard requires that all properties in a class have their visibility explicitly declared. If you declare a property using

class A {
    var $property;
}

the property is implicitly global.

To learn more about the PSR-2, please see the PHP-FIG site on the PSR-2.

Loading history...
27
28
	/**
29
	 * @since 1.9
30
	 * @var string String used for check valid edit entry form submission. Allows saving edit form values.
31
	 */
32
	private static $nonce_field = 'is_gv_edit_entry';
33
34
	/**
35
	 * @since 1.9
36
	 * @var bool Whether to allow save and continue functionality
37
	 */
38
	private static $supports_save_and_continue = false;
39
40
	/**
41
	 * Gravity Forms entry array
42
	 *
43
	 * @var array
44
	 */
45
	public $entry;
46
47
	/**
48
	 * Gravity Forms entry array (it won't get changed during this class lifecycle)
49
	 * @since 1.17.2
50
	 * @var array
51
	 */
52
	private static $original_entry = array();
53
54
	/**
55
	 * Gravity Forms form array (GravityView modifies the content through this class lifecycle)
56
	 *
57
	 * @var array
58
	 */
59
	public $form;
60
61
	/**
62
	 * Gravity Forms form array (it won't get changed during this class lifecycle)
63
	 * @since 1.16.2.1
64
	 * @var array
65
	 */
66
	private static $original_form;
67
68
	/**
69
	 * Gravity Forms form array after the form validation process
70
	 * @since 1.13
71
	 * @var array
72
	 */
73
	public $form_after_validation = null;
74
75
	/**
76
	 * Hold an array of GF field objects that have calculation rules
77
	 * @var array
78
	 */
79
	public $fields_with_calculation = array();
80
81
	/**
82
	 * Gravity Forms form id
83
	 *
84
	 * @var int
85
	 */
86
	public $form_id;
87
88
	/**
89
	 * ID of the current view
90
	 *
91
	 * @var int
92
	 */
93
	public $view_id;
94
95
	/**
96
	 * ID of the current post. May also be ID of the current View.
97
     *
98
     * @since 2.0.13
99
     * 
100
     * @var int
101
	 */
102
	public $post_id;
103
104
	/**
105
	 * Updated entry is valid (GF Validation object)
106
	 *
107
	 * @var array
108
	 */
109
	public $is_valid = NULL;
0 ignored issues
show
Coding Style introduced by
TRUE, FALSE and NULL must be lowercase; expected null, but found NULL.
Loading history...
110
111 11
	function __construct( GravityView_Edit_Entry $loader ) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
112 11
		$this->loader = $loader;
113 11
	}
114
115 11
	function load() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
116
117
		/** @define "GRAVITYVIEW_DIR" "../../../" */
118 11
		include_once( GRAVITYVIEW_DIR .'includes/class-admin-approve-entries.php' );
119
120
		// Don't display an embedded form when editing an entry
121 11
		add_action( 'wp_head', array( $this, 'prevent_render_form' ) );
122 11
		add_action( 'wp_footer', array( $this, 'prevent_render_form' ) );
123
124
		// Stop Gravity Forms processing what is ours!
125 11
		add_filter( 'wp', array( $this, 'prevent_maybe_process_form'), 8 );
0 ignored issues
show
introduced by
No space before closing parenthesis of array is bad style
Loading history...
126
127 11
		add_filter( 'gravityview_is_edit_entry', array( $this, 'is_edit_entry') );
0 ignored issues
show
introduced by
No space before closing parenthesis of array is bad style
Loading history...
128
129 11
		add_action( 'gravityview_edit_entry', array( $this, 'init' ) );
130
131
		// Disable conditional logic if needed (since 1.9)
132 11
		add_filter( 'gform_has_conditional_logic', array( $this, 'manage_conditional_logic' ), 10, 2 );
133
134
		// Make sure GF doesn't validate max files (since 1.9)
135 11
		add_filter( 'gform_plupload_settings', array( $this, 'modify_fileupload_settings' ), 10, 3 );
136
137
		// Add fields expected by GFFormDisplay::validate()
138 11
		add_filter( 'gform_pre_validation', array( $this, 'gform_pre_validation') );
0 ignored issues
show
introduced by
No space before closing parenthesis of array is bad style
Loading history...
139
140
		// Fix multiselect value for GF 2.2
141 11
		add_filter( 'gravityview/edit_entry/field_value_multiselect', array( $this, 'fix_multiselect_value_serialization' ), 10, 3 );
142 11
	}
143
144
	/**
145
	 * Don't show any forms embedded on a page when GravityView is in Edit Entry mode
146
	 *
147
	 * Adds a `__return_empty_string` filter on the Gravity Forms shortcode on the `wp_head` action
148
	 * And then removes it on the `wp_footer` action
149
	 *
150
	 * @since 1.16.1
151
	 *
152
	 * @return void
153
	 */
154 1
	public function prevent_render_form() {
155 1
		if( $this->is_edit_entry() ) {
156 1
			if( 'wp_head' === current_filter() ) {
157 1
				add_filter( 'gform_shortcode_form', '__return_empty_string' );
158
			} else {
159 1
				remove_filter( 'gform_shortcode_form', '__return_empty_string' );
160
			}
161
		}
162 1
	}
163
164
	/**
165
	 * Because we're mimicking being a front-end Gravity Forms form while using a Gravity Forms
166
	 * backend form, we need to prevent them from saving twice.
167
	 * @return void
168
	 */
169 1
	public function prevent_maybe_process_form() {
170
171 1
		if( ! empty( $_POST ) ) {
0 ignored issues
show
introduced by
Detected access of super global var $_POST, probably need manual inspection.
Loading history...
172
	        gravityview()->log->debug( 'GravityView_Edit_Entry[prevent_maybe_process_form] $_POSTed data (sanitized): ', array( 'data' => esc_html( print_r( $_POST, true ) ) ) );
0 ignored issues
show
introduced by
The use of function print_r() is discouraged
Loading history...
introduced by
Detected access of super global var $_POST, probably need manual inspection.
Loading history...
173
		}
174
175 1
		if( $this->is_edit_entry_submission() ) {
176
			remove_action( 'wp',  array( 'RGForms', 'maybe_process_form'), 9 );
0 ignored issues
show
introduced by
No space before closing parenthesis of array is bad style
Loading history...
177
	        remove_action( 'wp',  array( 'GFForms', 'maybe_process_form'), 9 );
0 ignored issues
show
introduced by
No space before closing parenthesis of array is bad style
Loading history...
178
		}
179 1
	}
180
181
	/**
182
	 * Is the current page an Edit Entry page?
183
	 * @return boolean
184
	 */
185 16
	public function is_edit_entry() {
186
187 16
		$is_edit_entry = GravityView_frontend::is_single_entry() && ! empty( $_GET['edit'] );
0 ignored issues
show
introduced by
Detected access of super global var $_GET, probably need manual inspection.
Loading history...
188
189 16
		return ( $is_edit_entry || $this->is_edit_entry_submission() );
190
	}
191
192
	/**
193
	 * Is the current page an Edit Entry page?
194
	 * @since 1.9
195
	 * @return boolean
196
	 */
197 16
	public function is_edit_entry_submission() {
198 16
		return !empty( $_POST[ self::$nonce_field ] );
0 ignored issues
show
introduced by
Expected 1 space after "!"; 0 found
Loading history...
introduced by
Detected access of super global var $_POST, probably need manual inspection.
Loading history...
199
	}
200
201
	/**
202
	 * When Edit entry view is requested setup the vars
203
	 */
204 11
	private function setup_vars() {
205 11
        global $post;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
206
207 11
		$gravityview_view = GravityView_View::getInstance();
208
0 ignored issues
show
Coding Style introduced by
Functions must not contain multiple empty lines in a row; found 2 empty lines
Loading history...
209
210 11
		$entries = $gravityview_view->getEntries();
211 11
	    self::$original_entry = $entries[0];
212 11
	    $this->entry = $entries[0];
213
214 11
		self::$original_form = $gravityview_view->getForm();
215 11
		$this->form = $gravityview_view->getForm();
216 11
		$this->form_id = $gravityview_view->getFormId();
217 11
		$this->view_id = $gravityview_view->getViewId();
218 11
		$this->post_id = \GV\Utils::get( $post, 'ID', null );
219
220 11
		self::$nonce_key = GravityView_Edit_Entry::get_nonce_key( $this->view_id, $this->form_id, $this->entry['id'] );
221 11
	}
222
223
224
	/**
225
	 * Load required files and trigger edit flow
226
	 *
227
	 * Run when the is_edit_entry returns true.
228
	 *
229
	 * @param \GravityView_View_Data $gv_data GravityView Data object
230
	 * @return void
231
	 */
232 12
	public function init( $gv_data = null ) {
233
234 12
		require_once( GFCommon::get_base_path() . '/form_display.php' );
235 12
		require_once( GFCommon::get_base_path() . '/entry_detail.php' );
236
237 12
		$this->setup_vars();
238
239 12
		if ( ! $gv_data ) {
240
			$gv_data = GravityView_View_Data::getInstance();
241
		}
242
243
		// Multiple Views embedded, don't proceed if nonce fails
244 12
		if ( $gv_data->has_multiple_views() && ! $this->verify_nonce() ) {
0 ignored issues
show
Deprecated Code introduced by
The method GravityView_View_Data::has_multiple_views() has been deprecated.

This method has been deprecated.

Loading history...
245
			gravityview()->log->error( 'Nonce validation failed for the Edit Entry request; returning' );
246
			return;
247
		}
248
249
		// Sorry, you're not allowed here.
250 12
		if ( false === $this->user_can_edit_entry( true ) ) {
251 1
			gravityview()->log->error( 'User is not allowed to edit this entry; returning', array( 'data' => $this->entry ) );
252 1
			return;
253
		}
254
255 12
		$this->print_scripts();
256
257 12
		$this->process_save( $gv_data );
258
259 12
		$this->edit_entry_form();
260
261 12
	}
262
263
264
	/**
265
	 * Force Gravity Forms to output scripts as if it were in the admin
266
	 * @return void
267
	 */
268 11
	private function print_scripts() {
269 11
		$gravityview_view = GravityView_View::getInstance();
270
271 11
		wp_register_script( 'gform_gravityforms', GFCommon::get_base_url().'/js/gravityforms.js', array( 'jquery', 'gform_json', 'gform_placeholder', 'sack', 'plupload-all', 'gravityview-fe-view' ) );
272
273 11
		GFFormDisplay::enqueue_form_scripts( $gravityview_view->getForm(), false);
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
274
275 11
		wp_localize_script( 'gravityview-fe-view', 'gvGlobals', array( 'cookiepath' => COOKIEPATH ) );
276
277
		// Sack is required for images
278 11
		wp_print_scripts( array( 'sack', 'gform_gravityforms', 'gravityview-fe-view' ) );
279 11
	}
280
281
282
	/**
283
	 * Process edit entry form save
284
	 *
285
	 * @param array $gv_data The View data.
286
	 */
287 12
	private function process_save( $gv_data ) {
288
289 12
		if ( empty( $_POST ) || ! isset( $_POST['lid'] ) ) {
0 ignored issues
show
introduced by
Detected access of super global var $_POST, probably need manual inspection.
Loading history...
290 5
			return;
291
		}
292
293
		// Make sure the entry, view, and form IDs are all correct
294 11
		$valid = $this->verify_nonce();
295
296 11
		if ( !$valid ) {
0 ignored issues
show
introduced by
Expected 1 space after "!"; 0 found
Loading history...
297
			gravityview()->log->error( 'Nonce validation failed.' );
298
			return;
299
		}
300
301 11
		if ( $this->entry['id'] !== $_POST['lid'] ) {
0 ignored issues
show
introduced by
Detected access of super global var $_POST, probably need manual inspection.
Loading history...
introduced by
Detected usage of a non-sanitized input variable: $_POST
Loading history...
302
			gravityview()->log->error( 'Entry ID did not match posted entry ID.' );
303
			return;
304
		}
305
306 11
		gravityview()->log->debug( '$_POSTed data (sanitized): ', array( 'data' => esc_html( print_r( $_POST, true ) ) ) );
0 ignored issues
show
introduced by
The use of function print_r() is discouraged
Loading history...
introduced by
Detected access of super global var $_POST, probably need manual inspection.
Loading history...
307
308 11
		$this->process_save_process_files( $this->form_id );
309
310 11
		$this->validate();
311
312 11
		if( $this->is_valid ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->is_valid of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
313
314 11
			gravityview()->log->debug( 'Submission is valid.' );
315
316
			/**
317
			 * @hack This step is needed to unset the adminOnly from form fields, to add the calculation fields
318
			 */
319 11
			$form = $this->form_prepare_for_save();
320
321
			/**
322
			 * @hack to avoid the capability validation of the method save_lead for GF 1.9+
323
			 */
324 11
			unset( $_GET['page'] );
0 ignored issues
show
introduced by
Detected access of super global var $_GET, probably need manual inspection.
Loading history...
325
326 11
			$date_created = $this->entry['date_created'];
327
328
			/**
329
			 * @hack to force Gravity Forms to use $read_value_from_post in GFFormsModel::save_lead()
330
			 * @since 1.17.2
331
			 */
332 11
			unset( $this->entry['date_created'] );
333
334 11
			GFFormsModel::save_lead( $form, $this->entry );
335
336
	        // Delete the values for hidden inputs
337 11
	        $this->unset_hidden_field_values();
338
			
339 11
			$this->entry['date_created'] = $date_created;
340
341
			// Process calculation fields
342 11
			$this->update_calculation_fields();
343
344
			// Perform actions normally performed after updating a lead
345 11
			$this->after_update();
346
347
	        /**
348
			 * Must be AFTER after_update()!
349
			 * @see https://github.com/gravityview/GravityView/issues/764
350
			 */
351 11
			$this->maybe_update_post_fields( $form );
352
353
			/**
354
			 * @action `gravityview/edit_entry/after_update` Perform an action after the entry has been updated using Edit Entry
355
             * @since 2.1 Added $gv_data parameter
356
			 * @param array $form Gravity Forms form array
357
			 * @param string $entry_id Numeric ID of the entry that was updated
358
			 * @param GravityView_Edit_Entry_Render $this This object
359
			 * @param GravityView_View_Data $gv_data The View data
360
			 */
361 11
			do_action( 'gravityview/edit_entry/after_update', $this->form, $this->entry['id'], $this, $gv_data );
362
363
		} else {
364
			gravityview()->log->error( 'Submission is NOT valid.', array( 'entry' => $this->entry ) );
365
		}
366
367 11
	} // process_save
368
369
	/**
370
	 * Delete the value of fields hidden by conditional logic when the entry is edited
371
	 *
372
	 * @uses GFFormsModel::update_lead_field_value()
373
	 *
374
	 * @since 1.17.4
375
	 *
376
	 * @return void
377
	 */
378 10
	private function unset_hidden_field_values() {
379 10
	    global $wpdb;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
380
381
		/**
382
		 * @filter `gravityview/edit_entry/unset_hidden_field_values` Whether to delete values of fields hidden by conditional logic
383
		 * @since 1.22.2
384
		 * @param bool $unset_hidden_field_values Default: true
385
		 * @param GravityView_Edit_Entry_Render $this This object
386
		 */
387 10
		$unset_hidden_field_values = apply_filters( 'gravityview/edit_entry/unset_hidden_field_values', true, $this );
388
389 10
		if( ! $unset_hidden_field_values ) {
390
			return;
391
		}
392
393 10
		if ( version_compare( GravityView_GFFormsModel::get_database_version(), '2.3-dev-1', '>=' ) && method_exists( 'GFFormsModel', 'get_entry_meta_table_name' ) ) {
394 10
			$entry_meta_table = GFFormsModel::get_entry_meta_table_name();
395 10
			$current_fields = $wpdb->get_results( $wpdb->prepare( "SELECT meta_key, meta_value FROM $entry_meta_table WHERE entry_id=%d", $this->entry['id'] ) );
0 ignored issues
show
introduced by
Usage of a direct database call is discouraged.
Loading history...
introduced by
Usage of a direct database call without caching is prohibited. Use wp_cache_get / wp_cache_set.
Loading history...
396
		} else {
397
			$lead_detail_table = GFFormsModel::get_lead_details_table_name();
398
			$current_fields = $wpdb->get_results( $wpdb->prepare( "SELECT id, field_number FROM $lead_detail_table WHERE lead_id=%d", $this->entry['id'] ) );
0 ignored issues
show
introduced by
Usage of a direct database call is discouraged.
Loading history...
introduced by
Usage of a direct database call without caching is prohibited. Use wp_cache_get / wp_cache_set.
Loading history...
399
		}
400
401 10
	    foreach ( $this->entry as $input_id => $field_value ) {
402
403 10
		    $field = RGFormsModel::get_field( $this->form, $input_id );
404
405
		    // Reset fields that are hidden
406
		    // Don't pass $entry as fourth parameter; force using $_POST values to calculate conditional logic
407 10
		    if ( GFFormsModel::is_field_hidden( $this->form, $field, array(), NULL ) ) {
0 ignored issues
show
Coding Style introduced by
TRUE, FALSE and NULL must be lowercase; expected null, but found NULL.
Loading history...
408
409
		        // List fields are stored as empty arrays when empty
410
			    $empty_value = $this->is_field_json_encoded( $field ) ? '[]' : '';
411
412
			    $lead_detail_id = GFFormsModel::get_lead_detail_id( $current_fields, $input_id );
413
414
			    GFFormsModel::update_lead_field_value( $this->form, $this->entry, $field, $lead_detail_id, $input_id, $empty_value );
415
416
			    // Prevent the $_POST values of hidden fields from being used as default values when rendering the form
417
				// after submission
418
			    $post_input_id = 'input_' . str_replace( '.', '_', $input_id );
419 10
			    $_POST[ $post_input_id ] = '';
420
		    }
421
	    }
422 10
	}
423
424
	/**
425
	 * Have GF handle file uploads
426
	 *
427
	 * Copy of code from GFFormDisplay::process_form()
428
	 *
429
	 * @param int $form_id
430
	 */
431 10
	private function process_save_process_files( $form_id ) {
432
433
		//Loading files that have been uploaded to temp folder
434 10
		$files = GFCommon::json_decode( stripslashes( RGForms::post( 'gform_uploaded_files' ) ) );
435 10
		if ( ! is_array( $files ) ) {
436 9
			$files = array();
437
		}
438
439
		/**
440
		 * Make sure the fileuploads are not overwritten if no such request was done.
441
		 * @since 1.20.1
442
		 */
443 10
		add_filter( "gform_save_field_value_$form_id", array( $this, 'save_field_value' ), 99, 5 );
444
445 10
		RGFormsModel::$uploaded_files[ $form_id ] = $files;
446 10
	}
447
448
	/**
449
	 * Make sure the fileuploads are not overwritten if no such request was done.
450
	 *
451
	 * TO ONLY BE USED INTERNALLY; DO NOT DEVELOP ON; MAY BE REMOVED AT ANY TIME.
452
	 *
453
	 * @since 1.20.1
454
	 *
455
	 * @param string $value Field value
456
	 * @param array $entry GF entry array
457
	 * @param GF_Field_FileUpload $field
458
	 * @param array $form GF form array
459
	 * @param string $input_id ID of the input being saved
460
	 *
461
	 * @return string
462
	 */
463 10
	public function save_field_value( $value = '', $entry = array(), $field = null, $form = array(), $input_id = '' ) {
464
465 10
		if ( ! $field || $field->type != 'fileupload' ) {
0 ignored issues
show
introduced by
Found "!= '". Use Yoda Condition checks, you must
Loading history...
466 10
			return $value;
467
		}
468
469 1
		$input_name = 'input_' . str_replace( '.', '_', $input_id );
470
471 1
		if ( $field->multipleFiles ) {
472
			if ( empty( $value ) ) {
473
				return json_decode( $entry[ $input_id ], true );
474
			}
475
			return $value;
476
		}
477
478
		/** No file is being uploaded. */
479 1
		if ( empty( $_FILES[ $input_name ]['name'] ) ) {
480
			/** So return the original upload */
481 1
			return $entry[ $input_id ];
482
		}
483
484 1
		return $value;
485
	}
486
487
	/**
488
	 * Remove max_files validation (done on gravityforms.js) to avoid conflicts with GravityView
489
	 * Late validation done on self::custom_validation
490
	 *
491
	 * @param $plupload_init array Plupload settings
492
	 * @param $form_id
493
	 * @param $instance
494
	 * @return mixed
495
	 */
496 2
	public function modify_fileupload_settings( $plupload_init, $form_id, $instance ) {
0 ignored issues
show
Unused Code introduced by
The parameter $form_id is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $instance is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
497 2
		if( ! $this->is_edit_entry() ) {
498
			return $plupload_init;
499
		}
500
501 2
		$plupload_init['gf_vars']['max_files'] = 0;
502
503 2
		return $plupload_init;
504
	}
505
506
507
	/**
508
	 * Set visibility to visible and convert field input key to string
509
	 * @return array $form
510
	 */
511 10
	private function form_prepare_for_save() {
512
513 10
		$form = $this->form;
514
515
	    /** @var GF_Field $field */
516 10
		foreach( $form['fields'] as $k => &$field ) {
517
518
			/**
519
			 * Remove the fields with calculation formulas before save to avoid conflicts with GF logic
520
			 * @since 1.16.3
521
			 * @var GF_Field $field
522
			 */
523 10
			if( $field->has_calculation() ) {
524 3
				unset( $form['fields'][ $k ] );
525
			}
526
527 10
			$field->adminOnly = false;
528
529 10
			if( isset( $field->inputs ) && is_array( $field->inputs ) ) {
530 2
				foreach( $field->inputs as $key => $input ) {
531 10
				    $field->inputs[ $key ][ 'id' ] = (string)$input['id'];
0 ignored issues
show
introduced by
Array keys should NOT be surrounded by spaces if they only contain a string or an integer.
Loading history...
introduced by
No space after closing casting parenthesis is prohibited
Loading history...
532
				}
533
			}
534
		}
535
536 10
		$form['fields'] = array_values( $form['fields'] );
537
538 10
		return $form;
539
	}
540
541 10
	private function update_calculation_fields() {
542 10
		global $wpdb;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
543
544 10
		$form = self::$original_form;
545 10
		$update = false;
546
547
		// get the most up to date entry values
548 10
		$entry = GFAPI::get_entry( $this->entry['id'] );
549
550 10
		if ( version_compare( GravityView_GFFormsModel::get_database_version(), '2.3-dev-1', '>=' ) && method_exists( 'GFFormsModel', 'get_entry_meta_table_name' ) ) {
551 10
			$entry_meta_table = GFFormsModel::get_entry_meta_table_name();
552 10
			$current_fields = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM $entry_meta_table WHERE entry_id=%d", $entry['id'] ) );
0 ignored issues
show
introduced by
Usage of a direct database call is discouraged.
Loading history...
introduced by
Usage of a direct database call without caching is prohibited. Use wp_cache_get / wp_cache_set.
Loading history...
553
		} else {
554
			$lead_detail_table = GFFormsModel::get_lead_details_table_name();
555
			$current_fields = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM $lead_detail_table WHERE lead_id=%d", $entry['id'] ) );
0 ignored issues
show
introduced by
Usage of a direct database call is discouraged.
Loading history...
introduced by
Usage of a direct database call without caching is prohibited. Use wp_cache_get / wp_cache_set.
Loading history...
556
		}
557
0 ignored issues
show
Coding Style introduced by
Functions must not contain multiple empty lines in a row; found 2 empty lines
Loading history...
558
559 10
		if ( ! empty( $this->fields_with_calculation ) ) {
560 3
			$update = true;
561 3
			foreach ( $this->fields_with_calculation as $field ) {
562 3
				$inputs = $field->get_entry_inputs();
563 3
				if ( is_array( $inputs ) ) {
564 2
				    foreach ( $inputs as $input ) {
565 2
						GFFormsModel::save_input( $form, $field, $entry, $current_fields, $input['id'] );
566
				    }
567
				} else {
568 3
					GFFormsModel::save_input( $form, $field, $entry, $current_fields, $field->id );
569
				}
570
			}
571
572 3
			if ( method_exists( 'GFFormsModel', 'commit_batch_field_operations' ) ) {
573 3
				GFFormsModel::commit_batch_field_operations();
574
			}
575
		}
576 10
	}
577
578
	/**
579
	 * Handle updating the Post Image field
580
	 *
581
	 * Sets a new Featured Image if configured in Gravity Forms; otherwise uploads/updates media
582
	 *
583
	 * @since 1.17
584
	 *
585
	 * @uses GFFormsModel::media_handle_upload
586
	 * @uses set_post_thumbnail
587
	 * 
588
	 * @param array $form GF Form array
589
	 * @param GF_Field $field GF Field
590
	 * @param string $field_id Numeric ID of the field
591
	 * @param string $value
592
	 * @param array $entry GF Entry currently being edited
593
	 * @param int $post_id ID of the Post being edited
594
	 *
595
	 * @return mixed|string
596
	 */
597 1
	private function update_post_image( $form, $field, $field_id, $value, $entry, $post_id ) {
598
599 1
		$input_name = 'input_' . $field_id;
600
601 1
		if ( !empty( $_FILES[ $input_name ]['name'] ) ) {
0 ignored issues
show
introduced by
Expected 1 space after "!"; 0 found
Loading history...
602
603
			// We have a new image
604
605
			$value = RGFormsModel::prepare_value( $form, $field, $value, $input_name, $entry['id'] );
606
607
			$ary = ! empty( $value ) ? explode( '|:|', $value ) : array();
608
	        $ary = stripslashes_deep( $ary );
609
			$img_url = \GV\Utils::get( $ary, 0 );
610
611
			$img_title       = count( $ary ) > 1 ? $ary[1] : '';
612
			$img_caption     = count( $ary ) > 2 ? $ary[2] : '';
613
			$img_description = count( $ary ) > 3 ? $ary[3] : '';
614
615
			$image_meta = array(
616
				'post_excerpt' => $img_caption,
617
				'post_content' => $img_description,
618
			);
619
620
			//adding title only if it is not empty. It will default to the file name if it is not in the array
621
			if ( ! empty( $img_title ) ) {
622
				$image_meta['post_title'] = $img_title;
623
			}
624
625
			/**
626
			 * 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.
627
			 * Note: the method became public in GF 1.9.17.7, but we don't require that version yet.
628
			 */
629
			require_once GRAVITYVIEW_DIR . 'includes/class-gravityview-gfformsmodel.php';
630
			$media_id = GravityView_GFFormsModel::media_handle_upload( $img_url, $post_id, $image_meta );
631
632
			// is this field set as featured image?
633
			if ( $media_id && $field->postFeaturedImage ) {
634
				set_post_thumbnail( $post_id, $media_id );
635
			}
636
637 1
		} elseif ( ! empty( $_POST[ $input_name ] ) && is_array( $value ) ) {
638
639 1
			$img_url         = stripslashes_deep( $_POST[ $input_name ] );
0 ignored issues
show
introduced by
Detected access of super global var $_POST, probably need manual inspection.
Loading history...
introduced by
Detected usage of a non-sanitized input variable: $_POST
Loading history...
640 1
			$img_title       = stripslashes_deep( \GV\Utils::_POST( $input_name . '_1' ) );
641 1
			$img_caption     = stripslashes_deep( \GV\Utils::_POST( $input_name . '_4' ) );
642 1
			$img_description = stripslashes_deep( \GV\Utils::_POST( $input_name . '_7' ) );
643
644 1
			$value = ! empty( $img_url ) ? $img_url . "|:|" . $img_title . "|:|" . $img_caption . "|:|" . $img_description : '';
0 ignored issues
show
Coding Style Comprehensibility introduced by
The string literal |:| does not require double quotes, as per coding-style, please use single quotes.

PHP provides two ways to mark string literals. Either with single quotes 'literal' or with double quotes "literal". The difference between these is that string literals in double quotes may contain variables with are evaluated at run-time as well as escape sequences.

String literals in single quotes on the other hand are evaluated very literally and the only two characters that needs escaping in the literal are the single quote itself (\') and the backslash (\\). Every other character is displayed as is.

Double quoted string literals may contain other variables or more complex escape sequences.

<?php

$singleQuoted = 'Value';
$doubleQuoted = "\tSingle is $singleQuoted";

print $doubleQuoted;

will print an indented: Single is Value

If your string literal does not contain variables or escape sequences, it should be defined using single quotes to make that fact clear.

For more information on PHP string literals and available escape sequences see the PHP core documentation.

Loading history...
645
646 1
			if ( $field->postFeaturedImage ) {
647
648
				$image_meta = array(
649 1
					'ID' => get_post_thumbnail_id( $post_id ),
650 1
					'post_title' => $img_title,
651 1
					'post_excerpt' => $img_caption,
652 1
					'post_content' => $img_description,
653
				);
654
655
				// update image title, caption or description
656 1
				wp_update_post( $image_meta );
657
			}
658
		} else {
659
660
			// if we get here, image was removed or not set.
661
			$value = '';
662
663
			if ( $field->postFeaturedImage ) {
664
				delete_post_thumbnail( $post_id );
665
			}
666
		}
667
668 1
		return $value;
669
	}
670
671
	/**
672
	 * Loop through the fields being edited and if they include Post fields, update the Entry's post object
673
	 *
674
	 * @param array $form Gravity Forms form
675
	 *
676
	 * @return void
677
	 */
678 10
	private function maybe_update_post_fields( $form ) {
679
680 10
		if( empty( $this->entry['post_id'] ) ) {
681 9
	        gravityview()->log->debug( 'This entry has no post fields. Continuing...' );
682 9
			return;
683
		}
684
685 1
		$post_id = $this->entry['post_id'];
686
687
		// Security check
688 1
		if( false === GVCommon::has_cap( 'edit_post', $post_id ) ) {
689
			gravityview()->log->error( 'The current user does not have the ability to edit Post #{post_id}', array( 'post_id' => $post_id ) );
690
			return;
691
		}
692
693 1
		$update_entry = false;
694
695 1
		$updated_post = $original_post = get_post( $post_id );
696
697 1
		foreach ( $this->entry as $field_id => $value ) {
698
699 1
			$field = RGFormsModel::get_field( $form, $field_id );
700
701 1
			if( ! $field ) {
702 1
				continue;
703
			}
704
705 1
			if( GFCommon::is_post_field( $field ) && 'post_category' !== $field->type ) {
706
707
				// Get the value of the field, including $_POSTed value
708 1
				$value = RGFormsModel::get_field_value( $field );
709
710
				// Use temporary entry variable, to make values available to fill_post_template() and update_post_image()
711 1
				$entry_tmp = $this->entry;
712 1
				$entry_tmp["{$field_id}"] = $value;
0 ignored issues
show
introduced by
Array keys should be surrounded by spaces unless they contain a string or an integer.
Loading history...
713
714 1
				switch( $field->type ) {
715
716 1
				    case 'post_title':
717
				        $post_title = $value;
718
				        if ( \GV\Utils::get( $form, 'postTitleTemplateEnabled' ) ) {
719
				            $post_title = $this->fill_post_template( $form['postTitleTemplate'], $form, $entry_tmp );
720
				        }
721
				        $updated_post->post_title = $post_title;
722
				        $updated_post->post_name  = $post_title;
723
				        unset( $post_title );
724
				        break;
725
726 1
				    case 'post_content':
727
				        $post_content = $value;
728
				        if ( \GV\Utils::get( $form, 'postContentTemplateEnabled' ) ) {
729
				            $post_content = $this->fill_post_template( $form['postContentTemplate'], $form, $entry_tmp, true );
730
				        }
731
				        $updated_post->post_content = $post_content;
732
				        unset( $post_content );
733
				        break;
734 1
				    case 'post_excerpt':
735
				        $updated_post->post_excerpt = $value;
736
				        break;
737 1
				    case 'post_tags':
738
				        wp_set_post_tags( $post_id, $value, false );
739
				        break;
740 1
				    case 'post_category':
741
				        break;
742 1
				    case 'post_custom_field':
743
						if ( is_array( $value ) && ( floatval( $field_id ) !== floatval( $field->id ) ) ) {
744
							$value = $value[ $field_id ];
745
						}
746
747
				        if( ! empty( $field->customFieldTemplateEnabled ) ) {
748
				            $value = $this->fill_post_template( $field->customFieldTemplate, $form, $entry_tmp, true );
749
				        }
750
751
	                    if ( $this->is_field_json_encoded( $field ) && ! is_string( $value ) ) {
752
		                    $value = wp_json_encode( $value );
753
	                    }
754
755
				        update_post_meta( $post_id, $field->postCustomFieldName, $value );
756
				        break;
757
758 1
				    case 'post_image':
759 1
				        $value = $this->update_post_image( $form, $field, $field_id, $value, $this->entry, $post_id );
760 1
				        break;
761
762
				}
763
764
				// update entry after
765 1
				$this->entry["{$field_id}"] = $value;
0 ignored issues
show
introduced by
Array keys should be surrounded by spaces unless they contain a string or an integer.
Loading history...
766
767 1
				$update_entry = true;
768
769 1
				unset( $entry_tmp );
770
			}
771
772
		}
773
774 1
		if( $update_entry ) {
775
776 1
			$return_entry = GFAPI::update_entry( $this->entry );
777
778 1
			if( is_wp_error( $return_entry ) ) {
779
				gravityview()->log->error( 'Updating the entry post fields failed', array( 'data' => array( '$this->entry' => $this->entry, '$return_entry' => $return_entry ) ) );
780
			} else {
781 1
				gravityview()->log->debug( 'Updating the entry post fields for post #{post_id} succeeded', array( 'post_id' => $post_id ) );
782
			}
783
784
		}
785
786 1
		$return_post = wp_update_post( $updated_post, true );
787
788 1
		if( is_wp_error( $return_post ) ) {
789
			$return_post->add_data( $updated_post, '$updated_post' );
790
			gravityview()->log->error( 'Updating the post content failed', array( 'data' => compact( 'updated_post', 'return_post' ) ) );
791
		} else {
792 1
			gravityview()->log->debug( 'Updating the post content for post #{post_id} succeeded', array( 'post_id' => $post_id, 'data' => $updated_post ) );
793
		}
794 1
	}
795
796
	/**
797
	 * Is the field stored in a JSON-encoded manner?
798
	 *
799
	 * @param GF_Field $field
800
	 *
801
	 * @return bool True: stored in DB json_encode()'d; False: not encoded
802
	 */
803
	private function is_field_json_encoded( $field ) {
804
805
	    $json_encoded = false;
806
807
		$input_type = RGFormsModel::get_input_type( $field );
808
809
	    // Only certain custom field types are supported
810
	    switch( $input_type ) {
811
		    case 'fileupload':
812
		    case 'list':
813
		    case 'multiselect':
814
			    $json_encoded = true;
815
			    break;
816
	    }
817
818
	    return $json_encoded;
819
	}
820
821
	/**
822
	 * Convert a field content template into prepared output
823
	 *
824
	 * @uses GravityView_GFFormsModel::get_post_field_images()
825
	 *
826
	 * @since 1.17
827
	 *
828
	 * @param string $template The content template for the field
829
	 * @param array $form Gravity Forms form
830
	 * @param bool $do_shortcode Whether to process shortcode inside content. In GF, only run on Custom Field and Post Content fields
831
	 *
832
	 * @return string
833
	 */
834
	private function fill_post_template( $template, $form, $entry, $do_shortcode = false ) {
835
836
		require_once GRAVITYVIEW_DIR . 'includes/class-gravityview-gfformsmodel.php';
837
838
		$post_images = GravityView_GFFormsModel::get_post_field_images( $form, $entry );
839
840
		//replacing post image variables
841
		$output = GFCommon::replace_variables_post_image( $template, $post_images, $entry );
842
843
		//replacing all other variables
844
		$output = GFCommon::replace_variables( $output, $form, $entry, false, false, false );
845
846
		// replace conditional shortcodes
847
		if( $do_shortcode ) {
848
			$output = do_shortcode( $output );
849
		}
850
851
		return $output;
852
	}
853
854
855
	/**
856
	 * Perform actions normally performed after updating a lead
857
	 *
858
	 * @since 1.8
859
	 *
860
	 * @see GFEntryDetail::lead_detail_page()
861
	 *
862
	 * @return void
863
	 */
864 10
	private function after_update() {
865
866 10
		do_action( 'gform_after_update_entry', $this->form, $this->entry['id'], self::$original_entry );
867 10
		do_action( "gform_after_update_entry_{$this->form['id']}", $this->form, $this->entry['id'], self::$original_entry );
868
869
		// Re-define the entry now that we've updated it.
870 10
		$entry = RGFormsModel::get_lead( $this->entry['id'] );
871
872 10
		$entry = GFFormsModel::set_entry_meta( $entry, self::$original_form );
873
874 10
		if ( version_compare( GFFormsModel::get_database_version(), '2.3-dev-1', '<' ) ) {
875
			// We need to clear the cache because Gravity Forms caches the field values, which
876
			// we have just updated.
877
			foreach ($this->form['fields'] as $key => $field) {
0 ignored issues
show
introduced by
No space after opening parenthesis is prohibited
Loading history...
introduced by
No space before closing parenthesis is prohibited
Loading history...
878
				GFFormsModel::refresh_lead_field_value( $entry['id'], $field->id );
879
			}
880
		}
881
882 10
		$this->entry = $entry;
883 10
	}
884
885
886
	/**
887
	 * Display the Edit Entry form
888
	 *
889
	 * @return void
890
	 */
891 11
	public function edit_entry_form() {
892
893
		?>
894
895
		<div class="gv-edit-entry-wrapper"><?php
896
897 11
			$javascript = gravityview_ob_include( GravityView_Edit_Entry::$file .'/partials/inline-javascript.php', $this );
0 ignored issues
show
Bug introduced by
The property file cannot be accessed from this context as it is declared private in class GravityView_Edit_Entry.

This check looks for access to properties that are not accessible from the current context.

If you need to make a property accessible to another context you can either raise its visibility level or provide an accessible getter in the defining class.

Loading history...
898
899
			/**
900
			 * Fixes weird wpautop() issue
901
			 * @see https://github.com/katzwebservices/GravityView/issues/451
902
			 */
903 11
			echo gravityview_strip_whitespace( $javascript );
0 ignored issues
show
introduced by
Expected a sanitizing function (see Codex for 'Data Validation'), but instead saw 'gravityview_strip_whitespace'
Loading history...
904
905
			?><h2 class="gv-edit-entry-title">
906
				<span><?php
907
908
				    /**
909
				     * @filter `gravityview_edit_entry_title` Modify the edit entry title
910
				     * @param string $edit_entry_title Modify the "Edit Entry" title
911
				     * @param GravityView_Edit_Entry_Render $this This object
912
				     */
913 11
				    $edit_entry_title = apply_filters('gravityview_edit_entry_title', __('Edit Entry', 'gravityview'), $this );
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
914
915 11
				    echo esc_attr( $edit_entry_title );
916
			?></span>
917
			</h2>
918
919
			<?php $this->maybe_print_message(); ?>
920
921
			<?php // The ID of the form needs to be `gform_{form_id}` for the pluploader ?>
922
923
			<form method="post" id="gform_<?php echo $this->form_id; ?>" enctype="multipart/form-data">
0 ignored issues
show
introduced by
Expected next thing to be a escaping function, not '$this'
Loading history...
924
925
				<?php
926
927 11
				wp_nonce_field( self::$nonce_key, self::$nonce_key );
928
929 11
				wp_nonce_field( self::$nonce_field, self::$nonce_field, false );
930
931
				// Print the actual form HTML
932 11
				$this->render_edit_form();
933
934
				?>
935 11
			</form>
936
937
			<script>
938
				gform.addFilter('gform_reset_pre_conditional_logic_field_action', function ( reset, formId, targetId, defaultValues, isInit ) {
939
				    return false;
940
				});
941
			</script>
942
943
		</div>
944
945
	<?php
946 11
	}
947
948
	/**
949
	 * Display success or error message if the form has been submitted
950
	 *
951
	 * @uses GVCommon::generate_notice
952
	 *
953
	 * @since 1.16.2.2
954
	 *
955
	 * @return void
956
	 */
957 11
	private function maybe_print_message() {
958
959 11
		if ( \GV\Utils::_POST( 'action' ) === 'update' ) {
0 ignored issues
show
introduced by
Found "=== '". Use Yoda Condition checks, you must
Loading history...
960
961 10
			$back_link = remove_query_arg( array( 'page', 'view', 'edit' ) );
962
963 10
			if( ! $this->is_valid ){
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->is_valid of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
964
965
				// Keeping this compatible with Gravity Forms.
966
				$validation_message = "<div class='validation_error'>" . __('There was a problem with your submission.', 'gravityview') . " " . __('Errors have been highlighted below.', 'gravityview') . "</div>";
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
Coding Style Comprehensibility introduced by
The string literal does not require double quotes, as per coding-style, please use single quotes.

PHP provides two ways to mark string literals. Either with single quotes 'literal' or with double quotes "literal". The difference between these is that string literals in double quotes may contain variables with are evaluated at run-time as well as escape sequences.

String literals in single quotes on the other hand are evaluated very literally and the only two characters that needs escaping in the literal are the single quote itself (\') and the backslash (\\). Every other character is displayed as is.

Double quoted string literals may contain other variables or more complex escape sequences.

<?php

$singleQuoted = 'Value';
$doubleQuoted = "\tSingle is $singleQuoted";

print $doubleQuoted;

will print an indented: Single is Value

If your string literal does not contain variables or escape sequences, it should be defined using single quotes to make that fact clear.

For more information on PHP string literals and available escape sequences see the PHP core documentation.

Loading history...
introduced by
Expected a sanitizing function (see Codex for 'Data Validation'), but instead saw '__'
Loading history...
Coding Style Comprehensibility introduced by
The string literal </div> does not require double quotes, as per coding-style, please use single quotes.

PHP provides two ways to mark string literals. Either with single quotes 'literal' or with double quotes "literal". The difference between these is that string literals in double quotes may contain variables with are evaluated at run-time as well as escape sequences.

String literals in single quotes on the other hand are evaluated very literally and the only two characters that needs escaping in the literal are the single quote itself (\') and the backslash (\\). Every other character is displayed as is.

Double quoted string literals may contain other variables or more complex escape sequences.

<?php

$singleQuoted = 'Value';
$doubleQuoted = "\tSingle is $singleQuoted";

print $doubleQuoted;

will print an indented: Single is Value

If your string literal does not contain variables or escape sequences, it should be defined using single quotes to make that fact clear.

For more information on PHP string literals and available escape sequences see the PHP core documentation.

Loading history...
967
				$message = apply_filters("gform_validation_message_{$this->form['id']}", apply_filters("gform_validation_message", $validation_message, $this->form), $this->form);
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
Coding Style Comprehensibility introduced by
The string literal gform_validation_message does not require double quotes, as per coding-style, please use single quotes.

PHP provides two ways to mark string literals. Either with single quotes 'literal' or with double quotes "literal". The difference between these is that string literals in double quotes may contain variables with are evaluated at run-time as well as escape sequences.

String literals in single quotes on the other hand are evaluated very literally and the only two characters that needs escaping in the literal are the single quote itself (\') and the backslash (\\). Every other character is displayed as is.

Double quoted string literals may contain other variables or more complex escape sequences.

<?php

$singleQuoted = 'Value';
$doubleQuoted = "\tSingle is $singleQuoted";

print $doubleQuoted;

will print an indented: Single is Value

If your string literal does not contain variables or escape sequences, it should be defined using single quotes to make that fact clear.

For more information on PHP string literals and available escape sequences see the PHP core documentation.

Loading history...
968
969
				echo GVCommon::generate_notice( $message , 'gv-error' );
0 ignored issues
show
introduced by
Expected a sanitizing function (see Codex for 'Data Validation'), but instead saw 'GVCommon'
Loading history...
970
971
			} else {
972 10
				$view = \GV\View::by_id( $this->view_id );
973 10
				$edit_redirect = $view->settings->get( 'edit_redirect' );
974 10
				$edit_redirect_url = $view->settings->get( 'edit_redirect_url' );
975
976
				switch ( $edit_redirect ) {
977
978 10
                    case '0':
979 1
	                    $redirect_url = $back_link;
980 1
	                    $entry_updated_message = sprintf( esc_attr__('Entry Updated. %sReturning to Entry%s', 'gravityview'), '<a href="'. esc_url( $redirect_url ) .'">', '</a>' );
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
981 1
                        break;
982
983 9
                    case '1':
984 1
	                    $redirect_url = $directory_link = GravityView_API::directory_link();
985 1
	                    $entry_updated_message = sprintf( esc_attr__('Entry Updated. %sReturning to %s%s', 'gravityview'), '<a href="'. esc_url( $redirect_url ) . '">', esc_html( $view->post_title ), '</a>' );
0 ignored issues
show
Documentation introduced by
The property post_title does not exist on object<GV\View>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
986 1
	                    break;
987
988 8
                    case '2':
989 1
	                    $redirect_url = $edit_redirect_url;
990 1
	                    $redirect_url = GFCommon::replace_variables( $redirect_url, $this->form, $this->entry, false, false, false, 'text' );
991 1
	                    $entry_updated_message = sprintf( esc_attr__('Entry Updated. %sRedirecting to %s%s', 'gravityview'), '<a href="'. esc_url( $redirect_url ) . '">', esc_html( $edit_redirect_url ), '</a>' );
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
992 1
                        break;
993
994 7
                    case '':
995
                    default:
996 7
					    $entry_updated_message = sprintf( esc_attr__('Entry Updated. %sReturn to Entry%s', 'gravityview'), '<a href="'. esc_url( $back_link ) .'">', '</a>' );
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
997 7
                        break;
998
				}
999
1000 10
				if ( isset( $redirect_url ) ) {
1001 3
					$entry_updated_message .= sprintf( '<script>window.location.href = %s;</script>', json_encode( $redirect_url ) );
1002
				}
1003
1004
				/**
1005
				 * @filter `gravityview/edit_entry/success` Modify the edit entry success message (including the anchor link)
1006
				 * @since 1.5.4
1007
				 * @param string $entry_updated_message Existing message
1008
				 * @param int $view_id View ID
1009
				 * @param array $entry Gravity Forms entry array
1010
				 * @param string $back_link URL to return to the original entry. @since 1.6
1011
				 */
1012 10
				$message = apply_filters( 'gravityview/edit_entry/success', $entry_updated_message , $this->view_id, $this->entry, $back_link );
1013
1014 10
				echo GVCommon::generate_notice( $message );
0 ignored issues
show
introduced by
Expected a sanitizing function (see Codex for 'Data Validation'), but instead saw 'GVCommon'
Loading history...
1015
			}
1016
1017
		}
1018 11
	}
1019
1020
	/**
1021
	 * Display the Edit Entry form in the original Gravity Forms format
1022
	 *
1023
	 * @since 1.9
1024
	 *
1025
	 * @return void
1026
	 */
1027 11
	private function render_edit_form() {
1028
1029
		/**
1030
		 * @action `gravityview/edit-entry/render/before` Before rendering the Edit Entry form
1031
		 * @since 1.17
1032
		 * @param GravityView_Edit_Entry_Render $this
1033
		 */
1034 11
		do_action( 'gravityview/edit-entry/render/before', $this );
1035
1036 11
		add_filter( 'gform_pre_render', array( $this, 'filter_modify_form_fields'), 5000, 3 );
0 ignored issues
show
introduced by
No space before closing parenthesis of array is bad style
Loading history...
1037 11
		add_filter( 'gform_submit_button', array( $this, 'render_form_buttons') );
0 ignored issues
show
introduced by
No space before closing parenthesis of array is bad style
Loading history...
1038 11
		add_filter( 'gform_disable_view_counter', '__return_true' );
1039
1040 11
		add_filter( 'gform_field_input', array( $this, 'verify_user_can_edit_post' ), 5, 5 );
1041 11
		add_filter( 'gform_field_input', array( $this, 'modify_edit_field_input' ), 10, 5 );
1042
1043
		// We need to remove the fake $_GET['page'] arg to avoid rendering form as if in admin.
1044 11
		unset( $_GET['page'] );
0 ignored issues
show
introduced by
Detected access of super global var $_GET, probably need manual inspection.
Loading history...
1045
1046
		// TODO: Verify multiple-page forms
1047
1048 11
		ob_start(); // Prevent PHP warnings possibly caused by prefilling list fields for conditional logic
1049
1050 11
		$html = GFFormDisplay::get_form( $this->form['id'], false, false, true, $this->entry );
1051
1052 11
		ob_get_clean();
1053
1054 11
	    remove_filter( 'gform_pre_render', array( $this, 'filter_modify_form_fields' ), 5000 );
1055 11
		remove_filter( 'gform_submit_button', array( $this, 'render_form_buttons' ) );
1056 11
		remove_filter( 'gform_disable_view_counter', '__return_true' );
1057 11
		remove_filter( 'gform_field_input', array( $this, 'verify_user_can_edit_post' ), 5 );
1058 11
		remove_filter( 'gform_field_input', array( $this, 'modify_edit_field_input' ), 10 );
1059
1060 11
		echo $html;
0 ignored issues
show
introduced by
Expected next thing to be a escaping function, not '$html'
Loading history...
1061
1062
		/**
1063
		 * @action `gravityview/edit-entry/render/after` After rendering the Edit Entry form
1064
		 * @since 1.17
1065
		 * @param GravityView_Edit_Entry_Render $this
1066
		 */
1067 11
		do_action( 'gravityview/edit-entry/render/after', $this );
1068 11
	}
1069
1070
	/**
1071
	 * Display the Update/Cancel/Delete buttons for the Edit Entry form
1072
	 * @since 1.8
1073
	 * @return string
1074
	 */
1075 11
	public function render_form_buttons() {
1076 11
		return gravityview_ob_include( GravityView_Edit_Entry::$file .'/partials/form-buttons.php', $this );
0 ignored issues
show
Bug introduced by
The property file cannot be accessed from this context as it is declared private in class GravityView_Edit_Entry.

This check looks for access to properties that are not accessible from the current context.

If you need to make a property accessible to another context you can either raise its visibility level or provide an accessible getter in the defining class.

Loading history...
1077
	}
1078
1079
1080
	/**
1081
	 * Modify the form fields that are shown when using GFFormDisplay::get_form()
1082
	 *
1083
	 * By default, all fields will be shown. We only want the Edit Tab configured fields to be shown.
1084
	 *
1085
	 * @param array $form
1086
	 * @param boolean $ajax Whether in AJAX mode
1087
	 * @param array|string $field_values Passed parameters to the form
1088
	 *
1089
	 * @since 1.9
1090
	 *
1091
	 * @return array Modified form array
1092
	 */
1093 11
	public function filter_modify_form_fields( $form, $ajax = false, $field_values = '' ) {
0 ignored issues
show
Unused Code introduced by
The parameter $ajax is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $field_values is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
1094
1095
		// In case we have validated the form, use it to inject the validation results into the form render
1096 11
		if( isset( $this->form_after_validation ) ) {
1097 10
			$form = $this->form_after_validation;
1098
		} else {
1099 4
			$form['fields'] = $this->get_configured_edit_fields( $form, $this->view_id );
1100
		}
1101
1102 11
		$form = $this->filter_conditional_logic( $form );
1103
1104 11
		$form = $this->prefill_conditional_logic( $form );
1105
1106
		// for now we don't support Save and Continue feature.
1107 11
		if( ! self::$supports_save_and_continue ) {
1108 11
	        unset( $form['save'] );
1109
		}
1110
1111 11
		$form = $this->unselect_default_values( $form );
1112
1113 11
		return $form;
1114
	}
1115
1116
	/**
1117
	 * 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.
1118
	 *
1119
	 * @since 1.16.2.2
1120
	 *
1121
	 * @param string $field_content Always empty. Returning not-empty overrides the input.
1122
	 * @param GF_Field $field
1123
	 * @param string|array $value If array, it's a field with multiple inputs. If string, single input.
1124
	 * @param int $lead_id Lead ID. Always 0 for the `gform_field_input` filter.
1125
	 * @param int $form_id Form ID
1126
	 *
1127
	 * @return string If error, the error message. If no error, blank string (modify_edit_field_input() runs next)
1128
	 */
1129 11
	public function verify_user_can_edit_post( $field_content = '', $field, $value, $lead_id = 0, $form_id ) {
0 ignored issues
show
Unused Code introduced by
The parameter $value is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $lead_id is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $form_id is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
1130
1131 11
		if( ! GFCommon::is_post_field( $field ) ) {
1132 11
			return $field_content;
1133
		}
1134
1135 2
        $message = null;
1136
1137
        // First, make sure they have the capability to edit the post.
1138 2
        if( false === current_user_can( 'edit_post', $this->entry['post_id'] ) ) {
1139
1140
            /**
1141
             * @filter `gravityview/edit_entry/unsupported_post_field_text` Modify the message when someone isn't able to edit a post
1142
             * @param string $message The existing "You don't have permission..." text
1143
             */
1144 1
            $message = apply_filters('gravityview/edit_entry/unsupported_post_field_text', __('You don&rsquo;t have permission to edit this post.', 'gravityview') );
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
1145
1146 1
        } elseif( null === get_post( $this->entry['post_id'] ) ) {
1147
            /**
1148
             * @filter `gravityview/edit_entry/no_post_text` Modify the message when someone is editing an entry attached to a post that no longer exists
1149
             * @param string $message The existing "This field is not editable; the post no longer exists." text
1150
             */
1151
            $message = apply_filters('gravityview/edit_entry/no_post_text', __('This field is not editable; the post no longer exists.', 'gravityview' ) );
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
1152
        }
1153
1154 2
        if( $message ) {
1155 1
            $field_content = sprintf('<div class="ginput_container ginput_container_' . $field->type . '">%s</div>', wpautop( $message ) );
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
1156
        }
1157
1158 2
        return $field_content;
1159
	}
1160
1161
	/**
1162
	 *
1163
	 * Fill-in the saved values into the form inputs
1164
	 *
1165
	 * @param string $field_content Always empty. Returning not-empty overrides the input.
1166
	 * @param GF_Field $field
1167
	 * @param string|array $value If array, it's a field with multiple inputs. If string, single input.
1168
	 * @param int $lead_id Lead ID. Always 0 for the `gform_field_input` filter.
1169
	 * @param int $form_id Form ID
1170
	 *
1171
	 * @return mixed
1172
	 */
1173 11
	public function modify_edit_field_input( $field_content = '', $field, $value, $lead_id = 0, $form_id ) {
0 ignored issues
show
Unused Code introduced by
The parameter $value is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $lead_id is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $form_id is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
1174
1175 11
		$gv_field = GravityView_Fields::get_associated_field( $field );
1176
1177
		// If the form has been submitted, then we don't need to pre-fill the values,
1178
		// Except for fileupload type and when a field input is overridden- run always!!
1179
		if(
1180 11
			( $this->is_edit_entry_submission() && !in_array( $field->type, array( 'fileupload', 'post_image' ) ) )
0 ignored issues
show
introduced by
Expected 1 space after "!"; 0 found
Loading history...
1181 11
			&& false === ( $gv_field && is_callable( array( $gv_field, 'get_field_input' ) ) )
1182
			&& ! GFCommon::is_product_field( $field->type )
1183 11
			|| ! empty( $field_content )
1184 11
			|| in_array( $field->type, array( 'honeypot' ) )
1185
		) {
1186 1
	        return $field_content;
1187
		}
1188
1189
		// SET SOME FIELD DEFAULTS TO PREVENT ISSUES
1190 11
		$field->adminOnly = false; /** @see GFFormDisplay::get_counter_init_script() need to prevent adminOnly */
1191
1192 11
		$field_value = $this->get_field_value( $field );
1193
1194
	    // Prevent any PHP warnings, like undefined index
1195 11
	    ob_start();
1196
1197 11
	    $return = null;
1198
1199
		/** @var GravityView_Field $gv_field */
1200 11
		if( $gv_field && is_callable( array( $gv_field, 'get_field_input' ) ) ) {
1201 3
			$return = $gv_field->get_field_input( $this->form, $field_value, $this->entry, $field );
1202
		} else {
1203 11
	        $return = $field->get_field_input( $this->form, $field_value, $this->entry );
1204
	    }
1205
1206
	    // If there was output, it's an error
1207 11
	    $warnings = ob_get_clean();
1208
1209 11
	    if( !empty( $warnings ) ) {
0 ignored issues
show
introduced by
Expected 1 space after "!"; 0 found
Loading history...
1210
		    gravityview()->log->error( '{warning}', array( 'warning' => $warnings, 'data' => $field_value ) );
1211
	    }
1212
1213 11
		return $return;
1214
	}
1215
1216
	/**
1217
	 * Modify the value for the current field input
1218
	 *
1219
	 * @param GF_Field $field
1220
	 *
1221
	 * @return array|mixed|string
1222
	 */
1223 11
	private function get_field_value( $field ) {
1224
1225
		/**
1226
		 * @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.
1227
		 * @param boolean True: override saved values; False: don't override (default)
1228
		 * @param $field GF_Field object Gravity Forms field object
1229
		 * @since 1.13
1230
		 */
1231 11
		$override_saved_value = apply_filters( 'gravityview/edit_entry/pre_populate/override', false, $field );
1232
1233
		// We're dealing with multiple inputs (e.g. checkbox) but not time or date (as it doesn't store data in input IDs)
1234 11
		if( isset( $field->inputs ) && is_array( $field->inputs ) && !in_array( $field->type, array( 'time', 'date' ) ) ) {
0 ignored issues
show
introduced by
Expected 1 space after "!"; 0 found
Loading history...
1235
1236 3
			$field_value = array();
1237
1238
			// only accept pre-populated values if the field doesn't have any choice selected.
1239 3
			$allow_pre_populated = $field->allowsPrepopulate;
1240
1241 3
			foreach ( (array)$field->inputs as $input ) {
0 ignored issues
show
introduced by
No space after closing casting parenthesis is prohibited
Loading history...
1242
1243 3
				$input_id = strval( $input['id'] );
1244
				
1245 3
				if ( isset( $this->entry[ $input_id ] ) && ! gv_empty( $this->entry[ $input_id ], false, false ) ) {
1246 3
				    $field_value[ $input_id ] =  'post_category' === $field->type ? GFCommon::format_post_category( $this->entry[ $input_id ], true ) : $this->entry[ $input_id ];
0 ignored issues
show
introduced by
Expected 1 space after "="; 2 found
Loading history...
1247 3
				    $allow_pre_populated = false;
1248
				}
1249
1250
			}
1251
1252 3
			$pre_value = $field->get_value_submission( array(), false );
1253
1254 3
			$field_value = ! $allow_pre_populated && ! ( $override_saved_value && !gv_empty( $pre_value, false, false ) ) ? $field_value : $pre_value;
0 ignored issues
show
introduced by
Expected 1 space after "!"; 0 found
Loading history...
1255
1256
		} else {
1257
1258 11
			$id = intval( $field->id );
1259
1260
			// get pre-populated value if exists
1261 11
			$pre_value = $field->allowsPrepopulate ? GFFormsModel::get_parameter_value( $field->inputName, array(), $field ) : '';
1262
1263
			// saved field entry value (if empty, fallback to the pre-populated value, if exists)
1264
			// or pre-populated value if not empty and set to override saved value
1265 11
			$field_value = isset( $this->entry[ $id ] ) && ! gv_empty( $this->entry[ $id ], false, false ) && ! ( $override_saved_value && !gv_empty( $pre_value, false, false ) ) ? $this->entry[ $id ] : $pre_value;
0 ignored issues
show
introduced by
Expected 1 space after "!"; 0 found
Loading history...
1266
1267
			// in case field is post_category but inputType is select, multi-select or radio, convert value into array of category IDs.
1268 11
			if ( 'post_category' === $field->type && !gv_empty( $field_value, false, false ) ) {
0 ignored issues
show
introduced by
Expected 1 space after "!"; 0 found
Loading history...
1269
				$categories = array();
1270
				foreach ( explode( ',', $field_value ) as $cat_string ) {
1271
				    $categories[] = GFCommon::format_post_category( $cat_string, true );
1272
				}
1273
				$field_value = 'multiselect' === $field->get_input_type() ? $categories : implode( '', $categories );
1274
			}
1275
1276
		}
1277
1278
		// if value is empty get the default value if defined
1279 11
		$field_value = $field->get_value_default_if_empty( $field_value );
1280
1281
	    /**
1282
	     * @filter `gravityview/edit_entry/field_value` Change the value of an Edit Entry field, if needed
1283
	     * @since 1.11
1284
	     * @since 1.20 Added third param
1285
	     * @param mixed $field_value field value used to populate the input
1286
	     * @param object $field Gravity Forms field object ( Class GF_Field )
1287
	     * @param GravityView_Edit_Entry_Render $this Current object
1288
	     */
1289 11
	    $field_value = apply_filters( 'gravityview/edit_entry/field_value', $field_value, $field, $this );
1290
1291
	    /**
1292
	     * @filter `gravityview/edit_entry/field_value_{field_type}` Change the value of an Edit Entry field for a specific field type
1293
	     * @since 1.17
1294
	     * @since 1.20 Added third param
1295
	     * @param mixed $field_value field value used to populate the input
1296
	     * @param GF_Field $field Gravity Forms field object
1297
	     * @param GravityView_Edit_Entry_Render $this Current object
1298
	     */
1299 11
	    $field_value = apply_filters( 'gravityview/edit_entry/field_value_' . $field->type , $field_value, $field, $this );
1300
1301 11
		return $field_value;
1302
	}
1303
1304
1305
	// ---- Entry validation
1306
1307
	/**
1308
	 * Add field keys that Gravity Forms expects.
1309
	 *
1310
	 * @see GFFormDisplay::validate()
1311
	 * @param  array $form GF Form
1312
	 * @return array       Modified GF Form
1313
	 */
1314 10
	public function gform_pre_validation( $form ) {
1315
1316 10
		if( ! $this->verify_nonce() ) {
1317
			return $form;
1318
		}
1319
1320
		// Fix PHP warning regarding undefined index.
1321 10
		foreach ( $form['fields'] as &$field) {
0 ignored issues
show
introduced by
No space before closing parenthesis is prohibited
Loading history...
1322
1323
			// This is because we're doing admin form pretending to be front-end, so Gravity Forms
1324
			// expects certain field array items to be set.
1325 10
			foreach ( array( 'noDuplicates', 'adminOnly', 'inputType', 'isRequired', 'enablePrice', 'inputs', 'allowedExtensions' ) as $key ) {
1326 10
	            $field->{$key} = isset( $field->{$key} ) ? $field->{$key} : NULL;
0 ignored issues
show
Coding Style introduced by
TRUE, FALSE and NULL must be lowercase; expected null, but found NULL.
Loading history...
1327
			}
1328
1329 10
			switch( RGFormsModel::get_input_type( $field ) ) {
1330
1331
				/**
1332
				 * 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.
1333
				 *
1334
				 * 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.
1335
				 *
1336
				 * @hack
1337
				 */
1338 10
				case 'fileupload':
1339
1340
				    // Set the previous value
1341 1
				    $entry = $this->get_entry();
1342
1343 1
				    $input_name = 'input_'.$field->id;
1344 1
				    $form_id = $form['id'];
1345
1346 1
				    $value = NULL;
0 ignored issues
show
Coding Style introduced by
TRUE, FALSE and NULL must be lowercase; expected null, but found NULL.
Loading history...
1347
1348
				    // Use the previous entry value as the default.
1349 1
				    if( isset( $entry[ $field->id ] ) ) {
1350 1
				        $value = $entry[ $field->id ];
1351
				    }
1352
1353
				    // If this is a single upload file
1354 1
				    if( !empty( $_FILES[ $input_name ] ) && !empty( $_FILES[ $input_name ]['name'] ) ) {
0 ignored issues
show
introduced by
Expected 1 space after "!"; 0 found
Loading history...
1355 1
				        $file_path = GFFormsModel::get_file_upload_path( $form['id'], $_FILES[ $input_name ]['name'] );
1356 1
				        $value = $file_path['url'];
1357
1358
				    } else {
1359
1360
				        // Fix PHP warning on line 1498 of form_display.php for post_image fields
1361
				        // Fix PHP Notice:  Undefined index:  size in form_display.php on line 1511
1362 1
				        $_FILES[ $input_name ] = array('name' => '', 'size' => '' );
0 ignored issues
show
introduced by
No space after opening parenthesis of array is bad style
Loading history...
1363
1364
				    }
1365
1366 1
				    if ( \GV\Utils::get( $field, "multipleFiles" ) ) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
The string literal multipleFiles does not require double quotes, as per coding-style, please use single quotes.

PHP provides two ways to mark string literals. Either with single quotes 'literal' or with double quotes "literal". The difference between these is that string literals in double quotes may contain variables with are evaluated at run-time as well as escape sequences.

String literals in single quotes on the other hand are evaluated very literally and the only two characters that needs escaping in the literal are the single quote itself (\') and the backslash (\\). Every other character is displayed as is.

Double quoted string literals may contain other variables or more complex escape sequences.

<?php

$singleQuoted = 'Value';
$doubleQuoted = "\tSingle is $singleQuoted";

print $doubleQuoted;

will print an indented: Single is Value

If your string literal does not contain variables or escape sequences, it should be defined using single quotes to make that fact clear.

For more information on PHP string literals and available escape sequences see the PHP core documentation.

Loading history...
1367
1368
				        // If there are fresh uploads, process and merge them.
1369
				        // Otherwise, use the passed values, which should be json-encoded array of URLs
1370 1
				        if( isset( GFFormsModel::$uploaded_files[$form_id][$input_name] ) ) {
0 ignored issues
show
introduced by
Array keys should be surrounded by spaces unless they contain a string or an integer.
Loading history...
1371
				            $value = empty( $value ) ? '[]' : $value;
1372
				            $value = stripslashes_deep( $value );
1373 1
				            $value = GFFormsModel::prepare_value( $form, $field, $value, $input_name, $entry['id'], array());
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
1374
				        }
1375
1376
				    } else {
1377
1378
				        // A file already exists when editing an entry
1379
				        // We set this to solve issue when file upload fields are required.
1380 1
				        GFFormsModel::$uploaded_files[ $form_id ][ $input_name ] = $value;
1381
1382
				    }
1383
1384 1
				    $this->entry[ $input_name ] = $value;
1385 1
				    $_POST[ $input_name ] = $value;
1386
1387 1
				    break;
1388
1389 10
				case 'number':
1390
				    // Fix "undefined index" issue at line 1286 in form_display.php
1391 8
				    if( !isset( $_POST['input_'.$field->id ] ) ) {
0 ignored issues
show
introduced by
Expected 1 space after "!"; 0 found
Loading history...
introduced by
Array keys should be surrounded by spaces unless they contain a string or an integer.
Loading history...
1392 5
				        $_POST['input_'.$field->id ] = NULL;
0 ignored issues
show
introduced by
Array keys should be surrounded by spaces unless they contain a string or an integer.
Loading history...
Coding Style introduced by
TRUE, FALSE and NULL must be lowercase; expected null, but found NULL.
Loading history...
1393
				    }
1394 10
				    break;
1395
			}
1396
1397
		}
1398
1399 10
		return $form;
1400
	}
1401
1402
1403
	/**
1404
	 * Process validation for a edit entry submission
1405
	 *
1406
	 * Sets the `is_valid` object var
1407
	 *
1408
	 * @return void
1409
	 */
1410 11
	private function validate() {
1411
1412
		/**
1413
		 * If using GF User Registration Add-on, remove the validation step, otherwise generates error when updating the entry
1414
		 * GF User Registration Add-on version > 3.x has a different class name
1415
		 * @since 1.16.2
1416
		 */
1417 11
		if ( class_exists( 'GF_User_Registration' ) ) {
1418 11
			remove_filter( 'gform_validation', array( GF_User_Registration::get_instance(), 'validate' ) );
1419
		} else  if ( class_exists( 'GFUser' ) ) {
1420
			remove_filter( 'gform_validation', array( 'GFUser', 'user_registration_validation' ) );
1421
		}
1422
0 ignored issues
show
Coding Style introduced by
Functions must not contain multiple empty lines in a row; found 2 empty lines
Loading history...
1423
1424
		/**
1425
		 * For some crazy reason, Gravity Forms doesn't validate Edit Entry form submissions.
1426
		 * You can enter whatever you want!
1427
		 * We try validating, and customize the results using `self::custom_validation()`
1428
		 */
1429 11
		add_filter( 'gform_validation_'. $this->form_id, array( $this, 'custom_validation' ), 10, 4);
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
1430
1431
		// Needed by the validate funtion
1432 11
		$failed_validation_page = NULL;
0 ignored issues
show
Coding Style introduced by
TRUE, FALSE and NULL must be lowercase; expected null, but found NULL.
Loading history...
1433 11
		$field_values = RGForms::post( 'gform_field_values' );
1434
1435
		// Prevent entry limit from running when editing an entry, also
1436
		// prevent form scheduling from preventing editing
1437 11
		unset( $this->form['limitEntries'], $this->form['scheduleForm'] );
1438
1439
		// Hide fields depending on Edit Entry settings
1440 11
		$this->form['fields'] = $this->get_configured_edit_fields( $this->form, $this->view_id );
1441
1442 11
		$this->is_valid = GFFormDisplay::validate( $this->form, $field_values, 1, $failed_validation_page );
1443
1444 11
		remove_filter( 'gform_validation_'. $this->form_id, array( $this, 'custom_validation' ), 10 );
1445 11
	}
1446
1447
1448
	/**
1449
	 * Make validation work for Edit Entry
1450
	 *
1451
	 * Because we're calling the GFFormDisplay::validate() in an unusual way (as a front-end
1452
	 * form pretending to be a back-end form), validate() doesn't know we _can't_ edit post
1453
	 * fields. This goes through all the fields and if they're an invalid post field, we
1454
	 * set them as valid. If there are still issues, we'll return false.
1455
	 *
1456
	 * @param  [type] $validation_results [description]
0 ignored issues
show
Documentation introduced by
The doc-type [type] could not be parsed: Unknown type name "" at position 0. [(view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
1457
	 * @return [type]                     [description]
0 ignored issues
show
Documentation introduced by
The doc-type [type] could not be parsed: Unknown type name "" at position 0. [(view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
1458
	 */
1459 11
	public function custom_validation( $validation_results ) {
1460
1461 11
		gravityview()->log->debug( 'GravityView_Edit_Entry[custom_validation] Validation results: ', array( 'data' => $validation_results ) );
1462
1463 11
		gravityview()->log->debug( 'GravityView_Edit_Entry[custom_validation] $_POSTed data (sanitized): ', array( 'data' => esc_html( print_r( $_POST, true ) ) ) );
0 ignored issues
show
introduced by
The use of function print_r() is discouraged
Loading history...
introduced by
Detected access of super global var $_POST, probably need manual inspection.
Loading history...
1464
1465 11
		$gv_valid = true;
1466
1467 11
		foreach ( $validation_results['form']['fields'] as $key => &$field ) {
1468
1469 11
			$value = RGFormsModel::get_field_value( $field );
1470 11
			$field_type = RGFormsModel::get_input_type( $field );
1471
1472
			// Validate always
1473 11
			switch ( $field_type ) {
1474
0 ignored issues
show
Coding Style introduced by
Functions must not contain multiple empty lines in a row; found 2 empty lines
Loading history...
1475
1476 11
				case 'fileupload' :
1477 11
				case 'post_image':
1478
1479
				    // in case nothing is uploaded but there are already files saved
1480 2
				    if( !empty( $field->failed_validation ) && !empty( $field->isRequired ) && !empty( $value ) ) {
0 ignored issues
show
introduced by
Expected 1 space after "!"; 0 found
Loading history...
1481
				        $field->failed_validation = false;
1482
				        unset( $field->validation_message );
1483
				    }
1484
1485
				    // validate if multi file upload reached max number of files [maxFiles] => 2
1486 2
				    if( \GV\Utils::get( $field, 'maxFiles') && \GV\Utils::get( $field, 'multipleFiles') ) {
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
1487
1488
				        $input_name = 'input_' . $field->id;
1489
				        //uploaded
1490
				        $file_names = isset( GFFormsModel::$uploaded_files[ $validation_results['form']['id'] ][ $input_name ] ) ? GFFormsModel::$uploaded_files[ $validation_results['form']['id'] ][ $input_name ] : array();
1491
1492
				        //existent
1493
				        $entry = $this->get_entry();
1494
				        $value = NULL;
0 ignored issues
show
Coding Style introduced by
TRUE, FALSE and NULL must be lowercase; expected null, but found NULL.
Loading history...
1495
				        if( isset( $entry[ $field->id ] ) ) {
1496
				            $value = json_decode( $entry[ $field->id ], true );
1497
				        }
1498
1499
				        // count uploaded files and existent entry files
1500
				        $count_files = count( $file_names ) + count( $value );
1501
1502
				        if( $count_files > $field->maxFiles ) {
1503
				            $field->validation_message = __( 'Maximum number of files reached', 'gravityview' );
1504
				            $field->failed_validation = 1;
1505
				            $gv_valid = false;
1506
1507
				            // in case of error make sure the newest upload files are removed from the upload input
1508
				            GFFormsModel::$uploaded_files[ $validation_results['form']['id'] ] = null;
1509
				        }
1510
1511
				    }
1512
0 ignored issues
show
Coding Style introduced by
Functions must not contain multiple empty lines in a row; found 2 empty lines
Loading history...
1513
1514 2
				    break;
1515
1516
			}
1517
1518
			// This field has failed validation.
1519 11
			if( !empty( $field->failed_validation ) ) {
0 ignored issues
show
introduced by
Expected 1 space after "!"; 0 found
Loading history...
1520
1521 1
				gravityview()->log->debug( 'GravityView_Edit_Entry[custom_validation] Field is invalid.', array( 'data' => array( 'field' => $field, 'value' => $value ) ) );
1522
1523 1
				switch ( $field_type ) {
1524
1525
				    // Captchas don't need to be re-entered.
1526 1
				    case 'captcha':
1527
1528
				        // Post Image fields aren't editable, so we un-fail them.
1529 1
				    case 'post_image':
1530
				        $field->failed_validation = false;
1531
				        unset( $field->validation_message );
1532
				        break;
1533
1534
				}
1535
1536
				// You can't continue inside a switch, so we do it after.
1537 1
				if( empty( $field->failed_validation ) ) {
1538
				    continue;
1539
				}
1540
1541
				// checks if the No Duplicates option is not validating entry against itself, since
1542
				// we're editing a stored entry, it would also assume it's a duplicate.
1543 1
				if( !empty( $field->noDuplicates ) ) {
0 ignored issues
show
introduced by
Expected 1 space after "!"; 0 found
Loading history...
1544
1545
				    $entry = $this->get_entry();
1546
1547
				    // If the value of the entry is the same as the stored value
1548
				    // Then we can assume it's not a duplicate, it's the same.
1549
				    if( !empty( $entry ) && $value == $entry[ $field->id ] ) {
0 ignored issues
show
introduced by
Expected 1 space after "!"; 0 found
Loading history...
1550
				        //if value submitted was not changed, then don't validate
1551
				        $field->failed_validation = false;
1552
1553
				        unset( $field->validation_message );
1554
1555
				        gravityview()->log->debug( 'GravityView_Edit_Entry[custom_validation] Field not a duplicate; it is the same entry.', array( 'data' => $entry ) );
1556
1557
				        continue;
1558
				    }
1559
				}
1560
1561
				// if here then probably we are facing the validation 'At least one field must be filled out'
1562 1
				if( GFFormDisplay::is_empty( $field, $this->form_id  ) && empty( $field->isRequired ) ) {
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces before closing bracket; 2 found
Loading history...
1563
				    unset( $field->validation_message );
1564
	                $field->validation_message = false;
1565
				    continue;
1566
				}
1567
1568 11
				$gv_valid = false;
1569
1570
			}
1571
1572
		}
1573
1574 11
		$validation_results['is_valid'] = $gv_valid;
1575
1576 11
		gravityview()->log->debug( 'GravityView_Edit_Entry[custom_validation] Validation results.', array( 'data' => $validation_results ) );
1577
1578
		// We'll need this result when rendering the form ( on GFFormDisplay::get_form )
1579 11
		$this->form_after_validation = $validation_results['form'];
1580
1581 11
		return $validation_results;
1582
	}
1583
1584
1585
	/**
1586
	 * TODO: This seems to be hacky... we should remove it. Entry is set when updating the form using setup_vars()!
1587
	 * Get the current entry and set it if it's not yet set.
1588
	 * @return array Gravity Forms entry array
1589
	 */
1590 2
	public function get_entry() {
1591
1592 2
		if( empty( $this->entry ) ) {
1593
			// Get the database value of the entry that's being edited
1594 1
			$this->entry = gravityview_get_entry( GravityView_frontend::is_single_entry() );
1595
		}
1596
1597 2
		return $this->entry;
1598
	}
1599
1600
1601
1602
	// --- Filters
1603
1604
	/**
1605
	 * Get the Edit Entry fields as configured in the View
1606
	 *
1607
	 * @since 1.8
1608
	 *
1609
	 * @param int $view_id
1610
	 *
1611
	 * @return array Array of fields that are configured in the Edit tab in the Admin
1612
	 */
1613 12
	private function get_configured_edit_fields( $form, $view_id ) {
1614
1615
		// Get all fields for form
1616 12
		if ( \GV\View::exists( $view_id ) ) {
1617 12
			$view = \GV\View::by_id( $view_id );
1618 12
			$properties = $view->fields ? $view->fields->as_configuration() : array();
1619
		} else {
1620
			$properties = null;
1621
		}
1622
1623
		// If edit tab not yet configured, show all fields
1624 12
		$edit_fields = !empty( $properties['edit_edit-fields'] ) ? $properties['edit_edit-fields'] : NULL;
0 ignored issues
show
introduced by
Expected 1 space after "!"; 0 found
Loading history...
Coding Style introduced by
TRUE, FALSE and NULL must be lowercase; expected null, but found NULL.
Loading history...
1625
1626
		// Hide fields depending on admin settings
1627 12
		$fields = $this->filter_fields( $form['fields'], $edit_fields );
1628
1629
	    // If Edit Entry fields are configured, remove adminOnly field settings. Otherwise, don't.
1630 12
	    $fields = $this->filter_admin_only_fields( $fields, $edit_fields, $form, $view_id );
1631
1632
		/**
1633
		 * @filter `gravityview/edit_entry/form_fields` Modify the fields displayed in Edit Entry form
1634
		 * @since 1.17
1635
		 * @param GF_Field[] $fields Gravity Forms form fields
1636
		 * @param array|null $edit_fields Fields for the Edit Entry tab configured in the View Configuration
1637
		 * @param array $form GF Form array (`fields` key modified to have only fields configured to show in Edit Entry)
1638
		 * @param int $view_id View ID
1639
		 */
1640 12
		$fields = apply_filters( 'gravityview/edit_entry/form_fields', $fields, $edit_fields, $form, $view_id );
1641
1642 12
		return $fields;
1643
	}
1644
1645
1646
	/**
1647
	 * Filter area fields based on specified conditions
1648
	 *  - This filter removes the fields that have calculation configured
1649
	 *
1650
	 * @uses GravityView_Edit_Entry::user_can_edit_field() Check caps
1651
	 * @access private
1652
	 * @param GF_Field[] $fields
1653
	 * @param array $configured_fields
1654
	 * @since  1.5
1655
	 * @return array $fields
1656
	 */
1657 11
	private function filter_fields( $fields, $configured_fields ) {
1658
1659 11
		if( empty( $fields ) || !is_array( $fields ) ) {
0 ignored issues
show
introduced by
Expected 1 space after "!"; 0 found
Loading history...
1660
			return $fields;
1661
		}
1662
1663 11
		$edit_fields = array();
1664
1665 11
		$field_type_blacklist = $this->loader->get_field_blacklist( $this->entry );
1666
1667
		// First, remove blacklist or calculation fields
1668 11
		foreach ( $fields as $key => $field ) {
1669
1670
			// Remove the fields that have calculation properties and keep them to be used later
1671
			// @since 1.16.2
1672 11
			if( $field->has_calculation() ) {
1673 3
				$this->fields_with_calculation[] = $field;
1674
				// don't remove the calculation fields on form render.
1675
			}
1676
1677 11
			if( in_array( $field->type, $field_type_blacklist ) ) {
1678 11
				unset( $fields[ $key ] );
1679
			}
1680
		}
1681
1682
		// The Edit tab has not been configured, so we return all fields by default.
1683 11
		if( empty( $configured_fields ) ) {
1684 11
			return array_values( $fields );
1685
		}
1686
1687
		// The edit tab has been configured, so we loop through to configured settings
1688
		foreach ( $configured_fields as $configured_field ) {
1689
1690
	        /** @var GF_Field $field */
1691
	        foreach ( $fields as $field ) {
1692
				if( intval( $configured_field['id'] ) === intval( $field->id ) && $this->user_can_edit_field( $configured_field, false ) ) {
1693
				    $edit_fields[] = $this->merge_field_properties( $field, $configured_field );
1694
				    break;
1695
				}
1696
1697
			}
1698
1699
		}
1700
1701
		return $edit_fields;
1702
1703
	}
1704
1705
	/**
1706
	 * Override GF Form field properties with the ones defined on the View
1707
	 * @param  GF_Field $field GF Form field object
1708
	 * @param  array $field_setting  GV field options
1709
	 * @since  1.5
1710
	 * @return array|GF_Field
1711
	 */
1712
	private function merge_field_properties( $field, $field_setting ) {
1713
1714
		$return_field = $field;
1715
1716
		if( empty( $field_setting['show_label'] ) ) {
1717
			$return_field->label = '';
1718
		} elseif ( !empty( $field_setting['custom_label'] ) ) {
0 ignored issues
show
introduced by
Expected 1 space after "!"; 0 found
Loading history...
1719
			$return_field->label = $field_setting['custom_label'];
1720
		}
1721
1722
		if( !empty( $field_setting['custom_class'] ) ) {
0 ignored issues
show
introduced by
Expected 1 space after "!"; 0 found
Loading history...
1723
			$return_field->cssClass .= ' '. gravityview_sanitize_html_class( $field_setting['custom_class'] );
1724
		}
1725
1726
		/**
1727
		 * Normalize page numbers - avoid conflicts with page validation
1728
		 * @since 1.6
1729
		 */
1730
		$return_field->pageNumber = 1;
1731
1732
		return $return_field;
1733
1734
	}
1735
1736
	/**
1737
	 * Remove fields that shouldn't be visible based on the Gravity Forms adminOnly field property
1738
	 *
1739
	 * @since 1.9.1
1740
	 *
1741
	 * @param array|GF_Field[] $fields Gravity Forms form fields
1742
	 * @param array|null $edit_fields Fields for the Edit Entry tab configured in the View Configuration
1743
	 * @param array $form GF Form array
1744
	 * @param int $view_id View ID
1745
	 *
1746
	 * @return array Possibly modified form array
1747
	 */
1748 11
	private function filter_admin_only_fields( $fields = array(), $edit_fields = null, $form = array(), $view_id = 0 ) {
1749
1750
	    /**
1751
		 * @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
1752
	     * If the Edit Entry tab is not configured, adminOnly fields will not be shown to non-administrators.
1753
	     * If the Edit Entry tab *is* configured, adminOnly fields will be shown to non-administrators, using the configured GV permissions
1754
	     * @since 1.9.1
1755
	     * @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.
1756
	     * @param array $form GF Form array
1757
	     * @param int $view_id View ID
1758
	     */
1759 11
	    $use_gf_adminonly_setting = apply_filters( 'gravityview/edit_entry/use_gf_admin_only_setting', empty( $edit_fields ), $form, $view_id );
1760
1761 11
	    if( $use_gf_adminonly_setting && false === GVCommon::has_cap( 'gravityforms_edit_entries', $this->entry['id'] ) ) {
1762
			foreach( $fields as $k => $field ) {
1763
				if( $field->adminOnly ) {
1764
				    unset( $fields[ $k ] );
1765
				}
1766
			}
1767
			return array_values( $fields );
1768
		}
1769
1770 11
	    foreach( $fields as &$field ) {
1771 11
		    $field->adminOnly = false;
1772
		}
1773
1774 11
		return $fields;
1775
	}
1776
1777
	/**
1778
	 * Checkboxes and other checkbox-based controls should not
1779
	 * display default checks in edit mode.
1780
	 *
1781
	 * https://github.com/gravityview/GravityView/1149
1782
	 *
1783
	 * @since 2.1
1784
	 *
1785
	 * @param array $form Gravity Forms array object
1786
	 *
1787
	 * @return array $form, modified to default checkboxes, radios from showing up.
1788
	 */
1789 11
	private function unselect_default_values( $form ) {
1790
1791 11
	    foreach ( $form['fields'] as &$field ) {
1792
1793 11
			if ( empty( $field->choices ) ) {
1794 11
                continue;
1795
			}
1796
1797 2
            foreach ( $field->choices as &$choice ) {
1798 2
				if ( \GV\Utils::get( $choice, 'isSelected' ) ) {
1799 2
					$choice['isSelected'] = false;
1800
				}
1801
			}
1802
		}
1803
1804 11
		return $form;
1805
	}
1806
1807
	// --- Conditional Logic
1808
1809
	/**
1810
	 * Conditional logic isn't designed to work with forms that already have content. When switching input values,
1811
	 * the dependent fields will be blank.
1812
	 *
1813
	 * Note: This is because GF populates a JavaScript variable with the input values. This is tough to filter at the input level;
1814
	 * via the `gform_field_value` filter; it requires lots of legwork. Doing it at the form level is easier.
1815
	 *
1816
	 * @since 1.17.4
1817
	 *
1818
	 * @param array $form Gravity Forms array object
1819
	 *
1820
	 * @return array $form, modified to fix conditional
1821
	 */
1822 11
	function prefill_conditional_logic( $form ) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
1823
1824 11
		if( ! GFFormDisplay::has_conditional_logic( $form ) ) {
1825 11
			return $form;
1826
		}
1827
1828
		// Have Conditional Logic pre-fill fields as if the data were default values
1829
		/** @var GF_Field $field */
1830
		foreach ( $form['fields'] as &$field ) {
1831
1832
			if( 'checkbox' === $field->type ) {
1833
				foreach ( $field->get_entry_inputs() as $key => $input ) {
1834
				    $input_id = $input['id'];
1835
				    $choice = $field->choices[ $key ];
1836
				    $value = \GV\Utils::get( $this->entry, $input_id );
1837
				    $match = RGFormsModel::choice_value_match( $field, $choice, $value );
1838
				    if( $match ) {
1839
				        $field->choices[ $key ]['isSelected'] = true;
1840
				    }
1841
				}
1842
			} else {
1843
1844
				// We need to run through each field to set the default values
1845
				foreach ( $this->entry as $field_id => $field_value ) {
1846
1847
				    if( floatval( $field_id ) === floatval( $field->id ) ) {
1848
1849
				        if( 'list' === $field->type ) {
1850
				            $list_rows = maybe_unserialize( $field_value );
1851
1852
				            $list_field_value = array();
1853
				            foreach ( (array) $list_rows as $row ) {
1854
				                foreach ( (array) $row as $column ) {
1855
				                    $list_field_value[] = $column;
1856
				                }
1857
				            }
1858
1859
				            $field->defaultValue = serialize( $list_field_value );
1860
				        } else {
1861
				            $field->defaultValue = $field_value;
1862
				        }
1863
				    }
1864
				}
1865
			}
1866
		}
1867
1868
		return $form;
1869
	}
1870
1871
	/**
1872
	 * Remove the conditional logic rules from the form button and the form fields, if needed.
1873
	 *
1874
	 * @todo Merge with caller method
1875
	 * @since 1.9
1876
	 *
1877
	 * @param array $form Gravity Forms form
1878
	 * @return array Modified form, if not using Conditional Logic
1879
	 */
1880 11
	private function filter_conditional_logic( $form ) {
1881
1882
		/**
1883
		 * @filter `gravityview/edit_entry/conditional_logic` Should the Edit Entry form use Gravity Forms conditional logic showing/hiding of fields?
1884
		 * @since 1.9
1885
		 * @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
1886
		 * @param array $form Gravity Forms form
1887
		 */
1888 11
		$use_conditional_logic = apply_filters( 'gravityview/edit_entry/conditional_logic', true, $form );
1889
1890 11
		if( $use_conditional_logic ) {
1891 11
			return $form;
1892
		}
1893
1894
		foreach( $form['fields'] as &$field ) {
1895
			/* @var GF_Field $field */
1896
			$field->conditionalLogic = null;
1897
		}
1898
1899
		unset( $form['button']['conditionalLogic'] );
1900
1901
		return $form;
1902
1903
	}
1904
1905
	/**
1906
	 * Disable the Gravity Forms conditional logic script and features on the Edit Entry screen
1907
	 *
1908
	 * @since 1.9
1909
	 *
1910
	 * @param $has_conditional_logic
1911
	 * @param $form
1912
	 * @return mixed
1913
	 */
1914 11
	public function manage_conditional_logic( $has_conditional_logic, $form ) {
1915
1916 11
		if( ! $this->is_edit_entry() ) {
1917
			return $has_conditional_logic;
1918
		}
1919
1920
	    /** @see GravityView_Edit_Entry_Render::filter_conditional_logic for filter documentation */
1921 11
		return apply_filters( 'gravityview/edit_entry/conditional_logic', $has_conditional_logic, $form );
1922
	}
1923
1924
1925
	// --- User checks and nonces
1926
1927
	/**
1928
	 * Check if the user can edit the entry
1929
	 *
1930
	 * - Is the nonce valid?
1931
	 * - Does the user have the right caps for the entry
1932
	 * - Is the entry in the trash?
1933
	 *
1934
	 * @todo Move to GVCommon
1935
	 *
1936
	 * @param  boolean $echo Show error messages in the form?
1937
	 * @return boolean        True: can edit form. False: nope.
1938
	 */
1939 12
	private function user_can_edit_entry( $echo = false ) {
1940
1941 12
		$error = NULL;
0 ignored issues
show
Coding Style introduced by
TRUE, FALSE and NULL must be lowercase; expected null, but found NULL.
Loading history...
1942
1943
		/**
1944
		 *  1. Permalinks are turned off
1945
		 *  2. There are two entries embedded using oEmbed
1946
		 *  3. One of the entries has just been saved
1947
		 */
1948 12
		if( !empty( $_POST['lid'] ) && !empty( $_GET['entry'] ) && ( $_POST['lid'] !== $_GET['entry'] ) ) {
0 ignored issues
show
introduced by
Expected 1 space after "!"; 0 found
Loading history...
1949
1950
			$error = true;
1951
1952
		}
1953
1954 12
		if( !empty( $_GET['entry'] ) && (string)$this->entry['id'] !== $_GET['entry'] ) {
0 ignored issues
show
introduced by
Expected 1 space after "!"; 0 found
Loading history...
introduced by
No space after closing casting parenthesis is prohibited
Loading history...
1955
1956
			$error = true;
1957
1958 12
		} elseif( ! $this->verify_nonce() ) {
1959
1960
			/**
1961
			 * If the Entry is embedded, there may be two entries on the same page.
1962
			 * If that's the case, and one is being edited, the other should fail gracefully and not display an error.
1963
			 */
1964
			if( GravityView_oEmbed::getInstance()->get_entry_id() ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression \GravityView_oEmbed::get...tance()->get_entry_id() of type integer|null is loosely compared to true; this is ambiguous if the integer can be zero. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
Deprecated Code introduced by
The method GravityView_oEmbed::getInstance() has been deprecated with message: Use \GV\oEmbed instead.

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
Deprecated Code introduced by
The method GravityView_oEmbed::get_entry_id() has been deprecated with message: Use \GV\oEmbed instead.

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
1965
				$error = true;
1966
			} else {
1967
				$error = __( 'The link to edit this entry is not valid; it may have expired.', 'gravityview');
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
1968
			}
1969
1970
		}
1971
1972 12
		if( ! GravityView_Edit_Entry::check_user_cap_edit_entry( $this->entry ) ) {
1973 1
			$error = __( 'You do not have permission to edit this entry.', 'gravityview');
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
1974
		}
1975
1976 12
		if( $this->entry['status'] === 'trash' ) {
0 ignored issues
show
introduced by
Found "=== '". Use Yoda Condition checks, you must
Loading history...
1977
			$error = __('You cannot edit the entry; it is in the trash.', 'gravityview' );
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
1978
		}
1979
1980
		// No errors; everything's fine here!
1981 12
		if( empty( $error ) ) {
1982 12
			return true;
1983
		}
1984
1985 1
		if( $echo && $error !== true ) {
0 ignored issues
show
introduced by
Found "!== true". Use Yoda Condition checks, you must
Loading history...
1986
1987 1
	        $error = esc_html( $error );
1988
1989
	        /**
1990
	         * @since 1.9
1991
	         */
1992 1
	        if ( ! empty( $this->entry ) ) {
1993 1
		        $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;" ) );
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
Coding Style Comprehensibility introduced by
The string literal window.history.go(-1); return false; does not require double quotes, as per coding-style, please use single quotes.

PHP provides two ways to mark string literals. Either with single quotes 'literal' or with double quotes "literal". The difference between these is that string literals in double quotes may contain variables with are evaluated at run-time as well as escape sequences.

String literals in single quotes on the other hand are evaluated very literally and the only two characters that needs escaping in the literal are the single quote itself (\') and the backslash (\\). Every other character is displayed as is.

Double quoted string literals may contain other variables or more complex escape sequences.

<?php

$singleQuoted = 'Value';
$doubleQuoted = "\tSingle is $singleQuoted";

print $doubleQuoted;

will print an indented: Single is Value

If your string literal does not contain variables or escape sequences, it should be defined using single quotes to make that fact clear.

For more information on PHP string literals and available escape sequences see the PHP core documentation.

Loading history...
1994
	        }
1995
1996 1
			echo GVCommon::generate_notice( wpautop( $error ), 'gv-error error');
0 ignored issues
show
introduced by
Expected a sanitizing function (see Codex for 'Data Validation'), but instead saw 'GVCommon'
Loading history...
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
1997
		}
1998
1999 1
		gravityview()->log->error( '{error}', array( 'error' => $error ) );
2000
2001 1
		return false;
2002
	}
2003
2004
2005
	/**
2006
	 * Check whether a field is editable by the current user, and optionally display an error message
2007
	 * @uses  GravityView_Edit_Entry->check_user_cap_edit_field() Check user capabilities
2008
	 * @param  array  $field Field or field settings array
2009
	 * @param  boolean $echo  Whether to show error message telling user they aren't allowed
2010
	 * @return boolean         True: user can edit the current field; False: nope, they can't.
2011
	 */
2012
	private function user_can_edit_field( $field, $echo = false ) {
2013
2014
		$error = NULL;
0 ignored issues
show
Coding Style introduced by
TRUE, FALSE and NULL must be lowercase; expected null, but found NULL.
Loading history...
2015
2016
		if( ! $this->check_user_cap_edit_field( $field ) ) {
2017
			$error = __( 'You do not have permission to edit this field.', 'gravityview');
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
2018
		}
2019
2020
		// No errors; everything's fine here!
2021
		if( empty( $error ) ) {
2022
			return true;
2023
		}
2024
2025
		if( $echo ) {
2026
			echo GVCommon::generate_notice( wpautop( esc_html( $error ) ), 'gv-error error');
0 ignored issues
show
introduced by
Expected a sanitizing function (see Codex for 'Data Validation'), but instead saw 'GVCommon'
Loading history...
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
2027
		}
2028
2029
		gravityview()->log->error( '{error}', array( 'error' => $error ) );
2030
2031
		return false;
2032
2033
	}
2034
2035
2036
	/**
2037
	 * checks if user has permissions to edit a specific field
2038
	 *
2039
	 * Needs to be used combined with GravityView_Edit_Entry::user_can_edit_field for maximum security!!
2040
	 *
2041
	 * @param  [type] $field [description]
0 ignored issues
show
Documentation introduced by
The doc-type [type] could not be parsed: Unknown type name "" at position 0. [(view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
2042
	 * @return bool
2043
	 */
2044
	private function check_user_cap_edit_field( $field ) {
2045
2046
		// If they can edit any entries (as defined in Gravity Forms), we're good.
2047
		if( GVCommon::has_cap( array( 'gravityforms_edit_entries', 'gravityview_edit_others_entries' ) ) ) {
2048
			return true;
2049
		}
2050
2051
		$field_cap = isset( $field['allow_edit_cap'] ) ? $field['allow_edit_cap'] : false;
2052
2053
		if( $field_cap ) {
2054
			return GVCommon::has_cap( $field['allow_edit_cap'] );
2055
		}
2056
2057
		return false;
2058
	}
2059
2060
2061
	/**
2062
	 * Is the current nonce valid for editing the entry?
2063
	 * @return boolean
2064
	 */
2065 11
	public function verify_nonce() {
2066
2067
		// Verify form submitted for editing single
2068 11
		if( $this->is_edit_entry_submission() ) {
2069
			$valid = wp_verify_nonce( $_POST[ self::$nonce_field ], self::$nonce_field );
0 ignored issues
show
introduced by
Detected access of super global var $_POST, probably need manual inspection.
Loading history...
introduced by
Detected usage of a non-validated input variable: $_POST
Loading history...
introduced by
Detected usage of a non-sanitized input variable: $_POST
Loading history...
2070
		}
2071
2072
		// Verify
2073 11
		else if( ! $this->is_edit_entry() ) {
2074
			$valid = false;
2075
		}
2076
2077
		else {
2078 11
			$valid = wp_verify_nonce( $_GET['edit'], self::$nonce_key );
0 ignored issues
show
introduced by
Detected access of super global var $_GET, probably need manual inspection.
Loading history...
introduced by
Detected usage of a non-validated input variable: $_GET
Loading history...
introduced by
Detected usage of a non-sanitized input variable: $_GET
Loading history...
2079
		}
2080
2081
		/**
2082
		 * @filter `gravityview/edit_entry/verify_nonce` Override Edit Entry nonce validation. Return true to declare nonce valid.
2083
		 * @since 1.13
2084
		 * @param int|boolean $valid False if invalid; 1 or 2 when nonce was generated
2085
		 * @param string $nonce_field Key used when validating submissions. Default: is_gv_edit_entry
2086
		 */
2087 11
		$valid = apply_filters( 'gravityview/edit_entry/verify_nonce', $valid, self::$nonce_field );
2088
2089 11
		return $valid;
2090
	}
2091
2092
2093
	/**
2094
	 * Multiselect in GF 2.2 became a json_encoded value. Fix it.
2095
	 *
2096
	 * As a hack for now we'll implode it back.
2097
	 */
2098
	public function fix_multiselect_value_serialization( $field_value, $field, $_this ) {
0 ignored issues
show
Unused Code introduced by
The parameter $_this is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
2099
		if ( empty ( $field->storageType ) || $field->storageType != 'json' ) {
0 ignored issues
show
introduced by
Found "!= '". Use Yoda Condition checks, you must
Loading history...
Coding Style introduced by
Space before opening parenthesis of function call prohibited
Loading history...
2100
			return $field_value;
2101
		}
2102
2103
		$maybe_json = @json_decode( $field_value, true );
0 ignored issues
show
Coding Style introduced by
Silencing errors is discouraged
Loading history...
2104
2105
		if ( $maybe_json ) {
2106
			return implode( ',', $maybe_json );
2107
		}
2108
2109
		return $field_value;
2110
	}
2111
2112
2113
2114
} //end class
2115