Completed
Push — develop ( d3c2ad...5bd886 )
by Zack
32:53 queued 30:32
created

GravityView_Entry_Approval::after_submission()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 34

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 11
CRAP Score 3.0052

Importance

Changes 0
Metric Value
cc 3
nc 3
nop 2
dl 0
loc 34
ccs 11
cts 12
cp 0.9167
crap 3.0052
rs 9.376
c 0
b 0
f 0
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() ) {
0 ignored issues
show
Unused Code introduced by
The parameter $form is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
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, $form_id ) {
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 ) {
0 ignored issues
show
Bug introduced by
The expression $entries of type boolean|array is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
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() );
0 ignored issues
show
Deprecated Code introduced by
The method GravityView_View_Data::get_views() has been deprecated.

This method has been deprecated.

Loading history...
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;