|
1
|
|
|
<?php |
|
2
|
|
|
/** |
|
3
|
|
|
* @file class-gravityview-entry-approval.php |
|
4
|
|
|
* @package GravityView |
|
5
|
|
|
* @license GPL2+ |
|
6
|
|
|
* @author Katz Web Services, Inc. |
|
7
|
|
|
* @link https://gravityview.co |
|
8
|
|
|
* @copyright Copyright 2016, Katz Web Services, Inc. |
|
9
|
|
|
* |
|
10
|
|
|
* @since 1.18 |
|
11
|
|
|
*/ |
|
12
|
|
|
|
|
13
|
|
|
/** If this file is called directly, abort. */ |
|
14
|
|
|
if ( ! defined( 'ABSPATH' ) ) { |
|
15
|
|
|
die; |
|
16
|
|
|
} |
|
17
|
|
|
|
|
18
|
|
|
/** |
|
19
|
|
|
* Generate linked list output for a list of entries. |
|
20
|
|
|
* |
|
21
|
|
|
* @since 1.18 |
|
22
|
|
|
*/ |
|
23
|
|
|
class GravityView_Entry_Approval { |
|
24
|
|
|
|
|
25
|
|
|
/** |
|
26
|
|
|
* @var string Key used to store approval status in the Gravity Forms entry meta table |
|
27
|
|
|
*/ |
|
28
|
|
|
const meta_key = 'is_approved'; |
|
29
|
|
|
|
|
30
|
|
|
public function __construct() { |
|
31
|
|
|
$this->add_hooks(); |
|
32
|
|
|
} |
|
33
|
|
|
|
|
34
|
|
|
/** |
|
35
|
|
|
* Add actions and filters related to entry approval |
|
36
|
|
|
* |
|
37
|
|
|
* @return void |
|
38
|
|
|
*/ |
|
39
|
|
|
private function add_hooks() { |
|
40
|
|
|
|
|
41
|
|
|
// in case entry is edited (on admin or frontend) |
|
42
|
|
|
add_action( 'gform_after_update_entry', array( $this, 'after_update_entry_update_approved_meta' ), 10, 2); |
|
43
|
|
|
|
|
44
|
|
|
// when using the User opt-in field, check on entry submission |
|
45
|
|
|
add_action( 'gform_after_submission', array( $this, 'after_submission' ), 10, 2 ); |
|
46
|
|
|
|
|
47
|
|
|
// process ajax approve entry requests |
|
48
|
|
|
add_action('wp_ajax_gv_update_approved', array( $this, 'ajax_update_approved')); |
|
49
|
|
|
|
|
50
|
|
|
// autounapprove |
|
51
|
|
|
add_action( 'gravityview/edit_entry/after_update', array( __CLASS__, 'autounapprove' ), 10, 4 ); |
|
52
|
|
|
|
|
53
|
|
|
add_filter( 'gform_notification_events', array( __CLASS__, 'add_approval_notification_events' ), 10, 2 ); |
|
54
|
|
|
|
|
55
|
|
|
add_action( 'gravityview/approve_entries/approved', array( $this, '_trigger_notifications' ) ); |
|
56
|
|
|
add_action( 'gravityview/approve_entries/disapproved', array( $this, '_trigger_notifications' ) ); |
|
57
|
|
|
add_action( 'gravityview/approve_entries/unapproved', array( $this, '_trigger_notifications' ) ); |
|
58
|
|
|
add_action( 'gravityview/approve_entries/updated', array( $this, '_trigger_notifications' ) ); |
|
59
|
|
|
} |
|
60
|
|
|
|
|
61
|
|
|
/** |
|
62
|
|
|
* Passes approval notification and action hook to the send_notifications method |
|
63
|
|
|
* |
|
64
|
|
|
* @see GravityView_Entry_Approval::send_notifications() |
|
65
|
|
|
* |
|
66
|
|
|
* @internal Developers, do not use! |
|
67
|
|
|
* |
|
68
|
|
|
* @since 2.1 |
|
69
|
|
|
* |
|
70
|
|
|
* @param int $entry_id ID of entry being updated |
|
71
|
|
|
* |
|
72
|
|
|
* @return void |
|
73
|
|
|
*/ |
|
74
|
3 |
|
public function _trigger_notifications( $entry_id = 0 ) { |
|
75
|
3 |
|
$this->_send_notifications( $entry_id, current_action() ); |
|
76
|
3 |
|
} |
|
77
|
|
|
|
|
78
|
|
|
/** |
|
79
|
|
|
* Passes along notification triggers to GFAPI::send_notifications() |
|
80
|
|
|
* |
|
81
|
|
|
* @since 2.1 |
|
82
|
|
|
* |
|
83
|
|
|
* @param int $entry_id ID of entry being updated |
|
84
|
|
|
* @param string $event Hook that triggered the notification. This is used as the key in the GF notifications array. |
|
85
|
|
|
* |
|
86
|
|
|
* @return void |
|
87
|
|
|
*/ |
|
88
|
3 |
|
private function _send_notifications( $entry_id = '', $event = '' ) { |
|
89
|
|
|
|
|
90
|
3 |
|
$entry = GFAPI::get_entry( $entry_id ); |
|
91
|
|
|
|
|
92
|
3 |
|
if ( ! $entry || is_wp_error( $entry ) ) { |
|
93
|
1 |
|
gravityview()->log->error( 'Entry not found at ID #{entry_id}', array( 'entry_id' => $entry_id ) ); |
|
94
|
1 |
|
return; |
|
95
|
|
|
} |
|
96
|
|
|
|
|
97
|
3 |
|
$form = GFAPI::get_form( $entry['form_id'] ); |
|
98
|
|
|
|
|
99
|
3 |
|
if ( ! $form ) { |
|
100
|
|
|
gravityview()->log->error( 'Form not found at ID #{form_id} for entry #{entry_id}', array( 'form_id' => $entry['form_id'], 'entry_id' => $entry_id ) ); |
|
101
|
|
|
return; |
|
102
|
|
|
} |
|
103
|
|
|
|
|
104
|
3 |
|
GFAPI::send_notifications( $form, $entry, $event ); |
|
105
|
3 |
|
} |
|
106
|
|
|
|
|
107
|
|
|
/** |
|
108
|
|
|
* Adds entry approval status change custom notification events |
|
109
|
|
|
* |
|
110
|
|
|
* @since 2.1 |
|
111
|
|
|
* |
|
112
|
|
|
* @param array $notification_events The notification events. |
|
113
|
|
|
* @param array $form The current form. |
|
114
|
|
|
*/ |
|
115
|
1 |
|
public static function add_approval_notification_events( $notification_events = array(), $form = array() ) { |
|
|
|
|
|
|
116
|
|
|
|
|
117
|
1 |
|
$notification_events['gravityview/approve_entries/approved'] = 'GravityView - ' . esc_html_x( 'Entry is approved', 'The title for an event in a notifications drop down list.', 'gravityview' ); |
|
118
|
1 |
|
$notification_events['gravityview/approve_entries/disapproved'] = 'GravityView - ' . esc_html_x( 'Entry is disapproved', 'The title for an event in a notifications drop down list.', 'gravityview' ); |
|
119
|
1 |
|
$notification_events['gravityview/approve_entries/unapproved'] = 'GravityView - ' . esc_html_x( 'Entry approval is reset', 'The title for an event in a notifications drop down list.', 'gravityview' ); |
|
120
|
1 |
|
$notification_events['gravityview/approve_entries/updated'] = 'GravityView - ' . esc_html_x( 'Entry approval is changed', 'The title for an event in a notifications drop down list.', 'gravityview' ); |
|
121
|
|
|
|
|
122
|
1 |
|
return $notification_events; |
|
123
|
|
|
} |
|
124
|
|
|
|
|
125
|
|
|
/** |
|
126
|
|
|
* Get the approval status for an entry |
|
127
|
|
|
* |
|
128
|
|
|
* @since 1.18 |
|
129
|
|
|
* @uses GVCommon::get_entry_id() Accepts entry slug or entry ID |
|
130
|
|
|
* |
|
131
|
|
|
* @param array|int|string $entry Entry array, entry slug, or entry ID |
|
132
|
|
|
* @param string $value_or_label "value" or "label" (default: "label") |
|
133
|
|
|
* |
|
134
|
|
|
* @return bool|string Return the label or value of entry approval |
|
135
|
|
|
*/ |
|
136
|
1 |
|
public static function get_entry_status( $entry, $value_or_label = 'label' ) { |
|
137
|
|
|
|
|
138
|
1 |
|
$entry_id = is_array( $entry ) ? $entry['id'] : GVCommon::get_entry_id( $entry, true ); |
|
139
|
|
|
|
|
140
|
1 |
|
$status = gform_get_meta( $entry_id, self::meta_key ); |
|
141
|
|
|
|
|
142
|
1 |
|
$status = GravityView_Entry_Approval_Status::maybe_convert_status( $status ); |
|
143
|
|
|
|
|
144
|
1 |
|
if( 'value' === $value_or_label ) { |
|
145
|
1 |
|
return $status; |
|
146
|
|
|
} |
|
147
|
|
|
|
|
148
|
|
|
return GravityView_Entry_Approval_Status::get_label( $status ); |
|
149
|
|
|
} |
|
150
|
|
|
|
|
151
|
|
|
/** |
|
152
|
|
|
* Approve/Disapprove entries using the × or ✓ icons in the GF Entries screen |
|
153
|
|
|
* |
|
154
|
|
|
* @uses wp_send_json_error() |
|
155
|
|
|
* @uses wp_send_json_success() |
|
156
|
|
|
* |
|
157
|
|
|
* Expects a $_POST request with the following $_POST keys and values: |
|
158
|
|
|
* |
|
159
|
|
|
* @global array $_POST { |
|
160
|
|
|
* @type int $form_id ID of the form connected to the entry being updated |
|
161
|
|
|
* @type string|int $entry_slug The ID or slug of the entry being updated |
|
162
|
|
|
* @type string $approved The value of the entry approval status {@see GravityView_Entry_Approval_Status::is_valid() } |
|
163
|
|
|
* } |
|
164
|
|
|
* |
|
165
|
|
|
* @return void Prints result using wp_send_json_success() and wp_send_json_error() |
|
166
|
|
|
*/ |
|
167
|
|
|
public function ajax_update_approved() { |
|
168
|
|
|
|
|
169
|
|
|
$form_id = intval( \GV\Utils::_POST( 'form_id' ) ); |
|
170
|
|
|
|
|
171
|
|
|
// We always want requests from the admin to allow entry IDs, but not from the frontend |
|
172
|
|
|
// There's another nonce sent when approving entries in the admin that we check |
|
173
|
|
|
$force_entry_ids = \GV\Utils::_POST( 'admin_nonce' ) && wp_verify_nonce( \GV\Utils::_POST( 'admin_nonce' ), 'gravityview_admin_entry_approval' ); |
|
174
|
|
|
|
|
175
|
|
|
$entry_id = GVCommon::get_entry_id( \GV\Utils::_POST( 'entry_slug' ), $force_entry_ids ); |
|
176
|
|
|
|
|
177
|
|
|
$approval_status = \GV\Utils::_POST( 'approved' ); |
|
178
|
|
|
|
|
179
|
|
|
$nonce = \GV\Utils::_POST( 'nonce' ); |
|
180
|
|
|
|
|
181
|
|
|
// Valid status |
|
182
|
|
|
if( ! GravityView_Entry_Approval_Status::is_valid( $approval_status ) ) { |
|
183
|
|
|
|
|
184
|
|
|
gravityview()->log->error( 'Invalid approval status', array( 'data' => $_POST ) ); |
|
185
|
|
|
|
|
186
|
|
|
$result = new WP_Error( 'invalid_status', __( 'The request was invalid. Refresh the page and try again.', 'gravityview' ) ); |
|
187
|
|
|
|
|
188
|
|
|
} |
|
189
|
|
|
|
|
190
|
|
|
// Valid values |
|
191
|
|
|
elseif ( empty( $entry_id ) || empty( $form_id ) ) { |
|
192
|
|
|
|
|
193
|
|
|
gravityview()->log->error( 'entry_id or form_id are empty.', array( 'data' => $_POST ) ); |
|
194
|
|
|
|
|
195
|
|
|
$result = new WP_Error( 'empty_details', __( 'The request was invalid. Refresh the page and try again.', 'gravityview' ) ); |
|
196
|
|
|
|
|
197
|
|
|
} |
|
198
|
|
|
|
|
199
|
|
|
// Valid nonce |
|
200
|
|
|
else if ( empty( $nonce ) || ! wp_verify_nonce( $nonce, 'gravityview_entry_approval' ) ) { |
|
201
|
|
|
|
|
202
|
|
|
gravityview()->log->error( 'Security check failed.', array( 'data' => $_POST ) ); |
|
203
|
|
|
|
|
204
|
|
|
$result = new WP_Error( 'invalid_nonce', __( 'The request was invalid. Refresh the page and try again.', 'gravityview' ) ); |
|
205
|
|
|
|
|
206
|
|
|
} |
|
207
|
|
|
|
|
208
|
|
|
// Has capability |
|
209
|
|
|
elseif ( ! GVCommon::has_cap( 'gravityview_moderate_entries', $entry_id ) ) { |
|
210
|
|
|
|
|
211
|
|
|
gravityview()->log->error( 'User does not have the `gravityview_moderate_entries` capability.' ); |
|
212
|
|
|
|
|
213
|
|
|
$result = new WP_Error( 'Missing Cap: gravityview_moderate_entries', __( 'You do not have permission to edit this entry.', 'gravityview') ); |
|
214
|
|
|
|
|
215
|
|
|
} |
|
216
|
|
|
|
|
217
|
|
|
// All checks passed |
|
218
|
|
|
else { |
|
219
|
|
|
|
|
220
|
|
|
$result = self::update_approved( $entry_id, $approval_status, $form_id ); |
|
221
|
|
|
|
|
222
|
|
|
} |
|
223
|
|
|
|
|
224
|
|
|
if ( is_wp_error( $result ) ) { |
|
225
|
|
|
gravityview()->log->error( 'Error updating approval: {error}', array( 'error' => $result->get_error_message() ) ); |
|
226
|
|
|
|
|
227
|
|
|
wp_send_json_error( $result ); |
|
228
|
|
|
} |
|
229
|
|
|
|
|
230
|
|
|
$current_status = self::get_entry_status( $entry_id, 'value' ); |
|
231
|
|
|
|
|
232
|
|
|
wp_send_json_success( array( |
|
233
|
|
|
'status' => $current_status |
|
234
|
|
|
) ); |
|
235
|
|
|
} |
|
236
|
|
|
|
|
237
|
|
|
/** |
|
238
|
|
|
* Update the is_approved meta whenever the entry is submitted (and it contains a User Opt-in field) |
|
239
|
|
|
* |
|
240
|
|
|
* @since 1.16.6 |
|
241
|
|
|
* @since 2.0.14 Set the default approval `is_approved` value upon submission |
|
242
|
|
|
* |
|
243
|
|
|
* @param $entry array Gravity Forms entry object |
|
244
|
|
|
* @param $form array Gravity Forms form object |
|
245
|
|
|
*/ |
|
246
|
1 |
|
public function after_submission( $entry, $form ) { |
|
247
|
|
|
|
|
248
|
|
|
/** |
|
249
|
|
|
* @filter `gravityview/approve_entries/after_submission` Modify whether to run the after_submission process |
|
250
|
|
|
* @since 2.3 |
|
251
|
|
|
* @param bool $process_after_submission default: true |
|
252
|
|
|
*/ |
|
253
|
1 |
|
$process_after_submission = apply_filters( 'gravityview/approve_entries/after_submission', true ); |
|
254
|
|
|
|
|
255
|
1 |
|
if ( ! $process_after_submission ) { |
|
256
|
|
|
return; |
|
257
|
|
|
} |
|
258
|
|
|
|
|
259
|
1 |
|
$default_status = GravityView_Entry_Approval_Status::UNAPPROVED; |
|
260
|
|
|
|
|
261
|
|
|
/** |
|
262
|
|
|
* @filter `gravityview/approve_entries/after_submission/default_status` Modify the default approval status for newly submitted entries |
|
263
|
|
|
* @since 2.0.14 |
|
264
|
|
|
* @param int $default_status See GravityView_Entry_Approval_Status() for valid statuses. |
|
265
|
|
|
*/ |
|
266
|
1 |
|
$filtered_status = apply_filters( 'gravityview/approve_entries/after_submission/default_status', $default_status ); |
|
267
|
|
|
|
|
268
|
1 |
|
if ( GravityView_Entry_Approval_Status::is_valid( $filtered_status ) ) { |
|
269
|
1 |
|
$default_status = $filtered_status; |
|
270
|
|
|
} else { |
|
271
|
1 |
|
gravityview()->log->error( 'Invalid approval status returned by `gravityview/approve_entries/after_submission/default_status` filter: {status}', array( 'status' => $filtered_status ) ); |
|
272
|
|
|
} |
|
273
|
|
|
|
|
274
|
|
|
// Set default |
|
275
|
1 |
|
self::update_approved_meta( $entry['id'], $default_status, $entry['form_id'] ); |
|
276
|
|
|
|
|
277
|
|
|
// Then check for if there is an approval column, and use that value instead |
|
278
|
1 |
|
$this->after_update_entry_update_approved_meta( $form , $entry['id'] ); |
|
279
|
1 |
|
} |
|
280
|
|
|
|
|
281
|
|
|
/** |
|
282
|
|
|
* Update the is_approved meta whenever the entry is updated |
|
283
|
|
|
* |
|
284
|
|
|
* @since 1.7.6.1 Was previously named `update_approved_meta` |
|
285
|
|
|
* |
|
286
|
|
|
* @param array $form Gravity Forms form array |
|
287
|
|
|
* @param int $entry_id ID of the Gravity Forms entry |
|
288
|
|
|
* @return void |
|
289
|
|
|
*/ |
|
290
|
21 |
|
public function after_update_entry_update_approved_meta( $form, $entry_id = NULL ) { |
|
291
|
|
|
|
|
292
|
21 |
|
$approved_column = self::get_approved_column( $form['id'] ); |
|
293
|
|
|
|
|
294
|
|
|
/** |
|
295
|
|
|
* If the form doesn't contain the approve field, don't assume anything. |
|
296
|
|
|
*/ |
|
297
|
21 |
|
if( empty( $approved_column ) ) { |
|
298
|
20 |
|
return; |
|
299
|
|
|
} |
|
300
|
|
|
|
|
301
|
1 |
|
$entry = GFAPI::get_entry( $entry_id ); |
|
302
|
|
|
|
|
303
|
|
|
// If the checkbox is blank, it's disapproved, regardless of the label |
|
304
|
1 |
|
if ( '' === \GV\Utils::get( $entry, $approved_column ) ) { |
|
305
|
1 |
|
$value = GravityView_Entry_Approval_Status::DISAPPROVED; |
|
306
|
|
|
} else { |
|
307
|
|
|
// If the checkbox is not blank, it's approved |
|
308
|
1 |
|
$value = GravityView_Entry_Approval_Status::APPROVED; |
|
309
|
|
|
} |
|
310
|
|
|
|
|
311
|
|
|
/** |
|
312
|
|
|
* @filter `gravityview/approve_entries/update_unapproved_meta` Filter the approval status on entry update. |
|
313
|
|
|
* @param[in,out] string $value The approval status. |
|
314
|
|
|
* @param array $form The form. |
|
315
|
|
|
* @param array $entry The entry. |
|
316
|
|
|
*/ |
|
317
|
1 |
|
$value = apply_filters( 'gravityview/approve_entries/update_unapproved_meta', $value, $form, $entry ); |
|
318
|
|
|
|
|
319
|
1 |
|
self::update_approved_meta( $entry_id, $value, $form['id'] ); |
|
320
|
1 |
|
} |
|
321
|
|
|
|
|
322
|
|
|
/** |
|
323
|
|
|
* Process a bulk of entries to update the approve field/property |
|
324
|
|
|
* |
|
325
|
|
|
* @since 1.18 Moved to GravityView_Entry_Approval |
|
326
|
|
|
* @since 1.18 Made public |
|
327
|
|
|
* |
|
328
|
|
|
* @access public |
|
329
|
|
|
* @static |
|
330
|
|
|
* @param array|boolean $entries If array, array of entry IDs that are to be updated. If true: update all entries. |
|
331
|
|
|
* @param int $approved Approved status. If `0`: unapproved, if not empty, `Approved` |
|
332
|
|
|
* @param int $form_id The Gravity Forms Form ID |
|
333
|
|
|
* @return boolean|null True: successfully updated all entries. False: there was an error updating at least one entry. NULL: an error occurred (see log) |
|
334
|
|
|
*/ |
|
335
|
1 |
|
public static function update_bulk( $entries = array(), $approved = 0, $form_id = 0 ) { |
|
336
|
|
|
|
|
337
|
1 |
|
if( empty($entries) || ( $entries !== true && !is_array($entries) ) ) { |
|
338
|
|
|
gravityview()->log->error( 'Entries were empty or malformed.', array( 'data' => $entries ) ); |
|
339
|
|
|
return NULL; |
|
340
|
|
|
} |
|
341
|
|
|
|
|
342
|
1 |
|
if( ! GVCommon::has_cap( 'gravityview_moderate_entries' ) ) { |
|
343
|
1 |
|
gravityview()->log->error( 'User does not have the `gravityview_moderate_entries` capability.' ); |
|
344
|
1 |
|
return NULL; |
|
345
|
|
|
} |
|
346
|
|
|
|
|
347
|
|
|
|
|
348
|
1 |
|
if ( ! GravityView_Entry_Approval_Status::is_valid( $approved ) ) { |
|
349
|
|
|
gravityview()->log->error( 'Invalid approval status', array( 'data' => $approved ) ); |
|
350
|
|
|
return NULL; |
|
351
|
|
|
} |
|
352
|
|
|
|
|
353
|
|
|
// calculate approved field id once instead of looping through in the update_approved() method |
|
354
|
1 |
|
$approved_column_id = self::get_approved_column( $form_id ); |
|
355
|
|
|
|
|
356
|
1 |
|
$success = true; |
|
357
|
1 |
|
foreach( $entries as $entry_id ) { |
|
|
|
|
|
|
358
|
1 |
|
$update_success = self::update_approved( (int)$entry_id, $approved, $form_id, $approved_column_id ); |
|
359
|
|
|
|
|
360
|
1 |
|
if( ! $update_success ) { |
|
361
|
1 |
|
$success = false; |
|
362
|
|
|
} |
|
363
|
|
|
} |
|
364
|
|
|
|
|
365
|
1 |
|
return $success; |
|
366
|
|
|
} |
|
367
|
|
|
|
|
368
|
|
|
/** |
|
369
|
|
|
* update_approved function. |
|
370
|
|
|
* |
|
371
|
|
|
* @since 1.18 Moved to GravityView_Entry_Approval class |
|
372
|
|
|
* |
|
373
|
|
|
* @access public |
|
374
|
|
|
* @static |
|
375
|
|
|
* @param int $entry_id (default: 0) |
|
376
|
|
|
* @param int $approved (default: 2) |
|
377
|
|
|
* @param int $form_id (default: 0) |
|
378
|
|
|
* @param int $approvedcolumn (default: 0) |
|
379
|
|
|
* |
|
380
|
|
|
* @return boolean True: It worked; False: it failed |
|
381
|
|
|
*/ |
|
382
|
2 |
|
public static function update_approved( $entry_id = 0, $approved = 2, $form_id = 0, $approvedcolumn = 0 ) { |
|
383
|
|
|
|
|
384
|
2 |
|
if( !class_exists( 'GFAPI' ) ) { |
|
385
|
|
|
gravityview()->log->error( 'GFAPI does not exist' ); |
|
386
|
|
|
return false; |
|
387
|
|
|
} |
|
388
|
|
|
|
|
389
|
2 |
|
if( ! GravityView_Entry_Approval_Status::is_valid( $approved ) ) { |
|
390
|
|
|
gravityview()->log->error( 'Not a valid approval value.' ); |
|
391
|
|
|
return false; |
|
392
|
|
|
} |
|
393
|
|
|
|
|
394
|
2 |
|
$approved = GravityView_Entry_Approval_Status::maybe_convert_status( $approved ); |
|
395
|
|
|
|
|
396
|
2 |
|
$entry = GFAPI::get_entry( $entry_id ); |
|
397
|
|
|
|
|
398
|
2 |
|
if ( is_wp_error( $entry ) ) { |
|
399
|
1 |
|
gravityview()->log->error( 'Entry does not exist' ); |
|
400
|
1 |
|
return false; |
|
401
|
|
|
} |
|
402
|
|
|
|
|
403
|
|
|
// If the form has an Approve/Reject field, update that value |
|
404
|
2 |
|
$result = self::update_approved_column( $entry_id, $approved, $form_id, $approvedcolumn ); |
|
405
|
|
|
|
|
406
|
2 |
|
if( is_wp_error( $result ) ) { |
|
407
|
|
|
gravityview()->log->error( 'Entry approval not updated: {error}', array( 'error' => $result->get_error_message() ) ); |
|
408
|
|
|
return false; |
|
409
|
|
|
} |
|
410
|
|
|
|
|
411
|
2 |
|
$form_id = intval( $form_id ); |
|
412
|
|
|
|
|
413
|
|
|
// Update the entry meta |
|
414
|
2 |
|
self::update_approved_meta( $entry_id, $approved, $form_id ); |
|
415
|
|
|
|
|
416
|
|
|
// add note to entry if approval field updating worked or there was no approved field |
|
417
|
|
|
// There's no validation for the meta |
|
418
|
2 |
|
if( true === $result ) { |
|
419
|
|
|
|
|
420
|
|
|
// Add an entry note |
|
421
|
2 |
|
self::add_approval_status_updated_note( $entry_id, $approved ); |
|
422
|
|
|
|
|
423
|
|
|
/** |
|
424
|
|
|
* Destroy the cache for this form |
|
425
|
|
|
* @see class-cache.php |
|
426
|
|
|
* @since 1.5.1 |
|
427
|
|
|
*/ |
|
428
|
2 |
|
do_action( 'gravityview_clear_form_cache', $form_id ); |
|
429
|
|
|
|
|
430
|
|
|
} |
|
431
|
|
|
|
|
432
|
2 |
|
return $result; |
|
433
|
|
|
} |
|
434
|
|
|
|
|
435
|
|
|
/** |
|
436
|
|
|
* Add a note when an entry is approved |
|
437
|
|
|
* |
|
438
|
|
|
* @see GravityView_Entry_Approval::update_approved |
|
439
|
|
|
* |
|
440
|
|
|
* @since 1.18 |
|
441
|
|
|
* |
|
442
|
|
|
* @param int $entry_id Gravity Forms entry ID |
|
443
|
|
|
* @param int $approved Approval status |
|
444
|
|
|
* |
|
445
|
|
|
* @return false|int|WP_Error Note ID if successful; WP_Error if error when adding note, FALSE if note not updated because of `gravityview/approve_entries/add-note` filter or `GravityView_Entry_Notes` class not existing |
|
446
|
|
|
*/ |
|
447
|
2 |
|
private static function add_approval_status_updated_note( $entry_id, $approved = 0 ) { |
|
448
|
2 |
|
$note = ''; |
|
449
|
|
|
|
|
450
|
2 |
|
switch ( $approved ) { |
|
451
|
|
|
case GravityView_Entry_Approval_Status::APPROVED: |
|
452
|
1 |
|
$note = __( 'Approved the Entry for GravityView', 'gravityview' ); |
|
453
|
1 |
|
break; |
|
454
|
|
|
case GravityView_Entry_Approval_Status::UNAPPROVED: |
|
455
|
|
|
$note = __( 'Reset Entry approval for GravityView', 'gravityview' ); |
|
456
|
|
|
break; |
|
457
|
|
|
case GravityView_Entry_Approval_Status::DISAPPROVED: |
|
458
|
1 |
|
$note = __( 'Disapproved the Entry for GravityView', 'gravityview' ); |
|
459
|
1 |
|
break; |
|
460
|
|
|
} |
|
461
|
|
|
|
|
462
|
|
|
/** |
|
463
|
|
|
* @filter `gravityview/approve_entries/add-note` Add a note when the entry has been approved or disapproved? |
|
464
|
|
|
* @since 1.16.3 |
|
465
|
|
|
* @param bool $add_note True: Yep, add that note! False: Do not, under any circumstances, add that note! |
|
466
|
|
|
*/ |
|
467
|
2 |
|
$add_note = apply_filters( 'gravityview/approve_entries/add-note', true ); |
|
468
|
|
|
|
|
469
|
2 |
|
$note_id = false; |
|
470
|
|
|
|
|
471
|
2 |
|
if( $add_note && class_exists( 'GravityView_Entry_Notes' ) ) { |
|
472
|
|
|
|
|
473
|
2 |
|
$current_user = wp_get_current_user(); |
|
474
|
|
|
|
|
475
|
2 |
|
$note_id = GravityView_Entry_Notes::add_note( $entry_id, $current_user->ID, $current_user->display_name, $note ); |
|
476
|
|
|
} |
|
477
|
|
|
|
|
478
|
2 |
|
return $note_id; |
|
479
|
|
|
} |
|
480
|
|
|
|
|
481
|
|
|
/** |
|
482
|
|
|
* Update the Approve/Disapproved field value |
|
483
|
|
|
* |
|
484
|
|
|
* @param int $entry_id ID of the Gravity Forms entry |
|
485
|
|
|
* @param string $status String whether entry is approved or not. `0` for not approved, `Approved` for approved. |
|
486
|
|
|
* @param int $form_id ID of the form of the entry being updated. Improves query performance. |
|
487
|
|
|
* @param string $approvedcolumn Gravity Forms Field ID |
|
488
|
|
|
* |
|
489
|
|
|
* @return true|WP_Error |
|
490
|
|
|
*/ |
|
491
|
1 |
|
private static function update_approved_column( $entry_id = 0, $status = '0', $form_id = 0, $approvedcolumn = 0 ) { |
|
492
|
|
|
|
|
493
|
1 |
|
if( empty( $approvedcolumn ) ) { |
|
494
|
1 |
|
$approvedcolumn = self::get_approved_column( $form_id ); |
|
495
|
|
|
} |
|
496
|
|
|
|
|
497
|
1 |
|
if ( empty( $approvedcolumn ) ) { |
|
498
|
1 |
|
return true; |
|
499
|
|
|
} |
|
500
|
|
|
|
|
501
|
|
|
if ( ! GravityView_Entry_Approval_Status::is_valid( $status ) ) { |
|
502
|
|
|
return new WP_Error( 'invalid_status', 'Invalid entry approval status', $status ); |
|
503
|
|
|
} |
|
504
|
|
|
|
|
505
|
|
|
//get the entry |
|
506
|
|
|
$entry = GFAPI::get_entry( $entry_id ); |
|
507
|
|
|
|
|
508
|
|
|
// Entry doesn't exist |
|
509
|
|
|
if ( is_wp_error( $entry ) ) { |
|
510
|
|
|
return $entry; |
|
511
|
|
|
} |
|
512
|
|
|
|
|
513
|
|
|
$status = GravityView_Entry_Approval_Status::maybe_convert_status( $status ); |
|
514
|
|
|
|
|
515
|
|
|
$new_value = ''; |
|
516
|
|
|
if( GravityView_Entry_Approval_Status::APPROVED === $status ) { |
|
517
|
|
|
$new_value = self::get_approved_column_input_label( $form_id, $approvedcolumn ); |
|
518
|
|
|
} |
|
519
|
|
|
|
|
520
|
|
|
//update entry |
|
521
|
|
|
$entry["{$approvedcolumn}"] = $new_value; |
|
522
|
|
|
|
|
523
|
|
|
/** |
|
524
|
|
|
* Note: GFAPI::update_entry() doesn't trigger `gform_after_update_entry`, so we trigger updating the meta ourselves |
|
525
|
|
|
* @see GravityView_Entry_Approval::after_update_entry_update_approved_meta |
|
526
|
|
|
* @var true|WP_Error $result |
|
527
|
|
|
*/ |
|
528
|
|
|
$result = GFAPI::update_entry( $entry ); |
|
529
|
|
|
|
|
530
|
|
|
return $result; |
|
531
|
|
|
} |
|
532
|
|
|
|
|
533
|
|
|
/** |
|
534
|
|
|
* Get the value for the approved field checkbox |
|
535
|
|
|
* |
|
536
|
|
|
* When approving a field via the entry meta, use the correct value for the new approved column input |
|
537
|
|
|
* |
|
538
|
|
|
* @since 1.19 |
|
539
|
|
|
* |
|
540
|
|
|
* @param array|int $form Form ID or form array |
|
541
|
|
|
* @param string $approved_column Approved column field ID |
|
542
|
|
|
* |
|
543
|
|
|
* @return string|null |
|
544
|
|
|
*/ |
|
545
|
|
|
private static function get_approved_column_input_label( $form, $approved_column ) { |
|
546
|
|
|
|
|
547
|
|
|
$field = gravityview_get_field( $form, $approved_column ); |
|
548
|
|
|
|
|
549
|
|
|
// If the user has enabled a different value than the label (for some reason), use it. |
|
550
|
|
|
// This is highly unlikely |
|
551
|
|
|
if ( is_array( $field->choices ) && ! empty( $field->choices ) ) { |
|
552
|
|
|
return isset( $field->choices[0]['value'] ) ? $field->choices[0]['value'] : $field->choices[0]['text']; |
|
553
|
|
|
} |
|
554
|
|
|
|
|
555
|
|
|
// Otherwise, fall back on the inputs array |
|
556
|
|
|
if ( is_array( $field->inputs ) && ! empty( $field->inputs ) ) { |
|
557
|
|
|
return $field->inputs[0]['label']; |
|
558
|
|
|
} |
|
559
|
|
|
|
|
560
|
|
|
return null; |
|
561
|
|
|
} |
|
562
|
|
|
|
|
563
|
|
|
/** |
|
564
|
|
|
* Update the `is_approved` entry meta value |
|
565
|
|
|
* |
|
566
|
|
|
* @since 1.7.6.1 `after_update_entry_update_approved_meta` was previously to be named `update_approved_meta` |
|
567
|
|
|
* @since 1.17.1 Added $form_id parameter |
|
568
|
|
|
* |
|
569
|
|
|
* @param int $entry_id ID of the Gravity Forms entry |
|
570
|
|
|
* @param string $status String whether entry is approved or not. `0` for not approved, `Approved` for approved. |
|
571
|
|
|
* @param int $form_id ID of the form of the entry being updated. Improves query performance. |
|
572
|
|
|
* |
|
573
|
|
|
* @return void |
|
574
|
|
|
*/ |
|
575
|
2 |
|
private static function update_approved_meta( $entry_id, $status, $form_id = 0 ) { |
|
576
|
|
|
|
|
577
|
2 |
|
if ( ! GravityView_Entry_Approval_Status::is_valid( $status ) ) { |
|
578
|
|
|
gravityview()->log->error( '$is_approved not valid value', array( 'data' => $status ) ); |
|
579
|
|
|
return; |
|
580
|
|
|
} |
|
581
|
|
|
|
|
582
|
2 |
|
if ( ! function_exists( 'gform_update_meta' ) ) { |
|
583
|
|
|
gravityview()->log->error( '`gform_update_meta` does not exist.' ); |
|
584
|
|
|
return; |
|
585
|
|
|
} |
|
586
|
|
|
|
|
587
|
2 |
|
$status = GravityView_Entry_Approval_Status::maybe_convert_status( $status ); |
|
588
|
|
|
|
|
589
|
|
|
// update entry meta |
|
590
|
2 |
|
gform_update_meta( $entry_id, self::meta_key, $status, $form_id ); |
|
591
|
|
|
|
|
592
|
|
|
/** |
|
593
|
|
|
* @action `gravityview/approve_entries/updated` Triggered when an entry approval is updated |
|
594
|
|
|
* @since 1.7.6.1 |
|
595
|
|
|
* @param int $entry_id ID of the Gravity Forms entry |
|
596
|
|
|
* @param string|int $status String whether entry is approved or not. See GravityView_Entry_Approval_Status for valid statuses. |
|
597
|
|
|
*/ |
|
598
|
2 |
|
do_action( 'gravityview/approve_entries/updated', $entry_id, $status ); |
|
599
|
|
|
|
|
600
|
2 |
|
$action = GravityView_Entry_Approval_Status::get_key( $status ); |
|
601
|
|
|
|
|
602
|
|
|
/** |
|
603
|
|
|
* @action `gravityview/approve_entries/{$action}` Triggered when an entry approval is set. {$action} can be 'approved', 'unapproved', or 'disapproved' |
|
604
|
|
|
* Note: If you want this to work with Bulk Actions, run in a plugin rather than a theme; the bulk updates hook runs before themes are loaded. |
|
605
|
|
|
* @since 1.7.6.1 |
|
606
|
|
|
* @since 1.18 Added "unapproved" |
|
607
|
|
|
* @param int $entry_id ID of the Gravity Forms entry |
|
608
|
|
|
*/ |
|
609
|
2 |
|
do_action( 'gravityview/approve_entries/' . $action , $entry_id ); |
|
610
|
2 |
|
} |
|
611
|
|
|
|
|
612
|
|
|
/** |
|
613
|
|
|
* Calculate the approve field.input id |
|
614
|
|
|
* |
|
615
|
|
|
* @access public |
|
616
|
|
|
* @static |
|
617
|
|
|
* @param mixed $form GF Form or Form ID |
|
618
|
|
|
* @return false|null|string Returns the input ID of the approved field. Returns NULL if no approved fields were found. Returns false if $form_id wasn't set. |
|
619
|
|
|
*/ |
|
620
|
22 |
|
static public function get_approved_column( $form ) { |
|
621
|
|
|
|
|
622
|
22 |
|
if( empty( $form ) ) { |
|
623
|
1 |
|
return null; |
|
624
|
|
|
} |
|
625
|
|
|
|
|
626
|
21 |
|
if( !is_array( $form ) ) { |
|
627
|
21 |
|
$form = GVCommon::get_form( $form ); |
|
628
|
|
|
} |
|
629
|
|
|
|
|
630
|
21 |
|
$approved_column_id = null; |
|
631
|
|
|
|
|
632
|
|
|
/** |
|
633
|
|
|
* @var string $key |
|
634
|
|
|
* @var GF_Field $field |
|
635
|
|
|
*/ |
|
636
|
21 |
|
foreach( $form['fields'] as $key => $field ) { |
|
637
|
|
|
|
|
638
|
21 |
|
$inputs = $field->get_entry_inputs(); |
|
639
|
|
|
|
|
640
|
21 |
|
if( !empty( $field->gravityview_approved ) ) { |
|
641
|
1 |
|
if ( ! empty( $inputs ) && !empty( $inputs[0]['id'] ) ) { |
|
642
|
1 |
|
$approved_column_id = $inputs[0]['id']; |
|
643
|
1 |
|
break; |
|
644
|
|
|
} |
|
645
|
|
|
} |
|
646
|
|
|
|
|
647
|
|
|
// Note: This is just for backward compatibility from GF Directory plugin and old GV versions - when using i18n it may not work.. |
|
648
|
21 |
|
if( 'checkbox' === $field->type && ! empty( $inputs ) ) { |
|
649
|
2 |
|
foreach ( $inputs as $input ) { |
|
650
|
2 |
|
if ( 'approved' === strtolower( $input['label'] ) ) { |
|
651
|
|
|
$approved_column_id = $input['id']; |
|
652
|
|
|
break; |
|
653
|
|
|
} |
|
654
|
|
|
} |
|
655
|
|
|
} |
|
656
|
|
|
} |
|
657
|
|
|
|
|
658
|
21 |
|
return $approved_column_id; |
|
659
|
|
|
} |
|
660
|
|
|
|
|
661
|
|
|
/** |
|
662
|
|
|
* Maybe unapprove entry on edit. |
|
663
|
|
|
* |
|
664
|
|
|
* Called from gravityview/edit_entry/after_update |
|
665
|
|
|
* |
|
666
|
|
|
* @param array $form Gravity Forms form array |
|
667
|
|
|
* @param string $entry_id Numeric ID of the entry that was updated |
|
668
|
|
|
* @param GravityView_Edit_Entry_Render $edit This object |
|
669
|
|
|
* @param GravityView_View_Data $gv_data The View data |
|
670
|
|
|
* |
|
671
|
|
|
* @return void |
|
672
|
|
|
*/ |
|
673
|
22 |
|
public static function autounapprove( $form, $entry_id, $edit, $gv_data ) { |
|
674
|
|
|
|
|
675
|
22 |
|
$view_keys = array_keys( $gv_data->get_views() ); |
|
|
|
|
|
|
676
|
|
|
|
|
677
|
22 |
|
$view = \GV\View::by_id( $view_keys[0] ); |
|
678
|
|
|
|
|
679
|
22 |
|
if ( ! $view->settings->get( 'unapprove_edit' ) ) { |
|
680
|
22 |
|
return; |
|
681
|
|
|
} |
|
682
|
|
|
|
|
683
|
1 |
|
if ( GVCommon::has_cap( 'gravityview_moderate_entries' ) ) { |
|
684
|
1 |
|
return; |
|
685
|
|
|
} |
|
686
|
|
|
|
|
687
|
|
|
/** |
|
688
|
|
|
* @filter `gravityview/approve_entries/autounapprove/status` |
|
689
|
|
|
* @since 2.2.2 |
|
690
|
|
|
* @param[in,out] int|false $approval_status Approval status integer, or false if you want to not update status. Use GravityView_Entry_Approval_Status constants. Default: 3 (GravityView_Entry_Approval_Status::UNAPPROVED) |
|
691
|
|
|
* @param array $form Gravity Forms form array |
|
692
|
|
|
* @param string $entry_id Numeric ID of the entry that was updated |
|
693
|
|
|
* @param \GV\View $view Current View where the entry was edited |
|
694
|
|
|
*/ |
|
695
|
1 |
|
$approval_status = apply_filters( 'gravityview/approve_entries/autounapprove/status', GravityView_Entry_Approval_Status::UNAPPROVED, $form, $entry_id, $view ); |
|
696
|
|
|
|
|
697
|
|
|
// Allow returning false to exit |
|
698
|
1 |
|
if ( false === $approval_status ) { |
|
699
|
|
|
return; |
|
700
|
|
|
} |
|
701
|
|
|
|
|
702
|
1 |
|
if( ! GravityView_Entry_Approval_Status::is_valid( $approval_status ) ) { |
|
703
|
|
|
$approval_status = GravityView_Entry_Approval_Status::UNAPPROVED; |
|
704
|
|
|
} |
|
705
|
|
|
|
|
706
|
1 |
|
self::update_approved_meta( $entry_id, $approval_status, $form['id'] ); |
|
707
|
1 |
|
} |
|
708
|
|
|
|
|
709
|
|
|
/** |
|
710
|
|
|
* Where should the popover be placed? |
|
711
|
|
|
* |
|
712
|
|
|
* @since 2.3.1 |
|
713
|
|
|
* |
|
714
|
|
|
* @return string Where to place the popover; 'right' (default ltr), 'left' (default rtl), 'top', or 'bottom' |
|
715
|
|
|
*/ |
|
716
|
1 |
|
public static function get_popover_placement() { |
|
717
|
|
|
|
|
718
|
1 |
|
$placement = is_rtl() ? 'left' : 'right'; |
|
719
|
|
|
|
|
720
|
|
|
/** |
|
721
|
|
|
* @filter `gravityview/approve_entries/popover_placement` Where should the popover be placed? |
|
722
|
|
|
* @since 2.3.1 |
|
723
|
|
|
* @param string $placement Where to place the popover; 'right' (default ltr), 'left' (default rtl), 'top', or 'bottom' |
|
724
|
|
|
*/ |
|
725
|
1 |
|
$placement = apply_filters( 'gravityview/approve_entries/popover_placement', $placement ); |
|
726
|
|
|
|
|
727
|
1 |
|
return $placement; |
|
728
|
|
|
} |
|
729
|
|
|
|
|
730
|
|
|
/** |
|
731
|
|
|
* Get HTML template for a popover used to display approval statuses |
|
732
|
|
|
* |
|
733
|
|
|
* @since 2.3.1 |
|
734
|
|
|
* |
|
735
|
|
|
* @internal For internal use only! |
|
736
|
|
|
* |
|
737
|
|
|
* @return string HTML code |
|
738
|
|
|
*/ |
|
739
|
1 |
|
public static function get_popover_template() { |
|
740
|
|
|
|
|
741
|
1 |
|
$choices = GravityView_Entry_Approval_Status::get_all(); |
|
742
|
|
|
|
|
743
|
|
|
return <<<TEMPLATE |
|
744
|
1 |
|
<a href="#" data-approved="{$choices['approved']['value']}" aria-role="button" aria-live="polite" class="gv-approval-toggle gv-approval-approved popover" title="{$choices['approved']['action']}"><span class="screen-reader-text">{$choices['approved']['action']}</span></a> |
|
745
|
1 |
|
<a href="#" data-approved="{$choices['disapproved']['value']}" aria-role="button" aria-live="polite" class="gv-approval-toggle gv-approval-disapproved popover" title="{$choices['disapproved']['action']}"><span class="screen-reader-text">{$choices['disapproved']['action']}</span></a> |
|
746
|
1 |
|
<a href="#" data-approved="{$choices['unapproved']['value']}" aria-role="button" aria-live="polite" class="gv-approval-toggle gv-approval-unapproved popover" title="{$choices['unapproved']['action']}"><span class="screen-reader-text">{$choices['unapproved']['action']}</span></a> |
|
747
|
|
|
TEMPLATE; |
|
748
|
|
|
} |
|
749
|
|
|
} |
|
750
|
|
|
|
|
751
|
|
|
new GravityView_Entry_Approval; |
This check looks from parameters that have been defined for a function or method, but which are not used in the method body.