Completed
Push — ignore/lazy-images-linting-pac... ( 3c044f...b5c515 )
by Jeremy
367:06 queued 352:42
created

admin.php ➔ grunion_manage_post_columns()   F

Complexity

Conditions 21
Paths 787

Size

Total Lines 220

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 21
nc 787
nop 2
dl 0
loc 220
rs 0.2366
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
use Automattic\Jetpack\Assets;
4
5
/**
6
 * Add a contact form button to the post composition screen
7
 */
8
add_action( 'media_buttons', 'grunion_media_button', 999 );
9
function grunion_media_button() {
10
	global $post_ID, $temp_ID, $pagenow;
11
12
	if ( 'press-this.php' === $pagenow ) {
13
		return;
14
	}
15
16
	$iframe_post_id = (int) ( 0 == $post_ID ? $temp_ID : $post_ID );
17
	$title          = __( 'Add Contact Form', 'jetpack' );
18
	$plugin_url     = esc_url( GRUNION_PLUGIN_URL );
0 ignored issues
show
Unused Code introduced by
$plugin_url is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
19
	$site_url       = esc_url( admin_url( "/admin-ajax.php?post_id={$iframe_post_id}&action=grunion_form_builder&TB_iframe=true&width=768" ) );
20
	?>
21
22
	<a id="insert-jetpack-contact-form" class="button thickbox" title="<?php echo esc_attr( $title ); ?>" data-editor="content" href="<?php echo $site_url; ?>&id=add_form">
23
		<span class="jetpack-contact-form-icon"></span> <?php echo esc_html( $title ); ?>
24
	</a>
25
26
	<?php
27
}
28
29
add_action( 'wp_ajax_grunion_form_builder', 'grunion_display_form_view' );
30
31
function grunion_display_form_view() {
32
	if ( current_user_can( 'edit_posts' ) ) {
33
		require_once GRUNION_PLUGIN_DIR . 'grunion-form-view.php';
34
	}
35
	exit;
36
}
37
38
// feedback specific css items
39
add_action( 'admin_print_styles', 'grunion_admin_css' );
40
function grunion_admin_css() {
41
	global $current_screen;
42
	if ( is_null( $current_screen ) ) {
43
		return;
44
	}
45
	if ( 'edit-feedback' !== $current_screen->id ) {
46
		return;
47
	}
48
49
	wp_enqueue_script( 'wp-lists' );
50
?>
51
52
<style type='text/css'>
53
.add-new-h2, .view-switch, body.no-js .tablenav select[name^=action], body.no-js #doaction, body.no-js #doaction2 {
54
	display: none
55
}
56
57
.column-feedback_from img {
58
	float:left;
59
	margin-right:10px;
60
	margin-top:3px;
61
}
62
63
.widefat .column-feedback_from {
64
	width: 17%;
65
}
66
.widefat .column-feedback_date {
67
	width: 17%;
68
}
69
70
.spam a {
71
	color: #BC0B0B;
72
}
73
74
.untrash a {
75
	color: #D98500;
76
}
77
78
.unspam a {
79
color: #D98500;
80
}
81
82
</style>
83
84
<?php
85
}
86
87
/**
88
 * Hack a 'Bulk Spam' option for bulk edit in other than spam view
89
 * Hack a 'Bulk Delete' option for bulk edit in spam view
90
 *
91
 * There isn't a better way to do this until
92
 * https://core.trac.wordpress.org/changeset/17297 is resolved
93
 */
94
add_action( 'admin_head', 'grunion_add_bulk_edit_option' );
95
function grunion_add_bulk_edit_option() {
96
97
	$screen = get_current_screen();
98
99
	if ( is_null( $screen ) ) {
100
		return;
101
	}
102
103
	if ( 'edit-feedback' != $screen->id ) {
104
		return;
105
	}
106
107
	// When viewing spam we want to be able to be able to bulk delete
108
	// When viewing anything we want to be able to bulk move to spam
109
	if ( isset( $_GET['post_status'] ) && 'spam' == $_GET['post_status'] ) {
110
		// Create Delete Permanently bulk item
111
		$option_val      = 'delete';
112
		$option_txt      = __( 'Delete Permanently', 'jetpack' );
113
		$pseudo_selector = 'last-child';
114
115
	} else {
116
		// Create Mark Spam bulk item
117
		$option_val      = 'spam';
118
		$option_txt      = __( 'Mark as Spam', 'jetpack' );
119
		$pseudo_selector = 'first-child';
120
	}
121
122
	?>
123
		<script type="text/javascript">
124
			jQuery(document).ready(function($) {
125
				$('#posts-filter .actions select').filter('[name=action], [name=action2]').find('option:<?php echo $pseudo_selector; ?>').after('<option value="<?php echo $option_val; ?>"><?php echo esc_attr( $option_txt ); ?></option>' );
126
			})
127
		</script>
128
	<?php
129
}
130
131
/**
132
 * Handle a bulk spam report
133
 */
