Completed
Push — develop ( 0382bd...a61784 )
by Zack
21:58 queued 06:07
created

GravityView_Edit_Entry::maybe_not_visible()   B

Complexity

Conditions 7
Paths 7

Size

Total Lines 31

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 33.2824

Importance

Changes 0
Metric Value
cc 7
nc 7
nop 3
dl 0
loc 31
ccs 3
cts 16
cp 0.1875
crap 33.2824
rs 8.4906
c 0
b 0
f 0
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    Katz Web Services, Inc.
10
 * @link      http://gravityview.co
11
 * @copyright Copyright 2014, Katz Web Services, Inc.
12
 */
13
14
if ( ! defined( 'WPINC' ) ) {
15
	die;
16
}
17
18
19
class GravityView_Edit_Entry {
20
21
    /**
22
     * @var string
23
     */
24
	static $file;
25
26
	static $instance;
27
28
    /**
29
     * Component instances.
30
     * @var array
31
     */
32
    public $instances = array();
33
34
35 22
	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...
36
37 22
        self::$file = plugin_dir_path( __FILE__ );
38
39 22
        if( is_admin() ) {
40
            $this->load_components( 'admin' );
41
        }
42
43
44 22
        $this->load_components( 'render' );
45
46
        // If GF User Registration Add-on exists
47 22
        $this->load_components( 'user-registration' );
48
49 22
        $this->add_hooks();
50
51
		// Process hooks for addons that may or may not be present
52 22
		$this->addon_specific_hooks();
53 22
	}
54
55
56 23
    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...
57
58 23
        if( empty( self::$instance ) ) {
59 22
            self::$instance = new GravityView_Edit_Entry;
60
        }
61
62 23
        return self::$instance;
63
    }
64
65
66 22
    private function load_components( $component ) {
67
68 22
        $dir = trailingslashit( self::$file );
69
70 22
        $filename  = $dir . 'class-edit-entry-' . $component . '.php';
71 22
        $classname = 'GravityView_Edit_Entry_' . str_replace( ' ', '_', ucwords( str_replace( '-', ' ', $component ) ) );
72
73
        // Loads component and pass extension's instance so that component can
74
        // talk each other.
75 22
        require_once $filename;
76 22
        $this->instances[ $component ] = new $classname( $this );
77 22
        $this->instances[ $component ]->load();
78
79 22
    }
80
81 22
    private function add_hooks() {
82
83
        // Add front-end access to Gravity Forms delete file action
84 22
        add_action( 'wp_ajax_nopriv_rg_delete_file', array( 'GFForms', 'delete_file') );
85
86
        // Make sure this hook is run for non-admins
87 22
        add_action( 'wp_ajax_rg_delete_file', array( 'GFForms', 'delete_file') );
88
89 22
        add_filter( 'gravityview_blacklist_field_types', array( $this, 'modify_field_blacklist' ), 10, 2 );
90
91
        // add template path to check for field
92 22
        add_filter( 'gravityview_template_paths', array( $this, 'add_template_path' ) );
93
94 22
		add_filter( 'gravityview/field/is_visible', array( $this, 'maybe_not_visible' ), 10, 3 );
95
96 22
    }
97
98
	/**
99
	 * Trigger hooks that are normally run in the admin for Addons, but need to be triggered manually because we're not in the admin
100
	 * @return void
101
	 */
102 22
	private function addon_specific_hooks() {
103
104 22
		if( class_exists( 'GFSignature' ) && is_callable( array( 'GFSignature', 'get_instance' ) ) ) {
105
			add_filter('gform_admin_pre_render', array( GFSignature::get_instance(), 'edit_lead_script'));
106
		}
107
108 22
	}
109
110
	/**
111
	 * Hide the field or not.
112
	 *
113
	 * For non-logged in users.
114
	 * For users that have no edit rights on any of the current entries.
115
	 *
116
	 * @param bool $visible Visible or not.
117
	 * @param \GF\Field $field The field.
118
	 * @param \GV\View $view The View context.
119
	 *
120
	 * @return bool
121
	 */
