Completed
Push — develop ( 2c39bb...a4e86c )
by Gennady
15:59 queued 10s
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 7
CRAP Score 7

Importance

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