PluginProbe
Stream – Activity Log & Audit Trail / 3.9.2
Stream – Activity Log & Audit Trail v3.9.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 +295 -172 3.0.63.9.2 View file →
@@ -1,5 +1,11 @@
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 10 use \WP_Roles;
5 11 use \WP_User;
@@ -4,11 +10,16 @@
4 10 use \WP_Roles;
5 11 use \WP_User;
6 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 /**
@@ -84,21 +109,31 @@
84 109 'message' => esc_html__( 'There was an error in the request', 'stream' ),
85 110 );
86 111
87 112 $search = '';
88 - if ( isset( $_POST['find'] ) ) {
89 - // @TODO: Make this pass phpcs
90 - $search = esc_html( wp_unslash( trim( $_POST['find'] ) ) ); // input var okay
113 + $input = wp_stream_filter_input( INPUT_POST, 'find' );
114 +
115 + if ( ! isset( $input['term'] ) ) {
116 + $search = wp_unslash( trim( $input['term'] ) );
91 117 }
118 +
92 119 $request = (object) array(
93 120 'find' => $search,
94 121 );
95 122
96 - 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 + );
97 132
98 133 $users = new WP_User_Query(
99 134 array(
100 - 'search' => "*{$request->find}*",
135 + 'search' => "*{$request->find}*",
101 136 'search_columns' => array(
102 137 'user_login',
103 138 'user_nicename',
104 139 'user_email',
@@ -103,14 +138,21 @@
103 138 'user_nicename',
104 139 'user_email',
105 140 'user_url',
106 141 ),
107 - 'orderby' => 'display_name',
108 - 'number' => $this->plugin->admin->preload_users_max,
142 + 'orderby' => 'display_name',
143 + 'number' => $this->plugin->admin->preload_users_max,
109 144 )
110 145 );
111 146
112 - 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 + );
113 155
114 156 if ( 0 === $users->get_total() ) {
115 157 wp_send_json_error( $response );
116 158 }
@@ -118,20 +160,21 @@
118 160
119 161 if ( is_multisite() && is_super_admin() ) {
120 162 $super_admins = get_super_admins();
121 163 foreach ( $super_admins as $admin ) {
122 - $user = get_user_by( 'login', $admin );
164 + $user = get_user_by( 'login', $admin );
123 165 $users_array[] = $user;
124 166 }
125 167 }
126 168
127 - $response->status = true;
128 - $response->message = '';
129 - $response->users = array();
169 + $response->status = true;
170 + $response->message = '';
171 + $response->roles = $this->get_roles();
172 + $response->users = array();
130 173 $users_added_to_response = array();
131 174
132 175 foreach ( $users_array as $key => $user ) {
133 - // exclude duplications:
176 + // exclude duplications.
134 177 if ( array_key_exists( $user->ID, $users_added_to_response ) ) {
135 178 continue;
136 179 } else {
137 180 $users_added_to_response[ $user->ID ] = true;
@@ -145,9 +188,10 @@
145 188 );
146 189
147 190 $args['tooltip'] = esc_attr(
148 191 sprintf(
149 - __( "ID: %d\nUser: %s\nEmail: %s\nRole: %s", 'stream' ),
192 + /* translators: %1$d: user ID, %2$s: username, %3$s: email, %4$s: user role (e.g. "42", "administrator", "foo@bar.com", "subscriber") */
193 + __( 'ID: %1$d\nUser: %2$s\nEmail: %3$s\nRole: %4$s', 'stream' ),
150 194 $author->id,
151 195 $author->user_login,
152 196 $author->user_email,
153 197 ucwords( $author->get_role() )
@@ -160,17 +204,17 @@
160 204 }
161 205
162 206 usort(
163 207 $response->users,
164 - function( $a, $b ) {
208 + function ( $a, $b ) {
165 209 return strcmp( $a['text'], $b['text'] );
166 210 }
167 211 );
168 212
169 213 if ( empty( $search ) || preg_match( '/wp|cli|system|unknown/i', $search ) ) {
170 - $author = new Author( 0 );
214 + $author = new Author( 0 );
171 215 $response->users[] = array(
172 - 'id' => $author->id,
216 + 'id' => '0',
173 217 'text' => $author->get_display_name(),
174 218 'icon' => $author->get_avatar_src( 32 ),
175 219 'tooltip' => esc_html__( 'Actions performed by the system when a user is not logged in (e.g. auto site upgrader, or invoking WP-CLI without --user)', 'stream' ),
176 220 );
@@ -179,10 +223,10 @@
179 223 wp_send_json_success( $response );
180 224 }
181 225
182 226 /**
183 - * Ajax callback function to search IP addresses, used on exclude setting page
184 - */
227 + * Ajax callback function to search IP addresses, used on exclude setting page
228 + */
185 229 public function get_ips() {
186 230 if ( ! defined( 'DOING_AJAX' ) || ! current_user_can( $this->plugin->admin->settings_cap ) ) {
187 231 return;
188 232 }
@@ -188,10 +232,20 @@
188 232 }
189 233
190 234 check_ajax_referer( 'stream_get_ips', 'nonce' );
191 235
192 - $ips = $this->plugin->db->existing_records( 'ip' );
236 + $ips = $this->plugin->db->existing_records( 'ip' );
237 + $find = wp_stream_filter_input( INPUT_POST, 'find' );
193 238
239 + if ( isset( $find['term'] ) && '' !== $find['term'] ) {
240 + $ips = array_filter(
241 + $ips,
242 + function ( $ip ) use ( $find ) {
243 + return 0 === strpos( $ip, $find['term'] );
244 + }
245 + );
246 + }
247 +
194 248 if ( $ips ) {
195 249 wp_send_json_success( $ips );
196 250 } else {
197 251 wp_send_json_error();
@@ -200,11 +254,11 @@
200 254
201 255 /**
202 256 * Filter the columns to search in a WP_User_Query search.
203 257 *
204 - * @param array $search_columns Array of column names to be searched.
205 - * @param string $search Text being searched.
206 - * @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.
207 261 *
208 262 * @return array
209 263 */
210 264 public function add_display_name_search_columns( $search_columns, $search, $query ) {
@@ -243,24 +297,24 @@
243 297 * @return array
244 298 */
245 299 public function get_fields() {
246 300 $fields = array(
247 - 'general' => array(
301 + 'general' => array(
248 302 'title' => esc_html__( 'General', 'stream' ),
249 303 'fields' => array(
250 304 array(
251 - 'name' => 'role_access',
252 - 'title' => esc_html__( 'Role Access', 'stream' ),
253 - 'type' => 'multi_checkbox',
254 - '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' ),
255 - 'choices' => $this->get_roles(),
256 - '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' ),
257 311 ),
258 312 array(
259 313 'name' => 'records_ttl',
260 314 'title' => esc_html__( 'Keep Records for', 'stream' ),
261 315 'type' => 'number',
262 - 'class' => 'small-text hidden',
316 + 'class' => 'small-text',
263 317 'desc' => esc_html__( 'Maximum number of days to keep activity records.', 'stream' ),
264 318 'default' => 30,
265 319 'min' => 1,
266 320 'max' => 999,
@@ -276,18 +330,18 @@
276 330 'default' => 0,
277 331 ),
278 332 ),
279 333 ),
280 - 'exclude' => array(
334 + 'exclude' => array(
281 335 'title' => esc_html__( 'Exclude', 'stream' ),
282 336 'fields' => array(
283 337 array(
284 - 'name' => 'rules',
285 - 'title' => esc_html__( 'Exclude Rules', 'stream' ),
286 - 'type' => 'rule_list',
287 - 'desc' => esc_html__( 'Create rules to exclude certain kinds of activity from being recorded by Stream.', 'stream' ),
288 - 'default' => array(),
289 - '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',
290 344 ),
291 345 ),
292 346 ),
293 347 'advanced' => array(
@@ -301,28 +355,28 @@
301 355 'after_field' => esc_html__( 'Enabled', 'stream' ),
302 356 'default' => 0,
303 357 ),
304 358 array(
305 - 'name' => 'delete_all_records',
306 - 'title' => esc_html__( 'Reset Stream Database', 'stream' ),
307 - 'type' => 'link',
308 - '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(
309 363 array(
310 - 'action' => 'wp_stream_reset',
311 - 'wp_stream_nonce' => wp_create_nonce( 'stream_nonce' ),
364 + 'action' => 'wp_stream_reset',
365 + 'wp_stream_nonce_reset' => wp_create_nonce( 'stream_nonce_reset' ),
312 366 ),
313 367 admin_url( 'admin-ajax.php' )
314 368 ),
315 - 'class' => 'warning',
316 - 'desc' => esc_html__( 'Warning: This will delete all activity records from the database.', 'stream' ),
317 - 'default' => 0,
318 - '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',
319 373 ),
320 374 ),
321 375 ),
322 376 );
323 377
324 - // 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.
325 379 if ( class_exists( 'Akismet' ) ) {
326 380 $akismet_tracking = array(
327 381 'name' => 'akismet_tracking',
328 382 'title' => esc_html__( 'Akismet Tracking', 'stream' ),
@@ -334,21 +388,18 @@
334 388
335 389 array_push( $fields['advanced']['fields'], $akismet_tracking );
336 390 }
337 391
338 - // If WP Cron is enabled, allow Admins to opt-in to WP Cron tracking
339 - if ( wp_stream_is_cron_enabled() ) {
340 - $wp_cron_tracking = array(
341 - 'name' => 'wp_cron_tracking',
342 - 'title' => esc_html__( 'WP Cron Tracking', 'stream' ),
343 - 'type' => 'checkbox',
344 - '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' ),
345 - 'after_field' => esc_html__( 'Enabled', 'stream' ),
346 - 'default' => 0,
347 - );
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 + );
348 400
349 - array_push( $fields['advanced']['fields'], $wp_cron_tracking );
350 - }
401 + array_push( $fields['advanced']['fields'], $wp_cron_tracking );
351 402
352 403 /**
353 404 * Filter allows for modification of options fields
354 405 *
@@ -355,9 +406,9 @@
355 406 * @return array Array of option fields
356 407 */
357 408 $this->fields = apply_filters( 'wp_stream_settings_option_fields', $fields );
358 409
359 - // Sort option fields in each tab by title ASC
410 + // Sort option fields in each tab by title ASC.
360 411 foreach ( $this->fields as $tab => $options ) {
361 412 $titles = array();
362 413
363 414 foreach ( $options['fields'] as $field ) {
@@ -427,9 +478,16 @@
427 478 */
428 479 public function register_settings() {
429 480 $sections = $this->get_fields();
430 481
431 - 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 + );
432 490
433 491 foreach ( $sections as $section_name => $section ) {
434 492 add_settings_section(
435 493 $section_name,
@@ -438,9 +496,10 @@
438 496 $this->option_key
439 497 );
440 498
441 499 foreach ( $section['fields'] as $field_idx => $field ) {
442 - if ( ! isset( $field['type'] ) ) { // No field type associated, skip, no GUI
500 + // No field type associated, skip, no GUI.
501 + if ( ! isset( $field['type'] ) ) {
443 502 continue;
444 503 }
445 504
446 505 add_settings_field(
@@ -445,14 +504,18 @@
445 504
446 505 add_settings_field(
447 506 $field['name'],
448 507 $field['title'],
449 - ( isset( $field['callback'] ) ? $field['callback'] : array( $this, 'output_field' ) ),
508 + ( isset( $field['callback'] ) ? $field['callback'] : array(
509 + $this,
510 + 'output_field',
511 + ) ),
450 512 $this->option_key,
451 513 $section_name,
452 514 $field + array(
453 515 'section' => $section_name,
454 - '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'] ),
517 + // xss ok.
455 518 )
456 519 );
457 520 }
458 521 }
@@ -460,9 +523,9 @@
460 523
461 524 /**
462 525 * Sanitization callback for settings field values before save
463 526 *
464 - * @param array $input
527 + * @param array $input Raw input.
465 528 *
466 529 * @return array
467 530 */
468 531 public function sanitize_settings( $input ) {
@@ -481,9 +544,9 @@
481 544 if ( empty( $type ) || ! isset( $input[ $name ] ) || '' === $input[ $name ] ) {
482 545 continue;
483 546 }
484 547
485 - // Sanitize depending on the type of field
548 + // Sanitize depending on the type of field.
486 549 switch ( $type ) {
487 550 case 'number':
488 551 $output[ $name ] = is_numeric( $input[ $name ] ) ? intval( trim( $input[ $name ] ) ) : '';
489 552 break;
@@ -493,14 +556,17 @@
493 556 default:
494 557 if ( is_array( $input[ $name ] ) ) {
495 558 $output[ $name ] = $input[ $name ];
496 559
497 - // Support all values in multidimentional arrays too
498 - array_walk_recursive( $output[ $name ], function( &$v, $k ) {
499 - $v = trim( $v );
500 - } );
560 + // Support all values in multidimentional arrays too.
561 + array_walk_recursive(
562 + $output[ $name ],
563 + function ( &$v ) {
564 + $v = sanitize_text_field( trim( $v ) );
565 + }
566 + );
501 567 } else {
502 - $output[ $name ] = trim( $input[ $name ] );
568 + $output[ $name ] = sanitize_text_field( trim( $input[ $name ] ) );
503 569 }
504 570 }
505 571 }
506 572 }
@@ -510,9 +576,9 @@
510 576
511 577 /**
512 578 * Compile HTML needed for displaying the field
513 579 *
514 - * @param array $field Field settings
580 + * @param array $field Field settings.
515 581 *
516 582 * @return string HTML to be displayed
517 583 */
518 584 public function render_field( $field ) {
@@ -553,11 +619,9 @@
553 619 if ( ! $type || ! $section || ! $name ) {
554 620 return '';
555 621 }
556 622
557 - if ( 'multi_checkbox' === $type
558 - && ( empty( $field['choices'] ) || ! is_array( $field['choices'] ) )
559 - ) {
623 + if ( 'multi_checkbox' === $type && ( empty( $field['choices'] ) || ! is_array( $field['choices'] ) ) ) {
560 624 return '';
561 625 }
562 626
563 627 switch ( $type ) {
@@ -616,10 +680,10 @@
616 680 esc_attr( $option_key ),
617 681 esc_attr( $section ),
618 682 esc_attr( $name )
619 683 );
620 - // Fallback if nothing is selected
621 - $output .= sprintf(
684 + // Fallback if nothing is selected.
685 + $output .= sprintf(
622 686 '<input type="hidden" name="%1$s[%2$s_%3$s][]" value="__placeholder__" />',
623 687 esc_attr( $option_key ),
624 688 esc_attr( $section ),
625 689 esc_attr( $name )
@@ -624,9 +688,9 @@
624 688 esc_attr( $section ),
625 689 esc_attr( $name )
626 690 );
627 691 $current_value = (array) $current_value;
628 - $choices = $field['choices'];
692 + $choices = $field['choices'];
629 693 if ( is_callable( $choices ) ) {
630 694 $choices = call_user_func( $choices );
631 695 }
632 696 foreach ( $choices as $value => $label ) {
@@ -691,9 +755,9 @@
691 755 esc_attr( $href ),
692 756 esc_attr( $title )
693 757 );
694 758 break;
695 - case 'select2' :
759 + case 'select2':
696 760 if ( ! isset( $current_value ) ) {
697 761 $current_value = '';
698 762 }
699 763
@@ -710,16 +774,26 @@
710 774 $child_values = array();
711 775 if ( isset( $value['children'] ) ) {
712 776 $child_values = array();
713 777 foreach ( $value['children'] as $child_key => $child_value ) {
714 - $child_values[] = array( 'id' => $child_key, 'text' => $child_value );
778 + $child_values[] = array(
779 + 'id' => $child_key,
780 + 'text' => $child_value,
781 + );
715 782 }
716 783 }
717 784 if ( isset( $value['label'] ) ) {
718 - $data_values[] = array( 'id' => $key, 'text' => $value['label'], 'children' => $child_values );
785 + $data_values[] = array(
786 + 'id' => $key,
787 + 'text' => $value['label'],
788 + 'children' => $child_values,
789 + );
719 790 }
720 791 } else {
721 - $data_values[] = array( 'id' => $key, 'text' => $value );
792 + $data_values[] = array(
793 + 'id' => $key,
794 + 'text' => $value,
795 + );
722 796 }
723 797 }
724 798 $class .= ' with-source';
725 799 }
@@ -731,8 +805,9 @@
731 805 esc_attr( $name ),
732 806 esc_attr( wp_stream_json_encode( $data_values ) ),
733 807 esc_attr( $current_value ),
734 808 esc_attr( $class ),
809 + /* translators: %s: the title of the dropdown menu (e.g. "users") */
735 810 sprintf( esc_html__( 'Any %s', 'stream' ), $title )
736 811 );
737 812
738 813 $output = sprintf(
@@ -743,13 +818,15 @@
743 818 $input_html
744 819 );
745 820
746 821 break;
747 - case 'rule_list' :
822 + case 'rule_list':
823 + $users = count_users();
824 + $form = new Form_Generator();
748 825 $output = '<p class="description">' . esc_html( $description ) . '</p>';
749 826
750 - $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' ) );
751 - $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' ) );
827 + $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' ) );
828 + $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' ) );
752 829
753 830 $output .= sprintf( '<div class="tablenav top">%1$s</div>', $actions_top );
754 831 $output .= '<table class="wp-list-table widefat fixed stream-exclude-list">';
755 832
@@ -773,13 +850,18 @@
773 850 );
774 851
775 852 $exclude_rows = array();
776 853
777 - // Prepend an empty row
778 - $current_value['exclude_row'] = array( 'helper' => '' ) + ( isset( $current_value['exclude_row'] ) ? $current_value['exclude_row'] : array() );
854 + // Account for when no rules have been added yet.
855 + if ( ! is_array( $current_value ) ) {
856 + $current_value = array();
857 + }
779 858
859 + // Prepend an empty row.
860 + $current_value['exclude_row'] = ( isset( $current_value['exclude_row'] ) ? $current_value['exclude_row'] : array() ) + array( 'helper' => '' );
861 +
780 862 foreach ( $current_value['exclude_row'] as $key => $value ) {
781 - // Prepare values
863 + // Prepare values.
782 864 $author_or_role = isset( $current_value['author_or_role'][ $key ] ) ? $current_value['author_or_role'][ $key ] : '';
783 865 $connector = isset( $current_value['connector'][ $key ] ) ? $current_value['connector'][ $key ] : '';
784 866 $context = isset( $current_value['context'][ $key ] ) ? $current_value['context'][ $key ] : '';
785 867 $action = isset( $current_value['action'][ $key ] ) ? $current_value['action'][ $key ] : '';
@@ -784,24 +866,27 @@
784 866 $context = isset( $current_value['context'][ $key ] ) ? $current_value['context'][ $key ] : '';
785 867 $action = isset( $current_value['action'][ $key ] ) ? $current_value['action'][ $key ] : '';
786 868 $ip_address = isset( $current_value['ip_address'][ $key ] ) ? $current_value['ip_address'][ $key ] : '';
787 869
788 - // Author or Role dropdown menu
870 + // Author or Role dropdown menu.
789 871 $author_or_role_values = array();
790 872 $author_or_role_selected = array();
791 873
792 874 foreach ( $this->get_roles() as $role_id => $role ) {
793 - $args = array( 'id' => $role_id, 'text' => $role );
794 - $users = count_users();
875 + $args = array(
876 + 'value' => $role_id,
877 + 'text' => $role,
878 + );
795 879 $count = isset( $users['avail_roles'][ $role_id ] ) ? $users['avail_roles'][ $role_id ] : 0;
796 880
797 881 if ( ! empty( $count ) ) {
798 - $args['user_count'] = sprintf( _n( '1 user', '%s users', absint( $count ), 'stream' ), absint( $count ) );
882 + /* translators: %d: a number of users (e.g. "42") */
883 + $args['user_count'] = sprintf( _n( '%d user', '%d users', absint( $count ), 'stream' ), absint( $count ) );
799 884 }
800 885
801 886 if ( $role_id === $author_or_role ) {
802 - $author_or_role_selected['id'] = $role_id;
803 - $author_or_role_selected['text'] = $role;
887 + $author_or_role_selected['value'] = $role_id;
888 + $author_or_role_selected['text'] = $role;
804 889 }
805 890
806 891 $author_or_role_values[] = $args;
807 892 }
@@ -808,25 +893,31 @@
808 893
809 894 if ( empty( $author_or_role_selected ) && is_numeric( $author_or_role ) ) {
810 895 $user = new WP_User( $author_or_role );
811 896 $display_name = ( 0 === $user->ID ) ? esc_html__( 'N/A', 'stream' ) : $user->display_name;
812 - $author_or_role_selected = array( 'id' => $user->ID, 'text' => $display_name );
897 + $author_or_role_selected = array(
898 + 'value' => $user->ID,
899 + 'text' => $display_name,
900 + );
901 + $author_or_role_values[] = $author_or_role_selected;
813 902 }
814 903
815 - $author_or_role_input = sprintf(
816 - '<input type="hidden" name="%1$s[%2$s_%3$s][%4$s][]" data-values=\'%5$s\' data-selected-id=\'%6$s\' data-selected-text=\'%7$s\' value="%6$s" class="select2-select %4$s" data-placeholder="%8$s" data-nonce="%9$s" />',
817 - esc_attr( $option_key ),
818 - esc_attr( $section ),
819 - esc_attr( $name ),
820 - 'author_or_role',
821 - esc_attr( wp_stream_json_encode( $author_or_role_values ) ),
822 - isset( $author_or_role_selected['id'] ) ? esc_attr( $author_or_role_selected['id'] ) : '',
823 - isset( $author_or_role_selected['text'] ) ? esc_attr( $author_or_role_selected['text'] ) : '',
824 - esc_html__( 'Any Author or Role', 'stream' ),
825 - esc_attr( wp_create_nonce( 'stream_get_users' ) )
904 + $author_or_role_input = $form->render_field(
905 + 'select2',
906 + array(
907 + 'name' => esc_attr( sprintf( '%1$s[%2$s_%3$s][%4$s][]', $option_key, $section, $name, 'author_or_role' ) ),
908 + 'options' => $author_or_role_values,
909 + 'classes' => 'author_or_role',
910 + 'data' => array(
911 + 'placeholder' => esc_html__( 'Any Author or Role', 'stream' ),
912 + 'nonce' => esc_attr( wp_create_nonce( 'stream_get_users' ) ),
913 + 'selected-id' => isset( $author_or_role_selected['value'] ) ? esc_attr( $author_or_role_selected['value'] ) : '',
914 + 'selected-text' => isset( $author_or_role_selected['text'] ) ? esc_attr( $author_or_role_selected['text'] ) : '',
915 + ),
916 + )
826 917 );
827 918
828 - // Context dropdown menu
919 + // Context dropdown menu.
829 920 $context_values = array();
830 921
831 922 foreach ( $this->get_terms_labels( 'context' ) as $context_id => $context_data ) {
832 923 if ( is_array( $context_data ) ) {
@@ -833,71 +924,100 @@
833 924 $child_values = array();
834 925 if ( isset( $context_data['children'] ) ) {
835 926 $child_values = array();
836 927 foreach ( $context_data['children'] as $child_id => $child_value ) {
837 - $child_values[] = array( 'id' => $child_id, 'text' => $child_value, 'parent' => $context_id );
928 + $child_values[] = array(
929 + 'value' => $context_id . '-' . $child_id,
930 + 'text' => $child_value,
931 + 'parent' => $context_id,
932 + );
838 933 }
839 934 }
840 935 if ( isset( $context_data['label'] ) ) {
841 - $context_values[] = array( 'id' => $context_id, 'text' => $context_data['label'], 'children' => $child_values );
936 + $context_values[] = array(
937 + 'value' => $context_id,
938 + 'text' => $context_data['label'],
939 + 'children' => $child_values,
940 + );
842 941 }
843 942 } else {
844 - $context_values[] = array( 'id' => $context_id, 'text' => $context_data );
943 + $context_values[] = array(
944 + 'value' => $context_id,
945 + 'text' => $context_data,
946 + );
845 947 }
846 948 }
847 949
848 - $connector_input = sprintf(
849 - '<input type="hidden" name="%1$s[%2$s_%3$s][%4$s][]" class="%4$s" value="%5$s">',
850 - esc_attr( $option_key ),
851 - esc_attr( $section ),
852 - esc_attr( $name ),
853 - esc_attr( 'connector' ),
854 - esc_attr( $connector )
950 + $connector_or_context_input = $form->render_field(
951 + 'select2',
952 + array(
953 + 'name' => esc_attr( sprintf( '%1$s[%2$s_%3$s][%4$s][]', $option_key, $section, $name, 'connector_or_context' ) ),
954 + 'options' => $context_values,
955 + 'classes' => 'connector_or_context',
956 + 'data' => array(
957 + 'group' => 'connector',
958 + 'placeholder' => __( 'Any Context', 'stream' ),
959 + ),
960 + )
855 961 );
856 962
857 - $context_input = sprintf(
858 - '<input type="hidden" name="%1$s[%2$s_%3$s][%4$s][]" data-values=\'%5$s\' value="%6$s" class="select2-select with-source %4$s" data-placeholder="%7$s" data-group="%8$s" />',
859 - esc_attr( $option_key ),
860 - esc_attr( $section ),
861 - esc_attr( $name ),
862 - 'context',
863 - esc_attr( wp_stream_json_encode( $context_values ) ),
864 - esc_attr( $context ),
865 - esc_html__( 'Any Context', 'stream' ),
866 - 'connector'
963 + $connector_input = $form->render_field(
964 + 'hidden',
965 + array(
966 + 'name' => esc_attr( sprintf( '%1$s[%2$s_%3$s][%4$s][]', $option_key, $section, $name, 'connector' ) ),
967 + 'value' => $connector,
968 + 'classes' => 'connector',
969 + )
867 970 );
868 971
869 - // Action dropdown menu
972 + $context_input = $form->render_field(
973 + 'hidden',
974 + array(
975 + 'name' => esc_attr( sprintf( '%1$s[%2$s_%3$s][%4$s][]', $option_key, $section, $name, 'context' ) ),
976 + 'value' => $context,
977 + 'classes' => 'context',
978 + )
979 + );
980 +
981 + // Action dropdown menu.
870 982 $action_values = array();
871 983
872 984 foreach ( $this->get_terms_labels( 'action' ) as $action_id => $action_data ) {
873 - $action_values[] = array( 'id' => $action_id, 'text' => $action_data );
985 + $action_values[] = array(
986 + 'value' => $action_id,
987 + 'text' => $action_data,
988 + );
874 989 }
875 990
876 - $action_input = sprintf(
877 - '<input type="hidden" name="%1$s[%2$s_%3$s][%4$s][]" data-values=\'%5$s\' value="%6$s" class="select2-select with-source %4$s" data-placeholder="%7$s" />',
878 - esc_attr( $option_key ),
879 - esc_attr( $section ),
880 - esc_attr( $name ),
881 - 'action',
882 - esc_attr( wp_stream_json_encode( $action_values ) ),
883 - esc_attr( $action ),
884 - esc_html__( 'Any Action', 'stream' )
991 + $action_input = $form->render_field(
992 + 'select2',
993 + array(
994 + 'name' => esc_attr( sprintf( '%1$s[%2$s_%3$s][%4$s][]', $option_key, $section, $name, 'action' ) ),
995 + 'value' => $action,
996 + 'options' => $action_values,
997 + 'classes' => 'action',
998 + 'data' => array(
999 + 'placeholder' => __( 'Any Action', 'stream' ),
1000 + ),
1001 + )
885 1002 );
886 1003
887 - // IP Address input
888 - $ip_address_input = sprintf(
889 - '<input type="hidden" name="%1$s[%2$s_%3$s][%4$s][]" value="%5$s" class="select2-select %4$s" data-placeholder="%6$s" data-nonce="%7$s" />',
890 - esc_attr( $option_key ),
891 - esc_attr( $section ),
892 - esc_attr( $name ),
893 - 'ip_address',
894 - esc_attr( $ip_address ),
895 - esc_html__( 'Any IP Address', 'stream' ),
896 - esc_attr( wp_create_nonce( 'stream_get_ips' ) )
1004 + // IP Address input.
1005 + $ip_address_input = $form->render_field(
1006 + 'select2',
1007 + array(
1008 + 'name' => esc_attr( sprintf( '%1$s[%2$s_%3$s][%4$s][]', $option_key, $section, $name, 'ip_address' ) ),
1009 + 'value' => $ip_address,
1010 + 'classes' => 'ip_address',
1011 + 'data' => array(
1012 + 'placeholder' => esc_attr__( 'Any IP Address', 'stream' ),
1013 + 'nonce' => esc_attr( wp_create_nonce( 'stream_get_ips' ) ),
1014 + ),
1015 + 'multiple' => true,
1016 + )
897 1017 );
898 1018
899 - // Hidden helper input
1019 + // Hidden helper input.
900 1020 $helper_input = sprintf(
901 1021 '<input type="hidden" name="%1$s[%2$s_%3$s][%4$s][]" value="" />',
902 1022 esc_attr( $option_key ),
903 1023 esc_attr( $section ),
@@ -908,18 +1028,19 @@
908 1028 $exclude_rows[] = sprintf(
909 1029 '<tr class="%1$s %2$s">
910 1030 <th scope="row" class="check-column">%3$s %4$s</th>
911 1031 <td>%5$s</td>
912 - <td>%6$s %7$s</td>
913 - <td>%8$s</td>
1032 + <td>%6$s %7$s %8$s</td>
914 1033 <td>%9$s</td>
915 - <th scope="row" class="actions-column">%10$s</th>
1034 + <td>%10$s</td>
1035 + <th scope="row" class="actions-column">%11$s</th>
916 1036 </tr>',
917 - ( 0 !== $key % 2 ) ? 'alternate' : '',
918 - ( 'helper' === $key ) ? 'hidden helper' : '',
1037 + ( 0 !== (int) $key % 2 ) ? 'alternate' : '',
1038 + ( 'helper' === (string) $key ) ? 'hidden helper' : '',
919 1039 '<input class="cb-select" type="checkbox" />',
920 1040 $helper_input,
921 1041 $author_or_role_input,
1042 + $connector_or_context_input,
922 1043 $connector_input,
923 1044 $context_input,
924 1045 $action_input,
925 1046 $ip_address_input,
@@ -949,9 +1070,9 @@
949 1070
950 1071 /**
951 1072 * Render Callback for post_types field
952 1073 *
953 - * @param array $field
1074 + * @param array $field Field to be rendered.
954 1075 *
955 1076 * @return string
956 1077 */
957 1078 public function output_field( $field ) {
@@ -962,9 +1083,9 @@
962 1083 }
963 1084
964 1085 $output = $this->render_field( $field );
965 1086
966 - echo $output; // xss ok
1087 + echo $output; // xss ok.
967 1088 }
968 1089
969 1090 /**
970 1091 * Get an array of user roles
@@ -984,9 +1105,9 @@
984 1105
985 1106 /**
986 1107 * Function will return all terms labels of given column
987 1108 *
988 - * @param string $column string Name of the column
1109 + * @param string $column Name of the column.
989 1110 *
990 1111 * @return array
991 1112 */
992 1113 public function get_terms_labels( $column ) {
@@ -1019,14 +1140,14 @@
1019 1140 * Remove records when records TTL is shortened
1020 1141 *
1021 1142 * @action update_option_wp_stream
1022 1143 *
1023 - * @param array $old_value
1024 - * @param array $new_value
1144 + * @param array $old_value Old value.
1145 + * @param array $new_value New value.
1025 1146 */
1026 1147 public function updated_option_ttl_remove_records( $old_value, $new_value ) {
1027 - $ttl_before = isset( $old_value['general_records_ttl'] ) ? (int) $old_value['general_records_ttl'] : -1;
1028 - $ttl_after = isset( $new_value['general_records_ttl'] ) ? (int) $new_value['general_records_ttl'] : -1;
1148 + $ttl_before = isset( $old_value['general_records_ttl'] ) ? (int) $old_value['general_records_ttl'] : - 1;
1149 + $ttl_after = isset( $new_value['general_records_ttl'] ) ? (int) $new_value['general_records_ttl'] : - 1;
1029 1150
1030 1151 if ( $ttl_after < $ttl_before ) {
1031 1152 /**
1032 1153 * Action assists in purging when TTL is shortened
@@ -1038,8 +1159,10 @@
1038 1159 /**
1039 1160 * Get translations of serialized Stream settings
1040 1161 *
1041 1162 * @filter wp_stream_serialized_labels
1163 + *
1164 + * @param array $labels Setting labels.
1042 1165 *
1043 1166 * @return array Multidimensional array of fields
1044 1167 */
1045 1168 public function get_settings_translations( $labels ) {