PluginProbe
Stream – Activity Log & Audit Trail / 3.4.2
Stream – Activity Log & Audit Trail v3.4.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-list-table.php +154 -291 trunk3.4.2 View file →
@@ -1,20 +1,12 @@
1 1 <?php
2 -/**
3 - * Generates a filterable list of provided records to be displayed HTML Table.
4 - *
5 - * @package WP_Stream
6 - */
7 2
8 3 namespace WP_Stream;
9 4
10 -/**
11 - * Class - List_Table
12 - */
13 5 class List_Table extends \WP_List_Table {
14 6
15 7 /**
16 - * Holds Instance of plugin object
8 + * Hold Plugin class
17 9 *
18 10 * @var Plugin
19 11 */
20 12 public $plugin;
@@ -21,10 +13,10 @@
21 13
22 14 /**
23 15 * Class constructor.
24 16 *
25 - * @param Plugin $plugin Instance of plugin object.
26 - * @param array $args Argument to filter rows by.
17 + * @param Plugin $plugin The main Plugin class.
18 + * @param array $args
27 19 */
28 20 public function __construct( $plugin, $args = array() ) {
29 21 $this->plugin = $plugin;
30 22
@@ -53,9 +45,9 @@
53 45 'option' => 'edit_stream_per_page',
54 46 )
55 47 );
56 48
57 - // Check for default hidden columns.
49 + // Check for default hidden columns
58 50 $this->get_hidden_columns();
59 51
60 52 add_filter(
61 53 'screen_settings',
@@ -78,40 +70,22 @@
78 70
79 71 set_screen_options();
80 72 }
81 73
82 - /**
83 - * Renders extra from navigation options.
84 - *
85 - * @param string $which Page location.
86 - * @return void
87 - */
88 74 public function extra_tablenav( $which ) {
89 75 if ( 'top' === $which ) {
90 - echo '<div class="alignleft actions">';
91 - $this->render_filters_form();
92 - echo '</div>';
76 + echo $this->filters_form(); // xss ok
93 77 }
94 78 }
95 79
96 - /**
97 - * Renders "No items found" message.
98 - *
99 - * @return void
100 - */
101 80 public function no_items() {
102 81 ?>
103 82 <div class="stream-list-table-no-items">
104 - <p><?php esc_html_e( 'No activity records were found.', 'stream' ); ?></p>
83 + <p><?php esc_html_e( 'Sorry, no activity records were found.', 'stream' ); ?></p>
105 84 </div>
106 85 <?php
107 86 }
108 87
109 - /**
110 - * Returns the table columns to be rendered.
111 - *
112 - * @return array
113 - */
114 88 public function get_columns() {
115 89 /**
116 90 * Allows devs to add new columns to table
117 91 *
@@ -129,13 +103,8 @@
129 103 )
130 104 );
131 105 }
132 106
133 - /**
134 - * Returns the columns the items can be sort by.
135 - *
136 - * @return array
137 - */
138 107 public function get_sortable_columns() {
139 108 return array(
140 109 'date' => array( 'date', false ),
141 110 );
@@ -140,13 +109,8 @@
140 109 'date' => array( 'date', false ),
141 110 );
142 111 }
143 112
144 - /**
145 - * Returns columns hidden from all except specific users.
146 - *
147 - * @return array|bool
148 - */
149 113 public function get_hidden_columns() {
150 114 $user = wp_get_current_user();
151 115 if ( ! $user ) {
152 116 return array();
@@ -151,25 +115,20 @@
151 115 if ( ! $user ) {
152 116 return array();
153 117 }
154 118
155 - // Directly checking the user meta; to check whether user has changed screen option or not.
156 - $hidden = get_user_meta( $user->ID, 'manage' . $this->screen->id . 'columnshidden', true );
119 + // Directly checking the user meta; to check whether user has changed screen option or not
120 + $hidden = $this->plugin->admin->get_user_meta( $user->ID, 'manage' . $this->screen->id . 'columnshidden', true );
157 121
158 - // If user meta is not found; add the default hidden column 'id'.
122 + // If user meta is not found; add the default hidden column 'id'
159 123 if ( ! $hidden ) {
160 124 $hidden = array( 'id' );
161 - update_user_meta( $user->ID, 'manage' . $this->screen->id . 'columnshidden', $hidden );
125 + $this->plugin->admin->update_user_meta( $user->ID, 'manage' . $this->screen->id . 'columnshidden', $hidden );
162 126 }
163 127
164 128 return $hidden;
165 129 }
166 130
167 - /**
168 - * Prepares table columns and data for render
169 - *
170 - * @return void
171 - */
172 131 public function prepare_items() {
173 132 $columns = $this->get_columns();
174 133 $sortable = $this->get_sortable_columns();
175 134 $hidden = $this->get_hidden_columns();
@@ -193,17 +152,12 @@
193 152 )
194 153 );
195 154 }
196 155
197 - /**
198 - * Returns records to be displayed
199 - *
200 - * @return array
201 - */
202 156 public function get_records() {
203 157 $args = array();
204 158
205 - // Parse sorting params.
159 + // Parse sorting params
206 160 $order = wp_stream_filter_input( INPUT_GET, 'order' );
207 161 if ( $order ) {
208 162 $args['order'] = $order;
209 163 }
@@ -229,9 +183,9 @@
229 183 $args[ $param ] = $value;
230 184 }
231 185 }
232 186
233 - // Additional filter properties.
187 + // Additional filter properties
234 188 $properties = array(
235 189 'record',
236 190 'site_id',
237 191 'blog_id',
@@ -243,13 +197,13 @@
243 197 'context',
244 198 'action',
245 199 );
246 200
247 - // Add property fields to defaults, including their __in/__not_in variations.
201 + // Add property fields to defaults, including their __in/__not_in variations
248 202 foreach ( $properties as $property ) {
249 203 $value = wp_stream_filter_input( INPUT_GET, $property );
250 204
251 - // Allow 0 values.
205 + // Allow 0 values
252 206 if ( isset( $value ) && '' !== $value && false !== $value ) {
253 207 $args[ $property ] = $value;
254 208 }
255 209
@@ -291,15 +245,8 @@
291 245 public function get_total_found_rows() {
292 246 return $this->plugin->db->get_found_records_count();
293 247 }
294 248
295 - /**
296 - * Returns the column content for the provided item and column.
297 - *
298 - * @param array $item Record data.
299 - * @param string $column_name Column name.
300 - * @return void
301 - */
302 249 public function column_default( $item, $column_name ) {
303 250 $out = '';
304 251 $record = new Record( $item );
305 252
@@ -304,9 +251,9 @@
304 251 $record = new Record( $item );
305 252
306 253 switch ( $column_name ) {
307 254 case 'date':
308 - $created = gmdate( 'Y-m-d H:i:s', strtotime( $record->created ) );
255 + $created = date( 'Y-m-d H:i:s', strtotime( $record->created ) );
309 256 $date_string = sprintf(
310 257 '<time datetime="%s" class="relative-time record-created">%s</time>',
311 258 wp_stream_get_iso_8601_extended_date( strtotime( $record->created ) ),
312 259 get_date_from_gmt( $created, 'Y/m/d' )
@@ -312,15 +259,15 @@
312 259 get_date_from_gmt( $created, 'Y/m/d' )
313 260 );
314 261 $out = $this->column_link( $date_string, 'date', get_date_from_gmt( $created, 'Y/m/d' ) );
315 262 $out .= '<br />';
316 - $out .= get_date_from_gmt( $created, 'h:i:s A T' );
263 + $out .= get_date_from_gmt( $created, 'h:i:s A' );
317 264 break;
318 265
319 266 case 'summary':
320 267 $out = $record->summary;
321 268 $object_title = $record->get_object_title();
322 - /* translators: %s: the title of any object, like a Post (e.g. "Hello World") */
269 + // translators: Placeholder refers to the title of any object, like a Post (e.g. "Hello World")
323 270 $view_all_text = $object_title ? sprintf( esc_html__( 'View all activity for "%s"', 'stream' ), esc_attr( $object_title ) ) : esc_html__( 'View all activity for this object', 'stream' );
324 271
325 272 if ( $record->object_id ) {
326 273 $out .= $this->column_link(
@@ -390,35 +337,39 @@
390 337 /**
391 338 * Registers new Columns to be inserted into the table. The cell contents of this column is set
392 339 * below with 'wp_stream_insert_column_default_'
393 340 *
394 - * @since 3.5.1
395 - * @deprecated 4.0.1 Use the {@see 'wp_stream_list_table_columns'} filter instead.
396 - *
397 - * @param array $new_columns Columns injected in the table.
398 - *
399 341 * @return array
400 342 */
401 - apply_filters_deprecated(
402 - 'wp_stream_register_column_defaults',
403 - array( array() ),
404 - /* translators: %s is the Stream version number. It is part of a filter deprecation notice and is preceded by: "{hook_name} is deprecated since version %s of Stream". */
405 - sprintf( __( '%s of Stream', 'stream' ), '4.0.1' ),
406 - 'wp_stream_list_table_columns',
407 - __( 'This filter is being deprecated as it is redundant. You can define custom column names and titles using the `wp_stream_list_table_columns` filter then provide the value for the custom columns using the `wp_stream_insert_column_default_{$column_name}` filter.', 'stream' )
408 - );
343 + $new_columns = array();
344 + $inserted_columns = apply_filters( 'wp_stream_register_column_defaults', $new_columns );
409 345
410 - /**
411 - * Allows for the addition of content under a specified column.
412 - *
413 - * @param string $out Column content.
414 - * @param object $record Record with row content.
415 - * @param string $column_name Column name.
416 - *
417 - * @return string
418 - */
419 - $out = (string) apply_filters( "wp_stream_insert_column_default_{$column_name}", $out, $record, $column_name );
420 - break;
346 + if ( ! empty( $inserted_columns ) && is_array( $inserted_columns ) ) {
347 + foreach ( $inserted_columns as $column_title ) {
348 + /**
349 + * If column title inserted via wp_stream_register_column_defaults ($column_title) exists
350 + * among columns registered with get_columns ($column_name) and there is an action associated
351 + * with this column, do the action
352 + *
353 + * Also, note that the action name must include the $column_title registered
354 + * with wp_stream_register_column_defaults
355 + */
356 + if ( $column_title === $column_name && has_filter( "wp_stream_insert_column_default_{$column_title}" ) ) {
357 + /**
358 + * Allows for the addition of content under a specified column.
359 + *
360 + * @param object $record Contents of the row
361 + *
362 + * @return string
363 + */
364 + $out = apply_filters( "wp_stream_insert_column_default_{$column_title}", $column_name, $record );
365 + } else {
366 + $out = $column_name;
367 + }
368 + }
369 + } else {
370 + $out = $column_name;
371 + }
421 372 }
422 373
423 374 $allowed_tags = wp_kses_allowed_html( 'post' );
424 375 $allowed_tags['time'] = array(
@@ -429,14 +380,8 @@
429 380
430 381 echo wp_kses( $out, $allowed_tags );
431 382 }
432 383
433 - /**
434 - * Returns the actions links for the provided record. (Eg. Edit, View)
435 - *
436 - * @param Record $record Record.
437 - * @return string
438 - */
439 384 public function get_action_links( $record ) {
440 385 $out = '';
441 386
442 387 /**
@@ -488,17 +433,8 @@
488 433
489 434 return $out;
490 435 }
491 436
492 - /**
493 - * Returns a link to be display in the table.
494 - *
495 - * @param string $display Text to be displayed in link.
496 - * @param string|array $key Query string variable(s).
497 - * @param string $value Single query string value.
498 - * @param string $title Tooltip value.
499 - * @return string
500 - */
501 437 public function column_link( $display, $key, $value = null, $title = null ) {
502 438 $url = add_query_arg(
503 439 array(
504 440 'page' => $this->plugin->admin->records_page_slug,
@@ -521,15 +457,8 @@
521 457 $display
522 458 );
523 459 }
524 460
525 - /**
526 - * Returns the label for a connector term.
527 - *
528 - * @param string $term Connector label type.
529 - * @param string $type Connector term.
530 - * @return string
531 - */
532 461 public function get_term_title( $term, $type ) {
533 462 if ( ! isset( $this->plugin->connectors->term_labels[ 'stream_' . $type ][ $term ] ) ) {
534 463 return $term;
535 464 }
@@ -543,9 +472,9 @@
543 472 * Gathers list of all users/connectors, then compares it to
544 473 * results of existing records. All items that do not exist in records
545 474 * get assigned a disabled value of "true".
546 475 *
547 - * @param string $column List table column name.
476 + * @param string $column List table column name
548 477 *
549 478 * @return array Options to be displayed in search filters
550 479 */
551 480 public function assemble_records( $column ) {
@@ -552,9 +481,9 @@
552 481 // @todo eliminate special condition for authors, especially using a WP_User object as the value; should use string or stringifiable object
553 482 if ( 'user_id' === $column ) {
554 483 $all_records = array();
555 484
556 - // If the number of users exceeds the max users constant value then return an empty array and use AJAX instead.
485 + // If the number of users exceeds the max users constant value then return an empty array and use AJAX instead
557 486 $user_count = count_users();
558 487 $total_users = $user_count['total_users'];
559 488
560 489 if ( $total_users > $this->plugin->admin->preload_users_max ) {
@@ -615,19 +544,19 @@
615 544 foreach ( $all_records as $record => $label ) {
616 545 if ( array_key_exists( $record, $existing_records ) ) {
617 546 $active_records[ $record ] = array(
618 547 'label' => $label,
619 - 'disabled' => false,
548 + 'disabled' => '',
620 549 );
621 550 } else {
622 551 $disabled_records[ $record ] = array(
623 552 'label' => $label,
624 - 'disabled' => true,
553 + 'disabled' => 'disabled="disabled"',
625 554 );
626 555 }
627 556 }
628 557
629 - // Remove WP-CLI pseudo user if no records with user=0 exist.
558 + // Remove WP-CLI pseudo user if no records with user=0 exist
630 559 if ( isset( $disabled_records[0] ) ) {
631 560 unset( $disabled_records[0] );
632 561 }
633 562
@@ -644,19 +573,14 @@
644 573
645 574 uasort( $active_records, $sort );
646 575 uasort( $disabled_records, $sort );
647 576
648 - // Not using array_merge() in order to preserve the array index for the users dropdown which uses the user_id as the key.
577 + // Not using array_merge() in order to preserve the array index for the users dropdown which uses the user_id as the key
649 578 $all_records = $active_records + $disabled_records;
650 579
651 580 return $all_records;
652 581 }
653 582
654 - /**
655 - * Returns list filters.
656 - *
657 - * @return array
658 - */
659 583 public function get_filters() {
660 584 $filters = array();
661 585
662 586 $date_interval = new Date_Interval();
@@ -695,18 +619,13 @@
695 619 */
696 620 return apply_filters( 'wp_stream_list_table_filters', $filters );
697 621 }
698 622
699 - /**
700 - * Renders table filters form.
701 - *
702 - * @return void
703 - */
704 - public function render_filters_form() {
623 + public function filters_form() {
705 624 $filters = $this->get_filters();
706 625
707 - printf( '<input type="hidden" name="page" value="%s" />', 'wp_stream' );
708 - printf( '<span class="filter_info hidden">%s</span>', esc_html__( 'Show filter controls via the screen options tab above.', 'stream' ) );
626 + $filters_string = sprintf( '<input type="hidden" name="page" value="%s" />', 'wp_stream' );
627 + $filters_string .= sprintf( '<span class="filter_info hidden">%s</span>', esc_html__( 'Show filter controls via the screen options tab above.', 'stream' ) );
709 628
710 629 foreach ( $filters as $name => $data ) {
711 630
712 631 $data = wp_parse_args(
@@ -718,12 +637,12 @@
718 637 )
719 638 );
720 639
721 640 if ( 'date' === $name ) {
722 - $this->filter_date( $data['items'] );
641 + $filters_string .= $this->filter_date( $data['items'] );
723 642 } else {
724 643 if ( 'context' === $name ) {
725 - // Add Connectors as parents, and apply the Contexts as children.
644 + // Add Connectors as parents, and apply the Contexts as children
726 645 $connectors = $this->assemble_records( 'connector' );
727 646 $context_items = array();
728 647
729 648 foreach ( $connectors as $connector => $item ) {
@@ -737,9 +656,9 @@
737 656
738 657 if ( isset( $context_items[ $connector ]['children'] ) ) {
739 658 $labels = wp_list_pluck( $context_items[ $connector ]['children'], 'label' );
740 659
741 - // Sort child items by label.
660 + // Sort child items by label
742 661 array_multisort( $labels, SORT_ASC, $context_items[ $connector ]['children'] );
743 662 }
744 663 }
745 664
@@ -752,36 +671,32 @@
752 671 $data['items'] = $context_items;
753 672
754 673 $labels = wp_list_pluck( $data['items'], 'label' );
755 674
756 - // Sort top-level items by label.
675 + // Sort top-level items by label
757 676 array_multisort( $labels, SORT_ASC, $data['items'] );
758 677
759 - // Output a hidden input to handle the connector value.
760 - printf(
678 + // Output a hidden input to handle the connector value
679 + $filters_string .= sprintf(
761 680 '<input type="hidden" name="connector" class="record-filter-connector" value="%s" />',
762 681 esc_attr( wp_stream_filter_input( INPUT_GET, 'connector' ) )
763 682 );
764 683 }
765 684
766 - $this->filter_select( $name, $data['title'], $data['items'], $data['ajax'] );
685 + $filters_string .= $this->filter_select( $name, $data['title'], $data['items'], $data['ajax'] );
767 686 }
768 687 }
769 688
770 - printf(
771 - '<input type="submit" id="record-query-submit" class="button" value="%s" />',
772 - esc_attr__( 'Filter', 'stream' )
773 - );
689 + $filters_string .= sprintf( '<input type="submit" id="record-query-submit" class="button" value="%s" />', __( 'Filter', 'stream' ) );
774 690
775 - // Parse all query vars into an array.
691 + // Parse all query vars into an array
776 692 $query_vars = array();
777 693
778 694 if ( isset( $_SERVER['QUERY_STRING'] ) ) {
779 - parse_str( wp_unslash( $_SERVER['QUERY_STRING'] ), $query_vars );
780 - $query_vars = map_deep( $query_vars, 'sanitize_text_field' );
695 + parse_str( urldecode( $_SERVER['QUERY_STRING'] ), $query_vars );
781 696 }
782 697
783 - // Ignore certain query vars and query vars that are empty.
698 + // Ignore certain query vars and query vars that are empty
784 699 foreach ( $query_vars as $query_var => $value ) {
785 700 if ( '' === $value || 'page' === $query_var || 'paged' === $query_var ) {
786 701 unset( $query_vars[ $query_var ] );
787 702 }
@@ -793,92 +708,75 @@
793 708 ),
794 709 self_admin_url( $this->plugin->admin->admin_parent_page )
795 710 );
796 711
797 - // Display reset action if records are being filtered.
712 + // Display reset action if records are being filtered
798 713 if ( ! empty( $query_vars ) ) {
799 - printf(
800 - '<a href="%1$s" id="record-query-reset"><span class="dashicons dashicons-dismiss"></span> <span class="record-query-reset-text">%2$s</span></a>',
801 - esc_url( $url ),
802 - esc_html__( 'Reset filters', 'stream' )
803 - );
714 + $filters_string .= sprintf( '<a href="%s" id="record-query-reset"><span class="dashicons dashicons-dismiss"></span> <span class="record-query-reset-text">%s</span></a>', esc_url( $url ), __( 'Reset filters', 'stream' ) );
804 715 }
716 +
717 + return sprintf( '<div class="alignleft actions">%s</div>', $filters_string ); // xss ok
805 718 }
806 719
807 - /**
808 - * Renders a filterable select control with filtered items.
809 - *
810 - * @param string $name Search input.
811 - * @param string $title Name of the control.
812 - * @param array $items Items to be filtered.
813 - * @param boolean $ajax Whether is an ajax request or not.
814 - *
815 - * @return void
816 - */
817 720 public function filter_select( $name, $title, $items, $ajax = false ) {
818 - $selected = wp_stream_filter_input( INPUT_GET, $name );
721 + if ( $ajax ) {
722 + $out = sprintf(
723 + '<input type="hidden" name="%s" class="chosen-select" value="%s" data-placeholder="%s" />',
724 + esc_attr( $name ),
725 + esc_attr( wp_stream_filter_input( INPUT_GET, $name ) ),
726 + esc_attr( $title )
727 + );
728 + } else {
729 + $options = array( '<option value=""></option>' );
730 + $selected = wp_stream_filter_input( INPUT_GET, $name );
819 731
820 - printf(
821 - '<select name="%1$s" class="chosen-select" data-placeholder="%2$s">',
822 - esc_attr( $name ),
823 - esc_attr(
824 - sprintf(
825 - /* translators: %s: the title of the dropdown menu (e.g. "users") */
826 - __( 'Show all %s', 'stream' ),
827 - $title
828 - )
829 - )
830 - );
732 + foreach ( $items as $key => $item ) {
733 + $value = isset( $item['children'] ) ? 'group-' . $key : $key;
734 + $option_args = array(
735 + 'value' => $value,
736 + 'selected' => selected( $value, $selected, false ),
737 + 'disabled' => isset( $item['disabled'] ) ? $item['disabled'] : null,
738 + 'icon' => isset( $item['icon'] ) ? $item['icon'] : null,
739 + 'group' => isset( $item['children'] ) ? $key : null,
740 + 'tooltip' => isset( $item['tooltip'] ) ? $item['tooltip'] : null,
741 + 'class' => isset( $item['children'] ) ? 'level-1' : null,
742 + 'label' => isset( $item['label'] ) ? $item['label'] : null,
743 + );
744 + $options[] = $this->filter_option( $option_args );
831 745
832 - // First option should be empty.
833 - echo '<option value=""></option>';
834 -
835 - foreach ( $items as $key => $item ) {
836 - $value = isset( $item['children'] ) ? 'group-' . $key : $key;
837 - $option_args = array(
838 - 'value' => $value,
839 - 'selected' => (string) $value === (string) $selected,
840 - 'disabled' => ! empty( $item['disabled'] ),
841 - 'icon' => isset( $item['icon'] ) ? $item['icon'] : null,
842 - 'group' => isset( $item['children'] ) ? $key : null,
843 - 'tooltip' => isset( $item['tooltip'] ) ? $item['tooltip'] : null,
844 - 'class' => isset( $item['children'] ) ? 'level-1' : null,
845 - 'label' => isset( $item['label'] ) ? $item['label'] : null,
846 - );
847 - $this->filter_option( $option_args );
848 -
849 - if ( isset( $item['children'] ) ) {
850 - foreach ( $item['children'] as $child_value => $child_item ) {
851 - $option_args = array(
852 - 'value' => $child_value,
853 - 'selected' => (string) $child_value === (string) $selected,
854 - 'disabled' => ! empty( $child_item['disabled'] ),
855 - 'icon' => isset( $child_item['icon'] ) ? $child_item['icon'] : null,
856 - 'group' => $key,
857 - 'tooltip' => isset( $child_item['tooltip'] ) ? $child_item['tooltip'] : null,
858 - 'class' => 'level-2',
859 - 'label' => isset( $child_item['label'] ) ? '- ' . $child_item['label'] : null,
860 - );
861 - $this->filter_option( $option_args );
746 + if ( isset( $item['children'] ) ) {
747 + foreach ( $item['children'] as $child_value => $child_item ) {
748 + $option_args = array(
749 + 'value' => $child_value,
750 + 'selected' => selected( $child_value, $selected, false ),
751 + 'disabled' => isset( $child_item['disabled'] ) ? $child_item['disabled'] : null,
752 + 'icon' => isset( $child_item['icon'] ) ? $child_item['icon'] : null,
753 + 'group' => $key,
754 + 'tooltip' => isset( $child_item['tooltip'] ) ? $child_item['tooltip'] : null,
755 + 'class' => 'level-2',
756 + 'label' => isset( $child_item['label'] ) ? '- ' . $child_item['label'] : null,
757 + );
758 + $options[] = $this->filter_option( $option_args );
759 + }
862 760 }
863 761 }
762 + $out = sprintf(
763 + '<select name="%s" class="chosen-select" data-placeholder="%s">%s</select>',
764 + esc_attr( $name ),
765 + // translators: Placeholder refers to the title of the dropdown menu (e.g. "users")
766 + sprintf( esc_attr__( 'Show all %s', 'stream' ), $title ),
767 + implode( '', $options )
768 + );
864 769 }
865 770
866 - echo '</select>';
771 + return $out;
867 772 }
868 773
869 - /**
870 - * Render a filterable select option.
871 - *
872 - * @param array $args Option attributes.
873 - *
874 - * @return void
875 - */
876 774 public function filter_option( $args ) {
877 775 $defaults = array(
878 776 'value' => null,
879 - 'selected' => false,
880 - 'disabled' => false,
777 + 'selected' => null,
778 + 'disabled' => null,
881 779 'icon' => null,
882 780 'group' => null,
883 781 'tooltip' => null,
884 782 'class' => null,
@@ -885,13 +783,13 @@
885 783 'label' => null,
886 784 );
887 785 wp_parse_args( $args, $defaults );
888 786
889 - printf(
787 + return sprintf(
890 788 '<option value="%s" %s %s %s %s %s class="%s">%s</option>',
891 789 esc_attr( $args['value'] ),
892 - selected( $args['selected'], true, false ),
893 - disabled( $args['disabled'], true, false ),
790 + $args['selected'],
791 + $args['disabled'],
894 792 $args['icon'] ? sprintf( 'data-icon="%s"', esc_attr( $args['icon'] ) ) : null,
895 793 $args['group'] ? sprintf( 'data-group="%s"', esc_attr( $args['group'] ) ) : null,
896 794 $args['tooltip'] ? sprintf( 'title="%s"', esc_attr( $args['tooltip'] ) ) : null,
897 795 $args['class'] ? esc_attr( $args['class'] ) : null,
@@ -898,33 +796,26 @@
898 796 esc_html( $args['label'] )
899 797 );
900 798 }
901 799
902 - /**
903 - * Render filter search box.
904 - *
905 - * @return void
906 - */
907 800 public function filter_search() {
908 - printf(
801 + $search = null;
802 + if ( isset( $_GET['search'] ) ) { // CSRF okay
803 + $search = esc_attr( wp_unslash( $_GET['search'] ) ); // input var okay, CSRF okay
804 + }
805 + $out = sprintf(
909 806 '<p class="search-box">
910 807 <label class="screen-reader-text" for="record-search-input">%1$s:</label>
911 808 <input type="search" id="record-search-input" name="search" value="%2$s" />
912 - <input type="submit" name="" id="search-submit" class="button" value="%3$s" />
809 + <input type="submit" name="" id="search-submit" class="button" value="%1$s" />
913 810 </p>',
914 - esc_html__( 'Search Records', 'stream' ),
915 - esc_attr( ! empty( $_GET['search'] ) ? sanitize_text_field( wp_unslash( $_GET['search'] ) ) : '' ), // phpcs:ignore WordPress.Security.NonceVerification.Recommended
916 - esc_attr__( 'Search Records', 'stream' )
811 + esc_attr__( 'Search Records', 'stream' ),
812 + $search
917 813 );
814 +
815 + return $out;
918 816 }
919 817
920 - /**
921 - * Renders a filter select box based upon date.
922 - *
923 - * @param array $items Records.
924 - *
925 - * @return void
926 - */
927 818 public function filter_date( $items ) {
928 819 wp_enqueue_style( 'jquery-ui' );
929 820 wp_enqueue_style( 'wp-stream-datepicker' );
930 821 wp_enqueue_script( 'jquery-ui-datepicker' );
@@ -932,8 +823,9 @@
932 823 $date_predefined = wp_stream_filter_input( INPUT_GET, 'date_predefined' );
933 824 $date_from = wp_stream_filter_input( INPUT_GET, 'date_from' );
934 825 $date_to = wp_stream_filter_input( INPUT_GET, 'date_to' );
935 826
827 + ob_start();
936 828 ?>
937 829 <div class="date-interval">
938 830
939 831 <select class="field-predefined hide-if-no-js chosen-select" name="date_predefined" data-placeholder="<?php esc_attr_e( 'All Time', 'stream' ); ?>">
@@ -969,14 +861,16 @@
969 861 </div>
970 862
971 863 </div>
972 864 <?php
865 +
866 + return ob_get_clean();
973 867 }
974 868
975 869 /**
976 - * Render a Select dropdown of actions relating to the Stream records
870 + * Output a Select dropdown of actions relating to the Stream records
977 871 *
978 - * @return void
872 + * @return string
979 873 */
980 874 public function record_actions_form() {
981 875 /**
982 876 * Filter the records screen actions dropdown menu
@@ -985,11 +879,12 @@
985 879 */
986 880 $actions = apply_filters( 'wp_stream_record_actions_menu', array() );
987 881
988 882 if ( empty( $actions ) ) {
989 - return;
883 + return '';
990 884 }
991 885
886 + ob_start();
992 887 printf( '<div class="alignleft actions recordactions"><select name="%s">', esc_attr( 'record-actions' ) );
993 888 printf( '<option value="">%s</option>', esc_attr__( 'Record Actions', 'stream' ) );
994 889 foreach ( $actions as $value => $name ) {
995 890 printf(
@@ -999,9 +894,8 @@
999 894 );
1000 895 }
1001 896 echo '</select></div>';
1002 897 wp_nonce_field( 'stream_record_actions_nonce', 'stream_record_actions_nonce' );
1003 - wp_nonce_field( 'stream_filters_user_search_nonce', 'stream_filters_user_search_nonce' );
1004 898
1005 899 printf( '<input type="hidden" name="page" value="%s">', esc_attr( wp_stream_filter_input( INPUT_GET, 'page' ) ) );
1006 900 printf( '<input type="hidden" name="date_predefined" value="%s">', esc_attr( wp_stream_filter_input( INPUT_GET, 'date_predefined' ) ) );
1007 901 printf( '<input type="hidden" name="date_from" value="%s">', esc_attr( wp_stream_filter_input( INPUT_GET, 'date_from' ) ) );
@@ -1012,49 +906,37 @@
1012 906 printf( '<input type="hidden" name="action" value="%s">', esc_attr( wp_stream_filter_input( INPUT_GET, 'action' ) ) );
1013 907
1014 908 printf( '<input type="submit" name="" id="record-actions-submit" class="button" value="%s">', esc_attr__( 'Apply', 'stream' ) );
1015 909 echo '<div class="clear"></div>';
910 +
911 + return ob_get_clean();
1016 912 }
1017 913
1018 - /**
1019 - * Renders record filter forms.
1020 - */
1021 914 public function display() {
1022 915 $url = self_admin_url( $this->plugin->admin->admin_parent_page );
1023 916
1024 917 echo '<form method="get" action="' . esc_url( $url ) . '" id="record-filter-form">';
1025 - $this->filter_search();
918 + echo $this->filter_search(); // xss ok
1026 919 parent::display();
1027 920 echo '</form>';
1028 921
1029 922 echo '<form method="get" action="' . esc_url( $url ) . '" id="record-actions-form">';
1030 - $this->record_actions_form();
923 + echo $this->record_actions_form(); // xss ok
1031 924 echo '</form>';
1032 925 }
1033 926
1034 - /**
1035 - * Renders a single record
1036 - *
1037 - * @param array $item Record data.
1038 - */
1039 927 public function single_row( $item ) {
1040 - $classes = apply_filters( 'wp_stream_record_classes', array(), $item );
1041 -
1042 - if ( empty( $classes ) ) {
1043 - echo '<tr>';
1044 - } else {
1045 - printf( '<tr class="%s">', esc_attr( join( ' ', $classes ) ) );
928 + $classes = apply_filters( 'wp_stream_record_classes', array(), $item );
929 + $class_string = '';
930 + if ( ! empty( $classes ) ) {
931 + $class_string = ' class="' . esc_attr( join( ' ', $classes ) ) . '"';
1046 932 }
1047 933
934 + echo sprintf( '<tr%s>', $class_string ); // xss ok
1048 935 $this->single_row_columns( $item );
1049 936 echo '</tr>';
1050 937 }
1051 938
1052 - /**
1053 - * Renders table navigation controls
1054 - *
1055 - * @param string $which Location controls.
1056 - */
1057 939 public function display_tablenav( $which ) {
1058 940 if ( 'top' === $which ) :
1059 941 ?>
1060 942 <div class="tablenav <?php echo esc_attr( $which ); ?>">
@@ -1081,16 +963,8 @@
1081 963 <?php
1082 964 endif;
1083 965 }
1084 966
1085 - /**
1086 - * Sets the screen options.
1087 - *
1088 - * @param string $dummy Unused.
1089 - * @param string $option Screen option name.
1090 - * @param string $value Screen option value.
1091 - * @return string
1092 - */
1093 967 public function set_screen_option( $dummy, $option, $value ) {
1094 968 if ( 'edit_stream_per_page' === $option ) {
1095 969 return $value;
1096 970 } else {
@@ -1097,16 +971,8 @@
1097 971 return $dummy;
1098 972 }
1099 973 }
1100 974
1101 - /**
1102 - * Sets the live update options.
1103 - *
1104 - * @param string $dummy Unused.
1105 - * @param string $option Screen option name.
1106 - * @param string $value Screen option value.
1107 - * @return string
1108 - */
1109 975 public function set_live_update_option( $dummy, $option, $value ) {
1110 976 unset( $value );
1111 977
1112 978 // @codingStandardsIgnoreStart
@@ -1124,15 +990,8 @@
1124 990
1125 991 return $dummy;
1126 992 }
1127 993
1128 - /**
1129 - * Return HTML string of the "Live updates" screen option.
1130 - *
1131 - * @param string $status Unused.
1132 - * @param array $args Unused.
1133 - * @return string
1134 - */
1135 994 public function screen_controls( $status, $args ) {
1136 995 unset( $status );
1137 996 unset( $args );
1138 997
@@ -1142,9 +1001,9 @@
1142 1001
1143 1002 if ( 'on' === $option && 'false' === $heartbeat ) {
1144 1003 $option = 'off';
1145 1004
1146 - update_user_meta( $user_id, $this->plugin->admin->live_update->user_meta_key, 'off' );
1005 + $this->plugin->admin->update_user_meta( $user_id, $this->plugin->admin->live_update->user_meta_key, 'off' );
1147 1006 }
1148 1007
1149 1008 $nonce = wp_create_nonce( $this->plugin->admin->live_update->user_meta_key . '_nonce' );
1150 1009
@@ -1155,8 +1014,11 @@
1155 1014
1156 1015 <div>
1157 1016 <input type="hidden" name="stream_live_update_nonce" id="stream_live_update_nonce" value="<?php echo esc_attr( $nonce ); ?>"/>
1158 1017 </div>
1018 + <div>
1019 + <input type="hidden" name="enable_live_update_user" id="enable_live_update_user" value="<?php echo absint( $user_id ); ?>"/>
1020 + </div>
1159 1021 <div class="metabox-prefs stream-live-update-checkbox">
1160 1022 <label for="enable_live_update">
1161 1023 <input type="checkbox" value="on" name="enable_live_update" id="enable_live_update" data-heartbeat="<?php echo esc_attr( $heartbeat ); ?>" <?php checked( $option, 'on' ); ?> />
1162 1024 <?php esc_html_e( 'Enabled', 'stream' ); ?>
@@ -1170,9 +1032,9 @@
1170 1032
1171 1033 /**
1172 1034 * This function is use to map List table column name with excluded setting keys
1173 1035 *
1174 - * @param string $column List table column name.
1036 + * @param string $column List table column name
1175 1037 *
1176 1038 * @return string setting name for that column
1177 1039 */
1178 1040 public function get_column_excluded_setting_key( $column ) {
@@ -1201,9 +1063,9 @@
1201 1063
1202 1064 /**
1203 1065 * Get users as dropdown items
1204 1066 *
1205 - * @param array $users Users.
1067 + * @param array $users
1206 1068 *
1207 1069 * @return array
1208 1070 */
1209 1071 public function get_users_dropdown_items( $users ) {
@@ -1209,9 +1071,10 @@
1209 1071 public function get_users_dropdown_items( $users ) {
1210 1072 $record_meta = array();
1211 1073
1212 1074 foreach ( $users as $user_id => $args ) {
1213 - $user = new Author( $user_id );
1075 + $user = new Author( $user_id );
1076 + $disabled = isset( $args['disabled'] ) ? $args['disabled'] : null;
1214 1077
1215 1078 $record_meta[ $user_id ] = array(
1216 1079 'text' => $user->get_display_name(),
1217 1080 'id' => $user_id,
@@ -1217,9 +1080,9 @@
1217 1080 'id' => $user_id,
1218 1081 'label' => $user->get_display_name(),
1219 1082 'icon' => $user->get_avatar_src( 32 ),
1220 1083 'title' => '',
1221 - 'disabled' => ! empty( $args['disabled'] ),
1084 + 'disabled' => $disabled,
1222 1085 );
1223 1086 }
1224 1087
1225 1088 return $record_meta;