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 +336 -174 3.0.03.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,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' ),
@@ -235,27 +313,35 @@
235 313 'name' => 'records_ttl',
236 314 'title' => esc_html__( 'Keep Records for', 'stream' ),
237 315 'type' => 'number',
238 316 'class' => 'small-text',
239 - 'desc' => esc_html__( 'Maximum number of days to keep activity records. Leave blank to keep records forever.', 'stream' ),
317 + 'desc' => esc_html__( 'Maximum number of days to keep activity records.', 'stream' ),
240 318 'default' => 30,
241 - 'min' => 0,
319 + 'min' => 1,
242 320 'max' => 999,
243 321 'step' => 1,
244 322 'after_field' => esc_html__( 'days', 'stream' ),
245 323 ),
324 + array(
325 + 'name' => 'keep_records_indefinitely',
326 + 'title' => esc_html__( 'Keep Records Indefinitely', 'stream' ),
327 + 'type' => 'checkbox',
328 + 'desc' => sprintf( '<strong>%s</strong> %s', esc_html__( 'Not recommended.', 'stream' ), esc_html__( 'Purging old records helps to keep your WordPress installation running optimally.', 'stream' ) ),
329 + 'after_field' => esc_html__( 'Enabled', 'stream' ),
330 + 'default' => 0,
331 + ),
246 332 ),
247 333 ),
248 - 'exclude' => array(
334 + 'exclude' => array(
249 335 'title' => esc_html__( 'Exclude', 'stream' ),
250 336 'fields' => array(
251 337 array(
252 - 'name' => 'rules',
253 - 'title' => esc_html__( 'Exclude Rules', 'stream' ),
254 - 'type' => 'rule_list',
255 - 'desc' => esc_html__( 'Create rules to exclude certain kinds of activity from being recorded by Stream.', 'stream' ),
256 - 'default' => array(),
257 - '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',
258 344 ),
259 345 ),
260 346 ),
261 347 'advanced' => array(
@@ -269,28 +355,28 @@
269 355 'after_field' => esc_html__( 'Enabled', 'stream' ),
270 356 'default' => 0,
271 357 ),
272 358 array(
273 - 'name' => 'delete_all_records',
274 - 'title' => esc_html__( 'Reset Stream Database', 'stream' ),
275 - 'type' => 'link',
276 - '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(
277 363 array(
278 - 'action' => 'wp_stream_reset',
279 - 'wp_stream_nonce' => wp_create_nonce( 'stream_nonce' ),
364 + 'action' => 'wp_stream_reset',
365 + 'wp_stream_nonce_reset' => wp_create_nonce( 'stream_nonce_reset' ),
280 366 ),
281 367 admin_url( 'admin-ajax.php' )
282 368 ),
283 - 'class' => 'warning',
284 - 'desc' => esc_html__( 'Warning: This will delete all activity records from the database.', 'stream' ),
285 - 'default' => 0,
286 - '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',
287 373 ),
288 374 ),
289 375 ),
290 376 );
291 377
292 - // 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.
293 379 if ( class_exists( 'Akismet' ) ) {
294 380 $akismet_tracking = array(
295 381 'name' => 'akismet_tracking',
296 382 'title' => esc_html__( 'Akismet Tracking', 'stream' ),
@@ -302,21 +388,18 @@
302 388
303 389 array_push( $fields['advanced']['fields'], $akismet_tracking );
304 390 }
305 391
306 - // If WP Cron is enabled, allow Admins to opt-in to WP Cron tracking
307 - if ( wp_stream_is_cron_enabled() ) {
308 - $wp_cron_tracking = array(
309 - 'name' => 'wp_cron_tracking',
310 - 'title' => esc_html__( 'WP Cron Tracking', 'stream' ),
311 - 'type' => 'checkbox',
312 - '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' ),
313 - 'after_field' => esc_html__( 'Enabled', 'stream' ),
314 - 'default' => 0,
315 - );
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 + );
316 400
317 - array_push( $fields['advanced']['fields'], $wp_cron_tracking );
318 - }
401 + array_push( $fields['advanced']['fields'], $wp_cron_tracking );
319 402
320 403 /**
321 404 * Filter allows for modification of options fields
322 405 *
@@ -323,9 +406,9 @@
323 406 * @return array Array of option fields
324 407 */
325 408 $this->fields = apply_filters( 'wp_stream_settings_option_fields', $fields );
326 409
327 - // Sort option fields in each tab by title ASC
410 + // Sort option fields in each tab by title ASC.
328 411 foreach ( $this->fields as $tab => $options ) {
329 412 $titles = array();
330 413
331 414 foreach ( $options['fields'] as $field ) {
@@ -395,9 +478,16 @@
395 478 */
396 479 public function register_settings() {
397 480 $sections = $this->get_fields();
398 481
399 - 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 + );
400 490
401 491 foreach ( $sections as $section_name => $section ) {
402 492 add_settings_section(
403 493 $section_name,
@@ -406,9 +496,10 @@
406 496 $this->option_key
407 497 );
408 498
409 499 foreach ( $section['fields'] as $field_idx => $field ) {
410 - if ( ! isset( $field['type'] ) ) { // No field type associated, skip, no GUI
500 + // No field type associated, skip, no GUI.
501 + if ( ! isset( $field['type'] ) ) {
411 502 continue;
412 503 }
413 504
414 505 add_settings_field(
@@ -413,14 +504,18 @@
413 504
414 505 add_settings_field(
415 506 $field['name'],
416 507 $field['title'],
417 - ( isset( $field['callback'] ) ? $field['callback'] : array( $this, 'output_field' ) ),
508 + ( isset( $field['callback'] ) ? $field['callback'] : array(
509 + $this,
510 + 'output_field',
511 + ) ),
418 512 $this->option_key,
419 513 $section_name,
420 514 $field + array(
421 515 'section' => $section_name,
422 - '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.
423 518 )
424 519 );
425 520 }
426 521 }
@@ -428,9 +523,9 @@
428 523
429 524 /**
430 525 * Sanitization callback for settings field values before save
431 526 *
432 - * @param array $input
527 + * @param array $input Raw input.
433 528 *
434 529 * @return array
435 530 */
436 531 public function sanitize_settings( $input ) {
@@ -449,9 +544,9 @@
449 544 if ( empty( $type ) || ! isset( $input[ $name ] ) || '' === $input[ $name ] ) {
450 545 continue;
451 546 }
452 547
453 - // Sanitize depending on the type of field
548 + // Sanitize depending on the type of field.
454 549 switch ( $type ) {
455 550 case 'number':
456 551 $output[ $name ] = is_numeric( $input[ $name ] ) ? intval( trim( $input[ $name ] ) ) : '';
457 552 break;
@@ -461,14 +556,17 @@
461 556 default:
462 557 if ( is_array( $input[ $name ] ) ) {
463 558 $output[ $name ] = $input[ $name ];
464 559
465 - // Support all values in multidimentional arrays too
466 - array_walk_recursive( $output[ $name ], function( &$v, $k ) {
467 - $v = trim( $v );
468 - } );
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 + );
469 567 } else {
470 - $output[ $name ] = trim( $input[ $name ] );
568 + $output[ $name ] = sanitize_text_field( trim( $input[ $name ] ) );
471 569 }
472 570 }
473 571 }
474 572 }
@@ -478,9 +576,9 @@
478 576
479 577 /**
480 578 * Compile HTML needed for displaying the field
481 579 *
482 - * @param array $field Field settings
580 + * @param array $field Field settings.
483 581 *
484 582 * @return string HTML to be displayed
485 583 */
486 584 public function render_field( $field ) {
@@ -521,11 +619,9 @@
521 619 if ( ! $type || ! $section || ! $name ) {
522 620 return '';
523 621 }
524 622
525 - if ( 'multi_checkbox' === $type
526 - && ( empty( $field['choices'] ) || ! is_array( $field['choices'] ) )
527 - ) {
623 + if ( 'multi_checkbox' === $type && ( empty( $field['choices'] ) || ! is_array( $field['choices'] ) ) ) {
528 624 return '';
529 625 }
530 626
531 627 switch ( $type ) {
@@ -560,14 +656,22 @@
560 656 wp_kses_post( $after_field )
561 657 );
562 658 break;
563 659 case 'checkbox':
660 + if ( isset( $current_value ) ) {
661 + $value = $current_value;
662 + } elseif ( isset( $default ) ) {
663 + $value = $default;
664 + } else {
665 + $value = 0;
666 + }
667 +
564 668 $output = sprintf(
565 669 '<label><input type="checkbox" name="%1$s[%2$s_%3$s]" id="%1$s[%2$s_%3$s]" value="1" %4$s /> %5$s</label>',
566 670 esc_attr( $option_key ),
567 671 esc_attr( $section ),
568 672 esc_attr( $name ),
569 - checked( $current_value, 1, false ),
673 + checked( $value, 1, false ),
570 674 wp_kses_post( $after_field )
571 675 );
572 676 break;
573 677 case 'multi_checkbox':
@@ -576,10 +680,10 @@
576 680 esc_attr( $option_key ),
577 681 esc_attr( $section ),
578 682 esc_attr( $name )
579 683 );
580 - // Fallback if nothing is selected
581 - $output .= sprintf(
684 + // Fallback if nothing is selected.
685 + $output .= sprintf(
582 686 '<input type="hidden" name="%1$s[%2$s_%3$s][]" value="__placeholder__" />',
583 687 esc_attr( $option_key ),
584 688 esc_attr( $section ),
585 689 esc_attr( $name )
@@ -584,9 +688,9 @@
584 688 esc_attr( $section ),
585 689 esc_attr( $name )
586 690 );
587 691 $current_value = (array) $current_value;
588 - $choices = $field['choices'];
692 + $choices = $field['choices'];
589 693 if ( is_callable( $choices ) ) {
590 694 $choices = call_user_func( $choices );
591 695 }
592 696 foreach ( $choices as $value => $label ) {
@@ -597,9 +701,9 @@
597 701 esc_attr( $option_key ),
598 702 esc_attr( $section ),
599 703 esc_attr( $name ),
600 704 esc_attr( $value ),
601 - checked( in_array( $value, $current_value ), true, false )
705 + checked( in_array( $value, $current_value, true ), true, false )
602 706 ),
603 707 esc_html( $label )
604 708 );
605 709 }
@@ -651,9 +755,9 @@
651 755 esc_attr( $href ),
652 756 esc_attr( $title )
653 757 );
654 758 break;
655 - case 'select2' :
759 + case 'select2':
656 760 if ( ! isset( $current_value ) ) {
657 761 $current_value = '';
658 762 }
659 763
@@ -670,16 +774,26 @@
670 774 $child_values = array();
671 775 if ( isset( $value['children'] ) ) {
672 776 $child_values = array();
673 777 foreach ( $value['children'] as $child_key => $child_value ) {
674 - $child_values[] = array( 'id' => $child_key, 'text' => $child_value );
778 + $child_values[] = array(
779 + 'id' => $child_key,
780 + 'text' => $child_value,
781 + );
675 782 }
676 783 }
677 784 if ( isset( $value['label'] ) ) {
678 - $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 + );
679 790 }
680 791 } else {
681 - $data_values[] = array( 'id' => $key, 'text' => $value );
792 + $data_values[] = array(
793 + 'id' => $key,
794 + 'text' => $value,
795 + );
682 796 }
683 797 }
684 798 $class .= ' with-source';
685 799 }
@@ -691,8 +805,9 @@
691 805 esc_attr( $name ),
692 806 esc_attr( wp_stream_json_encode( $data_values ) ),
693 807 esc_attr( $current_value ),
694 808 esc_attr( $class ),
809 + /* translators: %s: the title of the dropdown menu (e.g. "users") */
695 810 sprintf( esc_html__( 'Any %s', 'stream' ), $title )
696 811 );
697 812
698 813 $output = sprintf(
@@ -703,13 +818,15 @@
703 818 $input_html
704 819 );
705 820
706 821 break;
707 - case 'rule_list' :
822 + case 'rule_list':
823 + $users = count_users();
824 + $form = new Form_Generator();
708 825 $output = '<p class="description">' . esc_html( $description ) . '</p>';
709 826
710 - $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' ) );
711 - $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' ) );
712 829
713 830 $output .= sprintf( '<div class="tablenav top">%1$s</div>', $actions_top );
714 831 $output .= '<table class="wp-list-table widefat fixed stream-exclude-list">';
715 832
@@ -733,13 +850,18 @@
733 850 );
734 851
735 852 $exclude_rows = array();
736 853
737 - // Prepend an empty row
738 - $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 + }
739 858
859 + // Prepend an empty row.
860 + $current_value['exclude_row'] = ( isset( $current_value['exclude_row'] ) ? $current_value['exclude_row'] : array() ) + array( 'helper' => '' );
861 +
740 862 foreach ( $current_value['exclude_row'] as $key => $value ) {
741 - // Prepare values
863 + // Prepare values.
742 864 $author_or_role = isset( $current_value['author_or_role'][ $key ] ) ? $current_value['author_or_role'][ $key ] : '';
743 865 $connector = isset( $current_value['connector'][ $key ] ) ? $current_value['connector'][ $key ] : '';
744 866 $context = isset( $current_value['context'][ $key ] ) ? $current_value['context'][ $key ] : '';
745 867 $action = isset( $current_value['action'][ $key ] ) ? $current_value['action'][ $key ] : '';
@@ -744,24 +866,27 @@
744 866 $context = isset( $current_value['context'][ $key ] ) ? $current_value['context'][ $key ] : '';
745 867 $action = isset( $current_value['action'][ $key ] ) ? $current_value['action'][ $key ] : '';
746 868 $ip_address = isset( $current_value['ip_address'][ $key ] ) ? $current_value['ip_address'][ $key ] : '';
747 869
748 - // Author or Role dropdown menu
870 + // Author or Role dropdown menu.
749 871 $author_or_role_values = array();
750 872 $author_or_role_selected = array();
751 873
752 874 foreach ( $this->get_roles() as $role_id => $role ) {
753 - $args = array( 'id' => $role_id, 'text' => $role );
754 - $users = count_users();
875 + $args = array(
876 + 'value' => $role_id,
877 + 'text' => $role,
878 + );
755 879 $count = isset( $users['avail_roles'][ $role_id ] ) ? $users['avail_roles'][ $role_id ] : 0;
756 880
757 881 if ( ! empty( $count ) ) {
758 - $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 ) );
759 884 }
760 885
761 886 if ( $role_id === $author_or_role ) {
762 - $author_or_role_selected['id'] = $role_id;
763 - $author_or_role_selected['text'] = $role;
887 + $author_or_role_selected['value'] = $role_id;
888 + $author_or_role_selected['text'] = $role;
764 889 }
765 890
766 891 $author_or_role_values[] = $args;
767 892 }
@@ -768,25 +893,31 @@
768 893
769 894 if ( empty( $author_or_role_selected ) && is_numeric( $author_or_role ) ) {
770 895 $user = new WP_User( $author_or_role );
771 896 $display_name = ( 0 === $user->ID ) ? esc_html__( 'N/A', 'stream' ) : $user->display_name;
772 - $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;
773 902 }
774 903
775 - $author_or_role_input = sprintf(
776 - '<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" />',
777 - esc_attr( $option_key ),
778 - esc_attr( $section ),
779 - esc_attr( $name ),
780 - 'author_or_role',
781 - esc_attr( wp_stream_json_encode( $author_or_role_values ) ),
782 - isset( $author_or_role_selected['id'] ) ? esc_attr( $author_or_role_selected['id'] ) : '',
783 - isset( $author_or_role_selected['text'] ) ? esc_attr( $author_or_role_selected['text'] ) : '',
784 - esc_html__( 'Any Author or Role', 'stream' ),
785 - 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 + )
786 917 );
787 918
788 - // Context dropdown menu
919 + // Context dropdown menu.
789 920 $context_values = array();
790 921
791 922 foreach ( $this->get_terms_labels( 'context' ) as $context_id => $context_data ) {
792 923 if ( is_array( $context_data ) ) {
@@ -793,71 +924,100 @@
793 924 $child_values = array();
794 925 if ( isset( $context_data['children'] ) ) {
795 926 $child_values = array();
796 927 foreach ( $context_data['children'] as $child_id => $child_value ) {
797 - $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 + );
798 933 }
799 934 }
800 935 if ( isset( $context_data['label'] ) ) {
801 - $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 + );
802 941 }
803 942 } else {
804 - $context_values[] = array( 'id' => $context_id, 'text' => $context_data );
943 + $context_values[] = array(
944 + 'value' => $context_id,
945 + 'text' => $context_data,
946 + );
805 947 }
806 948 }
807 949
808 - $connector_input = sprintf(
809 - '<input type="hidden" name="%1$s[%2$s_%3$s][%4$s][]" class="%4$s" value="%5$s">',
810 - esc_attr( $option_key ),
811 - esc_attr( $section ),
812 - esc_attr( $name ),
813 - esc_attr( 'connector' ),
814 - 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 + )
815 961 );
816 962
817 - $context_input = sprintf(
818 - '<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" />',
819 - esc_attr( $option_key ),
820 - esc_attr( $section ),
821 - esc_attr( $name ),
822 - 'context',
823 - esc_attr( wp_stream_json_encode( $context_values ) ),
824 - esc_attr( $context ),
825 - esc_html__( 'Any Context', 'stream' ),
826 - '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 + )
827 970 );
828 971
829 - // 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.
830 982 $action_values = array();
831 983
832 984 foreach ( $this->get_terms_labels( 'action' ) as $action_id => $action_data ) {
833 - $action_values[] = array( 'id' => $action_id, 'text' => $action_data );
985 + $action_values[] = array(
986 + 'value' => $action_id,
987 + 'text' => $action_data,
988 + );
834 989 }
835 990
836 - $action_input = sprintf(
837 - '<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" />',
838 - esc_attr( $option_key ),
839 - esc_attr( $section ),
840 - esc_attr( $name ),
841 - 'action',
842 - esc_attr( wp_stream_json_encode( $action_values ) ),
843 - esc_attr( $action ),
844 - 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 + )
845 1002 );
846 1003
847 - // IP Address input
848 - $ip_address_input = sprintf(
849 - '<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" />',
850 - esc_attr( $option_key ),
851 - esc_attr( $section ),
852 - esc_attr( $name ),
853 - 'ip_address',
854 - esc_attr( $ip_address ),
855 - esc_html__( 'Any IP Address', 'stream' ),
856 - 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 + )
857 1017 );
858 1018
859 - // Hidden helper input
1019 + // Hidden helper input.
860 1020 $helper_input = sprintf(
861 1021 '<input type="hidden" name="%1$s[%2$s_%3$s][%4$s][]" value="" />',
862 1022 esc_attr( $option_key ),
863 1023 esc_attr( $section ),
@@ -868,18 +1028,19 @@
868 1028 $exclude_rows[] = sprintf(
869 1029 '<tr class="%1$s %2$s">
870 1030 <th scope="row" class="check-column">%3$s %4$s</th>
871 1031 <td>%5$s</td>
872 - <td>%6$s %7$s</td>
873 - <td>%8$s</td>
1032 + <td>%6$s %7$s %8$s</td>
874 1033 <td>%9$s</td>
875 - <th scope="row" class="actions-column">%10$s</th>
1034 + <td>%10$s</td>
1035 + <th scope="row" class="actions-column">%11$s</th>
876 1036 </tr>',
877 - ( 0 !== $key % 2 ) ? 'alternate' : '',
878 - ( 'helper' === $key ) ? 'hidden helper' : '',
1037 + ( 0 !== (int) $key % 2 ) ? 'alternate' : '',
1038 + ( 'helper' === (string) $key ) ? 'hidden helper' : '',
879 1039 '<input class="cb-select" type="checkbox" />',
880 1040 $helper_input,
881 1041 $author_or_role_input,
1042 + $connector_or_context_input,
882 1043 $connector_input,
883 1044 $context_input,
884 1045 $action_input,
885 1046 $ip_address_input,
@@ -909,9 +1070,9 @@
909 1070
910 1071 /**
911 1072 * Render Callback for post_types field
912 1073 *
913 - * @param array $field
1074 + * @param array $field Field to be rendered.
914 1075 *
915 1076 * @return string
916 1077 */
917 1078 public function output_field( $field ) {
@@ -922,9 +1083,9 @@
922 1083 }
923 1084
924 1085 $output = $this->render_field( $field );
925 1086
926 - echo $output; // xss ok
1087 + echo $output; // xss ok.
927 1088 }
928 1089
929 1090 /**
930 1091 * Get an array of user roles
@@ -944,9 +1105,9 @@
944 1105
945 1106 /**
946 1107 * Function will return all terms labels of given column
947 1108 *
948 - * @param string $column string Name of the column
1109 + * @param string $column Name of the column.
949 1110 *
950 1111 * @return array
951 1112 */
952 1113 public function get_terms_labels( $column ) {
@@ -979,14 +1140,14 @@
979 1140 * Remove records when records TTL is shortened
980 1141 *
981 1142 * @action update_option_wp_stream
982 1143 *
983 - * @param array $old_value
984 - * @param array $new_value
1144 + * @param array $old_value Old value.
1145 + * @param array $new_value New value.
985 1146 */
986 1147 public function updated_option_ttl_remove_records( $old_value, $new_value ) {
987 - $ttl_before = isset( $old_value['general_records_ttl'] ) ? (int) $old_value['general_records_ttl'] : -1;
988 - $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;
989 1150
990 1151 if ( $ttl_after < $ttl_before ) {
991 1152 /**
992 1153 * Action assists in purging when TTL is shortened
@@ -999,8 +1160,10 @@
999 1160 * Get translations of serialized Stream settings
1000 1161 *
1001 1162 * @filter wp_stream_serialized_labels
1002 1163 *
1164 + * @param array $labels Setting labels.
1165 + *
1003 1166 * @return array Multidimensional array of fields
1004 1167 */
1005 1168 public function get_settings_translations( $labels ) {
1006 1169 if ( ! isset( $labels[ $this->option_key ] ) ) {
@@ -1014,6 +1177,5 @@
1014 1177 }
1015 1178
1016 1179 return $labels;
1017 1180 }
1018 -
1019 1181 }