134
add_action( 'admin_init', 'grunion_handle_bulk_spam' );
135
function grunion_handle_bulk_spam() {
136
	global $pagenow;
137
138
	if ( 'edit.php' != $pagenow
139
	|| ( empty( $_REQUEST['post_type'] ) || 'feedback' != $_REQUEST['post_type'] ) ) {
140
		return;
141
	}
142
143
	// Slip in a success message
144
	if ( ! empty( $_REQUEST['message'] ) && 'marked-spam' == $_REQUEST['message'] ) {
145
		add_action( 'admin_notices', 'grunion_message_bulk_spam' );
146
	}
147
148
	if ( ( empty( $_REQUEST['action'] ) || 'spam' != $_REQUEST['action'] ) && ( empty( $_REQUEST['action2'] ) || 'spam' != $_REQUEST['action2'] ) ) {
149
		return;
150
	}
151
152
	check_admin_referer( 'bulk-posts' );
153
154
	if ( empty( $_REQUEST['post'] ) ) {
155
		wp_safe_redirect( wp_get_referer() );
156
		exit;
157
	}
158
159
	$post_ids = array_map( 'intval', $_REQUEST['post'] );
160
161
	foreach ( $post_ids as $post_id ) {
162
		if ( ! current_user_can( 'edit_page', $post_id ) ) {
163
			wp_die( __( 'You are not allowed to manage this item.', 'jetpack' ) );
164
		}
165
166
		$post           = array(
167
			'ID'          => $post_id,
168
			'post_status' => 'spam',
169
		);
170
		$akismet_values = get_post_meta( $post_id, '_feedback_akismet_values', true );
171
		wp_update_post( $post );
172
173
		/**
174
		 * Fires after a comment has been marked by Akismet.
175
		 *
176
		 * Typically this means the comment is spam.
177
		 *
178
		 * @module contact-form
179
		 *
180
		 * @since 2.2.0
181
		 *
182
		 * @param string $comment_status Usually is 'spam', otherwise 'ham'.
183
		 * @param array $akismet_values From '_feedback_akismet_values' in comment meta
184
		 */
185
		do_action( 'contact_form_akismet', 'spam', $akismet_values );
186
	}
187
188
	$redirect_url = add_query_arg( 'message', 'marked-spam', wp_get_referer() );
189
	wp_safe_redirect( $redirect_url );
190
	exit;
191
}
192
193
function grunion_message_bulk_spam() {
194
	echo '<div class="updated"><p>' . __( 'Feedback(s) marked as spam', 'jetpack' ) . '</p></div>';
195
}
196
197
// remove admin UI parts that we don't support in feedback management
198
add_action( 'admin_menu', 'grunion_admin_menu' );
199
function grunion_admin_menu() {
200
	global $menu, $submenu;
201
	unset( $submenu['edit.php?post_type=feedback'] );
202
}
203
204
add_filter( 'bulk_actions-edit-feedback', 'grunion_admin_bulk_actions' );
205
function grunion_admin_bulk_actions( $actions ) {
206
	global $current_screen;
207
	if ( 'edit-feedback' != $current_screen->id ) {
208
		return $actions;
209
	}
210
211
	unset( $actions['edit'] );
212
	return $actions;
213
}
214
215
add_filter( 'views_edit-feedback', 'grunion_admin_view_tabs' );
216
function grunion_admin_view_tabs( $views ) {
217
	global $current_screen;
218
	if ( 'edit-feedback' != $current_screen->id ) {
219
		return $views;
220
	}
221
222
	unset( $views['publish'] );
223
224
	preg_match( '|post_type=feedback\'( class="current")?\>(.*)\<span class=|', $views['all'], $match );
225
	if ( ! empty( $match[2] ) ) {
226
		$views['all'] = str_replace( $match[2], __( 'Messages', 'jetpack' ) . ' ', $views['all'] );
227
	}
228
229
	return $views;
230
}
231
232
add_filter( 'manage_feedback_posts_columns', 'grunion_post_type_columns_filter' );
233
function grunion_post_type_columns_filter( $cols ) {
234
	$cols = array(
235
		'cb'               => '<input type="checkbox" />',
236
		'feedback_from'    => __( 'From', 'jetpack' ),
237
		'feedback_message' => __( 'Message', 'jetpack' ),
238
		'feedback_date'    => __( 'Date', 'jetpack' ),
239
	);
240
241
	return $cols;
242
}
243
244
add_action( 'manage_posts_custom_column', 'grunion_manage_post_columns', 10, 2 );
245
function grunion_manage_post_columns( $col, $post_id ) {
246
	global $post;
247
248
	/**
249
	 * Only call parse_fields_from_content if we're dealing with a Grunion custom column.
250
	 */
251
	if ( ! in_array( $col, array( 'feedback_date', 'feedback_from', 'feedback_message' ) ) ) {
252
		return;
253
	}
254
255
	$content_fields = Grunion_Contact_Form_Plugin::parse_fields_from_content( $post_id );
256
257
	switch ( $col ) {
258
		case 'feedback_from':
259
			$author_name  = isset( $content_fields['_feedback_author'] ) ? $content_fields['_feedback_author'] : '';
260
			$author_email = isset( $content_fields['_feedback_author_email'] ) ? $content_fields['_feedback_author_email'] : '';
261
			$author_url   = isset( $content_fields['_feedback_author_url'] ) ? $content_fields['_feedback_author_url'] : '';
262
			$author_ip    = isset( $content_fields['_feedback_ip'] ) ? $content_fields['_feedback_ip'] : '';
263
			$form_url     = isset( $post->post_parent ) ? get_permalink( $post->post_parent ) : null;
264
265
			$author_name_line = '';
266
			if ( ! empty( $author_name ) ) {
267
				if ( ! empty( $author_email ) ) {
268
					$author_name_line = get_avatar( $author_email, 32 );
269
				}
270
271
				$author_name_line .= sprintf( '<strong>%s</strong><br />', esc_html( $author_name ) );
272
			}
273
274
			$author_email_line = '';
275
			if ( ! empty( $author_email ) ) {
276
				$author_email_line = sprintf( "<a href='%1\$s' target='_blank'>%2\$s</a><br />", esc_url( 'mailto:' . $author_email ), esc_html( $author_email ) );
277
			}
278
279
			$author_url_line = '';
280
			if ( ! empty( $author_url ) ) {
281
				$author_url_line = sprintf( "<a href='%1\$s'>%1\$s</a><br />", esc_url( $author_url ) );
282
			}
283
284
			echo $author_name_line;
285
			echo $author_email_line;
286
			echo $author_url_line;
287
			echo "<a href='edit.php?post_type=feedback&s=" . urlencode( $author_ip );
288
			echo "&mode=detail'>" . esc_html( $author_ip ) . '</a><br />';
289
			if ( $form_url ) {
290
				echo '<a href="' . esc_url( $form_url ) . '">' . esc_html( $form_url ) . '</a>';
291
			}
292
			break;
293
294
		case 'feedback_message':
295
			$post_type_object = get_post_type_object( $post->post_type );
296
			if ( isset( $content_fields['_feedback_subject'] ) ) {
297
				echo '<strong>';
298
				echo esc_html( $content_fields['_feedback_subject'] );
299
				echo '</strong>';
300
				echo '<br />';
301
			}
302
			echo sanitize_text_field( get_the_content( '' ) );
303
			echo '<br />';
304
305
			$extra_fields = get_post_meta( $post_id, '_feedback_extra_fields', true );
306
			if ( ! empty( $extra_fields ) ) {
307
				echo '<br /><hr />';
308
				echo '<table cellspacing="0" cellpadding="0" style="">' . "\n";
309
				foreach ( (array) $extra_fields as $k => $v ) {
310
					// Remove prefix from exta fields
311
					echo "<tr><td align='right'><b>" . esc_html( preg_replace( '#^\d+_#', '', $k ) ) . '</b></td><td>' . sanitize_text_field( $v ) . "</td></tr>\n";
312
				}
313
				echo '</table>';
314
			}
315
316
			echo '<div class="row-actions">';
317
			if ( $post->post_status == 'trash' ) {
318
				echo '<span class="untrash" id="feedback-restore-' . $post_id;
319
				echo '"><a title="';
320
				echo esc_attr__( 'Restore this item from the Trash', 'jetpack' );
321
				echo '" href="' . wp_nonce_url( admin_url( sprintf( $post_type_object->_edit_link . '&amp;action=untrash', $post->ID ) ), 'untrash-' . $post->post_type . '_' . $post->ID );
322
				echo '">' . __( 'Restore', 'jetpack' ) . '</a></span> | ';
323
324
				echo "<span class='delete'> <a class='submitdelete' title='";
325
				echo esc_attr( __( 'Delete this item permanently', 'jetpack' ) );
326
				echo "' href='" . get_delete_post_link( $post->ID, '', true );
327
				echo "'>" . __( 'Delete Permanently', 'jetpack' ) . '</a></span>';
328
?>
329
330
<script>
331
jQuery(document).ready(function($) {
332
$('#feedback-restore-<?php echo $post_id; ?>').click(function(e) {
333
	e.preventDefault();
334
	$.post(ajaxurl, {
335
			action: 'grunion_ajax_spam',
336
			post_id: '<?php echo $post_id; ?>',
337
			make_it: 'publish',
338
			sub_menu: jQuery('.subsubsub .current').attr('href'),
339
			_ajax_nonce: '<?php echo wp_create_nonce( 'grunion-post-status-' . $post_id ); ?>'
340
		},
341
		function(r) {
342
			$('#post-<?php echo $post_id; ?>')
343
				.css({backgroundColor: '#59C859'})
344
				.fadeOut(350, function() {
345
					$(this).remove();
346
					$('.subsubsub').html(r);
347
				});
348
		}
349
	);
350
});
351
});
352
</script>
353
354
<?php
355
			} elseif ( $post->post_status == 'publish' ) {
356
				echo '<span class="spam" id="feedback-spam-' . $post_id;
357
				echo '"><a title="';
358
				echo __( 'Mark this message as spam', 'jetpack' );
359
				echo '" href="' . wp_nonce_url( admin_url( 'admin-ajax.php?post_id=' . $post_id . '&amp;action=spam' ), 'spam-feedback_' . $post_id );
360
				echo '">Spam</a></span>';
361
				echo ' | ';
362
363
				echo '<span class="delete" id="feedback-trash-' . $post_id;
364
				echo '">';
365
				echo '<a class="submitdelete" title="' . esc_attr__( 'Trash', 'jetpack' );
366
				echo '" href="' . get_delete_post_link( $post_id );
367
				echo '">' . __( 'Trash', 'jetpack' ) . '</a></span>';
368
369
?>
370
371
<script>
372
jQuery(document).ready( function($) {
373
	$('#feedback-spam-<?php echo $post_id; ?>').click( function(e) {
374
		e.preventDefault();
375
		$.post( ajaxurl, {
376
				action: 'grunion_ajax_spam',
377
				post_id: '<?php echo $post_id; ?>',
378
				make_it: 'spam',
379
				sub_menu: jQuery('.subsubsub .current').attr('href'),
380
				_ajax_nonce: '<?php echo wp_create_nonce( 'grunion-post-status-' . $post_id ); ?>'
381
			},
382
			function( r ) {
383
				$('#post-<?php echo $post_id; ?>')
384
					.css( {backgroundColor:'#FF7979'} )
385
					.fadeOut(350, function() {
386
						$(this).remove();
387
						$('.subsubsub').html(r);
388
				});
389
		});
390
	});
391
392
	$('#feedback-trash-<?php echo $post_id; ?>').click(function(e) {
393
		e.preventDefault();
394
		$.post(ajaxurl, {
395
				action: 'grunion_ajax_spam',
396
				post_id: '<?php echo $post_id; ?>',
397
				make_it: 'trash',
398
				sub_menu: jQuery('.subsubsub .current').attr('href'),
399
				_ajax_nonce: '<?php echo wp_create_nonce( 'grunion-post-status-' . $post_id ); ?>'
400
			},
401
			function(r) {
402
				$('#post-<?php echo $post_id; ?>')
403
					.css({backgroundColor: '#FF7979'})
404
					.fadeOut(350, function() {
405
						$(this).remove();
406
						$('.subsubsub').html(r);
407
					});
408
			}
409
		);
410
	});
411
});
412
</script>
413
414
<?php
415
			} elseif ( $post->post_status == 'spam' ) {
416
				echo '<span class="unspam unapprove" id="feedback-ham-' . $post_id;
417
				echo '"><a title="';
418
				echo __( 'Mark this message as NOT spam', 'jetpack' );
419
				echo '" href="">Not Spam</a></span>';
420
				echo ' | ';
421
422
				echo "<span class='delete' id='feedback-trash-" . $post_id;
423
				echo "'> <a class='submitdelete' title='";
424
				echo esc_attr( __( 'Delete this item permanently', 'jetpack' ) );
425
				echo "' href='" . get_delete_post_link( $post->ID, '', true );
426
				echo "'>" . __( 'Delete Permanently', 'jetpack' ) . '</a></span>';
427
?>
428
429
<script>
430
jQuery(document).ready( function($) {
431
	$('#feedback-ham-<?php echo $post_id; ?>').click( function(e) {
432
		e.preventDefault();
433
		$.post( ajaxurl, {
434
				action: 'grunion_ajax_spam',
435
				post_id: '<?php echo $post_id; ?>',
436
				make_it: 'ham',
437
				sub_menu: jQuery('.subsubsub .current').attr('href'),
438
				_ajax_nonce: '<?php echo wp_create_nonce( 'grunion-post-status-' . $post_id ); ?>'
439
			},
440
			function( r ) {
441
				$('#post-<?php echo $post_id; ?>')
442
					.css( {backgroundColor:'#59C859'} )
443
					.fadeOut(350, function() {
444
						$(this).remove();
445
						$('.subsubsub').html(r);
446
				});
447
			});
448
	});
449
});
450
</script>
451
452
<?php
453
			}
454
			break;
455
456
		case 'feedback_date':
457
			$date_time_format = _x( '%1$s \a\t %2$s', '{$date_format} \a\t {$time_format}', 'jetpack' );
458
			$date_time_format = sprintf( $date_time_format, get_option( 'date_format' ), get_option( 'time_format' ) );
459
			$time             = date_i18n( $date_time_format, get_the_time( 'U' ) );
460
461
			echo $time;
462
			break;
463
	}
464
}
465
466
function grunion_esc_attr( $attr ) {
467
	$out = esc_attr( $attr );
468
	// we also have to entity-encode square brackets so they don't interfere with the shortcode parser
469
	// FIXME: do this better - just stripping out square brackets for now since they mysteriously keep reappearing
470
	$out = str_replace( '[', '', $out );
471
	$out = str_replace( ']', '', $out );
472
	return $out;
473
}
474
475
function grunion_sort_objects( $a, $b ) {
476
	if ( isset( $a['order'] ) && isset( $b['order'] ) ) {
477
		return $a['order'] - $b['order'];
478
	}
479
	return 0;
480
}
481
482
// take an array of field types from the form builder, and construct a shortcode form
483
// returns both the shortcode form, and HTML markup representing a preview of the form
484
function grunion_ajax_shortcode() {
485
	check_ajax_referer( 'grunion_shortcode' );
486
487
	if ( ! current_user_can( 'edit_posts' ) ) {
488
		die( '-1' );
489
	}
490
491
	$attributes = array();
492
493
	foreach ( array( 'subject', 'to' ) as $attribute ) {
494
		if ( isset( $_POST[ $attribute ] ) && strlen( $_POST[ $attribute ] ) ) {
495
			$attributes[ $attribute ] = stripslashes( $_POST[ $attribute ] );
496
		}
497
	}
498
499
	if ( is_array( $_POST['fields'] ) ) {
500
		$fields = stripslashes_deep( $_POST['fields'] );
501
		usort( $fields, 'grunion_sort_objects' );
502
503
		$field_shortcodes = array();
504
505
		foreach ( $fields as $field ) {
506
			$field_attributes = array();
507
508
			if ( isset( $field['required'] ) && 'true' === $field['required'] ) {
509
				$field_attributes['required'] = 'true';
510
			}
511
512
			foreach ( array( 'options', 'label', 'type' ) as $attribute ) {
513
				if ( isset( $field[ $attribute ] ) ) {
514
					$field_attributes[ $attribute ] = $field[ $attribute ];
515
				}
516
			}
517
518
			$field_shortcodes[] = new Grunion_Contact_Form_Field( $field_attributes );
519
		}
520
	}
521
522
	$grunion = new Grunion_Contact_Form( $attributes, $field_shortcodes );
0 ignored issues
show
Bug introduced by
The variable $field_shortcodes does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
523
524
	die( "\n$grunion\n" );
525
}
526
527
// takes a post_id, extracts the contact-form shortcode from that post (if there is one), parses it,
528
// and constructs a json object representing its contents and attributes
529
function grunion_ajax_shortcode_to_json() {
530
	global $post, $grunion_form;
531
532
	check_ajax_referer( 'grunion_shortcode_to_json' );
533
534
	if ( ! empty( $_POST['post_id'] ) && ! current_user_can( 'edit_post', $_POST['post_id'] ) ) {
535
		die( '-1' );
536
	} elseif ( ! current_user_can( 'edit_posts' ) ) {
537
		die( '-1' );
538
	}
539
540
	if ( ! isset( $_POST['content'] ) || ! is_numeric( $_POST['post_id'] ) ) {
541
		die( '-1' );
542
	}
543
544
	$content = stripslashes( $_POST['content'] );
545
546
	// doesn't look like a post with a [contact-form] already.
547
	if ( false === has_shortcode( $content, 'contact-form' ) ) {
548
		die( '' );
549
	}
550
551
	$post = get_post( $_POST['post_id'] );
552
553
	do_shortcode( $content );
554
555
	$grunion = Grunion_Contact_Form::$last;
0 ignored issues
show
Bug introduced by
The property last cannot be accessed from this context as it is declared private in class Grunion_Contact_Form.

This check looks for access to properties that are not accessible from the current context.

If you need to make a property accessible to another context you can either raise its visibility level or provide an accessible getter in the defining class.

Loading history...
556
557
	$out = array(
558
		'to'      => '',
559
		'subject' => '',
560
		'fields'  => array(),
561
	);
562
563
	foreach ( $grunion->fields as $field ) {
564
		$out['fields'][ $field->get_attribute( 'id' ) ] = $field->attributes;
565
	}
566
567
	$to      = $grunion->get_attribute( 'to' );
0 ignored issues
show
Unused Code introduced by
$to is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
568
	$subject = $grunion->get_attribute( 'subject' );
0 ignored issues
show
Unused Code introduced by
$subject is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
569
	foreach ( array( 'to', 'subject' ) as $attribute ) {
570
		$value = $grunion->get_attribute( $attribute );
571
		if ( isset( $grunion->defaults[ $attribute ] ) && $value == $grunion->defaults[ $attribute ] ) {
572
			$value = '';
573
		}
574
		$out[ $attribute ] = $value;
575
	}
576
577
	die( json_encode( $out ) );
578
}
579
580
581
add_action( 'wp_ajax_grunion_shortcode', 'grunion_ajax_shortcode' );
582
add_action( 'wp_ajax_grunion_shortcode_to_json', 'grunion_ajax_shortcode_to_json' );
583
584
585
// process row-action spam/not spam clicks
586
add_action( 'wp_ajax_grunion_ajax_spam', 'grunion_ajax_spam' );
587
function grunion_ajax_spam() {
588
	global $wpdb;
589
590
	if ( empty( $_POST['make_it'] ) ) {
591
		return;
592
	}
593
594
	$post_id = (int) $_POST['post_id'];
595
	check_ajax_referer( 'grunion-post-status-' . $post_id );
596
	if ( ! current_user_can( 'edit_page', $post_id ) ) {
597
		wp_die( __( 'You are not allowed to manage this item.', 'jetpack' ) );
598
	}
599
600
	require_once dirname( __FILE__ ) . '/grunion-contact-form.php';
601
602
	$current_menu = '';
603
	if ( isset( $_POST['sub_menu'] ) && preg_match( '|post_type=feedback|', $_POST['sub_menu'] ) ) {
604
		if ( preg_match( '|post_status=spam|', $_POST['sub_menu'] ) ) {
605
			$current_menu = 'spam';
606
		} elseif ( preg_match( '|post_status=trash|', $_POST['sub_menu'] ) ) {
607
			$current_menu = 'trash';
608
		} else {
609
			$current_menu = 'messages';
610
		}
611
	}
612
613
	$post             = get_post( $post_id );
614
	$post_type_object = get_post_type_object( $post->post_type );
615
	$akismet_values   = get_post_meta( $post_id, '_feedback_akismet_values', true );
616
	if ( $_POST['make_it'] == 'spam' ) {
617
		$post->post_status = 'spam';
618
		$status            = wp_insert_post( $post );
0 ignored issues
show
Unused Code introduced by
$status is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
619
620
		/** This action is already documented in modules/contact-form/admin.php */
621
		do_action( 'contact_form_akismet', 'spam', $akismet_values );
622
	} elseif ( $_POST['make_it'] == 'ham' ) {
623
		$post->post_status = 'publish';
624
		$status            = wp_insert_post( $post );
0 ignored issues
show
Unused Code introduced by
$status is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
625
626
		/** This action is already documented in modules/contact-form/admin.php */
627
		do_action( 'contact_form_akismet', 'ham', $akismet_values );
628
629
		$comment_author_email = $reply_to_addr = $message = $to = $headers = false;
0 ignored issues
show
Unused Code introduced by
$headers is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
630
		$blog_url             = wp_parse_url( site_url() );
631
632
		// resend the original email
633
		$email          = get_post_meta( $post_id, '_feedback_email', true );
634
		$content_fields = Grunion_Contact_Form_Plugin::parse_fields_from_content( $post_id );
635
636
		if ( ! empty( $email ) && ! empty( $content_fields ) ) {
637
			if ( isset( $content_fields['_feedback_author_email'] ) ) {
638
				$comment_author_email = $content_fields['_feedback_author_email'];
639
			}
640
641
			if ( isset( $email['to'] ) ) {
642
				$to = $email['to'];
643
			}
644
645
			if ( isset( $email['message'] ) ) {
646
				$message = $email['message'];
647
			}
648
649
			if ( isset( $email['headers'] ) ) {
650
				$headers = $email['headers'];
651
			} else {
652
				$headers = 'From: "' . $content_fields['_feedback_author'] . '" <wordpress@' . $blog_url['host'] . ">\r\n";
653
654
				if ( ! empty( $comment_author_email ) ) {
655
					$reply_to_addr = $comment_author_email;
656
				} elseif ( is_array( $to ) ) {
657
					$reply_to_addr = $to[0];
658
				}
659
660
				if ( $reply_to_addr ) {
661
					$headers .= 'Reply-To: "' . $content_fields['_feedback_author'] . '" <' . $reply_to_addr . ">\r\n";
662
				}
663
664
				$headers .= 'Content-Type: text/plain; charset="' . get_option( 'blog_charset' ) . '"';
665
			}
666
667
			/**
668
			 * Filters the subject of the email sent after a contact form submission.
669
			 *
670
			 * @module contact-form
671
			 *
672
			 * @since 3.0.0
673
			 *
674
			 * @param string $content_fields['_feedback_subject'] Feedback's subject line.
675
			 * @param array $content_fields['_feedback_all_fields'] Feedback's data from old fields.
676
			 */
677
			$subject = apply_filters( 'contact_form_subject', $content_fields['_feedback_subject'], $content_fields['_feedback_all_fields'] );
0 ignored issues
show
Unused Code introduced by
The call to apply_filters() has too many arguments starting with $content_fields['_feedback_all_fields'].

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
678
679
			Grunion_Contact_Form::wp_mail( $to, $subject, $message, $headers );
680
		}
681
	} elseif ( $_POST['make_it'] == 'publish' ) {
682
		if ( ! current_user_can( $post_type_object->cap->delete_post, $post_id ) ) {
683
			wp_die( __( 'You are not allowed to move this item out of the Trash.', 'jetpack' ) );
684
		}
685
686
		if ( ! wp_untrash_post( $post_id ) ) {
687
			wp_die( __( 'Error in restoring from Trash.', 'jetpack' ) );
688
		}
689
	} elseif ( $_POST['make_it'] == 'trash' ) {
690
		if ( ! current_user_can( $post_type_object->cap->delete_post, $post_id ) ) {
691
			wp_die( __( 'You are not allowed to move this item to the Trash.', 'jetpack' ) );
692
		}
693
694
		if ( ! wp_trash_post( $post_id ) ) {
695
			wp_die( __( 'Error in moving to Trash.', 'jetpack' ) );
696
		}
697
	}
698
699
	$sql          = "
700
		SELECT post_status,
701
			COUNT( * ) AS post_count
702
		FROM `{$wpdb->posts}`
703
		WHERE post_type =  'feedback'
704
		GROUP BY post_status
705
	";
706
	$status_count = (array) $wpdb->get_results( $sql, ARRAY_A );
707
708
	$status      = array();
709
	$status_html = '';
710
	foreach ( $status_count as $i => $row ) {
711
		$status[ $row['post_status'] ] = $row['post_count'];
712
	}
713
714 View Code Duplication
	if ( isset( $status['publish'] ) ) {
715
		$status_html .= '<li><a href="edit.php?post_type=feedback"';
716
		if ( $current_menu == 'messages' ) {
717
			$status_html .= ' class="current"';
718
		}
719
720
		$status_html .= '>' . __( 'Messages', 'jetpack' ) . ' <span class="count">';
721
		$status_html .= '(' . number_format( $status['publish'] ) . ')';
722
		$status_html .= '</span></a> |</li>';
723
	}
724
725
	if ( isset( $status['trash'] ) ) {
726
		$status_html .= '<li><a href="edit.php?post_status=trash&amp;post_type=feedback"';
727
		if ( $current_menu == 'trash' ) {
728
			$status_html .= ' class="current"';
729
		}
730
731
		$status_html .= '>' . __( 'Trash', 'jetpack' ) . ' <span class="count">';
732
		$status_html .= '(' . number_format( $status['trash'] ) . ')';
733
		$status_html .= '</span></a>';
734
		if ( isset( $status['spam'] ) ) {
735
			$status_html .= ' |';
736
		}
737
		$status_html .= '</li>';
738
	}
739
740 View Code Duplication
	if ( isset( $status['spam'] ) ) {
741
		$status_html .= '<li><a href="edit.php?post_status=spam&amp;post_type=feedback"';
742
		if ( $current_menu == 'spam' ) {
743
			$status_html .= ' class="current"';
744
		}
745
746
		$status_html .= '>' . __( 'Spam', 'jetpack' ) . ' <span class="count">';
747
		$status_html .= '(' . number_format( $status['spam'] ) . ')';
748
		$status_html .= '</span></a></li>';
749
	}
750
751
	echo $status_html;
752
	exit;
753
}
754
755
/**
756
 * Add the scripts that will add the "Check for Spam" button to the Feedbacks dashboard page.
757
 */