122 44
	public function maybe_not_visible( $visible, $field, $view ) {
123 44
		if ( 'edit_link' !== $field->ID ) {
124 44
			return $visible;
125
		}
126
127
		if ( ! is_user_logged_in() ) {
128
			return false;
129
		}
130
131
		if ( ! $view ) {
132
			return $visible;
133
		}
134
135
		static $visiblity_cache_for_view = array();
136
137
		if ( ! is_null( $result = \GV\Utils::get( $visiblity_cache_for_view, $view->ID, null ) ) ) {
138
			return $result;
139
		}
140
141
		foreach ( $view->get_entries()->all() as $entry ) {
142
			if ( self::check_user_cap_edit_entry( $entry->as_entry(), $view ) ) {
143
				// At least one entry is deletable for this user
144
				$visiblity_cache_for_view[ $view->ID ] = true;
145
				return true;
146
			}
147
		}
148
149
		$visiblity_cache_for_view[ $view->ID ] = false;
150
151
		return false;
152
	}
153
154
    /**
155
     * Include this extension templates path
156
     * @param array $file_paths List of template paths ordered
157
     */
158 2
    public function add_template_path( $file_paths ) {
159
160
        // Index 100 is the default GravityView template path.
161 2
        $file_paths[ 110 ] = self::$file;
162
163 2
        return $file_paths;
164
    }
165
166
    /**
167
     *
168
     * Return a well formatted nonce key according to GravityView Edit Entry protocol
169
     *
170
     * @param $view_id int GravityView view id
171
     * @param $form_id int Gravity Forms form id
172
     * @param $entry_id int Gravity Forms entry id
173
     * @return string
174
     */
175 24
    public static function get_nonce_key( $view_id, $form_id, $entry_id ) {
176 24
        return sprintf( 'edit_%d_%d_%d', $view_id, $form_id, $entry_id );
177
    }
178
179
180
    /**
181
     * The edit entry link creates a secure link with a nonce
182
     *
183
     * It also mimics the URL structure Gravity Forms expects to have so that
184
     * it formats the display of the edit form like it does in the backend, like
185
     * "You can edit this post from the post page" fields, for example.
186
     *
187
     * @param $entry array Gravity Forms entry object
188
     * @param $view_id int GravityView view id
189
     * @param $post_id int GravityView Post ID where View may be embedded {@since 1.9.2}
190
     * @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/ }
191
     * @return string
192
     */
193 3
    public static function get_edit_link( $entry, $view_id, $post_id = null, $field_values = '' ) {
194
195 3
        $nonce_key = self::get_nonce_key( $view_id, $entry['form_id'], $entry['id']  );
196
197 3
        $base = gv_entry_link( $entry, $post_id ? : $view_id  );
198
199 3
        $url = add_query_arg( array(
200 3
            'edit' => wp_create_nonce( $nonce_key )
201 3
        ), $base );
202
203 3
        if( $post_id ) {
204 2
	        $url = add_query_arg( array( 'gvid' => $view_id ), $url );
205
        }
206
207
	    /**
208
	     * Allow passing params to dynamically populate entry with values
209
	     * @since 1.9.2
210
	     */
211 3
	    if( !empty( $field_values ) ) {
212
213
		    if( is_array( $field_values ) ) {
214
			    // If already an array, no parse_str() needed
215
			    $params = $field_values;
216
		    } else {
217
			    parse_str( $field_values, $params );
218
		    }
219
220
		    $url = add_query_arg( $params, $url );
221
	    }
222
223 3
        return $url;
224
    }
225
226
	/**
227
	 * Edit mode doesn't allow certain field types.
228
	 * @param  array $fields  Existing blacklist fields
229
	 * @param  string|null $context Context
230
	 * @return array          If not edit context, original field blacklist. Otherwise, blacklist including post fields.
231
	 */
232
	public function modify_field_blacklist( $fields = array(), $context = NULL ) {
233
234
		if( empty( $context ) || $context !== 'edit' ) {
235
			return $fields;
236
		}
237
238
		$add_fields = $this->get_field_blacklist();
239
240
		return array_merge( $fields, $add_fields );
241
	}
242
243
	/**
244
	 * Returns array of field types that should not be displayed in Edit Entry
245
	 *
246
	 * @since 1.20
247
	 *
248
	 * @param array $entry Gravity Forms entry array
249
	 *
250
	 * @return array Blacklist of field types
251
	 */
252 22
	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...
