PluginProbe
Stream – Activity Log & Audit Trail / 2.0.2
Stream – Activity Log & Audit Trail v2.0.2
4.4.0 4.3.0 4.2.2 4.2.1 trunk 2.0.1 2.0.2 2.0.3 2.0.4 2.0.5 3.0.0 3.0.1 3.0.2 3.0.3 3.0.4 3.0.5 3.0.6 3.0.7 3.1 3.1.1 3.10.0 3.2.0 3.2.1 3.2.2 3.2.3 All 50 releases
stream / classes / class-wp-stream-settings.php

class-wp-stream-settings.php in Stream – Activity Log & Audit Trail 2.0.2, at classes/class-wp-stream-settings.php

924 lines 28.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Settings class
4 *
5 * @author X-Team <x-team.com>
6 * @author Shady Sharaf <shady@x-team.com>
7 */
8 class WP_Stream_Settings {
9
10 /**
11 * Settings key/identifier
12 */
13 const OPTION_KEY = 'wp_stream';
14
15 /**
16 * Plugin settings
17 *
18 * @var array
19 */
20 public static $options = array();
21
22 /**
23 * Option key for current screen
24 *
25 * @var array
26 */
27 public static $option_key = '';
28
29 /**
30 * Settings fields
31 *
32 * @var array
33 */
34 public static $fields = array();
35
36 /**
37 * Public constructor
38 *
39 * @return void
40 */
41 public static function load() {
42 self::$option_key = self::get_option_key();
43 self::$options = self::get_options();
44
45 // Register settings, and fields
46 add_action( 'admin_init', array( __CLASS__, 'register_settings' ) );
47
48 // Check if we need to flush rewrites rules
49 add_action( 'update_option_' . self::OPTION_KEY, array( __CLASS__, 'updated_option_trigger_flush_rules' ), 10, 2 );
50
51 add_filter( 'wp_stream_serialized_labels', array( __CLASS__, 'get_settings_translations' ) );
52
53 // Ajax callback function to search users
54 add_action( 'wp_ajax_stream_get_users', array( __CLASS__, 'get_users' ) );
55
56 // Ajax callback function to search IPs
57 add_action( 'wp_ajax_stream_get_ips', array( __CLASS__, 'get_ips' ) );
58 }
59
60 /**
61 * Ajax callback function to search users, used on exclude setting page
62 *
63 * @uses WP_User_Query WordPress User Query class.
64 * @return void
65 */
66 public static function get_users(){
67 if ( ! defined( 'DOING_AJAX' ) || ! current_user_can( WP_Stream_Admin::SETTINGS_CAP ) ) {
68 return;
69 }
70
71 check_ajax_referer( 'stream_get_users', 'nonce' );
72
73 $response = (object) array(
74 'status' => false,
75 'message' => esc_html__( 'There was an error in the request', 'stream' ),
76 );
77
78 $search = ( isset( $_POST['find'] )? wp_unslash( trim( $_POST['find'] ) ) : '' );
79 $request = (object) array(
80 'find' => $search,
81 );
82
83 add_filter( 'user_search_columns', array( __CLASS__, 'add_display_name_search_columns' ), 10, 3 );
84
85 $users = new WP_User_Query(
86 array(
87 'search' => "*{$request->find}*",
88 'search_columns' => array(
89 'user_login',
90 'user_nicename',
91 'user_email',
92 'user_url',
93 ),
94 'orderby' => 'display_name',
95 'number' => WP_Stream_Admin::PRELOAD_AUTHORS_MAX,
96 )
97 );
98
99 remove_filter( 'user_search_columns', array( __CLASS__, 'add_display_name_search_columns' ), 10 );
100
101 if ( 0 === $users->get_total() ) {
102 wp_send_json_error( $response );
103 }
104
105 $response->status = true;
106 $response->message = '';
107 $response->users = array();
108
109 foreach ( $users->results as $key => $user ) {
110 $author = new WP_Stream_Author( $user->ID );
111
112 $args = array(
113 'id' => $author->ID,
114 'text' => $author->display_name,
115 );
116
117 $args['tooltip'] = esc_attr(
118 sprintf(
119 __( "ID: %d\nUser: %s\nEmail: %s\nRole: %s", 'stream' ),
120 $author->id,
121 $author->user_login,
122 $author->user_email,
123 ucwords( $author->get_role() )
124 )
125 );
126
127 $args['icon'] = $author->get_avatar_src( 32 );
128
129 $response->users[] = $args;
130 }
131
132 if ( empty( $search ) || preg_match( '/wp|cli|system|unknown/i', $search ) ) {
133 $author = new WP_Stream_Author( 0 );
134 $response->users[] = array(
135 'id' => $author->id,
136 'text' => $author->get_display_name(),
137 'icon' => $author->get_avatar_src( 32 ),
138 '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' ),
139 );
140 }
141
142 wp_send_json_success( $response );
143 }
144
145 /**
146 * Ajax callback function to search IP addresses, used on exclude setting page
147 *
148 * @uses WP_User_Query WordPress User Query class.
149 * @return void
150 */
151 public static function get_ips(){
152 if ( ! defined( 'DOING_AJAX' ) || ! current_user_can( WP_Stream_Admin::SETTINGS_CAP ) ) {
153 return;
154 }
155
156 check_ajax_referer( 'stream_get_ips', 'nonce' );
157
158 $ips = wp_stream_existing_records( 'ip' );
159
160 if ( $ips ) {
161 wp_send_json_success( $ips );
162 } else {
163 wp_send_json_error();
164 }
165 }
166
167 /**
168 * Filter the columns to search in a WP_User_Query search.
169 *
170 * @param array $search_columns Array of column names to be searched.
171 * @param string $search Text being searched.
172 * @param WP_User_Query $query current WP_User_Query instance.
173 *
174 * @return array
175 */
176 public static function add_display_name_search_columns( $search_columns, $search, $query ){
177 $search_columns[] = 'display_name';
178
179 return $search_columns;
180 }
181
182 /**
183 * Returns the option key depending on which settings page is being viewed
184 *
185 * @return string Option key for this page
186 */
187 public static function get_option_key() {
188 $option_key = self::OPTION_KEY;
189
190 $current_page = wp_stream_filter_input( INPUT_GET, 'page' );
191
192 if ( ! $current_page ) {
193 $current_page = wp_stream_filter_input( INPUT_GET, 'action' );
194 }
195
196 return apply_filters( 'wp_stream_settings_option_key', $option_key );
197 }
198
199 /**
200 * Return settings fields
201 *
202 * @return array Multidimensional array of fields
203 */
204 public static function get_fields() {
205 $fields = array(
206 'general' => array(
207 'title' => esc_html__( 'General', 'stream' ),
208 'fields' => array(
209 array(
210 'name' => 'role_access',
211 'title' => esc_html__( 'Role Access', 'stream' ),
212 'type' => 'multi_checkbox',
213 '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' ),
214 'choices' => self::get_roles(),
215 'default' => array( 'administrator' ),
216 ),
217 array(
218 'name' => 'private_feeds',
219 'title' => esc_html__( 'Private Feeds', 'stream' ),
220 'type' => 'checkbox',
221 'desc' => sprintf(
222 __( 'Users from the selected roles above will be given a private key found in their %suser profile%s to access feeds of Stream Records securely. Please %sflush rewrite rules%s on your site after changing this setting.', 'stream' ),
223 sprintf(
224 '<a href="%s" title="%s">',
225 admin_url( sprintf( 'profile.php#wp-stream-highlight:%s', WP_Stream_Feeds::USER_FEED_OPTION_KEY ) ),
226 esc_attr__( 'View Profile', 'stream' )
227 ),
228 '</a>',
229 sprintf(
230 '<a href="%s" title="%s" target="_blank">',
231 esc_url( 'http://codex.wordpress.org/Rewrite_API/flush_rules#What_it_does' ),
232 esc_attr__( 'View Codex', 'stream' )
233 ),
234 '</a>'
235 ),
236 'after_field' => esc_html__( 'Enabled', 'stream' ),
237 'default' => 0,
238 ),
239 ),
240 ),
241 'exclude' => array(
242 'title' => esc_html__( 'Exclude', 'stream' ),
243 'fields' => array(
244 array(
245 'name' => 'rules',
246 'title' => esc_html__( 'Exclude Rules', 'stream' ),
247 'type' => 'rule_list',
248 'desc' => esc_html__( 'Create rules for excluding certain kinds of records from appearing in Stream.', 'stream' ),
249 'default' => array(),
250 'nonce' => 'stream_get_ips',
251 ),
252 ),
253 ),
254 'advanced' => array(
255 'title' => esc_html__( 'Advanced', 'stream' ),
256 'fields' => array(
257 array(
258 'name' => 'comment_flood_tracking',
259 'title' => esc_html__( 'Comment Flood Tracking', 'stream' ),
260 'type' => 'checkbox',
261 'desc' => __( 'WordPress will automatically prevent duplicate comments from flooding the database. By default, Stream does not track these attempts unless you opt-in here. Enabling this is not necessary or recommended for most sites.', 'stream' ),
262 'after_field' => esc_html__( 'Enabled', 'stream' ),
263 'default' => 0,
264 ),
265 array(
266 'name' => 'wp_cron_tracking',
267 'title' => esc_html__( 'WP Cron Tracking', 'stream' ),
268 'type' => 'checkbox',
269 'desc' => __( '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' ),
270 'after_field' => esc_html__( 'Enabled', 'stream' ),
271 'default' => 0,
272 ),
273 ),
274 ),
275 );
276
277 // If Akismet is active, allow Admins to opt-in to Akismet tracking
278 if ( class_exists( 'Akismet' ) ) {
279 $akismet_tracking = array(
280 'name' => 'akismet_tracking',
281 'title' => esc_html__( 'Akismet Tracking', 'stream' ),
282 'type' => 'checkbox',
283 'desc' => __( 'Akismet already keeps statistics for comment attempts that it blocks as SPAM. By default, Stream does not track these attempts unless you opt-in here. Enabling this is not necessary or recommended for most sites.', 'stream' ),
284 'after_field' => esc_html__( 'Enabled', 'stream' ),
285 'default' => 0,
286 );
287
288 array_push( $fields['advanced']['fields'], $akismet_tracking );
289 }
290
291 // Sort option fields in each tab by title ASC
292 foreach ( $fields as $tab => $options ) {
293 $titles = wp_list_pluck( $fields[ $tab ]['fields'], 'title' );
294
295 array_multisort( $titles, SORT_ASC, $fields[ $tab ]['fields'] );
296 }
297
298 /**
299 * Filter allows for modification of options fields
300 *
301 * @return array Array of option fields
302 */
303 self::$fields = apply_filters( 'wp_stream_settings_option_fields', $fields );
304
305 return self::$fields;
306 }
307
308 /**
309 * Returns a list of options based on the current screen.
310 *
311 * @return array Options
312 */
313 public static function get_options() {
314 $option_key = self::$option_key;
315 $defaults = self::get_defaults( $option_key );
316
317 /**
318 * Filter allows for modification of options
319 *
320 * @param array array of options
321 * @return array updated array of options
322 */
323 return apply_filters(
324 'wp_stream_settings_options',
325 wp_parse_args(
326 (array) get_option( $option_key, array() ),
327 $defaults
328 ),
329 $option_key
330 );
331 }
332
333 /**
334 * Iterate through registered fields and extract default values
335 *
336 * @return array Default option values
337 */
338 public static function get_defaults() {
339 $fields = self::get_fields();
340 $defaults = array();
341
342 foreach ( $fields as $section_name => $section ) {
343 foreach ( $section['fields'] as $field ) {
344 $defaults[ $section_name.'_'.$field['name'] ] = isset( $field['default'] )
345 ? $field['default']
346 : null;
347 }
348 }
349
350 /**
351 * Filter allows for modification of options defaults
352 *
353 * @param array array of options
354 * @return array updated array of option defaults
355 */
356 return apply_filters(
357 'wp_stream_settings_option_defaults',
358 $defaults
359 );
360 }
361
362 /**
363 * Registers settings fields and sections
364 *
365 * @return void
366 */
367 public static function register_settings() {
368 $sections = self::get_fields();
369
370 register_setting( self::$option_key, self::$option_key );
371
372 foreach ( $sections as $section_name => $section ) {
373 add_settings_section(
374 $section_name,
375 null,
376 '__return_false',
377 self::$option_key
378 );
379
380 foreach ( $section['fields'] as $field_idx => $field ) {
381 if ( ! isset( $field['type'] ) ) { // No field type associated, skip, no GUI
382 continue;
383 }
384 add_settings_field(
385 $field['name'],
386 $field['title'],
387 ( isset( $field['callback'] ) ? $field['callback'] : array( __CLASS__, 'output_field' ) ),
388 self::$option_key,
389 $section_name,
390 $field + array(
391 'section' => $section_name,
392 'label_for' => sprintf( '%s_%s_%s', self::$option_key, $section_name, $field['name'] ), // xss ok
393 )
394 );
395 }
396 }
397 }
398
399 /**
400 * Check if we have updated a settings that requires rewrite rules to be flushed
401 *
402 * @param array $old_value
403 * @param array $new_value
404 *
405 * @internal param $option
406 * @internal param string $option
407 * @action updated_option
408 * @return void
409 */
410 public static function updated_option_trigger_flush_rules( $old_value, $new_value ) {
411 if ( is_array( $new_value ) && is_array( $old_value ) ) {
412 $new_value = ( array_key_exists( 'general_private_feeds', $new_value ) ) ? $new_value['general_private_feeds'] : 0;
413 $old_value = ( array_key_exists( 'general_private_feeds', $old_value ) ) ? $old_value['general_private_feeds'] : 0;
414
415 if ( $new_value !== $old_value ) {
416 delete_option( 'rewrite_rules' );
417 }
418 }
419 }
420
421 /**
422 * Compile HTML needed for displaying the field
423 *
424 * @param array $field Field settings
425 * @return string HTML to be displayed
426 */
427 public static function render_field( $field ) {
428 $output = null;
429 $type = isset( $field['type'] ) ? $field['type'] : null;
430 $section = isset( $field['section'] ) ? $field['section'] : null;
431 $name = isset( $field['name'] ) ? $field['name'] : null;
432 $class = isset( $field['class'] ) ? $field['class'] : null;
433 $placeholder = isset( $field['placeholder'] ) ? $field['placeholder'] : null;
434 $description = isset( $field['desc'] ) ? $field['desc'] : null;
435 $href = isset( $field['href'] ) ? $field['href'] : null;
436 $rows = isset( $field['rows'] ) ? $field['rows'] : 10;
437 $cols = isset( $field['cols'] ) ? $field['cols'] : 50;
438 $after_field = isset( $field['after_field'] ) ? $field['after_field'] : null;
439 $default = isset( $field['default'] ) ? $field['default'] : null;
440 $title = isset( $field['title'] ) ? $field['title'] : null;
441 $nonce = isset( $field['nonce'] ) ? $field['nonce'] : null;
442
443 if ( isset( $field['value'] ) ) {
444 $current_value = $field['value'];
445 } else {
446 $current_value = self::$options[ $section . '_' . $name ];
447 }
448
449 $option_key = self::$option_key;
450
451 if ( is_callable( $current_value ) ) {
452 $current_value = call_user_func( $current_value );
453 }
454
455 if ( ! $type || ! $section || ! $name ) {
456 return;
457 }
458
459 if ( 'multi_checkbox' === $type
460 && ( empty( $field['choices'] ) || ! is_array( $field['choices'] ) )
461 ) {
462 return;
463 }
464
465 switch ( $type ) {
466 case 'text':
467 case 'number':
468 $output = sprintf(
469 '<input type="%1$s" name="%2$s[%3$s_%4$s]" id="%2$s_%3$s_%4$s" class="%5$s" placeholder="%6$s" value="%7$s" /> %8$s',
470 esc_attr( $type ),
471 esc_attr( $option_key ),
472 esc_attr( $section ),
473 esc_attr( $name ),
474 esc_attr( $class ),
475 esc_attr( $placeholder ),
476 esc_attr( $current_value ),
477 $after_field // xss ok
478 );
479 break;
480 case 'textarea':
481 $output = sprintf(
482 '<textarea name="%1$s[%2$s_%3$s]" id="%1$s_%2$s_%3$s" class="%4$s" placeholder="%5$s" rows="%6$d" cols="%7$d">%8$s</textarea> %9$s',
483 esc_attr( $option_key ),
484 esc_attr( $section ),
485 esc_attr( $name ),
486 esc_attr( $class ),
487 esc_attr( $placeholder ),
488 absint( $rows ),
489 absint( $cols ),
490 esc_textarea( $current_value ),
491 $after_field // xss ok
492 );
493 break;
494 case 'checkbox':
495 $output = sprintf(
496 '<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>',
497 esc_attr( $option_key ),
498 esc_attr( $section ),
499 esc_attr( $name ),
500 checked( $current_value, 1, false ),
501 $after_field // xss ok
502 );
503 break;
504 case 'multi_checkbox':
505 $output = sprintf(
506 '<div id="%1$s[%2$s_%3$s]"><fieldset>',
507 esc_attr( $option_key ),
508 esc_attr( $section ),
509 esc_attr( $name )
510 );
511 // Fallback if nothing is selected
512 $output .= sprintf(
513 '<input type="hidden" name="%1$s[%2$s_%3$s][]" value="__placeholder__" />',
514 esc_attr( $option_key ),
515 esc_attr( $section ),
516 esc_attr( $name )
517 );
518 $current_value = (array) $current_value;
519 $choices = $field['choices'];
520 if ( is_callable( $choices ) ) {
521 $choices = call_user_func( $choices );
522 }
523 foreach ( $choices as $value => $label ) {
524 $output .= sprintf(
525 '<label>%1$s <span>%2$s</span></label><br />',
526 sprintf(
527 '<input type="checkbox" name="%1$s[%2$s_%3$s][]" value="%4$s" %5$s />',
528 esc_attr( $option_key ),
529 esc_attr( $section ),
530 esc_attr( $name ),
531 esc_attr( $value ),
532 checked( in_array( $value, $current_value ), true, false )
533 ),
534 esc_html( $label )
535 );
536 }
537 $output .= '</fieldset></div>';
538 break;
539 case 'select':
540 $current_value = self::$options[ $section . '_' . $name ];
541 $default_value = isset( $default['value'] ) ? $default['value'] : '-1';
542 $default_name = isset( $default['name'] ) ? $default['name'] : 'Choose Setting';
543
544 $output = sprintf(
545 '<select name="%1$s[%2$s_%3$s]" class="%1$s_%2$s_%3$s">',
546 esc_attr( $option_key ),
547 esc_attr( $section ),
548 esc_attr( $name )
549 );
550 $output .= sprintf(
551 '<option value="%1$s" %2$s>%3$s</option>',
552 esc_attr( $default_value ),
553 checked( $default_value === $current_value, true, false ),
554 esc_html( $default_name )
555 );
556 foreach ( $field['choices'] as $value => $label ) {
557 $output .= sprintf(
558 '<option value="%1$s" %2$s>%3$s</option>',
559 esc_attr( $value ),
560 checked( $value === $current_value, true, false ),
561 esc_html( $label )
562 );
563 }
564 $output .= '</select>';
565 break;
566 case 'file':
567 $output = sprintf(
568 '<input type="file" name="%1$s[%2$s_%3$s]" class="%4$s">',
569 esc_attr( $option_key ),
570 esc_attr( $section ),
571 esc_attr( $name ),
572 esc_attr( $class )
573 );
574 break;
575 case 'link':
576 $output = sprintf(
577 '<a id="%1$s_%2$s_%3$s" class="%4$s" href="%5$s">%6$s</a>',
578 esc_attr( $option_key ),
579 esc_attr( $section ),
580 esc_attr( $name ),
581 esc_attr( $class ),
582 esc_attr( $href ),
583 esc_attr( $title )
584 );
585 break;
586 case 'select2' :
587 if ( ! isset( $current_value ) ) {
588 $current_value = '';
589 }
590
591 $data_values = array();
592
593 if ( isset( $field['choices'] ) ) {
594 $choices = $field['choices'];
595 if ( is_callable( $choices ) ) {
596 $param = ( isset( $field['param'] ) ) ? $field['param'] : null;
597 $choices = call_user_func( $choices, $param );
598 }
599 foreach ( $choices as $key => $value ) {
600 if ( is_array( $value ) ) {
601 $child_values = array();
602 if ( isset( $value['children'] ) ) {
603 $child_values = array();
604 foreach ( $value['children'] as $child_key => $child_value ) {
605 $child_values[] = array( 'id' => $child_key, 'text' => $child_value );
606 }
607 }
608 if ( isset( $value['label'] ) ) {
609 $data_values[] = array( 'id' => $key, 'text' => $value['label'], 'children' => $child_values );
610 }
611 } else {
612 $data_values[] = array( 'id' => $key, 'text' => $value );
613 }
614 }
615 $class .= ' with-source';
616 }
617
618 $input_html = sprintf(
619 '<input type="hidden" name="%1$s[%2$s_%3$s]" data-values=\'%4$s\' value="%5$s" class="select2-select %6$s" data-placeholder="%7$s" />',
620 esc_attr( $option_key ),
621 esc_attr( $section ),
622 esc_attr( $name ),
623 esc_attr( json_encode( $data_values ) ),
624 esc_attr( $current_value ),
625 $class,
626 sprintf( esc_html__( 'Any %s', 'stream' ), $title )
627 );
628
629 $output = sprintf(
630 '<div class="%1$s_%2$s_%3$s">%4$s</div>',
631 esc_attr( $option_key ),
632 esc_attr( $section ),
633 esc_attr( $name ),
634 $input_html
635 );
636
637 break;
638 case 'rule_list' :
639 $output = '<p class="description">' . esc_html( $description ) . '</p>';
640
641 $actions_top = sprintf( '<input type="button" class="button" id="%1$s_new_rule" value="&#43; %2$s" />', esc_attr( $section . '_' . $name ), __( 'Add New Rule', 'stream' ) );
642 $actions_bottom = sprintf( '<input type="button" class="button" id="%1$s_remove_rules" value="%2$s" />', esc_attr( $section . '_' . $name ), __( 'Delete Selected Rules', 'stream' ) );
643
644 $output .= sprintf( '<div class="tablenav top">%1$s</div>', $actions_top );
645 $output .= '<table class="wp-list-table widefat fixed stream-exclude-list">';
646
647 unset( $description );
648
649 $heading_row = sprintf(
650 '<tr>
651 <th scope="col" class="check-column manage-column">%1$s</th>
652 <th scope="col" class="manage-column">%2$s</th>
653 <th scope="col" class="manage-column">%3$s</th>
654 <th scope="col" class="manage-column">%4$s</th>
655 <th scope="col" class="manage-column">%5$s</th>
656 <th scope="col" class="actions-column manage-column"><span class="hidden">%6$s</span></th>
657 </tr>',
658 '<input class="cb-select" type="checkbox" />',
659 esc_html__( 'Author or Role', 'stream' ),
660 esc_html__( 'Context', 'stream' ),
661 esc_html__( 'Action', 'stream' ),
662 esc_html__( 'IP Address', 'stream' ),
663 esc_html__( 'Filters', 'stream' )
664 );
665
666 $exclude_rows = array();
667
668 // Prepend an empty row
669 $current_value['exclude_row'] = array( 'helper' => '' ) + ( isset( $current_value['exclude_row'] ) ? $current_value['exclude_row'] : array() );
670
671 foreach ( $current_value['exclude_row'] as $key => $value ) {
672 // Prepare values
673 $author_or_role = isset( $current_value['author_or_role'][ $key ] ) ? $current_value['author_or_role'][ $key ] : '';
674 $connector = isset( $current_value['connector'][ $key ] ) ? $current_value['connector'][ $key ] : '';
675 $context = isset( $current_value['context'][ $key ] ) ? $current_value['context'][ $key ] : '';
676 $action = isset( $current_value['action'][ $key ] ) ? $current_value['action'][ $key ] : '';
677 $ip_address = isset( $current_value['ip_address'][ $key ] ) ? $current_value['ip_address'][ $key ] : '';
678
679 // Author or Role dropdown menu
680 $author_or_role_values = array();
681 $author_or_role_selected = array();
682
683 foreach ( self::get_roles() as $role_id => $role ) {
684 $args = array( 'id' => $role_id, 'text' => $role );
685 $users = get_users( array( 'role' => $role_id ) );
686 if ( count( $users ) ) {
687 $args['user_count'] = sprintf( _n( '1 user', '%s users', count( $users ), 'stream' ), count( $users ) );
688 }
689 if ( $role_id === $author_or_role ) {
690 $author_or_role_selected['id'] = $role_id;
691 $author_or_role_selected['text'] = $role;
692 }
693 $author_or_role_values[] = $args;
694 }
695
696 if ( empty( $author_or_role_selected ) && is_numeric( $author_or_role ) ) {
697 $user = new WP_User( $author_or_role );
698 $author_or_role_selected = array( 'id' => $user->ID, 'text' => $user->display_name );
699 }
700
701 $author_or_role_input = sprintf(
702 '<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" />',
703 esc_attr( $option_key ),
704 esc_attr( $section ),
705 esc_attr( $name ),
706 'author_or_role',
707 esc_attr( json_encode( $author_or_role_values ) ),
708 isset( $author_or_role_selected['id'] ) ? esc_attr( $author_or_role_selected['id'] ) : '',
709 isset( $author_or_role_selected['text'] ) ? esc_attr( $author_or_role_selected['text'] ) : '',
710 esc_html__( 'Any Author or Role', 'stream' ),
711 esc_attr( wp_create_nonce( 'stream_get_users' ) )
712 );
713
714 // Context dropdown menu
715 $context_values = array();
716
717 foreach ( self::get_terms_labels( 'context' ) as $context_id => $context_data ) {
718 if ( is_array( $context_data ) ) {
719 $child_values = array();
720 if ( isset( $context_data['children'] ) ) {
721 $child_values = array();
722 foreach ( $context_data['children'] as $child_id => $child_value ) {
723 $child_values[] = array( 'id' => $child_id, 'text' => $child_value, 'parent' => $context_id );
724 }
725 }
726 if ( isset( $context_data['label'] ) ) {
727 $context_values[] = array( 'id' => $context_id, 'text' => $context_data['label'], 'children' => $child_values );
728 }
729 } else {
730 $context_values[] = array( 'id' => $context_id, 'text' => $context_data );
731 }
732 }
733
734 $connector_input = sprintf(
735 '<input type="hidden" name="%1$s[%2$s_%3$s][%4$s][]" class="%4$s" value="%5$s">',
736 esc_attr( $option_key ),
737 esc_attr( $section ),
738 esc_attr( $name ),
739 esc_attr( 'connector' ),
740 esc_attr( $connector )
741 );
742
743 $context_input = sprintf(
744 '<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" />',
745 esc_attr( $option_key ),
746 esc_attr( $section ),
747 esc_attr( $name ),
748 'context',
749 esc_attr( json_encode( $context_values ) ),
750 esc_attr( $context ),
751 esc_html__( 'Any Context', 'stream' ),
752 'connector'
753 );
754
755 // Action dropdown menu
756 $action_values = array();
757
758 foreach ( self::get_terms_labels( 'action' ) as $action_id => $action_data ) {
759 $action_values[] = array( 'id' => $action_id, 'text' => $action_data );
760 }
761
762 $action_input = sprintf(
763 '<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" />',
764 esc_attr( $option_key ),
765 esc_attr( $section ),
766 esc_attr( $name ),
767 'action',
768 esc_attr( json_encode( $action_values ) ),
769 esc_attr( $action ),
770 esc_html__( 'Any Action', 'stream' )
771 );
772
773 // IP Address input
774 $ip_address_input = sprintf(
775 '<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" />',
776 esc_attr( $option_key ),
777 esc_attr( $section ),
778 esc_attr( $name ),
779 'ip_address',
780 esc_attr( $ip_address ),
781 esc_html__( 'Any IP Address', 'stream' ),
782 esc_attr( wp_create_nonce( 'stream_get_ips' ) )
783 );
784
785 // Hidden helper input
786 $helper_input = sprintf(
787 '<input type="hidden" name="%1$s[%2$s_%3$s][%4$s][]" value="" />',
788 esc_attr( $option_key ),
789 esc_attr( $section ),
790 esc_attr( $name ),
791 'exclude_row'
792 );
793
794 $exclude_rows[] = sprintf(
795 '<tr class="%1$s %2$s">
796 <th scope="row" class="check-column">%3$s %4$s</th>
797 <td>%5$s</td>
798 <td>%6$s %7$s</td>
799 <td>%8$s</td>
800 <td>%9$s</td>
801 <th scope="row" class="actions-column">%10$s</th>
802 </tr>',
803 ( 0 !== $key % 2 ) ? 'alternate' : '',
804 ( 'helper' === $key ) ? 'hidden helper' : '',
805 '<input class="cb-select" type="checkbox" />',
806 $helper_input,
807 $author_or_role_input,
808 $connector_input,
809 $context_input,
810 $action_input,
811 $ip_address_input,
812 '<a href="#" class="exclude_rules_remove_rule_row">Delete</a>'
813 );
814 }
815
816 $no_rules_found_row = sprintf(
817 '<tr class="no-items hidden"><td class="colspanchange" colspan="5">%1$s</td></tr>',
818 esc_html__( 'No rules found.', 'stream' )
819 );
820
821 $output .= '<thead>' . $heading_row . '</thead>';
822 $output .= '<tfoot>' . $heading_row . '</tfoot>';
823 $output .= '<tbody>' . $no_rules_found_row . implode( '', $exclude_rows ) . '</tbody>';
824
825 $output .= '</table>';
826
827 $output .= sprintf( '<div class="tablenav bottom">%1$s</div>', $actions_bottom );
828
829 break;
830 }
831 $output .= ! empty( $description ) ? sprintf( '<p class="description">%s</p>', $description /* xss ok */ ) : null;
832
833 return $output;
834 }
835
836 /**
837 * Render Callback for post_types field
838 *
839 * @param array $field
840 *
841 * @internal param $args
842 * @return void
843 */
844 public static function output_field( $field ) {
845 $method = 'output_' . $field['name'];
846
847 if ( method_exists( __CLASS__, $method ) ) {
848 return call_user_func( array( __CLASS__, $method ), $field );
849 }
850
851 $output = self::render_field( $field );
852
853 echo $output; // xss okay
854 }
855
856 /**
857 * Get an array of user roles
858 *
859 * @return array
860 */
861 public static function get_roles() {
862 $wp_roles = new WP_Roles();
863 $roles = array();
864
865 foreach ( $wp_roles->get_names() as $role => $label ) {
866 $roles[ $role ] = translate_user_role( $label );
867 }
868
869 return $roles;
870 }
871
872 /**
873 * Function will return all terms labels of given column
874 *
875 * @param $column string Name of the column
876 * @return array
877 */
878 public static function get_terms_labels( $column ) {
879 $return_labels = array();
880
881 if ( isset( WP_Stream_Connectors::$term_labels[ 'stream_' . $column ] ) ) {
882 if ( 'context' === $column && isset( WP_Stream_Connectors::$term_labels['stream_connector'] ) ) {
883 $connectors = WP_Stream_Connectors::$term_labels['stream_connector'];
884 $contexts = WP_Stream_Connectors::$term_labels['stream_context'];
885
886 foreach ( $connectors as $connector => $connector_label ) {
887 $return_labels[ $connector ]['label'] = $connector_label;
888 foreach ( $contexts as $context => $context_label ) {
889 if ( isset( WP_Stream_Connectors::$contexts[ $connector ] ) && array_key_exists( $context, WP_Stream_Connectors::$contexts[ $connector ] ) ) {
890 $return_labels[ $connector ]['children'][ $context ] = $context_label;
891 }
892 }
893 }
894 } else {
895 $return_labels = WP_Stream_Connectors::$term_labels[ 'stream_' . $column ];
896 }
897
898 ksort( $return_labels );
899 }
900
901 return $return_labels;
902 }
903
904 /**
905 * Get translations of serialized Stream settings
906 *
907 * @filter wp_stream_serialized_labels
908 * @return array Multidimensional array of fields
909 */
910 public static function get_settings_translations( $labels ) {
911 if ( ! isset( $labels[ self::OPTION_KEY ] ) ) {
912 $labels[ self::OPTION_KEY ] = array();
913 }
914
915 foreach ( self::get_fields() as $section_slug => $section ) {
916 foreach ( $section['fields'] as $field ) {
917 $labels[ self::OPTION_KEY ][ sprintf( '%s_%s', $section_slug, $field['name'] ) ] = $field['title'];
918 }
919 }
920
921 return $labels;
922 }
923 }
924