PluginProbe
Stream – Activity Log & Audit Trail / 4.0.2
Stream – Activity Log & Audit Trail v4.0.2
4.4.0 4.3.0 4.2.2 4.2.1 trunk 2.0.1 2.0.2 2.0.3 2.0.4 2.0.5 3.0.0 3.0.1 3.0.2 3.0.3 3.0.4 3.0.5 3.0.6 3.0.7 3.1 3.1.1 3.10.0 3.2.0 3.2.1 3.2.2 3.2.3 All 50 releases
← All changes | classes/class-settings.php +322 -187 3.2.24.0.2 View file →
@@ -1,14 +1,25 @@
1 1 <?php
2 +/**
3 + * Renders and manages the plugin Settings page.
4 + *
5 + * @package WP_Stream
6 + */
7 +
2 8 namespace WP_Stream;
3 9
4 -use \WP_Roles;
5 -use \WP_User;
6 -use \WP_User_Query;
10 +use WP_Roles;
11 +use WP_User;
12 +use WP_User_Query;
7 13
14 +/**
15 + * Class - Settings
16 + */
8 17 class Settings {
18 +
9 19 /**
10 - * Hold Plugin class
20 + * Holds instance of plugin object
21 + *
11 22 * @var Plugin
12 23 */
13 24 public $plugin;
14 25
@@ -42,9 +53,9 @@
42 53
43 54 /**
44 55 * Class constructor.
45 56 *
46 - * @param Plugin $plugin The main Plugin class.
57 + * @param Plugin $plugin Instance of plugin object.
47 58 */
48 59 public function __construct( $plugin ) {
49 60 $this->plugin = $plugin;
50 61
@@ -50,21 +61,35 @@
50 61
51 62 $this->option_key = $this->get_option_key();
52 63 $this->options = $this->get_options();
53 64
54 - // Register settings, and fields
65 + // Register settings, and fields.
55 66 add_action( 'admin_init', array( $this, 'register_settings' ) );
56 67
57 - // Remove records when records TTL is shortened
58 - add_action( 'update_option_' . $this->option_key, array( $this, 'updated_option_ttl_remove_records' ), 10, 2 );
68 + // Remove records when records TTL is shortened.
69 + add_action(
70 + 'update_option_' . $this->option_key,
71 + array(
72 + $this,
73 + 'updated_option_ttl_remove_records',
74 + ),
75 + 10,
76 + 2
77 + );
59 78
60 - // Apply label translations for settings
61 - add_filter( 'wp_stream_serialized_labels', array( $this, 'get_settings_translations' ) );
79 + // Apply label translations for settings.
80 + add_filter(
81 + 'wp_stream_serialized_labels',
82 + array(
83 + $this,
84 + 'get_settings_translations',
85 + )
86 + );
62 87
63 - // Ajax callback function to search users
88 + // Ajax callback function to search users.
64 89 add_action( 'wp_ajax_stream_get_users', array( $this, 'get_users' ) );
65 90
66 - // Ajax callback function to search IPs
91 + // Ajax callback function to search IPs.
67 92 add_action( 'wp_ajax_stream_get_ips', array( $this, 'get_ips' ) );
68 93 }
69 94
70 95 /**
@@ -94,13 +119,21 @@
94 119 $request = (object) array(
95 120 'find' => $search,
96 121 );
97 122
98 - add_filter( 'user_search_columns', array( $this, 'add_display_name_search_columns' ), 10, 3 );
123 + add_filter(
124 + 'user_search_columns',
125 + array(
126 + $this,
127 + 'add_display_name_search_columns',
128 + ),
129 + 10,
130 + 3
131 + );
99 132
100 133 $users = new WP_User_Query(
101 134 array(
102 - 'search' => "*{$request->find}*",
135 + 'search' => "*{$request->find}*",
103 136 'search_columns' => array(
104 137 'user_login',
105 138 'user_nicename',
106 139 'user_email',
@@ -105,14 +138,21 @@
105 138 'user_nicename',
106 139 'user_email',
107 140 'user_url',
108 141 ),
109 - 'orderby' => 'display_name',
110 - 'number' => $this->plugin->admin->preload_users_max,
142 + 'orderby' => 'display_name',
143 + 'number' => $this->plugin->admin->preload_users_max,
111 144 )
112 145 );
113 146
114 - remove_filter( 'user_search_columns', array( $this, 'add_display_name_search_columns' ), 10 );
147 + remove_filter(
148 + 'user_search_columns',
149 + array(
150 + $this,
151 + 'add_display_name_search_columns',
152 + ),
153 + 10
154 + );
115 155
116 156 if ( 0 === $users->get_total() ) {
117 157 wp_send_json_error( $response );
118 158 }
@@ -120,21 +160,21 @@
120 160
121 161 if ( is_multisite() && is_super_admin() ) {
122 162 $super_admins = get_super_admins();
123 163 foreach ( $super_admins as $admin ) {
124 - $user = get_user_by( 'login', $admin );
164 + $user = get_user_by( 'login', $admin );
125 165 $users_array[] = $user;
126 166 }
127 167 }
128 168
129 - $response->status = true;
130 - $response->message = '';
131 - $response->roles = $this->get_roles();
132 - $response->users = array();
169 + $response->status = true;
170 + $response->message = '';
171 + $response->roles = $this->get_roles();
172 + $response->users = array();
133 173 $users_added_to_response = array();
134 174
135 175 foreach ( $users_array as $key => $user ) {
136 - // exclude duplications:
176 + // exclude duplications.
137 177 if ( array_key_exists( $user->ID, $users_added_to_response ) ) {
138 178 continue;
139 179 } else {
140 180 $users_added_to_response[ $user->ID ] = true;
@@ -148,8 +188,9 @@
148 188 );
149 189
150 190 $args['tooltip'] = esc_attr(
151 191 sprintf(
192 + /* translators: %1$d: user ID, %2$s: username, %3$s: email, %4$s: user role (e.g. "42", "administrator", "foo@bar.com", "subscriber") */
152 193 __( 'ID: %1$d\nUser: %2$s\nEmail: %3$s\nRole: %4$s', 'stream' ),
153 194 $author->id,
154 195 $author->user_login,
155 196 $author->user_email,
@@ -163,15 +204,15 @@
163 204 }
164 205
165 206 usort(
166 207 $response->users,
167 - function( $a, $b ) {
208 + function ( $a, $b ) {
168 209 return strcmp( $a['text'], $b['text'] );
169 210 }
170 211 );
171 212
172 213 if ( empty( $search ) || preg_match( '/wp|cli|system|unknown/i', $search ) ) {
173 - $author = new Author( 0 );
214 + $author = new Author( 0 );
174 215 $response->users[] = array(
175 216 'id' => '0',
176 217 'text' => $author->get_display_name(),
177 218 'icon' => $author->get_avatar_src( 32 ),
@@ -182,10 +223,10 @@
182 223 wp_send_json_success( $response );
183 224 }
184 225
185 226 /**
186 - * Ajax callback function to search IP addresses, used on exclude setting page
187 - */
227 + * Ajax callback function to search IP addresses, used on exclude setting page
228 + */
188 229 public function get_ips() {
189 230 if ( ! defined( 'DOING_AJAX' ) || ! current_user_can( $this->plugin->admin->settings_cap ) ) {
190 231 return;
191 232 }
@@ -195,11 +236,14 @@
195 236 $ips = $this->plugin->db->existing_records( 'ip' );
196 237 $find = wp_stream_filter_input( INPUT_POST, 'find' );
197 238
198 239 if ( isset( $find['term'] ) && '' !== $find['term'] ) {
199 - $ips = array_filter( $ips, function ( $ip ) use ( $find ) {
200 - return 0 === strpos( $ip, $find['term'] );
201 - } );
240 + $ips = array_filter(
241 + $ips,
242 + function ( $ip ) use ( $find ) {
243 + return 0 === strpos( $ip, $find['term'] );
244 + }
245 + );
202 246 }
203 247
204 248 if ( $ips ) {
205 249 wp_send_json_success( $ips );
@@ -210,11 +254,11 @@
210 254
211 255 /**
212 256 * Filter the columns to search in a WP_User_Query search.
213 257 *
214 - * @param array $search_columns Array of column names to be searched.
215 - * @param string $search Text being searched.
216 - * @param \WP_User_Query $query current WP_User_Query instance.
258 + * @param array $search_columns Array of column names to be searched.
259 + * @param string $search Text being searched.
260 + * @param \WP_User_Query $query current WP_User_Query instance.
217 261 *
218 262 * @return array
219 263 */
220 264 public function add_display_name_search_columns( $search_columns, $search, $query ) {
@@ -253,18 +297,18 @@
253 297 * @return array
254 298 */
255 299 public function get_fields() {
256 300 $fields = array(
257 - 'general' => array(
301 + 'general' => array(
258 302 'title' => esc_html__( 'General', 'stream' ),
259 303 'fields' => array(
260 304 array(
261 - 'name' => 'role_access',
262 - 'title' => esc_html__( 'Role Access', 'stream' ),
263 - 'type' => 'multi_checkbox',
264 - 'desc' => esc_html__( 'Users from the selected roles above will have permission to view Stream Records. However, only site Administrators can access Stream Settings.', 'stream' ),
265 - 'choices' => $this->get_roles(),
266 - 'default' => array( 'administrator' ),
305 + 'name' => 'role_access',
306 + 'title' => esc_html__( 'Role Access', 'stream' ),
307 + 'type' => 'multi_checkbox',
308 + 'desc' => esc_html__( 'Users from the selected roles above will have permission to view Stream Records. However, only site Administrators can access Stream Settings.', 'stream' ),
309 + 'choices' => $this->get_roles(),
310 + 'default' => array( 'administrator' ),
267 311 ),
268 312 array(
269 313 'name' => 'records_ttl',
270 314 'title' => esc_html__( 'Keep Records for', 'stream' ),
@@ -286,18 +330,18 @@
286 330 'default' => 0,
287 331 ),
288 332 ),
289 333 ),
290 - 'exclude' => array(
334 + 'exclude' => array(
291 335 'title' => esc_html__( 'Exclude', 'stream' ),
292 336 'fields' => array(
293 337 array(
294 - 'name' => 'rules',
295 - 'title' => esc_html__( 'Exclude Rules', 'stream' ),
296 - 'type' => 'rule_list',
297 - 'desc' => esc_html__( 'Create rules to exclude certain kinds of activity from being recorded by Stream.', 'stream' ),
298 - 'default' => array(),
299 - 'nonce' => 'stream_get_ips',
338 + 'name' => 'rules',
339 + 'title' => esc_html__( 'Exclude Rules', 'stream' ),
340 + 'type' => 'rule_list',
341 + 'desc' => esc_html__( 'Create rules to exclude certain kinds of activity from being recorded by Stream.', 'stream' ),
342 + 'default' => array(),
343 + 'nonce' => 'stream_get_ips',
300 344 ),
301 345 ),
302 346 ),
303 347 'advanced' => array(
@@ -311,28 +355,28 @@
311 355 'after_field' => esc_html__( 'Enabled', 'stream' ),
312 356 'default' => 0,
313 357 ),
314 358 array(
315 - 'name' => 'delete_all_records',
316 - 'title' => esc_html__( 'Reset Stream Database', 'stream' ),
317 - 'type' => 'link',
318 - 'href' => add_query_arg(
359 + 'name' => 'delete_all_records',
360 + 'title' => esc_html__( 'Reset Stream Database', 'stream' ),
361 + 'type' => 'link',
362 + 'href' => add_query_arg(
319 363 array(
320 - 'action' => 'wp_stream_reset',
321 - 'wp_stream_nonce' => wp_create_nonce( 'stream_nonce' ),
364 + 'action' => 'wp_stream_reset',
365 + 'wp_stream_nonce_reset' => wp_create_nonce( 'stream_nonce_reset' ),
322 366 ),
323 367 admin_url( 'admin-ajax.php' )
324 368 ),
325 - 'class' => 'warning',
326 - 'desc' => esc_html__( 'Warning: This will delete all activity records from the database.', 'stream' ),
327 - 'default' => 0,
328 - 'sticky' => 'bottom',
369 + 'class' => 'warning',
370 + 'desc' => esc_html__( 'Warning: This will delete all activity records from the database.', 'stream' ),
371 + 'default' => 0,
372 + 'sticky' => 'bottom',
329 373 ),
330 374 ),
331 375 ),
332 376 );
333 377
334 - // If Akismet is active, allow Admins to opt-in to Akismet tracking
378 + // If Akismet is active, allow Admins to opt-in to Akismet tracking.
335 379 if ( class_exists( 'Akismet' ) ) {
336 380 $akismet_tracking = array(
337 381 'name' => 'akismet_tracking',
338 382 'title' => esc_html__( 'Akismet Tracking', 'stream' ),
@@ -344,21 +388,18 @@
344 388
345 389 array_push( $fields['advanced']['fields'], $akismet_tracking );
346 390 }
347 391
348 - // If WP Cron is enabled, allow Admins to opt-in to WP Cron tracking
349 - if ( wp_stream_is_cron_enabled() ) {
350 - $wp_cron_tracking = array(
351 - 'name' => 'wp_cron_tracking',
352 - 'title' => esc_html__( 'WP Cron Tracking', 'stream' ),
353 - 'type' => 'checkbox',
354 - 'desc' => esc_html__( 'By default, Stream does not track activity performed by WordPress cron events unless you opt-in here. Enabling this is not necessary or recommended for most sites.', 'stream' ),
355 - 'after_field' => esc_html__( 'Enabled', 'stream' ),
356 - 'default' => 0,
357 - );
392 + $wp_cron_tracking = array(
393 + 'name' => 'wp_cron_tracking',
394 + 'title' => esc_html__( 'WP Cron Tracking', 'stream' ),
395 + 'type' => 'checkbox',
396 + 'desc' => esc_html__( 'By default, Stream does not track activity performed by WordPress cron events unless you opt-in here. Enabling this is not necessary or recommended for most sites.', 'stream' ),
397 + 'after_field' => esc_html__( 'Enabled', 'stream' ),
398 + 'default' => 0,
399 + );
358 400
359 - array_push( $fields['advanced']['fields'], $wp_cron_tracking );
360 - }
401 + array_push( $fields['advanced']['fields'], $wp_cron_tracking );
361 402
362 403 /**
363 404 * Filter allows for modification of options fields
364 405 *
@@ -365,9 +406,9 @@
365 406 * @return array Array of option fields
366 407 */
367 408 $this->fields = apply_filters( 'wp_stream_settings_option_fields', $fields );
368 409
369 - // Sort option fields in each tab by title ASC
410 + // Sort option fields in each tab by title ASC.
370 411 foreach ( $this->fields as $tab => $options ) {
371 412 $titles = array();
372 413
373 414 foreach ( $options['fields'] as $field ) {
@@ -437,9 +478,16 @@
437 478 */
438 479 public function register_settings() {
439 480 $sections = $this->get_fields();
440 481
441 - register_setting( $this->option_key, $this->option_key, array( $this, 'sanitize_settings' ) );
482 + register_setting(
483 + $this->option_key,
484 + $this->option_key,
485 + array(
486 + $this,
487 + 'sanitize_settings',
488 + )
489 + );
442 490
443 491 foreach ( $sections as $section_name => $section ) {
444 492 add_settings_section(
445 493 $section_name,
@@ -448,9 +496,10 @@
448 496 $this->option_key
449 497 );
450 498
451 499 foreach ( $section['fields'] as $field_idx => $field ) {
452 - if ( ! isset( $field['type'] ) ) { // No field type associated, skip, no GUI
500 + // No field type associated, skip, no GUI.
501 + if ( ! isset( $field['type'] ) ) {
453 502 continue;
454 503 }
455 504
456 505 add_settings_field(
@@ -455,14 +504,17 @@
455 504
456 505 add_settings_field(
457 506 $field['name'],
458 507 $field['title'],
459 - ( isset( $field['callback'] ) ? $field['callback'] : array( $this, 'output_field' ) ),
508 + ( isset( $field['callback'] ) ? $field['callback'] : array(
509 + $this,
510 + 'output_field',
511 + ) ),
460 512 $this->option_key,
461 513 $section_name,
462 514 $field + array(
463 515 'section' => $section_name,
464 - 'label_for' => sprintf( '%s_%s_%s', $this->option_key, $section_name, $field['name'] ), // xss ok
516 + 'label_for' => sprintf( '%s_%s_%s', $this->option_key, $section_name, $field['name'] ),
465 517 )
466 518 );
467 519 }
468 520 }
@@ -470,9 +522,9 @@
470 522
471 523 /**
472 524 * Sanitization callback for settings field values before save
473 525 *
474 - * @param array $input
526 + * @param array $input Raw input.
475 527 *
476 528 * @return array
477 529 */
478 530 public function sanitize_settings( $input ) {
@@ -491,38 +543,56 @@
491 543 if ( empty( $type ) || ! isset( $input[ $name ] ) || '' === $input[ $name ] ) {
492 544 continue;
493 545 }
494 546
495 - // Sanitize depending on the type of field
496 - switch ( $type ) {
497 - case 'number':
498 - $output[ $name ] = is_numeric( $input[ $name ] ) ? intval( trim( $input[ $name ] ) ) : '';
499 - break;
500 - case 'checkbox':
501 - $output[ $name ] = is_numeric( $input[ $name ] ) ? absint( trim( $input[ $name ] ) ) : '';
502 - break;
503 - default:
504 - if ( is_array( $input[ $name ] ) ) {
505 - $output[ $name ] = $input[ $name ];
547 + $output[ $name ] = $this->sanitize_setting_by_field_type( $input[ $name ], $type );
548 + }
549 + }
506 550
507 - // Support all values in multidimentional arrays too
508 - array_walk_recursive( $output[ $name ], function( &$v, $k ) {
509 - $v = trim( $v );
510 - } );
511 - } else {
512 - $output[ $name ] = trim( $input[ $name ] );
551 + return $output;
552 + }
553 +
554 + /**
555 + * Sanitizes a setting value based on the field type.
556 + *
557 + * @param mixed $value The value to be sanitized.
558 + * @param string $field_type The type of field.
559 + *
560 + * @return mixed The sanitized value.
561 + */
562 + public function sanitize_setting_by_field_type( $value, $field_type ) {
563 +
564 + // Sanitize depending on the type of field.
565 + switch ( $field_type ) {
566 + case 'number':
567 + $sanitized_value = is_numeric( $value ) ? intval( trim( $value ) ) : '';
568 + break;
569 + case 'checkbox':
570 + $sanitized_value = is_numeric( $value ) ? absint( trim( $value ) ) : '';
571 + break;
572 + default:
573 + if ( is_array( $value ) ) {
574 + $sanitized_value = $value;
575 +
576 + // Support all values in multidimentional arrays too.
577 + array_walk_recursive(
578 + $sanitized_value,
579 + function ( &$v ) {
580 + $v = sanitize_text_field( trim( $v ) );
513 581 }
582 + );
583 + } else {
584 + $sanitized_value = sanitize_text_field( trim( $value ) );
514 585 }
515 - }
516 586 }
517 587
518 - return $output;
588 + return $sanitized_value;
519 589 }
520 590
521 591 /**
522 592 * Compile HTML needed for displaying the field
523 593 *
524 - * @param array $field Field settings
594 + * @param array $field Field settings.
525 595 *
526 596 * @return string HTML to be displayed
527 597 */
528 598 public function render_field( $field ) {
@@ -545,14 +615,12 @@
545 615 $nonce = isset( $field['nonce'] ) ? $field['nonce'] : null;
546 616
547 617 if ( isset( $field['value'] ) ) {
548 618 $current_value = $field['value'];
619 + } elseif ( isset( $this->options[ $section . '_' . $name ] ) ) {
620 + $current_value = $this->options[ $section . '_' . $name ];
549 621 } else {
550 - if ( isset( $this->options[ $section . '_' . $name ] ) ) {
551 - $current_value = $this->options[ $section . '_' . $name ];
552 - } else {
553 - $current_value = null;
554 - }
622 + $current_value = null;
555 623 }
556 624
557 625 $option_key = $this->option_key;
558 626
@@ -563,11 +631,9 @@
563 631 if ( ! $type || ! $section || ! $name ) {
564 632 return '';
565 633 }
566 634
567 - if ( 'multi_checkbox' === $type
568 - && ( empty( $field['choices'] ) || ! is_array( $field['choices'] ) )
569 - ) {
635 + if ( 'multi_checkbox' === $type && ( empty( $field['choices'] ) || ! is_array( $field['choices'] ) ) ) {
570 636 return '';
571 637 }
572 638
573 639 switch ( $type ) {
@@ -626,10 +692,10 @@
626 692 esc_attr( $option_key ),
627 693 esc_attr( $section ),
628 694 esc_attr( $name )
629 695 );
630 - // Fallback if nothing is selected
631 - $output .= sprintf(
696 + // Fallback if nothing is selected.
697 + $output .= sprintf(
632 698 '<input type="hidden" name="%1$s[%2$s_%3$s][]" value="__placeholder__" />',
633 699 esc_attr( $option_key ),
634 700 esc_attr( $section ),
635 701 esc_attr( $name )
@@ -634,9 +700,9 @@
634 700 esc_attr( $section ),
635 701 esc_attr( $name )
636 702 );
637 703 $current_value = (array) $current_value;
638 - $choices = $field['choices'];
704 + $choices = $field['choices'];
639 705 if ( is_callable( $choices ) ) {
640 706 $choices = call_user_func( $choices );
641 707 }
642 708 foreach ( $choices as $value => $label ) {
@@ -701,9 +767,9 @@
701 767 esc_attr( $href ),
702 768 esc_attr( $title )
703 769 );
704 770 break;
705 - case 'select2' :
771 + case 'select2':
706 772 if ( ! isset( $current_value ) ) {
707 773 $current_value = '';
708 774 }
709 775
@@ -720,16 +786,26 @@
720 786 $child_values = array();
721 787 if ( isset( $value['children'] ) ) {
722 788 $child_values = array();
723 789 foreach ( $value['children'] as $child_key => $child_value ) {
724 - $child_values[] = array( 'id' => $child_key, 'text' => $child_value );
790 + $child_values[] = array(
791 + 'id' => $child_key,
792 + 'text' => $child_value,
793 + );
725 794 }
726 795 }
727 796 if ( isset( $value['label'] ) ) {
728 - $data_values[] = array( 'id' => $key, 'text' => $value['label'], 'children' => $child_values );
797 + $data_values[] = array(
798 + 'id' => $key,
799 + 'text' => $value['label'],
800 + 'children' => $child_values,
801 + );
729 802 }
730 803 } else {
731 - $data_values[] = array( 'id' => $key, 'text' => $value );
804 + $data_values[] = array(
805 + 'id' => $key,
806 + 'text' => $value,
807 + );
732 808 }
733 809 }
734 810 $class .= ' with-source';
735 811 }
@@ -738,11 +814,12 @@
738 814 '<input type="hidden" name="%1$s[%2$s_%3$s]" data-values=\'%4$s\' value="%5$s" class="select2-select %6$s" data-placeholder="%7$s" />',
739 815 esc_attr( $option_key ),
740 816 esc_attr( $section ),
741 817 esc_attr( $name ),
742 - esc_attr( wp_stream_json_encode( $data_values ) ),
818 + esc_attr( wp_json_encode( $data_values ) ),
743 819 esc_attr( $current_value ),
744 820 esc_attr( $class ),
821 + /* translators: %s: the title of the dropdown menu (e.g. "users") */
745 822 sprintf( esc_html__( 'Any %s', 'stream' ), $title )
746 823 );
747 824
748 825 $output = sprintf(
@@ -753,14 +830,15 @@
753 830 $input_html
754 831 );
755 832
756 833 break;
757 - case 'rule_list' :
758 - $form = new Form_Generator;
834 + case 'rule_list':
835 + $users = count_users();
836 + $form = new Form_Generator();
759 837 $output = '<p class="description">' . esc_html( $description ) . '</p>';
760 838
761 - $actions_top = sprintf( '<input type="button" class="button" id="%1$s_new_rule" value="&#43; %2$s" />', esc_attr( $section . '_' . $name ), esc_html__( 'Add New Rule', 'stream' ) );
762 - $actions_bottom = sprintf( '<input type="button" class="button" id="%1$s_remove_rules" value="%2$s" />', esc_attr( $section . '_' . $name ), esc_html__( 'Delete Selected Rules', 'stream' ) );
839 + $actions_top = sprintf( '<input type="button" class="button" id="%1$s_new_rule" value="&#43; %2$s" />', esc_attr( $section . '_' . $name ), esc_html__( 'Add New Rule', 'stream' ) );
840 + $actions_bottom = sprintf( '<input type="button" class="button" id="%1$s_remove_rules" value="%2$s" />', esc_attr( $section . '_' . $name ), esc_html__( 'Delete Selected Rules', 'stream' ) );
763 841
764 842 $output .= sprintf( '<div class="tablenav top">%1$s</div>', $actions_top );
765 843 $output .= '<table class="wp-list-table widefat fixed stream-exclude-list">';
766 844
@@ -784,13 +862,18 @@
784 862 );
785 863
786 864 $exclude_rows = array();
787 865
788 - // Prepend an empty row
789 - $current_value['exclude_row'] = array( 'helper' => '' ) + ( isset( $current_value['exclude_row'] ) ? $current_value['exclude_row'] : array() );
866 + // Account for when no rules have been added yet.
867 + if ( ! is_array( $current_value ) ) {
868 + $current_value = array();
869 + }
790 870
871 + // Prepend an empty row.
872 + $current_value['exclude_row'] = ( isset( $current_value['exclude_row'] ) ? $current_value['exclude_row'] : array() ) + array( 'helper' => '' );
873 +
791 874 foreach ( $current_value['exclude_row'] as $key => $value ) {
792 - // Prepare values
875 + // Prepare values.
793 876 $author_or_role = isset( $current_value['author_or_role'][ $key ] ) ? $current_value['author_or_role'][ $key ] : '';
794 877 $connector = isset( $current_value['connector'][ $key ] ) ? $current_value['connector'][ $key ] : '';
795 878 $context = isset( $current_value['context'][ $key ] ) ? $current_value['context'][ $key ] : '';
796 879 $action = isset( $current_value['action'][ $key ] ) ? $current_value['action'][ $key ] : '';
@@ -795,18 +878,21 @@
795 878 $context = isset( $current_value['context'][ $key ] ) ? $current_value['context'][ $key ] : '';
796 879 $action = isset( $current_value['action'][ $key ] ) ? $current_value['action'][ $key ] : '';
797 880 $ip_address = isset( $current_value['ip_address'][ $key ] ) ? $current_value['ip_address'][ $key ] : '';
798 881
799 - // Author or Role dropdown menu
882 + // Author or Role dropdown menu.
800 883 $author_or_role_values = array();
801 884 $author_or_role_selected = array();
802 885
803 886 foreach ( $this->get_roles() as $role_id => $role ) {
804 - $args = array( 'value' => $role_id, 'text' => $role );
805 - $users = count_users();
887 + $args = array(
888 + 'value' => $role_id,
889 + 'text' => $role,
890 + );
806 891 $count = isset( $users['avail_roles'][ $role_id ] ) ? $users['avail_roles'][ $role_id ] : 0;
807 892
808 893 if ( ! empty( $count ) ) {
894 + /* translators: %d: a number of users (e.g. "42") */
809 895 $args['user_count'] = sprintf( _n( '%d user', '%d users', absint( $count ), 'stream' ), absint( $count ) );
810 896 }
811 897
812 898 if ( $role_id === $author_or_role ) {
@@ -819,25 +905,33 @@
819 905
820 906 if ( empty( $author_or_role_selected ) && is_numeric( $author_or_role ) ) {
821 907 $user = new WP_User( $author_or_role );
822 908 $display_name = ( 0 === $user->ID ) ? esc_html__( 'N/A', 'stream' ) : $user->display_name;
823 - $author_or_role_selected = array( 'value' => $user->ID, 'text' => $display_name );
909 + $author_or_role_selected = array(
910 + 'value' => $user->ID,
911 + 'text' => $display_name,
912 + );
824 913 $author_or_role_values[] = $author_or_role_selected;
825 914 }
826 915
827 - $author_or_role_input = $form->render_field( 'select2', array(
828 - 'name' => esc_attr( sprintf( '%1$s[%2$s_%3$s][%4$s][]' , $option_key, $section, $name, 'author_or_role' ) ),
829 - 'options' => $author_or_role_values,
830 - 'classes' => 'author_or_role',
831 - 'data' => array(
832 - 'placeholder' => esc_html__( 'Any Author or Role', 'stream' ),
833 - 'nonce' => esc_attr( wp_create_nonce( 'stream_get_users' ) ),
834 - 'selected-id' => isset( $author_or_role_selected['value'] ) ? esc_attr( $author_or_role_selected['value'] ) : '',
835 - 'selected-text' => isset( $author_or_role_selected['text'] ) ? esc_attr( $author_or_role_selected['text'] ) : '',
916 + $author_or_role_input = $form->render_field(
917 + 'select2',
918 + array(
919 + 'name' => esc_attr( sprintf( '%1$s[%2$s_%3$s][%4$s][]', $option_key, $section, $name, 'author_or_role' ) ),
920 + 'options' => $author_or_role_values,
921 + 'classes' => 'author_or_role',
922 + // Data attributes are escaped in Form_Generator::prepare_data_attributes_string().
923 + 'data' => array(
924 + 'placeholder' => __( 'Any Author or Role', 'stream' ),
925 + 'nonce' => wp_create_nonce( 'stream_get_users' ),
926 + 'selected-id' => isset( $author_or_role_selected['value'] ) ? $author_or_role_selected['value'] : '',
927 + 'selected-text' => isset( $author_or_role_selected['text'] ) ? $author_or_role_selected['text'] : '',
928 + ),
836 929 ),
837 - ) );
930 + false
931 + );
838 932
839 - // Context dropdown menu
933 + // Context dropdown menu.
840 934 $context_values = array();
841 935
842 936 foreach ( $this->get_terms_labels( 'context' ) as $context_id => $context_data ) {
843 937 if ( is_array( $context_data ) ) {
@@ -844,71 +938,108 @@
844 938 $child_values = array();
845 939 if ( isset( $context_data['children'] ) ) {
846 940 $child_values = array();
847 941 foreach ( $context_data['children'] as $child_id => $child_value ) {
848 - $child_values[] = array( 'value' => $context_id . '-' . $child_id, 'text' => $child_value, 'parent' => $context_id );
942 + $child_values[] = array(
943 + 'value' => $context_id . '-' . $child_id,
944 + 'text' => $child_value,
945 + 'parent' => $context_id,
946 + );
849 947 }
850 948 }
851 949 if ( isset( $context_data['label'] ) ) {
852 - $context_values[] = array( 'value' => $context_id, 'text' => $context_data['label'], 'children' => $child_values );
950 + $context_values[] = array(
951 + 'value' => $context_id,
952 + 'text' => $context_data['label'],
953 + 'children' => $child_values,
954 + );
853 955 }
854 956 } else {
855 - $context_values[] = array( 'value' => $context_id, 'text' => $context_data );
957 + $context_values[] = array(
958 + 'value' => $context_id,
959 + 'text' => $context_data,
960 + );
856 961 }
857 962 }
858 963
859 - $connector_or_context_input = $form->render_field( 'select2', array(
860 - 'name' => esc_attr( sprintf( '%1$s[%2$s_%3$s][%4$s][]' , $option_key, $section, $name, 'connector_or_context' ) ),
861 - 'options' => $context_values,
862 - 'classes' => 'connector_or_context',
863 - 'data' => array(
864 - 'group' => 'connector',
865 - 'placeholder' => __( 'Any Context', 'stream' ),
964 + $connector_or_context_input = $form->render_field(
965 + 'select2',
966 + array(
967 + 'name' => esc_attr( sprintf( '%1$s[%2$s_%3$s][%4$s][]', $option_key, $section, $name, 'connector_or_context' ) ),
968 + 'options' => $context_values,
969 + 'classes' => 'connector_or_context',
970 + // Data attributes are escaped in Form_Generator::prepare_data_attributes_string().
971 + 'data' => array(
972 + 'group' => 'connector',
973 + 'placeholder' => __( 'Any Context', 'stream' ),
974 + ),
866 975 ),
867 - ) );
976 + false
977 + );
868 978
869 - $connector_input = $form->render_field( 'hidden', array(
870 - 'name' => esc_attr( sprintf( '%1$s[%2$s_%3$s][%4$s][]' , $option_key, $section, $name, 'connector' ) ),
871 - 'value' => $connector,
872 - 'classes' => 'connector',
873 - ) );
979 + $connector_input = $form->render_field(
980 + 'hidden',
981 + array(
982 + 'name' => esc_attr( sprintf( '%1$s[%2$s_%3$s][%4$s][]', $option_key, $section, $name, 'connector' ) ),
983 + 'value' => $connector,
984 + 'classes' => 'connector',
985 + ),
986 + false
987 + );
874 988
875 - $context_input = $form->render_field( 'hidden', array(
876 - 'name' => esc_attr( sprintf( '%1$s[%2$s_%3$s][%4$s][]' , $option_key, $section, $name, 'context' ) ),
877 - 'value' => $context,
878 - 'classes' => 'context',
879 - ) );
989 + $context_input = $form->render_field(
990 + 'hidden',
991 + array(
992 + 'name' => esc_attr( sprintf( '%1$s[%2$s_%3$s][%4$s][]', $option_key, $section, $name, 'context' ) ),
993 + 'value' => $context,
994 + 'classes' => 'context',
995 + ),
996 + false
997 + );
880 998
881 - // Action dropdown menu
999 + // Action dropdown menu.
882 1000 $action_values = array();
883 1001
884 1002 foreach ( $this->get_terms_labels( 'action' ) as $action_id => $action_data ) {
885 - $action_values[] = array( 'value' => $action_id, 'text' => $action_data );
1003 + $action_values[] = array(
1004 + 'value' => $action_id,
1005 + 'text' => $action_data,
1006 + );
886 1007 }
887 1008
888 - $action_input = $form->render_field( 'select2', array(
889 - 'name' => esc_attr( sprintf( '%1$s[%2$s_%3$s][%4$s][]' , $option_key, $section, $name, 'action' ) ),
890 - 'value' => $action,
891 - 'options' => $action_values,
892 - 'classes' => 'action',
893 - 'data' => array(
894 - 'placeholder' => __( 'Any Action', 'stream' ),
1009 + $action_input = $form->render_field(
1010 + 'select2',
1011 + array(
1012 + 'name' => esc_attr( sprintf( '%1$s[%2$s_%3$s][%4$s][]', $option_key, $section, $name, 'action' ) ),
1013 + 'value' => $action,
1014 + 'options' => $action_values,
1015 + 'classes' => 'action',
1016 + // Data attributes are escaped in Form_Generator::prepare_data_attributes_string().
1017 + 'data' => array(
1018 + 'placeholder' => __( 'Any Action', 'stream' ),
1019 + ),
895 1020 ),
896 - ) );
1021 + false
1022 + );
897 1023
898 - // IP Address input
899 - $ip_address_input = $form->render_field( 'select2', array(
900 - 'name' => esc_attr( sprintf( '%1$s[%2$s_%3$s][%4$s][]' , $option_key, $section, $name, 'ip_address' ) ),
901 - 'value' => $ip_address,
902 - 'classes' => 'ip_address',
903 - 'data' => array(
904 - 'placeholder' => esc_attr__( 'Any IP Address', 'stream' ),
905 - 'nonce' => esc_attr( wp_create_nonce( 'stream_get_ips' ) ),
1024 + // IP Address input.
1025 + $ip_address_input = $form->render_field(
1026 + 'select2',
1027 + array(
1028 + 'name' => esc_attr( sprintf( '%1$s[%2$s_%3$s][%4$s][]', $option_key, $section, $name, 'ip_address' ) ),
1029 + 'value' => $ip_address,
1030 + 'classes' => 'ip_address',
1031 + // Data attributes are escaped in Form_Generator::prepare_data_attributes_string().
1032 + 'data' => array(
1033 + 'placeholder' => __( 'Any IP Address', 'stream' ),
1034 + 'nonce' => wp_create_nonce( 'stream_get_ips' ),
1035 + ),
1036 + 'multiple' => true,
906 1037 ),
907 - 'multiple' => true,
908 - ) );
1038 + false
1039 + );
909 1040
910 - // Hidden helper input
1041 + // Hidden helper input.
911 1042 $helper_input = sprintf(
912 1043 '<input type="hidden" name="%1$s[%2$s_%3$s][%4$s][]" value="" />',
913 1044 esc_attr( $option_key ),
914 1045 esc_attr( $section ),
@@ -922,12 +1053,14 @@
922 1053 <td>%5$s</td>
923 1054 <td>%6$s %7$s %8$s</td>
924 1055 <td>%9$s</td>
925 1056 <td>%10$s</td>
926 - <th scope="row" class="actions-column">%11$s</th>
1057 + <th scope="row" class="actions-column">
1058 + <a href="#" class="exclude_rules_remove_rule_row">%11$s</a>
1059 + </th>
927 1060 </tr>',
928 - ( 0 !== $key % 2 ) ? 'alternate' : '',
929 - ( 'helper' === $key ) ? 'hidden helper' : '',
1061 + ( 0 !== (int) $key % 2 ) ? 'alternate' : '',
1062 + ( 'helper' === (string) $key ) ? 'hidden helper' : '',
930 1063 '<input class="cb-select" type="checkbox" />',
931 1064 $helper_input,
932 1065 $author_or_role_input,
933 1066 $connector_or_context_input,
@@ -934,9 +1067,9 @@
934 1067 $connector_input,
935 1068 $context_input,
936 1069 $action_input,
937 1070 $ip_address_input,
938 - '<a href="#" class="exclude_rules_remove_rule_row">Delete</a>'
1071 + esc_html__( 'Delete', 'stream' )
939 1072 );
940 1073 }
941 1074
942 1075 $no_rules_found_row = sprintf(
@@ -961,9 +1094,9 @@
961 1094
962 1095 /**
963 1096 * Render Callback for post_types field
964 1097 *
965 - * @param array $field
1098 + * @param array $field Field to be rendered.
966 1099 *
967 1100 * @return string
968 1101 */
969 1102 public function output_field( $field ) {
@@ -974,9 +1107,9 @@
974 1107 }
975 1108
976 1109 $output = $this->render_field( $field );
977 1110
978 - echo $output; // xss ok
1111 + echo $output; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
979 1112 }
980 1113
981 1114 /**
982 1115 * Get an array of user roles
@@ -996,9 +1129,9 @@
996 1129
997 1130 /**
998 1131 * Function will return all terms labels of given column
999 1132 *
1000 - * @param string $column string Name of the column
1133 + * @param string $column Name of the column.
1001 1134 *
1002 1135 * @return array
1003 1136 */
1004 1137 public function get_terms_labels( $column ) {
@@ -1031,14 +1164,14 @@
1031 1164 * Remove records when records TTL is shortened
1032 1165 *
1033 1166 * @action update_option_wp_stream
1034 1167 *
1035 - * @param array $old_value
1036 - * @param array $new_value
1168 + * @param array $old_value Old value.
1169 + * @param array $new_value New value.
1037 1170 */
1038 1171 public function updated_option_ttl_remove_records( $old_value, $new_value ) {
1039 - $ttl_before = isset( $old_value['general_records_ttl'] ) ? (int) $old_value['general_records_ttl'] : -1;
1040 - $ttl_after = isset( $new_value['general_records_ttl'] ) ? (int) $new_value['general_records_ttl'] : -1;
1172 + $ttl_before = isset( $old_value['general_records_ttl'] ) ? (int) $old_value['general_records_ttl'] : - 1;
1173 + $ttl_after = isset( $new_value['general_records_ttl'] ) ? (int) $new_value['general_records_ttl'] : - 1;
1041 1174
1042 1175 if ( $ttl_after < $ttl_before ) {
1043 1176 /**
1044 1177 * Action assists in purging when TTL is shortened
@@ -1050,8 +1183,10 @@
1050 1183 /**
1051 1184 * Get translations of serialized Stream settings
1052 1185 *
1053 1186 * @filter wp_stream_serialized_labels
1187 + *
1188 + * @param array $labels Setting labels.
1054 1189 *
1055 1190 * @return array Multidimensional array of fields
1056 1191 */
1057 1192 public function get_settings_translations( $labels ) {