PluginProbe
Stream – Activity Log & Audit Trail / 3.9.0
Stream – Activity Log & Audit Trail v3.9.0
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 +316 -169 3.0.53.9.0 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,24 +138,49 @@
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 }
159 + $users_array = $users->results;
117 160
118 - $response->status = true;
119 - $response->message = '';
120 - $response->users = array();
161 + if ( is_multisite() && is_super_admin() ) {
162 + $super_admins = get_super_admins();
163 + foreach ( $super_admins as $admin ) {
164 + $user = get_user_by( 'login', $admin );
165 + $users_array[] = $user;
166 + }
167 + }
121 168
122 - foreach ( $users->results as $key => $user ) {
169 + $response->status = true;
170 + $response->message = '';
171 + $response->roles = $this->get_roles();
172 + $response->users = array();
173 + $users_added_to_response = array();
174 +
175 + foreach ( $users_array as $key => $user ) {
176 + // exclude duplications.
177 + if ( array_key_exists( $user->ID, $users_added_to_response ) ) {
178 + continue;
179 + } else {
180 + $users_added_to_response[ $user->ID ] = true;
181 + }
182 +
123 183 $author = new Author( $user->ID );
124 184
125 185 $args = array(
126 186 'id' => $author->ID,
@@ -128,9 +188,10 @@
128 188 );
129 189
130 190 $args['tooltip'] = esc_attr(
131 191 sprintf(
132 - __( "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' ),
133 194 $author->id,
134 195 $author->user_login,
135 196 $author->user_email,
136 197 ucwords( $author->get_role() )
@@ -141,12 +202,19 @@
141 202
142 203 $response->users[] = $args;
143 204 }
144 205
206 + usort(
207 + $response->users,
208 + function ( $a, $b ) {
209 + return strcmp( $a['text'], $b['text'] );
210 + }
211 + );
212 +
145 213 if ( empty( $search ) || preg_match( '/wp|cli|system|unknown/i', $search ) ) {
146 - $author = new Author( 0 );
214 + $author = new Author( 0 );
147 215 $response->users[] = array(
148 - 'id' => $author->id,
216 + 'id' => '0',
149 217 'text' => $author->get_display_name(),
150 218 'icon' => $author->get_avatar_src( 32 ),
151 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' ),
152 220 );
@@ -155,10 +223,10 @@
155 223 wp_send_json_success( $response );
156 224 }
157 225
158 226 /**
159 - * Ajax callback function to search IP addresses, used on exclude setting page
160 - */
227 + * Ajax callback function to search IP addresses, used on exclude setting page
228 + */
161 229 public function get_ips() {
162 230 if ( ! defined( 'DOING_AJAX' ) || ! current_user_can( $this->plugin->admin->settings_cap ) ) {
163 231 return;
164 232 }
@@ -164,10 +232,20 @@
164 232 }
165 233
166 234 check_ajax_referer( 'stream_get_ips', 'nonce' );
167 235
168 - $ips = $this->plugin->db->existing_records( 'ip' );
236 + $ips = $this->plugin->db->existing_records( 'ip' );
237 + $find = wp_stream_filter_input( INPUT_POST, 'find' );
169 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 +
170 248 if ( $ips ) {
171 249 wp_send_json_success( $ips );
172 250 } else {
173 251 wp_send_json_error();
@@ -176,11 +254,11 @@
176 254
177 255 /**
178 256 * Filter the columns to search in a WP_User_Query search.
179 257 *
180 - * @param array $search_columns Array of column names to be searched.
181 - * @param string $search Text being searched.
182 - * @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.
183 261 *
184 262 * @return array
185 263 */
186 264 public function add_display_name_search_columns( $search_columns, $search, $query ) {
@@ -219,18 +297,18 @@
219 297 * @return array
220 298 */
221 299 public function get_fields() {
222 300 $fields = array(
223 - 'general' => array(
301 + 'general' => array(
224 302 'title' => esc_html__( 'General', 'stream' ),
225 303 'fields' => array(
226 304 array(
227 - 'name' => 'role_access',
228 - 'title' => esc_html__( 'Role Access', 'stream' ),
229 - 'type' => 'multi_checkbox',
230 - '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' ),
231 - 'choices' => $this->get_roles(),
232 - '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' ),
233 311 ),
234 312 array(
235 313 'name' => 'records_ttl',
236 314 'title' => esc_html__( 'Keep Records for', 'stream' ),
@@ -252,18 +330,18 @@
252 330 'default' => 0,
253 331 ),
254 332 ),
255 333 ),
256 - 'exclude' => array(
334 + 'exclude' => array(
257 335 'title' => esc_html__( 'Exclude', 'stream' ),
258 336 'fields' => array(
259 337 array(
260 - 'name' => 'rules',
261 - 'title' => esc_html__( 'Exclude Rules', 'stream' ),
262 - 'type' => 'rule_list',
263 - 'desc' => esc_html__( 'Create rules to exclude certain kinds of activity from being recorded by Stream.', 'stream' ),
264 - 'default' => array(),
265 - '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',
266 344 ),
267 345 ),
268 346 ),
269 347 'advanced' => array(
@@ -277,28 +355,28 @@
277 355 'after_field' => esc_html__( 'Enabled', 'stream' ),
278 356 'default' => 0,
279 357 ),
280 358 array(
281 - 'name' => 'delete_all_records',
282 - 'title' => esc_html__( 'Reset Stream Database', 'stream' ),
283 - 'type' => 'link',
284 - '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(
285 363 array(
286 - 'action' => 'wp_stream_reset',
287 - 'wp_stream_nonce' => wp_create_nonce( 'stream_nonce' ),
364 + 'action' => 'wp_stream_reset',
365 + 'wp_stream_nonce_reset' => wp_create_nonce( 'stream_nonce_reset' ),
288 366 ),
289 367 admin_url( 'admin-ajax.php' )
290 368 ),
291 - 'class' => 'warning',
292 - 'desc' => esc_html__( 'Warning: This will delete all activity records from the database.', 'stream' ),
293 - 'default' => 0,
294 - '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',
295 373 ),
296 374 ),
297 375 ),
298 376 );
299 377
300 - // 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.
301 379 if ( class_exists( 'Akismet' ) ) {
302 380 $akismet_tracking = array(
303 381 'name' => 'akismet_tracking',
304 382 'title' => esc_html__( 'Akismet Tracking', 'stream' ),
@@ -310,21 +388,18 @@
310 388
311 389 array_push( $fields['advanced']['fields'], $akismet_tracking );
312 390 }
313 391
314 - // If WP Cron is enabled, allow Admins to opt-in to WP Cron tracking
315 - if ( wp_stream_is_cron_enabled() ) {
316 - $wp_cron_tracking = array(
317 - 'name' => 'wp_cron_tracking',
318 - 'title' => esc_html__( 'WP Cron Tracking', 'stream' ),
319 - 'type' => 'checkbox',
320 - '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' ),
321 - 'after_field' => esc_html__( 'Enabled', 'stream' ),
322 - 'default' => 0,
323 - );
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 + );
324 400
325 - array_push( $fields['advanced']['fields'], $wp_cron_tracking );
326 - }
401 + array_push( $fields['advanced']['fields'], $wp_cron_tracking );
327 402
328 403 /**
329 404 * Filter allows for modification of options fields
330 405 *
@@ -331,9 +406,9 @@
331 406 * @return array Array of option fields
332 407 */
333 408 $this->fields = apply_filters( 'wp_stream_settings_option_fields', $fields );
334 409
335 - // Sort option fields in each tab by title ASC
410 + // Sort option fields in each tab by title ASC.
336 411 foreach ( $this->fields as $tab => $options ) {
337 412 $titles = array();
338 413
339 414 foreach ( $options['fields'] as $field ) {
@@ -403,9 +478,16 @@
403 478 */
404 479 public function register_settings() {
405 480 $sections = $this->get_fields();
406 481
407 - 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 + );
408 490
409 491 foreach ( $sections as $section_name => $section ) {
410 492 add_settings_section(
411 493 $section_name,
@@ -414,9 +496,10 @@
414 496 $this->option_key
415 497 );
416 498
417 499 foreach ( $section['fields'] as $field_idx => $field ) {
418 - if ( ! isset( $field['type'] ) ) { // No field type associated, skip, no GUI
500 + // No field type associated, skip, no GUI.
501 + if ( ! isset( $field['type'] ) ) {
419 502 continue;
420 503 }
421 504
422 505 add_settings_field(
@@ -421,14 +504,18 @@
421 504
422 505 add_settings_field(
423 506 $field['name'],
424 507 $field['title'],
425 - ( isset( $field['callback'] ) ? $field['callback'] : array( $this, 'output_field' ) ),
508 + ( isset( $field['callback'] ) ? $field['callback'] : array(
509 + $this,
510 + 'output_field',
511 + ) ),
426 512 $this->option_key,
427 513 $section_name,
428 514 $field + array(
429 515 'section' => $section_name,
430 - '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.
431 518 )
432 519 );
433 520 }
434 521 }
@@ -436,9 +523,9 @@
436 523
437 524 /**
438 525 * Sanitization callback for settings field values before save
439 526 *
440 - * @param array $input
527 + * @param array $input Raw input.
441 528 *
442 529 * @return array
443 530 */
444 531 public function sanitize_settings( $input ) {
@@ -457,9 +544,9 @@
457 544 if ( empty( $type ) || ! isset( $input[ $name ] ) || '' === $input[ $name ] ) {
458 545 continue;
459 546 }
460 547
461 - // Sanitize depending on the type of field
548 + // Sanitize depending on the type of field.
462 549 switch ( $type ) {
463 550 case 'number':
464 551 $output[ $name ] = is_numeric( $input[ $name ] ) ? intval( trim( $input[ $name ] ) ) : '';
465 552 break;
@@ -469,14 +556,17 @@
469 556 default:
470 557 if ( is_array( $input[ $name ] ) ) {
471 558 $output[ $name ] = $input[ $name ];
472 559
473 - // Support all values in multidimentional arrays too
474 - array_walk_recursive( $output[ $name ], function( &$v, $k ) {
475 - $v = trim( $v );
476 - } );
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 + );
477 567 } else {
478 - $output[ $name ] = trim( $input[ $name ] );
568 + $output[ $name ] = sanitize_text_field( trim( $input[ $name ] ) );
479 569 }
480 570 }
481 571 }
482 572 }
@@ -486,9 +576,9 @@
486 576
487 577 /**
488 578 * Compile HTML needed for displaying the field
489 579 *
490 - * @param array $field Field settings
580 + * @param array $field Field settings.
491 581 *
492 582 * @return string HTML to be displayed
493 583 */
494 584 public function render_field( $field ) {
@@ -529,11 +619,9 @@
529 619 if ( ! $type || ! $section || ! $name ) {
530 620 return '';
531 621 }
532 622
533 - if ( 'multi_checkbox' === $type
534 - && ( empty( $field['choices'] ) || ! is_array( $field['choices'] ) )
535 - ) {
623 + if ( 'multi_checkbox' === $type && ( empty( $field['choices'] ) || ! is_array( $field['choices'] ) ) ) {
536 624 return '';
537 625 }
538 626
539 627 switch ( $type ) {
@@ -592,10 +680,10 @@
592 680 esc_attr( $option_key ),
593 681 esc_attr( $section ),
594 682 esc_attr( $name )
595 683 );
596 - // Fallback if nothing is selected
597 - $output .= sprintf(
684 + // Fallback if nothing is selected.
685 + $output .= sprintf(
598 686 '<input type="hidden" name="%1$s[%2$s_%3$s][]" value="__placeholder__" />',
599 687 esc_attr( $option_key ),
600 688 esc_attr( $section ),
601 689 esc_attr( $name )
@@ -600,9 +688,9 @@
600 688 esc_attr( $section ),
601 689 esc_attr( $name )
602 690 );
603 691 $current_value = (array) $current_value;
604 - $choices = $field['choices'];
692 + $choices = $field['choices'];
605 693 if ( is_callable( $choices ) ) {
606 694 $choices = call_user_func( $choices );
607 695 }
608 696 foreach ( $choices as $value => $label ) {
@@ -667,9 +755,9 @@
667 755 esc_attr( $href ),
668 756 esc_attr( $title )
669 757 );
670 758 break;
671 - case 'select2' :
759 + case 'select2':
672 760 if ( ! isset( $current_value ) ) {
673 761 $current_value = '';
674 762 }
675 763
@@ -686,16 +774,26 @@
686 774 $child_values = array();
687 775 if ( isset( $value['children'] ) ) {
688 776 $child_values = array();
689 777 foreach ( $value['children'] as $child_key => $child_value ) {
690 - $child_values[] = array( 'id' => $child_key, 'text' => $child_value );
778 + $child_values[] = array(
779 + 'id' => $child_key,
780 + 'text' => $child_value,
781 + );
691 782 }
692 783 }
693 784 if ( isset( $value['label'] ) ) {
694 - $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 + );
695 790 }
696 791 } else {
697 - $data_values[] = array( 'id' => $key, 'text' => $value );
792 + $data_values[] = array(
793 + 'id' => $key,
794 + 'text' => $value,
795 + );
698 796 }
699 797 }
700 798 $class .= ' with-source';
701 799 }
@@ -707,8 +805,9 @@
707 805 esc_attr( $name ),
708 806 esc_attr( wp_stream_json_encode( $data_values ) ),
709 807 esc_attr( $current_value ),
710 808 esc_attr( $class ),
809 + /* translators: %s: the title of the dropdown menu (e.g. "users") */
711 810 sprintf( esc_html__( 'Any %s', 'stream' ), $title )
712 811 );
713 812
714 813 $output = sprintf(
@@ -719,13 +818,15 @@
719 818 $input_html
720 819 );
721 820
722 821 break;
723 - case 'rule_list' :
822 + case 'rule_list':
823 + $users = count_users();
824 + $form = new Form_Generator();
724 825 $output = '<p class="description">' . esc_html( $description ) . '</p>';
725 826
726 - $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' ) );
727 - $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' ) );
728 829
729 830 $output .= sprintf( '<div class="tablenav top">%1$s</div>', $actions_top );
730 831 $output .= '<table class="wp-list-table widefat fixed stream-exclude-list">';
731 832
@@ -749,13 +850,18 @@
749 850 );
750 851
751 852 $exclude_rows = array();
752 853
753 - // Prepend an empty row
754 - $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 + }
755 858
859 + // Prepend an empty row.
860 + $current_value['exclude_row'] = ( isset( $current_value['exclude_row'] ) ? $current_value['exclude_row'] : array() ) + array( 'helper' => '' );
861 +
756 862 foreach ( $current_value['exclude_row'] as $key => $value ) {
757 - // Prepare values
863 + // Prepare values.
758 864 $author_or_role = isset( $current_value['author_or_role'][ $key ] ) ? $current_value['author_or_role'][ $key ] : '';
759 865 $connector = isset( $current_value['connector'][ $key ] ) ? $current_value['connector'][ $key ] : '';
760 866 $context = isset( $current_value['context'][ $key ] ) ? $current_value['context'][ $key ] : '';
761 867 $action = isset( $current_value['action'][ $key ] ) ? $current_value['action'][ $key ] : '';
@@ -760,24 +866,27 @@
760 866 $context = isset( $current_value['context'][ $key ] ) ? $current_value['context'][ $key ] : '';
761 867 $action = isset( $current_value['action'][ $key ] ) ? $current_value['action'][ $key ] : '';
762 868 $ip_address = isset( $current_value['ip_address'][ $key ] ) ? $current_value['ip_address'][ $key ] : '';
763 869
764 - // Author or Role dropdown menu
870 + // Author or Role dropdown menu.
765 871 $author_or_role_values = array();
766 872 $author_or_role_selected = array();
767 873
768 874 foreach ( $this->get_roles() as $role_id => $role ) {
769 - $args = array( 'id' => $role_id, 'text' => $role );
770 - $users = count_users();
875 + $args = array(
876 + 'value' => $role_id,
877 + 'text' => $role,
878 + );
771 879 $count = isset( $users['avail_roles'][ $role_id ] ) ? $users['avail_roles'][ $role_id ] : 0;
772 880
773 881 if ( ! empty( $count ) ) {
774 - $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 ) );
775 884 }
776 885
777 886 if ( $role_id === $author_or_role ) {
778 - $author_or_role_selected['id'] = $role_id;
779 - $author_or_role_selected['text'] = $role;
887 + $author_or_role_selected['value'] = $role_id;
888 + $author_or_role_selected['text'] = $role;
780 889 }
781 890
782 891 $author_or_role_values[] = $args;
783 892 }
@@ -784,25 +893,31 @@
784 893
785 894 if ( empty( $author_or_role_selected ) && is_numeric( $author_or_role ) ) {
786 895 $user = new WP_User( $author_or_role );
787 896 $display_name = ( 0 === $user->ID ) ? esc_html__( 'N/A', 'stream' ) : $user->display_name;
788 - $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;
789 902 }
790 903
791 - $author_or_role_input = sprintf(
792 - '<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" />',
793 - esc_attr( $option_key ),
794 - esc_attr( $section ),
795 - esc_attr( $name ),
796 - 'author_or_role',
797 - esc_attr( wp_stream_json_encode( $author_or_role_values ) ),
798 - isset( $author_or_role_selected['id'] ) ? esc_attr( $author_or_role_selected['id'] ) : '',
799 - isset( $author_or_role_selected['text'] ) ? esc_attr( $author_or_role_selected['text'] ) : '',
800 - esc_html__( 'Any Author or Role', 'stream' ),
801 - 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 + )
802 917 );
803 918
804 - // Context dropdown menu
919 + // Context dropdown menu.
805 920 $context_values = array();
806 921
807 922 foreach ( $this->get_terms_labels( 'context' ) as $context_id => $context_data ) {
808 923 if ( is_array( $context_data ) ) {
@@ -809,71 +924,100 @@
809 924 $child_values = array();
810 925 if ( isset( $context_data['children'] ) ) {
811 926 $child_values = array();
812 927 foreach ( $context_data['children'] as $child_id => $child_value ) {
813 - $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 + );
814 933 }
815 934 }
816 935 if ( isset( $context_data['label'] ) ) {
817 - $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 + );
818 941 }
819 942 } else {
820 - $context_values[] = array( 'id' => $context_id, 'text' => $context_data );
943 + $context_values[] = array(
944 + 'value' => $context_id,
945 + 'text' => $context_data,
946 + );
821 947 }
822 948 }
823 949
824 - $connector_input = sprintf(
825 - '<input type="hidden" name="%1$s[%2$s_%3$s][%4$s][]" class="%4$s" value="%5$s">',
826 - esc_attr( $option_key ),
827 - esc_attr( $section ),
828 - esc_attr( $name ),
829 - esc_attr( 'connector' ),
830 - 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 + )
831 961 );
832 962
833 - $context_input = sprintf(
834 - '<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" />',
835 - esc_attr( $option_key ),
836 - esc_attr( $section ),
837 - esc_attr( $name ),
838 - 'context',
839 - esc_attr( wp_stream_json_encode( $context_values ) ),
840 - esc_attr( $context ),
841 - esc_html__( 'Any Context', 'stream' ),
842 - '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 + )
843 970 );
844 971
845 - // 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.
846 982 $action_values = array();
847 983
848 984 foreach ( $this->get_terms_labels( 'action' ) as $action_id => $action_data ) {
849 - $action_values[] = array( 'id' => $action_id, 'text' => $action_data );
985 + $action_values[] = array(
986 + 'value' => $action_id,
987 + 'text' => $action_data,
988 + );
850 989 }
851 990
852 - $action_input = sprintf(
853 - '<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" />',
854 - esc_attr( $option_key ),
855 - esc_attr( $section ),
856 - esc_attr( $name ),
857 - 'action',
858 - esc_attr( wp_stream_json_encode( $action_values ) ),
859 - esc_attr( $action ),
860 - 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 + )
861 1002 );
862 1003
863 - // IP Address input
864 - $ip_address_input = sprintf(
865 - '<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" />',
866 - esc_attr( $option_key ),
867 - esc_attr( $section ),
868 - esc_attr( $name ),
869 - 'ip_address',
870 - esc_attr( $ip_address ),
871 - esc_html__( 'Any IP Address', 'stream' ),
872 - 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 + )
873 1017 );
874 1018
875 - // Hidden helper input
1019 + // Hidden helper input.
876 1020 $helper_input = sprintf(
877 1021 '<input type="hidden" name="%1$s[%2$s_%3$s][%4$s][]" value="" />',
878 1022 esc_attr( $option_key ),
879 1023 esc_attr( $section ),
@@ -884,18 +1028,19 @@
884 1028 $exclude_rows[] = sprintf(
885 1029 '<tr class="%1$s %2$s">
886 1030 <th scope="row" class="check-column">%3$s %4$s</th>
887 1031 <td>%5$s</td>
888 - <td>%6$s %7$s</td>
889 - <td>%8$s</td>
1032 + <td>%6$s %7$s %8$s</td>
890 1033 <td>%9$s</td>
891 - <th scope="row" class="actions-column">%10$s</th>
1034 + <td>%10$s</td>
1035 + <th scope="row" class="actions-column">%11$s</th>
892 1036 </tr>',
893 - ( 0 !== $key % 2 ) ? 'alternate' : '',
894 - ( 'helper' === $key ) ? 'hidden helper' : '',
1037 + ( 0 !== (int) $key % 2 ) ? 'alternate' : '',
1038 + ( 'helper' === (string) $key ) ? 'hidden helper' : '',
895 1039 '<input class="cb-select" type="checkbox" />',
896 1040 $helper_input,
897 1041 $author_or_role_input,
1042 + $connector_or_context_input,
898 1043 $connector_input,
899 1044 $context_input,
900 1045 $action_input,
901 1046 $ip_address_input,
@@ -925,9 +1070,9 @@
925 1070
926 1071 /**
927 1072 * Render Callback for post_types field
928 1073 *
929 - * @param array $field
1074 + * @param array $field Field to be rendered.
930 1075 *
931 1076 * @return string
932 1077 */
933 1078 public function output_field( $field ) {
@@ -938,9 +1083,9 @@
938 1083 }
939 1084
940 1085 $output = $this->render_field( $field );
941 1086
942 - echo $output; // xss ok
1087 + echo $output; // xss ok.
943 1088 }
944 1089
945 1090 /**
946 1091 * Get an array of user roles
@@ -960,9 +1105,9 @@
960 1105
961 1106 /**
962 1107 * Function will return all terms labels of given column
963 1108 *
964 - * @param string $column string Name of the column
1109 + * @param string $column Name of the column.
965 1110 *
966 1111 * @return array
967 1112 */
968 1113 public function get_terms_labels( $column ) {
@@ -995,14 +1140,14 @@
995 1140 * Remove records when records TTL is shortened
996 1141 *
997 1142 * @action update_option_wp_stream
998 1143 *
999 - * @param array $old_value
1000 - * @param array $new_value
1144 + * @param array $old_value Old value.
1145 + * @param array $new_value New value.
1001 1146 */
1002 1147 public function updated_option_ttl_remove_records( $old_value, $new_value ) {
1003 - $ttl_before = isset( $old_value['general_records_ttl'] ) ? (int) $old_value['general_records_ttl'] : -1;
1004 - $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;
1005 1150
1006 1151 if ( $ttl_after < $ttl_before ) {
1007 1152 /**
1008 1153 * Action assists in purging when TTL is shortened
@@ -1014,8 +1159,10 @@
1014 1159 /**
1015 1160 * Get translations of serialized Stream settings
1016 1161 *
1017 1162 * @filter wp_stream_serialized_labels
1163 + *
1164 + * @param array $labels Setting labels.
1018 1165 *
1019 1166 * @return array Multidimensional array of fields
1020 1167 */
1021 1168 public function get_settings_translations( $labels ) {