Completed
Push — develop ( c38b5d...31c9ca )
by Zack
18:12
created

GravityView_Edit_Entry::add_hooks()   B

Complexity

Conditions 6
Paths 1

Size

Total Lines 150

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 26
CRAP Score 8.2236

Importance

Changes 0
Metric Value
cc 6
nc 1
nop 0
dl 0
loc 150
ccs 26
cts 43
cp 0.6047
crap 8.2236
rs 7.3777
c 0
b 0
f 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * The GravityView Edit Entry Extension
4
 *
5
 * Easily edit entries in GravityView.
6
 *
7
 * @package   GravityView
8
 * @license   GPL2+
9
 * @author    GravityView <[email protected]>
10
 * @link      http://gravityview.co
11
 * @copyright Copyright 2014, Katz Web Services, Inc.
12
 */
13
14
if ( ! defined( 'WPINC' ) ) {
15
	die;
16
}
17
18
// Needed to allow JS in the Close link because of esc_url()
19
add_filter( 'kses_allowed_protocols', function($protocols) {
20
	$protocols[] = 'javascript';
21
	return $protocols;
22
});
23
24
class GravityView_Edit_Entry {
25
26
    /**
27
     * @var string
28
     */
29
	static $file;
30
31
	static $instance;
32
33
    /**
34
     * Component instances.
35 22
     * @var array
36
     */
37 22
    public $instances = array();
38
39 22
40
	function __construct() {
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...
41
42
        self::$file = plugin_dir_path( __FILE__ );
43 22
44
        if( is_admin() ) {
45 22
            $this->load_components( 'admin' );
46
        }
47
48 22
		$this->load_components( 'locking' );
49
50 22
        $this->load_components( 'render' );
51
52
        // If GF User Registration Add-on exists
53 22
        $this->load_components( 'user-registration' );
54 22
55
        $this->add_hooks();
56
57 23
		// Process hooks for addons that may or may not be present
58
		$this->addon_specific_hooks();
59 23
	}
60 22
61
62
    static function getInstance() {
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...
63 23
64
        if( empty( self::$instance ) ) {
65
            self::$instance = new GravityView_Edit_Entry;
66
        }
67 22
68
        return self::$instance;
69 22
    }
70
71 22
72 22
    private function load_components( $component ) {
73
74
        $dir = trailingslashit( self::$file );
75
76 22
        $filename  = $dir . 'class-edit-entry-' . $component . '.php';
77 22
        $classname = 'GravityView_Edit_Entry_' . str_replace( ' ', '_', ucwords( str_replace( '-', ' ', $component ) ) );
78 22
79
        // Loads component and pass extension's instance so that component can
80 22
        // talk each other.
81
        require_once $filename;
82 22
        $this->instances[ $component ] = new $classname( $this );
83
        $this->instances[ $component ]->load();
84
85 22
    }
86
87
    private function add_hooks() {
88 22
89
        // Add front-end access to Gravity Forms delete file action
90 22
        add_action( 'wp_ajax_nopriv_rg_delete_file', array( 'GFForms', 'delete_file') );
91
92
        // Make sure this hook is run for non-admins
93 22
        add_action( 'wp_ajax_rg_delete_file', array( 'GFForms', 'delete_file') );
94
95 22
        add_filter( 'gravityview_blacklist_field_types', array( $this, 'modify_field_blacklist' ), 10, 2 );
96
97 22
        // add template path to check for field
98
        add_filter( 'gravityview_template_paths', array( $this, 'add_template_path' ) );
99
100
		add_filter( 'gravityview/field/is_visible', array( $this, 'maybe_not_visible' ), 10, 3 );
101
102
		add_filter( 'gravityview/api/reserved_query_args', array( $this, 'add_reserved_arg' ) );
103 22
104
	    add_action( 'template_redirect', function() {
105 22
		    if ( ! isset( $_GET['gv-iframe'] ) ) {
106
			    return;
107
		    }
108
109 22
		    // If user doesn't have appropriate permissions, die.
110
			if ( ! GFCommon::current_user_can_any( array( 'gravityforms_edit_forms', 'gravityforms_create_form', 'gravityforms_preview_forms' ) ) ) {
111
				die( esc_html__( "You don't have adequate permission to preview forms.", 'gravityforms' ) );
112
			}
113
114
/**
115
 * Fires when a Form Preview is loaded.
116
 *
117
 * The hook fires when a Form Preview is initialized and before it is rendered.
118
 *
119
 * @since 2.5
120
 */
121
do_action( 'gform_preview_init' );
122
123 44
// Load form display class.
124
require_once( GFCommon::get_base_path() . '/form_display.php' );
125 44
126 44
// Get form ID.
127
$form_id = absint( rgget( 'id' ) );
128
129
// Get form object.
130
$form = RGFormsModel::get_form_meta( $_GET['id'] );
131
132
?>
133
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
134
<html xmlns="http://www.w3.org/1999/xhtml" <?php language_attributes(); ?>>
135
<head>
136
	<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
137
	<meta http-equiv="Imagetoolbar" content="No" />
138
	<meta name="viewport" content="width=device-width, initial-scale=1">
139
	<title><?php esc_html_e( 'Form Preview', 'gravityforms' ) ?></title>
140
	<?php
141
142
		// If form exists, enqueue its scripts.
143
		if ( ! empty( $form ) ) {
144
			GFFormDisplay::enqueue_form_scripts( $form );
145
		}
146
147
		wp_enqueue_script( 'gform_preview' );
148
149
		wp_print_head_scripts();
150
151
		$styles = array();
152
153
		/**
154
		 * Filters Form Preview Styles.
155
		 *
156 2
		 * This filter modifies the enqueued styles for the Form Preview. Any handles returned in the array
157
		 * will be loaded in the Preview header (if they've been registered with wp_register_style).
158
		 *
159 2
		 * @since 2.4
160
		 *
161 2
		 * @param array $styles An empty array representing the currently-active styles.
162
		 * @param array $form An array representing the current Form.
163
		 *
164
		 * @return array An array of handles to enqueue in the header.
165
		 */
166
		$styles = apply_filters( 'gform_preview_styles', $styles, $form );
167
168
		if ( ! empty( $styles ) ) {
169
			wp_print_styles( $styles );
170
		}
171
172
		/**
173 24
		 * Fire before the closing <head> tag of the preview page.
174 24
		 *
175
		 * @since 2.4.19
176
		 *
177
		 * @param int $form_id The ID of the form currently being previewed.
178
		 */
179
		do_action( 'gform_preview_header', $form_id );
180
181
	?>
182
	<script type="text/javascript">
183
		jQuery(function($) {
184
			$( '.gv-button-cancel' ).on( 'click', function () {
185
				parent.jQuery.fancybox.getInstance().close();
186
			} );
187
		});
188
	</script>
189
</head>
190
<body <?php body_class(); ?>>
191 3
<div id="preview_form_container">
192
193 3
<?php
194
195 3
$entry = gravityview()->request->is_edit_entry();
196
197 3
if ( ! $entry ) {
198 3
	return;
199 3
}
200
201 3
add_filter( 'clean_url', function( $good_protocol_url, $original_url, $_context ) {
0 ignored issues
show
Unused Code introduced by
The parameter $_context 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...
202 2
	return $original_url;
203
}, 20, 3 );
204
205
add_filter( 'gravityview/edit_entry/cancel_link', function ( $link ) {
0 ignored issues
show
Unused Code introduced by
The parameter $link 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...
206
	return '';
207
} );
208
209 3
210
$view = gravityview()->request->is_view();
211
$gravityview_view = GravityView_View::getInstance( $view );
212
$gravityview_view->setViewId( $view->ID );
213
$gravityview_view->setCurrentEntry( $entry->as_entry() );
214
$data = GravityView_View_Data::getInstance( $view );
215
$loader = GravityView_Edit_Entry::getInstance();
216
$render = $loader->instances['render'];
217
218
$render->init( $data, $entry, $view );
219
220
remove_all_filters( 'clean_url');
221
wp_print_footer_scripts();
222
223
/**
224
 * Fires in the footer of a Form Preview page
225
 *
226
 * @param int $_GET['id'] The ID of the form currently being previewed
227 3
 */
228
do_action( 'gform_preview_footer', $form_id );
229
?>
230
</div>
231
</body>
232
</html>
233
<?php
234
		    exit();
235
	    } );
236
    }
237
238
	/**
239
	 * Adds "edit" to the list of internal reserved query args
240
	 *
241
	 * @since 2.10
242
	 *
243
	 * @param array $args Existing reserved args
244
	 *
245
	 * @return array
246
	 */
247
	public function add_reserved_arg( $args ) {
248
249
		$args[] = 'edit';
250
251
		return $args;
252
	}
253
254
	/**
255
	 * Trigger hooks that are normally run in the admin for Addons, but need to be triggered manually because we're not in the admin
256 22
	 * @return void
257
	 */
258
	private function addon_specific_hooks() {
259 22
260
		if( class_exists( 'GFSignature' ) && is_callable( array( 'GFSignature', 'get_instance' ) ) ) {
261
			add_filter('gform_admin_pre_render', array( GFSignature::get_instance(), 'edit_lead_script'));
262
		}
263
264
	}
265
266
	/**
267
	 * Hide the field or not.
268
	 *
269
	 * For non-logged in users.
270
	 * For users that have no edit rights on any of the current entries.
271
	 *
272
	 * @param bool $visible Visible or not.
273
	 * @param \GV\Field $field The field.
274
	 * @param \GV\View $view The View context.
275
	 *
276
	 * @return bool
277 22
	 */
278
	public function maybe_not_visible( $visible, $field, $view ) {
279 22
280
		if ( 'edit_link' !== $field->ID ) {
281
			return $visible;
282
		}
283
284
		if ( ! $view instanceof \GV\View ) {
285
			return $visible;
286
		}
287
288
		static $visibility_cache_for_view = array();
289
290
		if ( ! is_null( $result = \GV\Utils::get( $visibility_cache_for_view, $view->ID, null ) ) ) {
291
			return $result;
292 24
		}
293
294
		foreach ( $view->get_entries()->all() as $entry ) {
295 24
			if ( self::check_user_cap_edit_entry( $entry->as_entry(), $view ) ) {
296
				// At least one entry is deletable for this user
297
				$visibility_cache_for_view[ $view->ID ] = true;
298 24
				return true;
299
			}
300 22
		}
301 22
302
		$visibility_cache_for_view[ $view->ID ] = false;
303 2
304
		return false;
305
	}
306 2
307
    /**
308
     * Include this extension templates path
309
     * @param array $file_paths List of template paths ordered
310 2
     */
311
    public function add_template_path( $file_paths ) {
312
313
        // Index 100 is the default GravityView template path.
314
        $file_paths[ 110 ] = self::$file;
315
316 24
        return $file_paths;
317
    }
318 23
319
    /**
320 23
     *
321
     * Return a well formatted nonce key according to GravityView Edit Entry protocol
322 3
     *
323
     * @param $view_id int GravityView view id
324 1
     * @param $form_id int Gravity Forms form id
325
     * @param $entry_id int Gravity Forms entry id
326 1
     * @return string
327
     */
328
    public static function get_nonce_key( $view_id, $form_id, $entry_id ) {
329
        return sprintf( 'edit_%d_%d_%d', $view_id, $form_id, $entry_id );
330 3
    }
331
332
333 3
    /**
334
     * The edit entry link creates a secure link with a nonce
335 2
     *
336
     * It also mimics the URL structure Gravity Forms expects to have so that
337 2
     * it formats the display of the edit form like it does in the backend, like
338
     * "You can edit this post from the post page" fields, for example.
339
     *
340
     * @param $entry array Gravity Forms entry object
341 2
     * @param $view_id int GravityView view id
342
     * @param $post_id int GravityView Post ID where View may be embedded {@since 1.9.2}
343 2
     * @param string|array $field_values Parameters to pass in to the Edit Entry form to prefill data. Uses the same format as Gravity Forms "Allow field to be populated dynamically" {@since 1.9.2} {@see https://www.gravityhelp.com/documentation/article/allow-field-to-be-populated-dynamically/ }
344
     * @return string
345 2
     */
346
    public static function get_edit_link( $entry, $view_id, $post_id = null, $field_values = '' ) {
347 2
348
        $nonce_key = self::get_nonce_key( $view_id, $entry['form_id'], $entry['id']  );
349
350
        $base = gv_entry_link( $entry, $post_id ? : $view_id  );
351
352
        $url = add_query_arg( array(
353
            'edit' => wp_create_nonce( $nonce_key )
354
        ), $base );
355
356
        if( $post_id ) {
357
	        $url = add_query_arg( array( 'gvid' => $view_id ), $url );
358
        }
359
360
	    /**
361
	     * Allow passing params to dynamically populate entry with values
362
	     * @since 1.9.2
363 24
	     */
364
	    if( !empty( $field_values ) ) {
365 24
366
		    if( is_array( $field_values ) ) {
367
			    // If already an array, no parse_str() needed
368
			    $params = $field_values;
369
		    } else {
370
			    parse_str( $field_values, $params );
371
		    }
372
373
		    $url = add_query_arg( $params, $url );
374
	    }
375
376
		/**
377
		 * @filter `gravityview/edit/link` Filter the edit URL link.
378
		 * @param[in,out] string $url The url.
379
		 * @param array $entry The entry.
380
		 * @param \GV\View $view The View.
381
		 */
382
		return apply_filters( 'gravityview/edit/link', $url, $entry, \GV\View::by_id( $view_id  ) );
383
    }
384
385
	/**
386
	 * Edit mode doesn't allow certain field types.
387
	 * @param  array $fields  Existing blacklist fields
388
	 * @param  string|null $context Context
389
	 * @return array          If not edit context, original field blacklist. Otherwise, blacklist including post fields.
390
	 */
391
	public function modify_field_blacklist( $fields = array(), $context = NULL ) {
392
393
		if( empty( $context ) || $context !== 'edit' ) {
394
			return $fields;
395
		}
396
397
		$add_fields = $this->get_field_blacklist();
398
399
		return array_merge( $fields, $add_fields );
400
	}
401
402
	/**
403
	 * Returns array of field types that should not be displayed in Edit Entry
404
	 *
405
	 * @since 1.20
406
	 *
407
	 * @param array $entry Gravity Forms entry array
408
	 *
409
	 * @return array Blacklist of field types
410
	 */
411
	function get_field_blacklist( $entry = array() ) {
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...
412
413
		$fields = array(
414
			'page',
415
			'payment_status',
416
			'payment_date',
417
			'payment_amount',
418
			'is_fulfilled',
419
			'transaction_id',
420
			'transaction_type',
421
			'captcha',
422
			'honeypot',
423
			'creditcard',
424
		);
425
426
		/**
427
		 * @filter `gravityview/edit_entry/field_blacklist` Array of fields that should not be displayed in Edit Entry
428
		 * @since 1.20
429
		 * @param array $fields Blacklist field type array
430
		 * @param array $entry Gravity Forms entry array
431
		 */
432
		$fields = apply_filters( 'gravityview/edit_entry/field_blacklist', $fields, $entry );
433
434
		return $fields;
435
	}
436
437
438
    /**
439
     * checks if user has permissions to edit a specific entry
440
     *
441
     * Needs to be used combined with GravityView_Edit_Entry::user_can_edit_entry for maximum security!!
442
     *
443
     * @param  array $entry Gravity Forms entry array
444
     * @param \GV\View|int $view ID of the view you want to check visibility against {@since 1.9.2}. Required since 2.0
445
     * @return bool
446
     */
447
    public static function check_user_cap_edit_entry( $entry, $view = 0 ) {
448
449
        // No permission by default
450
        $user_can_edit = false;
451
452
		// get user_edit setting
453
		if ( empty( $view ) ) {
454
			// @deprecated path
455
			$view_id = GravityView_View::getInstance()->getViewId();
456
			$user_edit = GravityView_View::getInstance()->getAtts( 'user_edit' );
457
		} else {
458
			if ( $view instanceof \GV\View ) {
459
				$view_id = $view->ID;
460
			} else {
461
				$view_id = $view;
462
			}
463
464
			// in case is specified and not the current view
465
			$user_edit = GVCommon::get_template_setting( $view_id, 'user_edit' );
466
		}
467
468
        // If they can edit any entries (as defined in Gravity Forms)
469
        // Or if they can edit other people's entries
470
        // Then we're good.
471
        if( GVCommon::has_cap( array( 'gravityforms_edit_entries', 'gravityview_edit_others_entries' ), $entry['id'] ) ) {
472
473
            gravityview()->log->debug( 'User has ability to edit all entries.' );
474
475
            $user_can_edit = true;
476
477
        } else if( !isset( $entry['created_by'] ) ) {
478
479
            gravityview()->log->error( 'Entry `created_by` doesn\'t exist.');
480
481
            $user_can_edit = false;
482
483
        } else {
484
485
            $current_user = wp_get_current_user();
486
487
            // User edit is disabled
488
            if( empty( $user_edit ) ) {
489
490
                gravityview()->log->debug( 'User Edit is disabled. Returning false.' );
491
492
                $user_can_edit = false;
493
            }
494
495
            // User edit is enabled and the logged-in user is the same as the user who created the entry. We're good.
496
            else if( is_user_logged_in() && intval( $current_user->ID ) === intval( $entry['created_by'] ) ) {
497
498
                gravityview()->log->debug( 'User {user_id} created the entry.', array( 'user_id', $current_user->ID ) );
499
500
                $user_can_edit = true;
501
502
            } else if( ! is_user_logged_in() ) {
503
504
                gravityview()->log->debug( 'No user defined; edit entry requires logged in user' );
505
506
	            $user_can_edit = false; // Here just for clarity
507
            }
508
509
        }
510
511
        /**
512
         * @filter `gravityview/edit_entry/user_can_edit_entry` Modify whether user can edit an entry.
513
         * @since 1.15 Added `$entry` and `$view_id` parameters
514
         * @param[in,out] boolean $user_can_edit Can the current user edit the current entry? (Default: false)
515
         * @param[in] array $entry Gravity Forms entry array {@since 1.15}
516
         * @param[in] int $view_id ID of the view you want to check visibility against {@since 1.15}
517
         */
518
        $user_can_edit = apply_filters( 'gravityview/edit_entry/user_can_edit_entry', $user_can_edit, $entry, $view_id );
519
520
        return (bool) $user_can_edit;
521
    }
522
523
524
525
} // end class
526
527
//add_action( 'plugins_loaded', array('GravityView_Edit_Entry', 'getInstance'), 6 );
528
GravityView_Edit_Entry::getInstance();
529
530