758
function grunion_enable_spam_recheck() {
759
	if ( ! defined( 'AKISMET_VERSION' ) ) {
760
		return;
761
	}
762
763
	$screen = get_current_screen();
764
765
	// Only add to feedback, only to non-spam view
766
	if ( 'edit-feedback' != $screen->id || ( ! empty( $_GET['post_status'] ) && 'spam' == $_GET['post_status'] ) ) {
767
		return;
768
	}
769
770
	// Add the actual "Check for Spam" button.
771
	add_action( 'admin_head', 'grunion_check_for_spam_button' );
772
}
773
774
add_action( 'admin_enqueue_scripts', 'grunion_enable_spam_recheck' );
775
776
/**
777
 * Add the JS and CSS necessary for the Feedback admin page to function.
778
 */
779
function grunion_add_admin_scripts() {
780
	$screen = get_current_screen();
781
782
	if ( 'edit-feedback' !== $screen->id ) {
783
		return;
784
	}
785
786
	// Add the scripts that handle the spam check event.
787
	wp_register_script(
788
		'grunion-admin',
789
		Assets::get_file_url_for_environment(
790
			'_inc/build/contact-form/js/grunion-admin.min.js',
791
			'modules/contact-form/js/grunion-admin.js'
792
		),
793
		array( 'jquery' ),
794
		JETPACK__VERSION,
795
		true
796
	);
797
798
	wp_enqueue_script( 'grunion-admin' );
799
800
	wp_enqueue_style( 'grunion.css' );
801
802
	// Only add to feedback, only to spam view.
803
	if ( empty( $_GET['post_status'] ) || 'spam' !== $_GET['post_status'] ) {
804
		return;
805
	}
806
807
	$feedbacks_count = wp_count_posts( 'feedback' );
808
	$nonce           = wp_create_nonce( 'jetpack_delete_spam_feedbacks' );
809
	$success_url     = remove_query_arg( array( 'jetpack_empty_feedback_spam_error', 'post_status' ) ); // Go to the "All Feedback" page.
810
	$failure_url     = add_query_arg( 'jetpack_empty_feedback_spam_error', '1' ); // Refresh the current page and show an error.
811
	$spam_count      = $feedbacks_count->spam;
812
813
	$button_parameters = array(
814
		/* translators: The placeholder is for showing how much of the process has completed, as a percent. e.g., "Emptying Spam (40%)" */
815
		'progress_label' => __( 'Emptying Spam (%1$s%)', 'jetpack' ),
816
		'success_url'    => $success_url,
817
		'failure_url'    => $failure_url,
818
		'spam_count'     => $spam_count,
819
		'nonce'          => $nonce,
820
		'label'          => __( 'Empty Spam', 'jetpack' ),
821
	);
822
823
	wp_localize_script( 'grunion-admin', 'jetpack_empty_spam_button_parameters', $button_parameters );
824
}
825
826
add_action( 'admin_enqueue_scripts', 'grunion_add_admin_scripts' );
827
828
/**
829
 * Add the "Check for Spam" button to the Feedbacks dashboard page.
830
 */