253
254
		$fields = array(
255 22
			'page',
256
			'payment_status',
257
			'payment_date',
258
			'payment_amount',
259
			'is_fulfilled',
260
			'transaction_id',
261
			'transaction_type',
262
			'captcha',
263
			'honeypot',
264
			'creditcard',
265
		);
266
267
		/**
268
		 * @filter `gravityview/edit_entry/field_blacklist` Array of fields that should not be displayed in Edit Entry
269
		 * @since 1.20
270
		 * @param array $fields Blacklist field type array
271
		 * @param array $entry Gravity Forms entry array
272
		 */
273 22
		$fields = apply_filters( 'gravityview/edit_entry/field_blacklist', $fields, $entry );
274
275 22
		return $fields;
276
	}
277
278
279
    /**
280
     * checks if user has permissions to edit a specific entry
281
     *
282
     * Needs to be used combined with GravityView_Edit_Entry::user_can_edit_entry for maximum security!!
283
     *
284
     * @param  array $entry Gravity Forms entry array
285
     * @param \GV\View int $view_id ID of the view you want to check visibility against {@since 1.9.2}. Required since 2.0
286
     * @return bool
287
     */
288 24
    public static function check_user_cap_edit_entry( $entry, $view = 0 ) {
289
290
        // No permission by default
291 24
        $user_can_edit = false;
292
293
		// get user_edit setting
294 24
		if ( empty( $view ) ) {
295
			// @deprecated path
296 22
			$view_id = GravityView_View::getInstance()->getViewId();
297 22
			$user_edit = GravityView_View::getInstance()->getAtts( 'user_edit' );
298
		} else {
299 2
			if ( $view instanceof \GV\View ) {
300
				$view_id = $view->ID;
301
			} else {
302 2
				$view_id = $view;
303
			}
304
305
			// in case is specified and not the current view
306 2
			$user_edit = GVCommon::get_template_setting( $view_id, 'user_edit' );
307
		}
308
309
        // If they can edit any entries (as defined in Gravity Forms)
310
        // Or if they can edit other people's entries
311
        // Then we're good.
312 24
        if( GVCommon::has_cap( array( 'gravityforms_edit_entries', 'gravityview_edit_others_entries' ), $entry['id'] ) ) {
313
314 23
            gravityview()->log->debug( 'User has ability to edit all entries.' );
315
316 23
            $user_can_edit = true;
317
318 3
        } else if( !isset( $entry['created_by'] ) ) {
319
320 1
            gravityview()->log->error( 'Entry `created_by` doesn\'t exist.');
321
322 1
            $user_can_edit = false;
323
324
        } else {
325
326
327 3
            $current_user = wp_get_current_user();
328
329
            // User edit is disabled
330 3
            if( empty( $user_edit ) ) {
331
332 2
                gravityview()->log->debug( 'User Edit is disabled. Returning false.' );
333
334 2
                $user_can_edit = false;
335
            }
336
337
            // User edit is enabled and the logged-in user is the same as the user who created the entry. We're good.
338 2
            else if( is_user_logged_in() && intval( $current_user->ID ) === intval( $entry['created_by'] ) ) {
339
340 2
                gravityview()->log->debug( 'User {user_id} created the entry.', array( 'user_id', $current_user->ID ) );
341
342 2
                $user_can_edit = true;
343
344 2
            } else if( ! is_user_logged_in() ) {
345
346
                gravityview()->log->debug( 'No user defined; edit entry requires logged in user' );
347
            }
348
349
        }
350
351
        /**
352
         * @filter `gravityview/edit_entry/user_can_edit_entry` Modify whether user can edit an entry.
353
         * @since 1.15 Added `$entry` and `$view_id` parameters
354
         * @param[in,out] boolean $user_can_edit Can the current user edit the current entry? (Default: false)
355
         * @param[in] array $entry Gravity Forms entry array {@since 1.15}
356
         * @param[in] int $view_id ID of the view you want to check visibility against {@since 1.15}
357
         */
358 24
        $user_can_edit = apply_filters( 'gravityview/edit_entry/user_can_edit_entry', $user_can_edit, $entry, $view_id );
359
360 24
        return (bool)$user_can_edit;
361
    }
362
363
364
365
} // end class
366
367
//add_action( 'plugins_loaded', array('GravityView_Edit_Entry', 'getInstance'), 6 );
368
GravityView_Edit_Entry::getInstance();
369
370