1
|
|
|
<?php |
|
|
|
|
2
|
|
|
/** |
3
|
|
|
* The GravityView Delete Entry Extension |
4
|
|
|
* |
5
|
|
|
* Delete entries in GravityView. |
6
|
|
|
* |
7
|
|
|
* @since 1.5.1 |
8
|
|
|
* @package GravityView |
9
|
|
|
* @license GPL2+ |
10
|
|
|
* @author Katz Web Services, Inc. |
11
|
|
|
* @link http://gravityview.co |
12
|
|
|
* @copyright Copyright 2014, Katz Web Services, Inc. |
13
|
|
|
*/ |
14
|
|
|
|
15
|
|
|
if ( ! defined( 'WPINC' ) ) { |
16
|
|
|
die; |
17
|
|
|
} |
18
|
|
|
|
19
|
|
|
/** |
20
|
|
|
* @since 1.5.1 |
21
|
|
|
*/ |
22
|
|
|
final class GravityView_Delete_Entry { |
23
|
|
|
|
24
|
|
|
static $file; |
|
|
|
|
25
|
|
|
static $instance; |
|
|
|
|
26
|
|
|
var $entry; |
|
|
|
|
27
|
|
|
var $form; |
|
|
|
|
28
|
|
|
var $view_id; |
|
|
|
|
29
|
|
|
var $is_valid = NULL; |
|
|
|
|
30
|
|
|
|
31
|
|
|
function __construct() { |
|
|
|
|
32
|
|
|
|
33
|
|
|
self::$file = plugin_dir_path( __FILE__ ); |
34
|
|
|
|
35
|
|
|
$this->add_hooks(); |
36
|
|
|
} |
37
|
|
|
|
38
|
|
|
/** |
39
|
|
|
* @since 1.9.2 |
40
|
|
|
*/ |
41
|
|
|
private function add_hooks() { |
42
|
|
|
add_action( 'wp', array( $this, 'process_delete' ), 10000 ); |
43
|
|
|
|
44
|
|
|
add_filter( 'gravityview_entry_default_fields', array( $this, 'add_default_field'), 10, 3 ); |
|
|
|
|
45
|
|
|
|
46
|
|
|
add_action( 'gravityview_before', array( $this, 'display_message' ) ); |
47
|
|
|
|
48
|
|
|
// For the Delete Entry Link, you don't want visible to all users. |
49
|
|
|
add_filter( 'gravityview_field_visibility_caps', array( $this, 'modify_visibility_caps'), 10, 5 ); |
|
|
|
|
50
|
|
|
|
51
|
|
|
// Modify the field options based on the name of the field type |
52
|
|
|
add_filter( 'gravityview_template_delete_link_options', array( $this, 'delete_link_field_options' ), 10, 5 ); |
53
|
|
|
|
54
|
|
|
// add template path to check for field |
55
|
|
|
add_filter( 'gravityview_template_paths', array( $this, 'add_template_path' ) ); |
56
|
|
|
|
57
|
|
|
add_action( 'gravityview/edit-entry/publishing-action/after', array( $this, 'add_delete_button'), 10, 3 ); |
|
|
|
|
58
|
|
|
} |
59
|
|
|
|
60
|
|
|
/** |
61
|
|
|
* Return the instantiated class object |
62
|
|
|
* |
63
|
|
|
* @since 1.5.1 |
64
|
|
|
* @return GravityView_Delete_Entry |
65
|
|
|
*/ |
66
|
|
|
static function getInstance() { |
|
|
|
|
67
|
|
|
|
68
|
|
|
if( empty( self::$instance ) ) { |
|
|
|
|
69
|
|
|
self::$instance = new self; |
70
|
|
|
} |
71
|
|
|
|
72
|
|
|
return self::$instance; |
73
|
|
|
} |
74
|
|
|
|
75
|
|
|
/** |
76
|
|
|
* Include this extension templates path |
77
|
|
|
* |
78
|
|
|
* @since 1.5.1 |
79
|
|
|
* @param array $file_paths List of template paths ordered |
80
|
|
|
*/ |
81
|
|
|
function add_template_path( $file_paths ) { |
|
|
|
|
82
|
|
|
|
83
|
|
|
// Index 100 is the default GravityView template path. |
84
|
|
|
// Index 110 is Edit Entry link |
85
|
|
|
$file_paths[ 115 ] = self::$file; |
|
|
|
|
86
|
|
|
|
87
|
|
|
return $file_paths; |
88
|
|
|
} |
89
|
|
|
|
90
|
|
|
/** |
91
|
|
|
* Add "Delete Link Text" setting to the edit_link field settings |
92
|
|
|
* |
93
|
|
|
* @since 1.5.1 |
94
|
|
|
* @param [type] $field_options [description] |
|
|
|
|
95
|
|
|
* @param [type] $template_id [description] |
|
|
|
|
96
|
|
|
* @param [type] $field_id [description] |
|
|
|
|
97
|
|
|
* @param [type] $context [description] |
|
|
|
|
98
|
|
|
* @param [type] $input_type [description] |
|
|
|
|
99
|
|
|
* @return [type] [description] |
|
|
|
|
100
|
|
|
*/ |
101
|
|
|
function delete_link_field_options( $field_options, $template_id, $field_id, $context, $input_type ) { |
|
|
|
|
102
|
|
|
|
103
|
|
|
// Always a link, never a filter |
104
|
|
|
unset( $field_options['show_as_link'], $field_options['search_filter'] ); |
105
|
|
|
|
106
|
|
|
// Delete Entry link should only appear to visitors capable of editing entries |
107
|
|
|
unset( $field_options['only_loggedin'], $field_options['only_loggedin_cap'] ); |
108
|
|
|
|
109
|
|
|
$add_option['delete_link'] = array( |
|
|
|
|
110
|
|
|
'type' => 'text', |
111
|
|
|
'label' => __( 'Delete Link Text', 'gravityview' ), |
112
|
|
|
'desc' => NULL, |
|
|
|
|
113
|
|
|
'value' => __('Delete Entry', 'gravityview'), |
|
|
|
|
114
|
|
|
'merge_tags' => true, |
115
|
|
|
); |
116
|
|
|
|
117
|
|
|
$field_options['allow_edit_cap'] = array( |
118
|
|
|
'type' => 'select', |
119
|
|
|
'label' => __( 'Allow the following users to delete the entry:', 'gravityview' ), |
120
|
|
|
'choices' => GravityView_Render_Settings::get_cap_choices( $template_id, $field_id, $context, $input_type ), |
121
|
|
|
'tooltip' => 'allow_edit_cap', |
122
|
|
|
'class' => 'widefat', |
123
|
|
|
'value' => 'read', // Default: entry creator |
124
|
|
|
); |
125
|
|
|
|
|
|
|
|
126
|
|
|
|
127
|
|
|
return array_merge( $add_option, $field_options ); |
128
|
|
|
} |
129
|
|
|
|
130
|
|
|
|
131
|
|
|
/** |
132
|
|
|
* Add Edit Link as a default field, outside those set in the Gravity Form form |
133
|
|
|
* |
134
|
|
|
* @since 1.5.1 |
135
|
|
|
* @param array $entry_default_fields Existing fields |
136
|
|
|
* @param string|array $form form_ID or form object |
137
|
|
|
* @param string $zone Either 'single', 'directory', 'header', 'footer' |
138
|
|
|
*/ |
139
|
|
|
function add_default_field( $entry_default_fields, $form = array(), $zone = '' ) { |
|
|
|
|
140
|
|
|
|
141
|
|
|
$entry_default_fields['delete_link'] = array( |
142
|
|
|
'label' => __('Delete Entry', 'gravityview'), |
|
|
|
|
143
|
|
|
'type' => 'delete_link', |
144
|
|
|
'desc' => __('A link to delete the entry. Respects the Delete Entry permissions.', 'gravityview'), |
|
|
|
|
145
|
|
|
); |
146
|
|
|
|
147
|
|
|
return $entry_default_fields; |
148
|
|
|
} |
149
|
|
|
|
150
|
|
|
/** |
151
|
|
|
* Add Delete Entry Link to the Add Field dialog |
152
|
|
|
* @since 1.5.1 |
153
|
|
|
* @param array $available_fields |
154
|
|
|
*/ |
155
|
|
|
function add_available_field( $available_fields = array() ) { |
|
|
|
|
156
|
|
|
|
157
|
|
|
$available_fields['delete_link'] = array( |
158
|
|
|
'label_text' => __( 'Delete Entry', 'gravityview' ), |
159
|
|
|
'field_id' => 'delete_link', |
160
|
|
|
'label_type' => 'field', |
161
|
|
|
'input_type' => 'delete_link', |
162
|
|
|
'field_options' => NULL |
|
|
|
|
163
|
|
|
); |
164
|
|
|
|
165
|
|
|
return $available_fields; |
166
|
|
|
} |
167
|
|
|
|
168
|
|
|
/** |
169
|
|
|
* Change wording for the Edit context to read Entry Creator |
170
|
|
|
* |
171
|
|
|
* @since 1.5.1 |
172
|
|
|
* @param array $visibility_caps Array of capabilities to display in field dropdown. |
173
|
|
|
* @param string $field_type Type of field options to render (`field` or `widget`) |
|
|
|
|
174
|
|
|
* @param string $template_id Table slug |
175
|
|
|
* @param float $field_id GF Field ID - Example: `3`, `5.2`, `entry_link`, `created_by` |
176
|
|
|
* @param string $context What context are we in? Example: `single` or `directory` |
177
|
|
|
* @param string $input_type (textarea, list, select, etc.) |
178
|
|
|
* @return array Array of field options with `label`, `value`, `type`, `default` keys |
179
|
|
|
*/ |
180
|
|
|
public function modify_visibility_caps( $visibility_caps = array(), $template_id = '', $field_id = '', $context = '', $input_type = '' ) { |
|
|
|
|
181
|
|
|
|
182
|
|
|
$caps = $visibility_caps; |
183
|
|
|
|
184
|
|
|
// If we're configuring fields in the edit context, we want a limited selection |
185
|
|
|
if( $field_id === 'delete_link' ) { |
|
|
|
|
186
|
|
|
|
187
|
|
|
// Remove other built-in caps. |
188
|
|
|
unset( $caps['publish_posts'], $caps['gravityforms_view_entries'], $caps['delete_others_posts'] ); |
189
|
|
|
|
190
|
|
|
$caps['read'] = _x('Entry Creator', 'User capability', 'gravityview'); |
|
|
|
|
191
|
|
|
} |
192
|
|
|
|
193
|
|
|
return $caps; |
194
|
|
|
} |
195
|
|
|
|
196
|
|
|
/** |
197
|
|
|
* Make sure there's an entry |
198
|
|
|
* |
199
|
|
|
* @since 1.5.1 |
200
|
|
|
* @param [type] $entry [description] |
|
|
|
|
201
|
|
|
*/ |
202
|
|
|
function set_entry( $entry = null ) { |
|
|
|
|
203
|
|
|
$this->entry = empty( $entry ) ? GravityView_View::getInstance()->entries[0] : $entry; |
|
|
|
|
204
|
|
|
} |
205
|
|
|
|
206
|
|
|
/** |
207
|
|
|
* Generate a consistent nonce key based on the Entry ID |
208
|
|
|
* |
209
|
|
|
* @since 1.5.1 |
210
|
|
|
* @param int $entry_id Entry ID |
211
|
|
|
* @return string Key used to validate request |
212
|
|
|
*/ |
213
|
|
|
public static function get_nonce_key( $entry_id ) { |
214
|
|
|
return sprintf( 'delete_%s', $entry_id ); |
215
|
|
|
} |
216
|
|
|
|
217
|
|
|
|
218
|
|
|
/** |
219
|
|
|
* Generate a nonce link with the base URL of the current View embed |
220
|
|
|
* |
221
|
|
|
* We don't want to link to the single entry, because when deleted, there would be nothing to return to. |
222
|
|
|
* |
223
|
|
|
* @since 1.5.1 |
224
|
|
|
* @param array $entry Gravity Forms entry array |
225
|
|
|
* @return string|null If directory link is valid, the URL to process the delete request. Otherwise, `NULL`. |
226
|
|
|
*/ |
227
|
|
|
public static function get_delete_link( $entry, $view_id = 0, $post_id = null ) { |
228
|
|
|
|
229
|
|
|
self::getInstance()->set_entry( $entry ); |
230
|
|
|
|
231
|
|
|
$base = GravityView_API::directory_link( $post_id, true ); |
232
|
|
|
|
233
|
|
|
if( empty( $base ) ) { |
|
|
|
|
234
|
|
|
do_action( 'gravityview_log_error', __METHOD__ . ' - Post ID does not exist: '.$post_id ); |
235
|
|
|
return NULL; |
|
|
|
|
236
|
|
|
} |
237
|
|
|
|
238
|
|
|
// Use the slug instead of the ID for consistent security |
239
|
|
|
$entry_slug = GravityView_API::get_entry_slug( $entry['id'], $entry ); |
240
|
|
|
|
241
|
|
|
$view_id = empty( $view_id ) ? gravityview_get_view_id() : $view_id; |
242
|
|
|
|
243
|
|
|
$actionurl = add_query_arg( array( |
244
|
|
|
'action' => 'delete', |
245
|
|
|
'entry_id' => $entry_slug, |
246
|
|
|
'gvid' => $view_id, |
247
|
|
|
'view_id' => $view_id, |
248
|
|
|
), $base ); |
249
|
|
|
|
250
|
|
|
$url = wp_nonce_url( $actionurl, 'delete_'.$entry_slug, 'delete' ); |
251
|
|
|
|
252
|
|
|
return $url; |
253
|
|
|
} |
254
|
|
|
|
255
|
|
|
|
256
|
|
|
/** |
257
|
|
|
* Add a Delete button to the #publishing-action section of the Delete Entry form |
258
|
|
|
* |
259
|
|
|
* @since 1.5.1 |
260
|
|
|
* @param array $form Gravity Forms form array |
261
|
|
|
* @param array $entry Gravity Forms entry array |
262
|
|
|
* @param int $view_id GravityView View ID |
263
|
|
|
*/ |
264
|
|
|
function add_delete_button( $form = array(), $entry = array(), $view_id = NULL ) { |
|
|
|
|
265
|
|
|
|
266
|
|
|
// Only show the link to those who are allowed to see it. |
267
|
|
|
if( !self::check_user_cap_delete_entry( $entry ) ) { |
|
|
|
|
268
|
|
|
return; |
269
|
|
|
} |
270
|
|
|
|
271
|
|
|
/** |
272
|
|
|
* @filter `gravityview/delete-entry/show-delete-button` Should the Delete button be shown in the Edit Entry screen? |
273
|
|
|
* @param boolean $show_entry Default: true |
274
|
|
|
*/ |
275
|
|
|
$show_delete_button = apply_filters( 'gravityview/delete-entry/show-delete-button', true ); |
276
|
|
|
|
277
|
|
|
// If the button is hidden by the filter, don't show. |
278
|
|
|
if( !$show_delete_button ) { |
|
|
|
|
279
|
|
|
return; |
280
|
|
|
} |
281
|
|
|
|
282
|
|
|
$attributes = array( |
283
|
|
|
'class' => 'btn btn-sm button button-small alignright pull-right btn-danger gv-button-delete', |
284
|
|
|
'tabindex' => '5', |
285
|
|
|
'onclick' => self::get_confirm_dialog(), |
286
|
|
|
); |
287
|
|
|
|
288
|
|
|
echo gravityview_get_link( self::get_delete_link( $entry, $view_id ), esc_attr__( 'Delete', 'gravityview' ), $attributes ); |
|
|
|
|
289
|
|
|
|
290
|
|
|
} |
291
|
|
|
|
292
|
|
|
/** |
293
|
|
|
* Handle the deletion request, if $_GET['action'] is set to "delete" |
294
|
|
|
* |
295
|
|
|
* 1. Check referrer validity |
296
|
|
|
* 2. Make sure there's an entry with the slug of $_GET['entry_id'] |
297
|
|
|
* 3. If so, attempt to delete the entry. If not, set the error status |
298
|
|
|
* 4. Remove `action=delete` from the URL |
299
|
|
|
* 5. Redirect to the page using `wp_safe_redirect()` |
300
|
|
|
* |
301
|
|
|
* @since 1.5.1 |
302
|
|
|
* @uses wp_safe_redirect() |
303
|
|
|
* @return void |
304
|
|
|
*/ |
305
|
|
|
function process_delete() { |
|
|
|
|
306
|
|
|
|
307
|
|
|
// If the form is submitted |
308
|
|
|
if( 'delete' === RGForms::get("action") && isset( $_GET['entry_id'] ) ) { |
|
|
|
|
309
|
|
|
|
310
|
|
|
// Make sure it's a GravityView request |
311
|
|
|
$valid_nonce_key = wp_verify_nonce( $_GET['delete'], self::get_nonce_key( $_GET['entry_id'] ) ); |
|
|
|
|
312
|
|
|
|
313
|
|
|
if( ! $valid_nonce_key ) { |
|
|
|
|
314
|
|
|
do_action('gravityview_log_debug', __METHOD__ . ' Delete entry not processed: nonce validation failed.' ); |
|
|
|
|
315
|
|
|
return; |
316
|
|
|
} |
317
|
|
|
|
318
|
|
|
// Get the entry slug |
319
|
|
|
$entry_slug = esc_attr( $_GET['entry_id'] ); |
|
|
|
|
320
|
|
|
|
321
|
|
|
// See if there's an entry there |
322
|
|
|
$entry = gravityview_get_entry( $entry_slug ); |
323
|
|
|
|
324
|
|
|
if( $entry ) { |
|
|
|
|
325
|
|
|
|
326
|
|
|
$has_permission = $this->user_can_delete_entry( $entry ); |
327
|
|
|
|
328
|
|
|
if( is_wp_error( $has_permission ) ) { |
|
|
|
|
329
|
|
|
|
330
|
|
|
$messages = array( |
331
|
|
|
'message' => urlencode( $has_permission->get_error_message() ), |
332
|
|
|
'status' => 'error', |
333
|
|
|
); |
334
|
|
|
|
335
|
|
|
} else { |
336
|
|
|
|
337
|
|
|
// Delete the entry |
338
|
|
|
$delete_response = $this->delete_or_trash_entry( $entry['id'] ); |
339
|
|
|
|
340
|
|
|
if( is_wp_error( $delete_response ) ) { |
|
|
|
|
341
|
|
|
|
342
|
|
|
$messages = array( |
343
|
|
|
'message' => urlencode( $delete_response->get_error_message() ), |
344
|
|
|
'status' => 'error', |
345
|
|
|
); |
346
|
|
|
|
347
|
|
|
} else { |
348
|
|
|
|
349
|
|
|
$messages = array( |
350
|
|
|
'status' => $delete_response, |
351
|
|
|
); |
352
|
|
|
|
353
|
|
|
} |
|
|
|
|
354
|
|
|
|
355
|
|
|
} |
|
|
|
|
356
|
|
|
|
357
|
|
|
} else { |
358
|
|
|
|
359
|
|
|
do_action('gravityview_log_debug', __METHOD__ . ' Delete entry failed: there was no entry with the entry slug '. $entry_slug ); |
|
|
|
|
360
|
|
|
|
361
|
|
|
$messages = array( |
362
|
|
|
'message' => urlencode( __('The entry does not exist.', 'gravityview') ), |
|
|
|
|
363
|
|
|
'status' => 'error', |
364
|
|
|
); |
365
|
|
|
} |
366
|
|
|
|
367
|
|
|
$redirect_to_base = esc_url_raw( remove_query_arg( array( 'action' ) ) ); |
368
|
|
|
$redirect_to = add_query_arg( $messages, $redirect_to_base ); |
369
|
|
|
|
370
|
|
|
wp_safe_redirect( $redirect_to ); |
371
|
|
|
|
372
|
|
|
exit(); |
|
|
|
|
373
|
|
|
|
374
|
|
|
} // endif action is delete. |
375
|
|
|
|
376
|
|
|
} // process_delete |
377
|
|
|
|
378
|
|
|
/** |
379
|
|
|
* Delete mode: permanently delete, or move to trash? |
380
|
|
|
* |
381
|
|
|
* @return string `delete` or `trash` |
382
|
|
|
*/ |
383
|
|
|
private function get_delete_mode() { |
384
|
|
|
|
385
|
|
|
/** |
386
|
|
|
* @filter `gravityview/delete-entry/mode` Delete mode: permanently delete, or move to trash? |
387
|
|
|
* @since 1.13.1 |
388
|
|
|
* @param string $delete_mode Delete mode: `trash` or `delete`. Default: `delete` |
389
|
|
|
*/ |
390
|
|
|
$delete_mode = apply_filters( 'gravityview/delete-entry/mode', 'delete' ); |
391
|
|
|
|
392
|
|
|
return ( 'trash' === $delete_mode ) ? 'trash' : 'delete'; |
393
|
|
|
} |
394
|
|
|
|
395
|
|
|
/** |
396
|
|
|
* @since 1.13.1 |
397
|
|
|
* @see GFAPI::delete_entry() |
398
|
|
|
* @return WP_Error|boolean GFAPI::delete_entry() returns a WP_Error on error |
399
|
|
|
*/ |
400
|
|
|
private function delete_or_trash_entry( $entry_id ) { |
401
|
|
|
|
402
|
|
|
$mode = $this->get_delete_mode(); |
403
|
|
|
|
404
|
|
|
if( 'delete' === $mode ) { |
|
|
|
|
405
|
|
|
|
406
|
|
|
do_action( 'gravityview_log_debug', __METHOD__ . ' Starting delete entry: ', $entry_id ); |
407
|
|
|
|
408
|
|
|
// Delete the entry |
409
|
|
|
$delete_response = GFAPI::delete_entry( $entry_id ); |
410
|
|
|
|
411
|
|
|
if( ! is_wp_error( $delete_response ) ) { |
|
|
|
|
412
|
|
|
$delete_response = 'deleted'; |
413
|
|
|
} |
414
|
|
|
|
415
|
|
|
do_action( 'gravityview_log_debug', __METHOD__ . ' Delete response: ', $delete_response ); |
416
|
|
|
|
417
|
|
|
} else { |
418
|
|
|
|
419
|
|
|
do_action( 'gravityview_log_debug', __METHOD__ . ' Starting trash entry: ', $entry_id ); |
420
|
|
|
|
421
|
|
|
$trashed = GFAPI::update_entry_property( $entry_id, 'status', 'trash' ); |
422
|
|
|
new GravityView_Cache; |
423
|
|
|
|
424
|
|
|
if( ! $trashed ) { |
|
|
|
|
425
|
|
|
$delete_response = new WP_Error( 'trash_entry_failed', __('Moving the entry to the trash failed.', 'gravityview' ) ); |
|
|
|
|
426
|
|
|
} else { |
427
|
|
|
$delete_response = 'trashed'; |
428
|
|
|
} |
429
|
|
|
|
430
|
|
|
do_action( 'gravityview_log_debug', __METHOD__ . ' Trashed? ', $delete_response ); |
431
|
|
|
} |
432
|
|
|
|
433
|
|
|
return $delete_response; |
434
|
|
|
} |
435
|
|
|
|
436
|
|
|
/** |
437
|
|
|
* Is the current nonce valid for editing the entry? |
438
|
|
|
* |
439
|
|
|
* @since 1.5.1 |
440
|
|
|
* @return boolean |
441
|
|
|
*/ |
442
|
|
|
public function verify_nonce() { |
443
|
|
|
|
444
|
|
|
// No delete entry request was made |
445
|
|
|
if( empty( $_GET['entry_id'] ) || empty( $_GET['delete'] ) ) { |
|
|
|
|
446
|
|
|
return false; |
447
|
|
|
} |
448
|
|
|
|
449
|
|
|
$nonce_key = self::get_nonce_key( $_GET['entry_id'] ); |
|
|
|
|
450
|
|
|
|
451
|
|
|
$valid = wp_verify_nonce( $_GET['delete'], $nonce_key ); |
|
|
|
|
452
|
|
|
|
453
|
|
|
/** |
454
|
|
|
* @filter `gravityview/delete-entry/verify_nonce` Override Delete Entry nonce validation. Return true to declare nonce valid. |
455
|
|
|
* @since 1.15.2 |
456
|
|
|
* @see wp_verify_nonce() |
457
|
|
|
* @param int|boolean $valid False if invalid; 1 or 2 when nonce was generated |
458
|
|
|
* @param string $nonce_key Name of nonce action used in wp_verify_nonce. $_GET['delete'] holds the nonce value itself. Default: `delete_{entry_id}` |
459
|
|
|
*/ |
460
|
|
|
$valid = apply_filters( 'gravityview/delete-entry/verify_nonce', $valid, $nonce_key ); |
461
|
|
|
|
462
|
|
|
return $valid; |
463
|
|
|
} |
464
|
|
|
|
465
|
|
|
/** |
466
|
|
|
* Get the onclick attribute for the confirm dialogs that warns users before they delete an entry |
467
|
|
|
* |
468
|
|
|
* @since 1.5.1 |
469
|
|
|
* @return string HTML `onclick` attribute |
470
|
|
|
*/ |
471
|
|
|
public static function get_confirm_dialog() { |
472
|
|
|
|
473
|
|
|
$confirm = __('Are you sure you want to delete this entry? This cannot be undone.', 'gravityview'); |
|
|
|
|
474
|
|
|
|
475
|
|
|
/** |
476
|
|
|
* @filter `gravityview/delete-entry/confirm-text` Modify the Delete Entry Javascript confirmation text |
477
|
|
|
* @param string $confirm Default: "Are you sure you want to delete this entry? This cannot be undone." |
478
|
|
|
*/ |
479
|
|
|
$confirm = apply_filters( 'gravityview/delete-entry/confirm-text', $confirm ); |
480
|
|
|
|
481
|
|
|
return 'return window.confirm(\''. esc_js( $confirm ) .'\');'; |
482
|
|
|
} |
483
|
|
|
|
484
|
|
|
/** |
485
|
|
|
* Check if the user can edit the entry |
486
|
|
|
* |
487
|
|
|
* - Is the nonce valid? |
488
|
|
|
* - Does the user have the right caps for the entry |
489
|
|
|
* - Is the entry in the trash? |
490
|
|
|
* |
491
|
|
|
* @since 1.5.1 |
492
|
|
|
* @param array $entry Gravity Forms entry array |
493
|
|
|
* @return boolean|WP_Error True: can edit form. WP_Error: nope. |
494
|
|
|
*/ |
495
|
|
|
function user_can_delete_entry( $entry = array() ) { |
|
|
|
|
496
|
|
|
|
497
|
|
|
$error = NULL; |
|
|
|
|
498
|
|
|
|
499
|
|
|
if( ! $this->verify_nonce() ) { |
|
|
|
|
500
|
|
|
$error = __( 'The link to delete this entry is not valid; it may have expired.', 'gravityview'); |
|
|
|
|
501
|
|
|
} |
502
|
|
|
|
503
|
|
|
if( ! self::check_user_cap_delete_entry( $entry ) ) { |
|
|
|
|
504
|
|
|
$error = __( 'You do not have permission to delete this entry.', 'gravityview'); |
|
|
|
|
505
|
|
|
} |
506
|
|
|
|
507
|
|
|
if( $entry['status'] === 'trash' ) { |
|
|
|
|
508
|
|
|
if( 'trash' === $this->get_delete_mode() ) { |
|
|
|
|
509
|
|
|
$error = __( 'The entry is already in the trash.', 'gravityview' ); |
510
|
|
|
} else { |
511
|
|
|
$error = __( 'You cannot delete the entry; it is already in the trash.', 'gravityview' ); |
512
|
|
|
} |
513
|
|
|
} |
514
|
|
|
|
515
|
|
|
// No errors; everything's fine here! |
516
|
|
|
if( empty( $error ) ) { |
|
|
|
|
517
|
|
|
return true; |
518
|
|
|
} |
519
|
|
|
|
520
|
|
|
do_action('gravityview_log_error', 'GravityView_Delete_Entry[user_can_delete_entry]' . $error ); |
|
|
|
|
521
|
|
|
|
522
|
|
|
return new WP_Error( 'gravityview-delete-entry-permissions', $error ); |
523
|
|
|
} |
524
|
|
|
|
525
|
|
|
|
526
|
|
|
/** |
527
|
|
|
* checks if user has permissions to view the link or delete a specific entry |
528
|
|
|
* |
529
|
|
|
* @since 1.5.1 |
530
|
|
|
* @since 1.15 Added `$view_id` param |
531
|
|
|
* |
532
|
|
|
* @param array $entry Gravity Forms entry array |
533
|
|
|
* @param array $field Field settings (optional) |
534
|
|
|
* @param int $view_id Pass a View ID to check caps against. If not set, check against current View (optional) |
535
|
|
|
* @return bool |
536
|
|
|
*/ |
537
|
|
|
public static function check_user_cap_delete_entry( $entry, $field = array(), $view_id = 0 ) { |
538
|
|
|
$gravityview_view = GravityView_View::getInstance(); |
539
|
|
|
|
540
|
|
|
$current_user = wp_get_current_user(); |
541
|
|
|
|
542
|
|
|
$entry_id = isset( $entry['id'] ) ? $entry['id'] : NULL; |
|
|
|
|
543
|
|
|
|
544
|
|
|
// Or if they can delete any entries (as defined in Gravity Forms), we're good. |
545
|
|
|
if( GVCommon::has_cap( array( 'gravityforms_delete_entries', 'gravityview_delete_others_entries' ), $entry_id ) ) { |
|
|
|
|
546
|
|
|
|
547
|
|
|
do_action('gravityview_log_debug', 'GravityView_Delete_Entry[check_user_cap_delete_entry] Current user has `gravityforms_delete_entries` or `gravityview_delete_others_entries` capability.' ); |
|
|
|
|
548
|
|
|
|
549
|
|
|
return true; |
550
|
|
|
} |
551
|
|
|
|
|
|
|
|
552
|
|
|
|
553
|
|
|
// If field options are passed, check if current user can view the link |
554
|
|
|
if( !empty( $field ) ) { |
|
|
|
|
555
|
|
|
|
556
|
|
|
// If capability is not defined, something is not right! |
557
|
|
|
if( empty( $field['allow_edit_cap'] ) ) { |
|
|
|
|
558
|
|
|
|
559
|
|
|
do_action( 'gravityview_log_error', 'GravityView_Delete_Entry[check_user_cap_delete_entry] Cannot read delete entry field caps', $field ); |
560
|
|
|
|
561
|
|
|
return false; |
562
|
|
|
} |
563
|
|
|
|
564
|
|
|
if( GVCommon::has_cap( $field['allow_edit_cap'] ) ) { |
|
|
|
|
565
|
|
|
|
566
|
|
|
// Do not return true if cap is read, as we need to check if the current user created the entry |
567
|
|
|
if( $field['allow_edit_cap'] !== 'read' ) { |
|
|
|
|
568
|
|
|
return true; |
569
|
|
|
} |
|
|
|
|
570
|
|
|
|
571
|
|
|
} else { |
572
|
|
|
|
573
|
|
|
do_action( 'gravityview_log_debug', sprintf( 'GravityView_Delete_Entry[check_user_cap_delete_entry] User %s is not authorized to view delete entry link ', $current_user->ID ) ); |
574
|
|
|
|
575
|
|
|
return false; |
576
|
|
|
} |
|
|
|
|
577
|
|
|
|
578
|
|
|
} |
579
|
|
|
|
580
|
|
|
if( !isset( $entry['created_by'] ) ) { |
|
|
|
|
581
|
|
|
|
582
|
|
|
do_action('gravityview_log_error', 'GravityView_Delete_Entry[check_user_cap_delete_entry] Entry `created_by` doesn\'t exist.'); |
|
|
|
|
583
|
|
|
|
584
|
|
|
return false; |
585
|
|
|
} |
586
|
|
|
|
587
|
|
|
$view_id = empty( $view_id ) ? $gravityview_view->getViewId() : $view_id; |
588
|
|
|
|
589
|
|
|
// Only checks user_delete view option if view is already set |
590
|
|
|
if( $view_id ) { |
|
|
|
|
591
|
|
|
|
592
|
|
|
$current_view = gravityview_get_current_view_data( $view_id ); |
593
|
|
|
|
594
|
|
|
$user_delete = isset( $current_view['atts']['user_delete'] ) ? $current_view['atts']['user_delete'] : false; |
595
|
|
|
|
596
|
|
|
if( empty( $user_delete ) ) { |
|
|
|
|
597
|
|
|
|
598
|
|
|
do_action('gravityview_log_debug', 'GravityView_Delete_Entry[check_user_cap_delete_entry] User Delete is disabled. Returning false.' ); |
|
|
|
|
599
|
|
|
|
600
|
|
|
return false; |
601
|
|
|
} |
602
|
|
|
} |
603
|
|
|
|
604
|
|
|
// If the logged-in user is the same as the user who created the entry, we're good. |
605
|
|
|
if( is_user_logged_in() && intval( $current_user->ID ) === intval( $entry['created_by'] ) ) { |
|
|
|
|
606
|
|
|
|
607
|
|
|
do_action('gravityview_log_debug', sprintf( 'GravityView_Delete_Entry[check_user_cap_delete_entry] User %s created the entry.', $current_user->ID ) ); |
|
|
|
|
608
|
|
|
|
609
|
|
|
return true; |
610
|
|
|
} |
611
|
|
|
|
612
|
|
|
return false; |
613
|
|
|
} |
614
|
|
|
|
615
|
|
|
|
616
|
|
|
/** |
617
|
|
|
* After processing delete entry, the user will be redirected to the referring View or embedded post/page. Display a message on redirection. |
618
|
|
|
* |
619
|
|
|
* If success, there will be `status` URL parameters `status=>success` |
620
|
|
|
* If an error, there will be `status` and `message` URL parameters `status=>error&message=example` |
621
|
|
|
* |
622
|
|
|
* @since 1.15.2 Only show message when the URL parameter's View ID matches the current View ID |
623
|
|
|
* @since 1.5.1 |
624
|
|
|
* |
625
|
|
|
* @param int $current_view_id The ID of the View being rendered |
626
|
|
|
* @return void |
627
|
|
|
*/ |
628
|
|
|
public function display_message( $current_view_id = 0 ) { |
629
|
|
|
|
630
|
|
|
if( empty( $_GET['status'] ) || ! self::verify_nonce() ) { |
|
|
|
|
631
|
|
|
return; |
632
|
|
|
} |
633
|
|
|
|
634
|
|
|
// Entry wasn't deleted from current View |
635
|
|
|
if( intval( $_GET['gvid'] ) !== intval( $current_view_id ) ) { |
|
|
|
|
636
|
|
|
return; |
637
|
|
|
} |
638
|
|
|
|
639
|
|
|
$status = esc_attr( $_GET['status'] ); |
|
|
|
|
640
|
|
|
$message_from_url = rgget('message'); |
|
|
|
|
641
|
|
|
$message_from_url = urldecode( stripslashes_deep( $message_from_url ) ); |
642
|
|
|
$class = ''; |
643
|
|
|
|
644
|
|
|
switch ( $status ) { |
645
|
|
|
case 'error': |
646
|
|
|
$class = ' gv-error error'; |
647
|
|
|
$error_message = __('There was an error deleting the entry: %s', 'gravityview'); |
|
|
|
|
648
|
|
|
$message = sprintf( $error_message, $message_from_url ); |
649
|
|
|
break; |
650
|
|
|
case 'trashed': |
651
|
|
|
$message = __('The entry was successfully moved to the trash.', 'gravityview'); |
|
|
|
|
652
|
|
|
break; |
653
|
|
|
default: |
654
|
|
|
$message = __('The entry was successfully deleted.', 'gravityview'); |
|
|
|
|
655
|
|
|
break; |
656
|
|
|
} |
657
|
|
|
|
658
|
|
|
/** |
659
|
|
|
* @filter `gravityview/delete-entry/message` Modify the Delete Entry messages |
660
|
|
|
* @since 1.13.1 |
661
|
|
|
* @param string $message Message to be displayed |
662
|
|
|
* @param string $status Message status (`error` or `success`) |
663
|
|
|
* @param string $message_from_url The original error message, if any, without the "There was an error deleting the entry:" prefix |
664
|
|
|
*/ |
665
|
|
|
$message = apply_filters( 'gravityview/delete-entry/message', esc_attr( $message ), $status, $message_from_url ); |
666
|
|
|
|
667
|
|
|
// DISPLAY ERROR/SUCCESS MESSAGE |
668
|
|
|
echo '<div class="gv-notice' . esc_attr( $class ) .'">'. $message .'</div>'; |
|
|
|
|
669
|
|
|
} |
670
|
|
|
|
671
|
|
|
|
672
|
|
|
} // end class |
673
|
|
|
|
674
|
|
|
GravityView_Delete_Entry::getInstance(); |
675
|
|
|
|
676
|
|
|
|
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.