831
function grunion_check_for_spam_button() {
832
	// Nonce name.
833
	$nonce_name = 'jetpack_check_feedback_spam_' . (string) get_current_blog_id();
834
	// Get HTML for the button.
835
	$button_html  = get_submit_button(
836
		__( 'Check for Spam', 'jetpack' ),
837
		'secondary',
838
		'jetpack-check-feedback-spam',
839
		false,
840
		array(
841
			'data-failure-url' => add_query_arg( 'jetpack_check_feedback_spam_error', '1' ), // Refresh the current page and show an error.
842
			'data-nonce-name'  => $nonce_name,
843
		)
844
	);
845
	$button_html .= '<span class="jetpack-check-feedback-spam-spinner"></span>';
846
	$button_html .= wp_nonce_field( 'grunion_recheck_queue', $nonce_name, false, false );
847
848
	// Add the button next to the filter button via js.
849
	?>
850
	<script type="text/javascript">
851
		jQuery( function( $ ) {
852
			$( '#posts-filter #post-query-submit' ).after( '<?php echo $button_html; ?>' );
853
		} );
854
	</script>
855
	<?php
856
}
857
858
/**
859
 * Recheck all approved feedbacks for spam.
860
 */
861
function grunion_recheck_queue() {
862
	$blog_id = get_current_blog_id();
863
864
	if (
865
		empty( $_POST[ 'jetpack_check_feedback_spam_' . (string) $blog_id ] )
866
		|| ! wp_verify_nonce( sanitize_key( $_POST[ 'jetpack_check_feedback_spam_' . (string) $blog_id ] ), 'grunion_recheck_queue' )
867
	) {
868
		wp_send_json_error(
869
			__( 'You aren’t authorized to do that.', 'jetpack' ),
870
			403
871
		);
872
873
		return;
874
	}
875
876
	if ( ! current_user_can( 'delete_others_posts' ) ) {
877
		wp_send_json_error(
878
			__( 'You don’t have permission to do that.', 'jetpack' ),
879
			403
880
		);
881
882
		return;
883
	}
884
885
	$query = 'post_type=feedback&post_status=publish';
886
887
	if ( isset( $_POST['limit'], $_POST['offset'] ) ) {
888
		$query .= '&posts_per_page=' . (int) $_POST['limit'] . '&offset=' . (int) $_POST['offset'];
889
	}
890
891
	$approved_feedbacks = get_posts( $query );
892
893
	foreach ( $approved_feedbacks as $feedback ) {
894
		$meta = get_post_meta( $feedback->ID, '_feedback_akismet_values', true );
895
896
		if ( ! $meta ) {
897
			// _feedback_akismet_values is eventually deleted when it's no longer
898
			// within a reasonable time period to check the feedback for spam, so
899
			// if it's gone, don't attempt a spam recheck.
900
			continue;
901
		}
902
903
		$meta['recheck_reason'] = 'recheck_queue';
904
905
		/**
906
		 * Filter whether the submitted feedback is considered as spam.
907
		 *
908
		 * @module contact-form
909
		 *
910
		 * @since 3.4.0
911
		 *
912
		 * @param bool false Is the submitted feedback spam? Default to false.
913
		 * @param array $meta Feedack values returned by the Akismet plugin.
914
		 */
915
		$is_spam = apply_filters( 'jetpack_contact_form_is_spam', false, $meta );
0 ignored issues
show
Unused Code introduced by
The call to apply_filters() has too many arguments starting with $meta.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
916
917
		if ( $is_spam ) {
918
			wp_update_post(
919
				array(
920
					'ID'          => $feedback->ID,
921
					'post_status' => 'spam',
922
				)
923
			);
924
			/** This action is already documented in modules/contact-form/admin.php */
925
			do_action( 'contact_form_akismet', 'spam', $meta );
926
		}
927
	}
928
929
	wp_send_json(
930
		array(
931
			'processed' => count( $approved_feedbacks ),
932
		)
933
	);
934
}
935
936
add_action( 'wp_ajax_grunion_recheck_queue', 'grunion_recheck_queue' );
937
938
/**
939
 * Delete a number of spam feedbacks via an AJAX request.
940
 */
