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