941
function grunion_delete_spam_feedbacks() {
942
	if ( ! wp_verify_nonce( $_POST['nonce'], 'jetpack_delete_spam_feedbacks' ) ) {
943
		wp_send_json_error(
944
			__( 'You aren’t authorized to do that.', 'jetpack' ),
945
			403
946
		);
947
948
		return;
949
	}
950
951
	if ( ! current_user_can( 'delete_others_posts' ) ) {
952
		wp_send_json_error(
953
			__( 'You don’t have permission to do that.', 'jetpack' ),
954
			403
955
		);
956
957
		return;
958
	}
959
960
	$deleted_feedbacks = 0;
961
962
	$delete_limit = 25;
963
	/**
964
	 * Filter the amount of Spam feedback one can delete at once.
965
	 *
966
	 * @module contact-form
967
	 *
968
	 * @since 8.7.0
969
	 *
970
	 * @param int $delete_limit Number of spam to process at once. Default to 25.
971
	 */
972
	$delete_limit = apply_filters( 'jetpack_delete_spam_feedbacks_limit', $delete_limit );
973
	$delete_limit = (int) $delete_limit;
974
	$delete_limit = max( 1, min( 100, $delete_limit ) ); // Allow a range of 1-100 for the delete limit.
975
976
	$query_args = array(
977
		'post_type'      => 'feedback',
978
		'post_status'    => 'spam',
979
		'posts_per_page' => $delete_limit,
980
	);
981
982
	$query          = new WP_Query( $query_args );
983
	$spam_feedbacks = $query->get_posts();
984
985
	foreach ( $spam_feedbacks as $feedback ) {
986
		wp_delete_post( $feedback->ID, true );
987
988
		$deleted_feedbacks++;
989
	}
990
991
	wp_send_json(
992
		array(
993
			'success' => true,
994
			'data'    => array(
995
				'counts' => array(
996
					'deleted' => $deleted_feedbacks,
997
					'limit'   => $delete_limit,
998
				),
999
			),
1000
		)
1001
	);
1002
}
1003
add_action( 'wp_ajax_jetpack_delete_spam_feedbacks', 'grunion_delete_spam_feedbacks' );
1004
1005
/**
1006
 * Show an admin notice if the "Empty Spam" or "Check Spam" process was unable to complete, probably due to a permissions error.
1007
 */
1008
function grunion_feedback_admin_notice() {
1009
	if ( isset( $_GET['jetpack_empty_feedback_spam_error'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
1010
		echo '<div class="notice notice-error"><p>' . esc_html( __( 'An error occurred while trying to empty the Feedback spam folder.', 'jetpack' ) ) . '</p></div>';
1011
	} elseif ( isset( $_GET['jetpack_check_feedback_spam_error'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
1012
		echo '<div class="notice notice-error"><p>' . esc_html( __( 'An error occurred while trying to check for spam among the feedback you received.', 'jetpack' ) ) . '</p></div>';
1013
	}
1014
}
1015
add_action( 'admin_notices', 'grunion_feedback_admin_notice' );
1016