PluginProbe
Stream – Activity Log & Audit Trail / 3.6.1
Stream – Activity Log & Audit Trail v3.6.1
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 +452 -157 3.0.13.6.1 View file →
@@ -1,10 +1,21 @@
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 namespace WP_Stream;
3 9
10 +/**
11 + * Class - List_Table
12 + */
4 13 class List_Table extends \WP_List_Table {
14 +
5 15 /**
6 - * Hold Plugin class
16 + * Holds Instance of plugin object
17 + *
7 18 * @var Plugin
8 19 */
9 20 public $plugin;
10 21
@@ -10,12 +21,12 @@
10 21
11 22 /**
12 23 * Class constructor.
13 24 *
14 - * @param Plugin $plugin The main Plugin class.
15 - * @param array $args
25 + * @param Plugin $plugin Instance of plugin object.
26 + * @param array $args Argument to filter rows by.
16 27 */
17 - function __construct( $plugin, $args = array() ) {
28 + public function __construct( $plugin, $args = array() ) {
18 29 $this->plugin = $plugin;
19 30
20 31 $screen_id = isset( $args['screen'] ) ? $args['screen'] : null;
21 32
@@ -42,32 +53,64 @@
42 53 'option' => 'edit_stream_per_page',
43 54 )
44 55 );
45 56
46 - // Check for default hidden columns
57 + // Check for default hidden columns.
47 58 $this->get_hidden_columns();
48 59
49 - add_filter( 'screen_settings', array( $this, 'screen_controls' ), 10, 2 );
50 - add_filter( 'set-screen-option', array( $this, 'set_screen_option' ), 10, 3 );
60 + add_filter(
61 + 'screen_settings',
62 + array(
63 + $this,
64 + 'screen_controls',
65 + ),
66 + 10,
67 + 2
68 + );
69 + add_filter(
70 + 'set-screen-option',
71 + array(
72 + $this,
73 + 'set_screen_option',
74 + ),
75 + 10,
76 + 3
77 + );
51 78
52 79 set_screen_options();
53 80 }
54 81
55 - function extra_tablenav( $which ) {
82 + /**
83 + * Renders extra from navigation options.
84 + *
85 + * @param string $which Page location.
86 + * @return void
87 + */
88 + public function extra_tablenav( $which ) {
56 89 if ( 'top' === $which ) {
57 - echo $this->filters_form(); //xss ok
90 + echo $this->filters_form(); // xss ok.
58 91 }
59 92 }
60 93
61 - function no_items() {
94 + /**
95 + * Renders "No items found" message.
96 + *
97 + * @return void
98 + */
99 + public function no_items() {
62 100 ?>
63 101 <div class="stream-list-table-no-items">
64 - <p><?php esc_html_e( 'Sorry, no activity records were found.', 'stream' ) ?></p>
102 + <p><?php esc_html_e( 'No activity records were found.', 'stream' ); ?></p>
65 103 </div>
66 104 <?php
67 105 }
68 106
69 - function get_columns() {
107 + /**
108 + * Returns the table columns to be rendered.
109 + *
110 + * @return array
111 + */
112 + public function get_columns() {
70 113 /**
71 114 * Allows devs to add new columns to table
72 115 *
73 116 * @return array
@@ -84,23 +127,34 @@
84 127 )
85 128 );
86 129 }
87 130
88 - function get_sortable_columns() {
131 + /**
132 + * Returns the columns the items can be sort by.
133 + *
134 + * @return array
135 + */
136 + public function get_sortable_columns() {
89 137 return array(
90 138 'date' => array( 'date', false ),
91 139 );
92 140 }
93 141
94 - function get_hidden_columns() {
95 - if ( ! $user = wp_get_current_user() ) {
142 + /**
143 + * Returns columns hidden from all except specific users.
144 + *
145 + * @return array|bool
146 + */
147 + public function get_hidden_columns() {
148 + $user = wp_get_current_user();
149 + if ( ! $user ) {
96 150 return array();
97 151 }
98 152
99 - // Directly checking the user meta; to check whether user has changed screen option or not
153 + // Directly checking the user meta; to check whether user has changed screen option or not.
100 154 $hidden = $this->plugin->admin->get_user_meta( $user->ID, 'manage' . $this->screen->id . 'columnshidden', true );
101 155
102 - // If user meta is not found; add the default hidden column 'id'
156 + // If user meta is not found; add the default hidden column 'id'.
103 157 if ( ! $hidden ) {
104 158 $hidden = array( 'id' );
105 159 $this->plugin->admin->update_user_meta( $user->ID, 'manage' . $this->screen->id . 'columnshidden', $hidden );
106 160 }
@@ -107,15 +161,25 @@
107 161
108 162 return $hidden;
109 163 }
110 164
111 - function prepare_items() {
165 + /**
166 + * Prepares table columns and data for render
167 + *
168 + * @return void
169 + */
170 + public function prepare_items() {
112 171 $columns = $this->get_columns();
113 172 $sortable = $this->get_sortable_columns();
114 173 $hidden = $this->get_hidden_columns();
115 174 $primary = $columns['summary'];
116 175
117 - $this->_column_headers = array( $columns, $hidden, $sortable, $primary );
176 + $this->_column_headers = array(
177 + $columns,
178 + $hidden,
179 + $sortable,
180 + $primary,
181 + );
118 182
119 183 $this->items = $this->get_records();
120 184
121 185 $total_items = $this->get_total_found_rows();
@@ -127,17 +191,24 @@
127 191 )
128 192 );
129 193 }
130 194
131 - function get_records() {
195 + /**
196 + * Returns records to be displayed
197 + *
198 + * @return array
199 + */
200 + public function get_records() {
132 201 $args = array();
133 202
134 - // Parse sorting params
135 - if ( $order = wp_stream_filter_input( INPUT_GET, 'order' ) ) {
203 + // Parse sorting params.
204 + $order = wp_stream_filter_input( INPUT_GET, 'order' );
205 + if ( $order ) {
136 206 $args['order'] = $order;
137 207 }
138 208
139 - if ( $orderby = wp_stream_filter_input( INPUT_GET, 'orderby' ) ) {
209 + $orderby = wp_stream_filter_input( INPUT_GET, 'orderby' );
210 + if ( $orderby ) {
140 211 $args['orderby'] = $orderby;
141 212 }
142 213
143 214 $params = array(
@@ -156,9 +227,9 @@
156 227 $args[ $param ] = $value;
157 228 }
158 229 }
159 230
160 - // Additional filter properties
231 + // Additional filter properties.
161 232 $properties = array(
162 233 'record',
163 234 'site_id',
164 235 'blog_id',
@@ -170,13 +241,13 @@
170 241 'context',
171 242 'action',
172 243 );
173 244
174 - // Add property fields to defaults, including their __in/__not_in variations
245 + // Add property fields to defaults, including their __in/__not_in variations.
175 246 foreach ( $properties as $property ) {
176 247 $value = wp_stream_filter_input( INPUT_GET, $property );
177 248
178 - // Allow 0 values
249 + // Allow 0 values.
179 250 if ( isset( $value ) && '' !== $value && false !== $value ) {
180 251 $args[ $property ] = $value;
181 252 }
182 253
@@ -202,10 +273,11 @@
202 273
203 274 if ( ! isset( $args['records_per_page'] ) ) {
204 275 $args['records_per_page'] = $this->get_items_per_page( 'edit_stream_per_page', 20 );
205 276 }
277 + $args['records_per_page'] = apply_filters( 'stream_records_per_page', $args['records_per_page'] );
206 278
207 - $items = $this->plugin->db->query->query( $args );
279 + $items = $this->plugin->db->get_records( $args );
208 280
209 281 return $items;
210 282 }
211 283
@@ -214,31 +286,39 @@
214 286 *
215 287 * @return integer
216 288 */
217 289 public function get_total_found_rows() {
218 - return $this->plugin->db->query->found_records;
290 + return $this->plugin->db->get_found_records_count();
219 291 }
220 292
221 - function column_default( $item, $column_name ) {
222 - $out = '';
293 + /**
294 + * Returns the column content for the provided item and column.
295 + *
296 + * @param array $item Record data.
297 + * @param string $column_name Column name.
298 + * @return void
299 + */
300 + public function column_default( $item, $column_name ) {
301 + $out = '';
223 302 $record = new Record( $item );
224 303
225 304 switch ( $column_name ) {
226 - case 'date' :
227 - $created = date( 'Y-m-d H:i:s', strtotime( $record->created ) );
305 + case 'date':
306 + $created = gmdate( 'Y-m-d H:i:s', strtotime( $record->created ) );
228 307 $date_string = sprintf(
229 308 '<time datetime="%s" class="relative-time record-created">%s</time>',
230 309 wp_stream_get_iso_8601_extended_date( strtotime( $record->created ) ),
231 310 get_date_from_gmt( $created, 'Y/m/d' )
232 311 );
233 - $out = $this->column_link( $date_string, 'date', get_date_from_gmt( $created, 'Y/m/d' ) );
234 - $out .= '<br />';
235 - $out .= get_date_from_gmt( $created, 'h:i:s A' );
312 + $out = $this->column_link( $date_string, 'date', get_date_from_gmt( $created, 'Y/m/d' ) );
313 + $out .= '<br />';
314 + $out .= get_date_from_gmt( $created, 'h:i:s A' );
236 315 break;
237 316
238 - case 'summary' :
239 - $out = $record->summary;
240 - $object_title = $record->get_object_title();
317 + case 'summary':
318 + $out = $record->summary;
319 + $object_title = $record->get_object_title();
320 + /* translators: %s: the title of any object, like a Post (e.g. "Hello World") */
241 321 $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' );
242 322
243 323 if ( $record->object_id ) {
244 324 $out .= $this->column_link(
@@ -253,19 +333,27 @@
253 333 }
254 334 $out .= $this->get_action_links( $record );
255 335 break;
256 336
257 - case 'user_id' :
258 - $user = new Author( (int) $record->user_id, (array) maybe_unserialize( $record->user_meta ) );
337 + case 'user_id':
338 + $user = new Author( (int) $record->user_id, (array) $record->user_meta );
259 339
340 + $filtered_records_url = add_query_arg(
341 + array(
342 + 'page' => $this->plugin->admin->records_page_slug,
343 + 'user_id' => absint( $user->id ),
344 + ),
345 + self_admin_url( $this->plugin->admin->admin_parent_page )
346 + );
347 +
260 348 $out = sprintf(
261 349 '<a href="%s">%s <span>%s</span></a>%s%s%s',
262 - $user->get_records_page_url(),
350 + $filtered_records_url,
263 351 $user->get_avatar_img( 80 ),
264 352 $user->get_display_name(),
265 353 $user->is_deleted() ? sprintf( '<br /><small class="deleted">%s</small>', esc_html__( 'Deleted User', 'stream' ) ) : '',
266 - $user->get_role() ? sprintf( '<br /><small>%s</small>', $user->get_role() ) : '',
267 - $user->get_agent() ? sprintf( '<br /><small>%s</small>', $user->get_agent_label( $user->get_agent() ) ) : ''
354 + sprintf( '<br /><small>%s</small>', $user->get_role() ),
355 + sprintf( '<br /><small>%s</small>', $user->get_agent_label( $user->get_agent() ) )
268 356 );
269 357 break;
270 358
271 359 case 'context':
@@ -291,20 +379,22 @@
291 379 $blog = ( $record->blog_id && is_multisite() ) ? get_blog_details( $record->blog_id ) : $this->plugin->admin->network->get_network_blog();
292 380 $out = $this->column_link( $blog->blogname, 'blog_id', $blog->blog_id );
293 381 break;
294 382
295 - case 'ip' :
383 + case 'ip':
296 384 $out = $this->column_link( $record->{$column_name}, 'ip', $record->{$column_name} );
297 385 break;
298 386
299 - default :
387 + default:
300 388 /**
301 - * Registers new Columns to be inserted into the table. The cell contents of this column is set
302 - * below with 'wp_stream_inster_column_default-'
389 + * Registers new Columns to be inserted into the table. The cell contents of this column is set
390 + * below with 'wp_stream_insert_column_default_'
303 391 *
392 + * @param array $new_columns Columns injected in the table.
393 + *
304 394 * @return array
305 395 */
306 - $inserted_columns = apply_filters( 'wp_stream_register_column_defaults', $new_columns = array() );
396 + $inserted_columns = apply_filters( 'wp_stream_register_column_defaults', array() );
307 397
308 398 if ( ! empty( $inserted_columns ) && is_array( $inserted_columns ) ) {
309 399 foreach ( $inserted_columns as $column_title ) {
310 400 /**
@@ -314,29 +404,41 @@
314 404 *
315 405 * Also, note that the action name must include the $column_title registered
316 406 * with wp_stream_register_column_defaults
317 407 */
318 - if ( $column_title === $column_name && has_filter( "wp_stream_insert_column_default-{$column_title}" ) ) {
408 + if ( $column_title === $column_name ) {
319 409 /**
320 410 * Allows for the addition of content under a specified column.
321 411 *
322 - * @param object $record Contents of the row
412 + * @param string $out Column content.
413 + * @param object $record Record with row content.
414 + * @param string $column_name Column name.
323 415 *
324 416 * @return string
325 417 */
326 - $out = apply_filters( "wp_stream_insert_column_default-{$column_title}", $column_name, $record );
327 - } else {
328 - $out = $column_name;
418 + $out = apply_filters( "wp_stream_insert_column_default_{$column_title}", $out, $record, $column_name );
419 + break;
329 420 }
330 421 }
331 - } else {
332 - $out = $column_name;
333 422 }
334 423 }
335 424
336 - echo $out; // xss ok
425 + $allowed_tags = wp_kses_allowed_html( 'post' );
426 + $allowed_tags['time'] = array(
427 + 'datetime' => true,
428 + 'class' => true,
429 + );
430 + $allowed_tags['img']['srcset'] = true;
431 +
432 + echo wp_kses( $out, $allowed_tags );
337 433 }
338 434
435 + /**
436 + * Returns the actions links for the provided record. (Eg. Edit, View)
437 + *
438 + * @param Record $record Record.
439 + * @return string
440 + */
339 441 public function get_action_links( $record ) {
340 442 $out = '';
341 443
342 444 /**
@@ -388,9 +490,18 @@
388 490
389 491 return $out;
390 492 }
391 493
392 - function column_link( $display, $key, $value = null, $title = null ) {
494 + /**
495 + * Returns a link to be display in the table.
496 + *
497 + * @param string $display Text to be displayed in link.
498 + * @param string|array $key Query string variable(s).
499 + * @param string $value Single query string value.
500 + * @param string $title Tooltip value.
501 + * @return string
502 + */
503 + public function column_link( $display, $key, $value = null, $title = null ) {
393 504 $url = add_query_arg(
394 505 array(
395 506 'page' => $this->plugin->admin->records_page_slug,
396 507 ),
@@ -396,9 +507,11 @@
396 507 ),
397 508 self_admin_url( $this->plugin->admin->admin_parent_page )
398 509 );
399 510
400 - $args = ! is_array( $key ) ? array( $key => $value ) : $key;
511 + $args = ! is_array( $key ) ? array(
512 + $key => $value,
513 + ) : $key;
401 514
402 515 foreach ( $args as $k => $v ) {
403 516 $url = add_query_arg( $k, $v, $url );
404 517 }
@@ -410,14 +523,21 @@
410 523 $display
411 524 );
412 525 }
413 526
527 + /**
528 + * Returns the label for a connector term.
529 + *
530 + * @param string $term Connector label type.
531 + * @param string $type Connector term.
532 + * @return string
533 + */
414 534 public function get_term_title( $term, $type ) {
415 - if ( ! isset( $this->plugin->connectors->term_labels[ "stream_$type" ][ $term ] ) ) {
535 + if ( ! isset( $this->plugin->connectors->term_labels[ 'stream_' . $type ][ $term ] ) ) {
416 536 return $term;
417 537 }
418 538
419 - return $this->plugin->connectors->term_labels[ "stream_$type" ][ $term ];
539 + return $this->plugin->connectors->term_labels[ 'stream_' . $type ][ $term ];
420 540 }
421 541
422 542 /**
423 543 * Assembles records for display in search filters
@@ -425,34 +545,64 @@
425 545 * Gathers list of all users/connectors, then compares it to
426 546 * results of existing records. All items that do not exist in records
427 547 * get assigned a disabled value of "true".
428 548 *
429 - * @param string $column List table column name
549 + * @param string $column List table column name.
430 550 *
431 551 * @return array Options to be displayed in search filters
432 552 */
433 - function assemble_records( $column ) {
553 + public function assemble_records( $column ) {
434 554 // @todo eliminate special condition for authors, especially using a WP_User object as the value; should use string or stringifiable object
435 555 if ( 'user_id' === $column ) {
436 556 $all_records = array();
437 557
438 - // If the number of users exceeds the max users constant value then return an empty array and use AJAX instead
558 + // If the number of users exceeds the max users constant value then return an empty array and use AJAX instead.
439 559 $user_count = count_users();
440 560 $total_users = $user_count['total_users'];
441 561
442 562 if ( $total_users > $this->plugin->admin->preload_users_max ) {
443 - return array();
563 + $selected_user = wp_stream_filter_input( INPUT_GET, 'user_id' );
564 + if ( $selected_user ) {
565 + $user = new Author( $selected_user );
566 +
567 + return array(
568 + $selected_user => $user->get_display_name(),
569 + );
570 + } else {
571 + return array();
572 + }
444 573 }
445 574
446 575 $users = array_map(
447 - function( $user_id ) {
576 + function ( $user_id ) {
448 577 return new Author( $user_id );
449 578 },
450 - get_users( array( 'fields' => 'ID' ) )
579 + get_users(
580 + array(
581 + 'fields' => 'ID',
582 + )
583 + )
451 584 );
452 585
453 - $users[] = new Author( 0, array( 'is_wp_cli' => true ) );
586 + if ( is_multisite() && is_super_admin() ) {
587 + $super_admins = array_map(
588 + function ( $login ) {
589 + $user = get_user_by( 'login', $login );
454 590
591 + return new Author( $user->ID );
592 + },
593 + get_super_admins()
594 + );
595 + $users = array_unique( array_merge( $users, $super_admins ) );
596 + }
597 +
598 + $users[] = new Author(
599 + 0,
600 + array(
601 + 'is_wp_cli' => true,
602 + )
603 + );
604 +
455 605 foreach ( $users as $user ) {
456 606 $all_records[ $user->id ] = $user->get_display_name();
457 607 }
458 608 } else {
@@ -465,20 +615,26 @@
465 615 $disabled_records = array();
466 616
467 617 foreach ( $all_records as $record => $label ) {
468 618 if ( array_key_exists( $record, $existing_records ) ) {
469 - $active_records[ $record ] = array( 'label' => $label, 'disabled' => '' );
619 + $active_records[ $record ] = array(
620 + 'label' => $label,
621 + 'disabled' => '',
622 + );
470 623 } else {
471 - $disabled_records[ $record ] = array( 'label' => $label, 'disabled' => 'disabled="disabled"' );
624 + $disabled_records[ $record ] = array(
625 + 'label' => $label,
626 + 'disabled' => 'disabled="disabled"',
627 + );
472 628 }
473 629 }
474 630
475 - // Remove WP-CLI pseudo user if no records with user=0 exist
631 + // Remove WP-CLI pseudo user if no records with user=0 exist.
476 632 if ( isset( $disabled_records[0] ) ) {
477 633 unset( $disabled_records[0] );
478 634 }
479 635
480 - $sort = function( $a, $b ) use ( $column ) {
636 + $sort = function ( $a, $b ) use ( $column ) {
481 637 $label_a = (string) $a['label'];
482 638 $label_b = (string) $b['label'];
483 639
484 640 if ( $label_a === $label_b ) {
@@ -484,20 +640,25 @@
484 640 if ( $label_a === $label_b ) {
485 641 return 0;
486 642 }
487 643
488 - return ( strtolower( $label_a ) < strtolower( $label_b ) ) ? -1 : 1;
644 + return ( strtolower( $label_a ) < strtolower( $label_b ) ) ? - 1 : 1;
489 645 };
490 646
491 647 uasort( $active_records, $sort );
492 648 uasort( $disabled_records, $sort );
493 649
494 - // Not using array_merge() in order to preserve the array index for the users dropdown which uses the user_id as the key
650 + // Not using array_merge() in order to preserve the array index for the users dropdown which uses the user_id as the key.
495 651 $all_records = $active_records + $disabled_records;
496 652
497 653 return $all_records;
498 654 }
499 655
656 + /**
657 + * Returns list filters.
658 + *
659 + * @return array
660 + */
500 661 public function get_filters() {
501 662 $filters = array();
502 663
503 664 $date_interval = new Date_Interval();
@@ -536,10 +697,14 @@
536 697 */
537 698 return apply_filters( 'wp_stream_list_table_filters', $filters );
538 699 }
539 700
540 - function filters_form() {
541 - $user_id = get_current_user_id();
701 + /**
702 + * Returns table filters form.
703 + *
704 + * @return string
705 + */
706 + public function filters_form() {
542 707 $filters = $this->get_filters();
543 708
544 709 $filters_string = sprintf( '<input type="hidden" name="page" value="%s" />', 'wp_stream' );
545 710 $filters_string .= sprintf( '<span class="filter_info hidden">%s</span>', esc_html__( 'Show filter controls via the screen options tab above.', 'stream' ) );
@@ -544,13 +709,23 @@
544 709 $filters_string = sprintf( '<input type="hidden" name="page" value="%s" />', 'wp_stream' );
545 710 $filters_string .= sprintf( '<span class="filter_info hidden">%s</span>', esc_html__( 'Show filter controls via the screen options tab above.', 'stream' ) );
546 711
547 712 foreach ( $filters as $name => $data ) {
713 +
714 + $data = wp_parse_args(
715 + $data,
716 + array(
717 + 'title' => '',
718 + 'items' => array(),
719 + 'ajax' => false,
720 + )
721 + );
722 +
548 723 if ( 'date' === $name ) {
549 724 $filters_string .= $this->filter_date( $data['items'] );
550 725 } else {
551 726 if ( 'context' === $name ) {
552 - // Add Connectors as parents, and apply the Contexts as children
727 + // Add Connectors as parents, and apply the Contexts as children.
553 728 $connectors = $this->assemble_records( 'connector' );
554 729 $context_items = array();
555 730
556 731 foreach ( $connectors as $connector => $item ) {
@@ -564,9 +739,9 @@
564 739
565 740 if ( isset( $context_items[ $connector ]['children'] ) ) {
566 741 $labels = wp_list_pluck( $context_items[ $connector ]['children'], 'label' );
567 742
568 - // Sort child items by label
743 + // Sort child items by label.
569 744 array_multisort( $labels, SORT_ASC, $context_items[ $connector ]['children'] );
570 745 }
571 746 }
572 747
@@ -579,22 +754,25 @@
579 754 $data['items'] = $context_items;
580 755
581 756 $labels = wp_list_pluck( $data['items'], 'label' );
582 757
583 - // Sort top-level items by label
758 + // Sort top-level items by label.
584 759 array_multisort( $labels, SORT_ASC, $data['items'] );
585 760
586 - // Ouput a hidden input to handle the connector value
587 - $filters_string .= '<input type="hidden" name="connector" class="record-filter-connector" />';
761 + // Output a hidden input to handle the connector value.
762 + $filters_string .= sprintf(
763 + '<input type="hidden" name="connector" class="record-filter-connector" value="%s" />',
764 + esc_attr( wp_stream_filter_input( INPUT_GET, 'connector' ) )
765 + );
588 766 }
589 767
590 - $filters_string .= $this->filter_select( $name, $data['title'], $data['items'] );
768 + $filters_string .= $this->filter_select( $name, $data['title'], $data['items'], $data['ajax'] );
591 769 }
592 770 }
593 771
594 772 $filters_string .= sprintf( '<input type="submit" id="record-query-submit" class="button" value="%s" />', __( 'Filter', 'stream' ) );
595 773
596 - // Parse all query vars into an array
774 + // Parse all query vars into an array.
597 775 $query_vars = array();
598 776
599 777 if ( isset( $_SERVER['QUERY_STRING'] ) ) {
600 778 parse_str( urldecode( $_SERVER['QUERY_STRING'] ), $query_vars );
@@ -599,9 +777,9 @@
599 777 if ( isset( $_SERVER['QUERY_STRING'] ) ) {
600 778 parse_str( urldecode( $_SERVER['QUERY_STRING'] ), $query_vars );
601 779 }
602 780
603 - // Ignore certain query vars and query vars that are empty
781 + // Ignore certain query vars and query vars that are empty.
604 782 foreach ( $query_vars as $query_var => $value ) {
605 783 if ( '' === $value || 'page' === $query_var || 'paged' === $query_var ) {
606 784 unset( $query_vars[ $query_var ] );
607 785 }
@@ -613,70 +791,77 @@
613 791 ),
614 792 self_admin_url( $this->plugin->admin->admin_parent_page )
615 793 );
616 794
617 - // Display reset action if records are being filtered
795 + // Display reset action if records are being filtered.
618 796 if ( ! empty( $query_vars ) ) {
619 797 $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' ) );
620 798 }
621 799
622 - return sprintf( '<div class="alignleft actions">%s</div>', $filters_string ); // xss ok
800 + return sprintf( '<div class="alignleft actions">%s</div>', $filters_string ); // xss ok.
623 801 }
624 802
625 - function filter_select( $name, $title, $items, $ajax = false ) {
626 - if ( $ajax ) {
627 - $out = sprintf(
628 - '<input type="hidden" name="%s" class="chosen-select" value="%s" data-placeholder="%s" />',
629 - esc_attr( $name ),
630 - esc_attr( wp_stream_filter_input( INPUT_GET, $name ) ),
631 - esc_attr( $title )
803 + /**
804 + * Returns HTML string of filterable select control with filtered items.
805 + *
806 + * @param string $name Search input.
807 + * @param string $title Name of the control.
808 + * @param array $items Items to be filtered.
809 + * @param boolean $ajax Whether is an ajax request or not.
810 + * @return string
811 + */
812 + public function filter_select( $name, $title, $items, $ajax = false ) {
813 + $options = array( '<option value=""></option>' );
814 + $selected = wp_stream_filter_input( INPUT_GET, $name );
815 +
816 + foreach ( $items as $key => $item ) {
817 + $value = isset( $item['children'] ) ? 'group-' . $key : $key;
818 + $option_args = array(
819 + 'value' => $value,
820 + 'selected' => selected( $value, $selected, false ),
821 + 'disabled' => isset( $item['disabled'] ) ? $item['disabled'] : null,
822 + 'icon' => isset( $item['icon'] ) ? $item['icon'] : null,
823 + 'group' => isset( $item['children'] ) ? $key : null,
824 + 'tooltip' => isset( $item['tooltip'] ) ? $item['tooltip'] : null,
825 + 'class' => isset( $item['children'] ) ? 'level-1' : null,
826 + 'label' => isset( $item['label'] ) ? $item['label'] : null,
632 827 );
633 - } else {
634 - $options = array( '<option value=""></option>' );
635 - $selected = wp_stream_filter_input( INPUT_GET, $name );
828 + $options[] = $this->filter_option( $option_args );
636 829
637 - foreach ( $items as $key => $item ) {
638 - $value = isset( $item['children'] ) ? 'group-' . $key : $key;
639 - $option_args = array(
640 - 'value' => $value,
641 - 'selected' => selected( $value, $selected, false ),
642 - 'disabled' => isset( $item['disabled'] ) ? $item['disabled'] : null,
643 - 'icon' => isset( $item['icon'] ) ? $item['icon'] : null,
644 - 'group' => isset( $item['children'] ) ? $key : null,
645 - 'tooltip' => isset( $item['tooltip'] ) ? $item['tooltip'] : null,
646 - 'class' => isset( $item['children'] ) ? 'level-1' : null,
647 - 'label' => isset( $item['label'] ) ? $item['label'] : null,
648 - );
649 - $options[] = $this->filter_option( $option_args );
650 -
651 - if ( isset( $item['children'] ) ) {
652 - foreach ( $item['children'] as $child_value => $child_item ) {
653 - $option_args = array(
654 - 'value' => $child_value,
655 - 'selected' => selected( $child_value, $selected, false ),
656 - 'disabled' => isset( $child_item['disabled'] ) ? $child_item['disabled'] : null,
657 - 'icon' => isset( $child_item['icon'] ) ? $child_item['icon'] : null,
658 - 'group' => $key,
659 - 'tooltip' => isset( $child_item['tooltip'] ) ? $child_item['tooltip'] : null,
660 - 'class' => 'level-2',
661 - 'label' => isset( $child_item['label'] ) ? '- ' . $child_item['label'] : null,
662 - );
663 - $options[] = $this->filter_option( $option_args );
664 - }
830 + if ( isset( $item['children'] ) ) {
831 + foreach ( $item['children'] as $child_value => $child_item ) {
832 + $option_args = array(
833 + 'value' => $child_value,
834 + 'selected' => selected( $child_value, $selected, false ),
835 + 'disabled' => isset( $child_item['disabled'] ) ? $child_item['disabled'] : null,
836 + 'icon' => isset( $child_item['icon'] ) ? $child_item['icon'] : null,
837 + 'group' => $key,
838 + 'tooltip' => isset( $child_item['tooltip'] ) ? $child_item['tooltip'] : null,
839 + 'class' => 'level-2',
840 + 'label' => isset( $child_item['label'] ) ? '- ' . $child_item['label'] : null,
841 + );
842 + $options[] = $this->filter_option( $option_args );
665 843 }
666 844 }
667 - $out = sprintf(
668 - '<select name="%s" class="chosen-select" data-placeholder="%s">%s</select>',
669 - esc_attr( $name ),
670 - sprintf( esc_attr__( 'Show all %s', 'stream' ), $title ),
671 - implode( '', $options )
672 - );
673 845 }
846 + $out = sprintf(
847 + '<select name="%s" class="chosen-select" data-placeholder="%s">%s</select>',
848 + esc_attr( $name ),
849 + /* translators: %s: the title of the dropdown menu (e.g. "users") */
850 + sprintf( esc_attr__( 'Show all %s', 'stream' ), $title ),
851 + implode( '', $options )
852 + );
674 853
675 854 return $out;
676 855 }
677 856
678 - function filter_option( $args ) {
857 + /**
858 + * Return HTML string of a filterable select option.
859 + *
860 + * @param array $args Option attributes.
861 + * @return string
862 + */
863 + public function filter_option( $args ) {
679 864 $defaults = array(
680 865 'value' => null,
681 866 'selected' => null,
682 867 'disabled' => null,
@@ -700,13 +885,17 @@
700 885 esc_html( $args['label'] )
701 886 );
702 887 }
703 888
704 - function filter_search() {
889 + /**
890 + * Return HTML string of a filter search box.
891 + *
892 + * @return string
893 + */
894 + public function filter_search() {
705 895 $search = null;
706 - if ( isset( $_GET['search'] ) ) {
707 - // @TODO: Make this pass phpcs
708 - $search = esc_attr( wp_unslash( $_GET['search'] ) ); // input var okay
896 + if ( isset( $_GET['search'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
897 + $search = sanitize_key( wp_unslash( $_GET['search'] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
709 898 }
710 899 $out = sprintf(
711 900 '<p class="search-box">
712 901 <label class="screen-reader-text" for="record-search-input">%1$s:</label>
@@ -719,9 +908,15 @@
719 908
720 909 return $out;
721 910 }
722 911
723 - function filter_date( $items ) {
912 + /**
913 + * Return HTML string of a filter select box based upon date.
914 + *
915 + * @param array $items Records.
916 + * @return string
917 + */
918 + public function filter_date( $items ) {
724 919 wp_enqueue_style( 'jquery-ui' );
725 920 wp_enqueue_style( 'wp-stream-datepicker' );
726 921 wp_enqueue_script( 'jquery-ui-datepicker' );
727 922
@@ -732,11 +927,11 @@
732 927 ob_start();
733 928 ?>
734 929 <div class="date-interval">
735 930
736 - <select class="field-predefined hide-if-no-js" name="date_predefined" data-placeholder="<?php esc_attr_e( 'All Time', 'stream' ) ?>">
931 + <select class="field-predefined hide-if-no-js chosen-select" name="date_predefined" data-placeholder="<?php esc_attr_e( 'All Time', 'stream' ); ?>">
737 932 <option></option>
738 - <option value="custom" <?php selected( 'custom' === $date_predefined ); ?>><?php esc_attr_e( 'Custom', 'stream' ) ?></option>
933 + <option value="custom" <?php selected( 'custom' === $date_predefined ); ?>><?php esc_attr_e( 'Custom', 'stream' ); ?></option>
739 934 <?php
740 935 foreach ( $items as $key => $interval ) {
741 936 $end = isset( $interval['end'] ) ? $interval['end']->format( 'Y/m/d' ) : null;
742 937
@@ -754,15 +949,15 @@
754 949
755 950 <div class="date-inputs">
756 951 <div class="box">
757 952 <i class="date-remove dashicons"></i>
758 - <input type="text" name="date_from" class="date-picker field-from" placeholder="<?php esc_attr_e( 'Start Date', 'stream' ) ?>" value="<?php echo esc_attr( $date_from ) ?>" />
953 + <input type="text" name="date_from" class="date-picker field-from" placeholder="<?php esc_attr_e( 'Start Date', 'stream' ); ?>" value="<?php echo esc_attr( $date_from ); ?>"/>
759 954 </div>
760 955 <span class="connector dashicons"></span>
761 956
762 957 <div class="box">
763 958 <i class="date-remove dashicons"></i>
764 - <input type="text" name="date_to" class="date-picker field-to" placeholder="<?php esc_attr_e( 'End Date', 'stream' ) ?>" value="<?php echo esc_attr( $date_to ) ?>" />
959 + <input type="text" name="date_to" class="date-picker field-to" placeholder="<?php esc_attr_e( 'End Date', 'stream' ); ?>" value="<?php echo esc_attr( $date_to ); ?>"/>
765 960 </div>
766 961 </div>
767 962
768 963 </div>
@@ -770,20 +965,95 @@
770 965
771 966 return ob_get_clean();
772 967 }
773 968
774 - function display() {
969 + /**
970 + * Output a Select dropdown of actions relating to the Stream records
971 + *
972 + * @return string
973 + */
974 + public function record_actions_form() {
975 + /**
976 + * Filter the records screen actions dropdown menu
977 + *
978 + * @return array Should be in the format of action_slug => 'Action Name'
979 + */
980 + $actions = apply_filters( 'wp_stream_record_actions_menu', array() );
981 +
982 + if ( empty( $actions ) ) {
983 + return '';
984 + }
985 +
986 + ob_start();
987 + printf( '<div class="alignleft actions recordactions"><select name="%s">', esc_attr( 'record-actions' ) );
988 + printf( '<option value="">%s</option>', esc_attr__( 'Record Actions', 'stream' ) );
989 + foreach ( $actions as $value => $name ) {
990 + printf(
991 + '<option value="%s">%s</option>',
992 + esc_attr( $value ),
993 + esc_attr( $name )
994 + );
995 + }
996 + echo '</select></div>';
997 + wp_nonce_field( 'stream_record_actions_nonce', 'stream_record_actions_nonce' );
998 + wp_nonce_field( 'stream_filters_user_search_nonce', 'stream_filters_user_search_nonce' );
999 +
1000 + printf( '<input type="hidden" name="page" value="%s">', esc_attr( wp_stream_filter_input( INPUT_GET, 'page' ) ) );
1001 + printf( '<input type="hidden" name="date_predefined" value="%s">', esc_attr( wp_stream_filter_input( INPUT_GET, 'date_predefined' ) ) );
1002 + printf( '<input type="hidden" name="date_from" value="%s">', esc_attr( wp_stream_filter_input( INPUT_GET, 'date_from' ) ) );
1003 + printf( '<input type="hidden" name="date_to" value="%s">', esc_attr( wp_stream_filter_input( INPUT_GET, 'date_to' ) ) );
1004 + printf( '<input type="hidden" name="user_id" value="%s">', esc_attr( wp_stream_filter_input( INPUT_GET, 'user_id' ) ) );
1005 + printf( '<input type="hidden" name="connector" value="%s">', esc_attr( wp_stream_filter_input( INPUT_GET, 'connector' ) ) );
1006 + printf( '<input type="hidden" name="context" value="%s">', esc_attr( wp_stream_filter_input( INPUT_GET, 'context' ) ) );
1007 + printf( '<input type="hidden" name="action" value="%s">', esc_attr( wp_stream_filter_input( INPUT_GET, 'action' ) ) );
1008 +
1009 + printf( '<input type="submit" name="" id="record-actions-submit" class="button" value="%s">', esc_attr__( 'Apply', 'stream' ) );
1010 + echo '<div class="clear"></div>';
1011 +
1012 + return ob_get_clean();
1013 + }
1014 +
1015 + /**
1016 + * Renders record filter forms.
1017 + */
1018 + public function display() {
775 1019 $url = self_admin_url( $this->plugin->admin->admin_parent_page );
776 1020
777 1021 echo '<form method="get" action="' . esc_url( $url ) . '" id="record-filter-form">';
778 - echo $this->filter_search(); // xss ok
1022 + echo $this->filter_search(); // xss ok.
1023 + parent::display();
1024 + echo '</form>';
779 1025
780 - parent::display();
1026 + echo '<form method="get" action="' . esc_url( $url ) . '" id="record-actions-form">';
1027 + echo $this->record_actions_form(); // xss ok.
781 1028 echo '</form>';
782 1029 }
783 1030
784 - function display_tablenav( $which ) {
785 - if ( 'top' === $which ) : ?>
1031 + /**
1032 + * Renders a single record
1033 + *
1034 + * @param array $item Record data.
1035 + */
1036 + public function single_row( $item ) {
1037 + $classes = apply_filters( 'wp_stream_record_classes', array(), $item );
1038 + $class_string = '';
1039 + if ( ! empty( $classes ) ) {
1040 + $class_string = ' class="' . esc_attr( join( ' ', $classes ) ) . '"';
1041 + }
1042 +
1043 + echo sprintf( '<tr%s>', $class_string ); // xss ok.
1044 + $this->single_row_columns( $item );
1045 + echo '</tr>';
1046 + }
1047 +
1048 + /**
1049 + * Renders table navigation controls
1050 + *
1051 + * @param string $which Location controls.
1052 + */
1053 + public function display_tablenav( $which ) {
1054 + if ( 'top' === $which ) :
1055 + ?>
786 1056 <div class="tablenav <?php echo esc_attr( $which ); ?>">
787 1057 <?php
788 1058 $this->pagination( $which );
789 1059 $this->extra_tablenav( $which );
@@ -788,9 +1058,9 @@
788 1058 $this->pagination( $which );
789 1059 $this->extra_tablenav( $which );
790 1060 ?>
791 1061
792 - <br class="clear" />
1062 + <br class="clear"/>
793 1063 </div>
794 1064 <?php else : ?>
795 1065 <div class="tablenav <?php echo esc_attr( $which ); ?>">
796 1066 <?php
@@ -801,15 +1071,23 @@
801 1071 $this->pagination( $which );
802 1072 $this->extra_tablenav( $which );
803 1073 ?>
804 1074
805 - <br class="clear" />
1075 + <br class="clear"/>
806 1076 </div>
807 - <?php
1077 + <?php
808 1078 endif;
809 1079 }
810 1080
811 - function set_screen_option( $dummy, $option, $value ) {
1081 + /**
1082 + * Sets the screen options.
1083 + *
1084 + * @param string $dummy Unused.
1085 + * @param string $option Screen option name.
1086 + * @param string $value Screen option value.
1087 + * @return string
1088 + */
1089 + public function set_screen_option( $dummy, $option, $value ) {
812 1090 if ( 'edit_stream_per_page' === $option ) {
813 1091 return $value;
814 1092 } else {
815 1093 return $dummy;
@@ -815,9 +1093,17 @@
815 1093 return $dummy;
816 1094 }
817 1095 }
818 1096
819 - function set_live_update_option( $dummy, $option, $value ) {
1097 + /**
1098 + * Sets the live update options.
1099 + *
1100 + * @param string $dummy Unused.
1101 + * @param string $option Screen option name.
1102 + * @param string $value Screen option value.
1103 + * @return string
1104 + */
1105 + public function set_live_update_option( $dummy, $option, $value ) {
820 1106 unset( $value );
821 1107
822 1108 // @codingStandardsIgnoreStart
823 1109 if (
@@ -828,13 +1114,21 @@
828 1114 $value = esc_attr( $_POST[ $this->plugin->admin->live_update->user_meta_key ] ); //input var okay
829 1115
830 1116 return $value;
831 1117 }
1118 +
832 1119 // @codingStandardsIgnoreEnd
833 1120
834 1121 return $dummy;
835 1122 }
836 1123
1124 + /**
1125 + * Return HTML string of the "Live updates" screen option.
1126 + *
1127 + * @param string $status Unused.
1128 + * @param array $args Unused.
1129 + * @return string
1130 + */
837 1131 public function screen_controls( $status, $args ) {
838 1132 unset( $status );
839 1133 unset( $args );
840 1134
@@ -852,20 +1146,21 @@
852 1146
853 1147 ob_start();
854 1148 ?>
855 1149 <fieldset>
856 - <h5><?php esc_html_e( 'Live updates', 'stream' ) ?></h5>
1150 + <h5><?php esc_html_e( 'Live updates', 'stream' ); ?></h5>
857 1151
858 1152 <div>
859 - <input type="hidden" name="stream_live_update_nonce" id="stream_live_update_nonce" value="<?php echo esc_attr( $nonce ) ?>" />
1153 + <input type="hidden" name="stream_live_update_nonce" id="stream_live_update_nonce" value="<?php echo esc_attr( $nonce ); ?>"/>
860 1154 </div>
861 1155 <div>
862 - <input type="hidden" name="enable_live_update_user" id="enable_live_update_user" value="<?php echo absint( $user_id ) ?>" />
1156 + <input type="hidden" name="enable_live_update_user" id="enable_live_update_user" value="<?php echo absint( $user_id ); ?>"/>
863 1157 </div>
864 1158 <div class="metabox-prefs stream-live-update-checkbox">
865 1159 <label for="enable_live_update">
866 - <input type="checkbox" value="on" name="enable_live_update" id="enable_live_update" data-heartbeat="<?php echo esc_attr( $heartbeat ) ?>" <?php checked( $option, 'on' ) ?> />
867 - <?php esc_html_e( 'Enabled', 'stream' ) ?><span class="spinner"></span>
1160 + <input type="checkbox" value="on" name="enable_live_update" id="enable_live_update" data-heartbeat="<?php echo esc_attr( $heartbeat ); ?>" <?php checked( $option, 'on' ); ?> />
1161 + <?php esc_html_e( 'Enabled', 'stream' ); ?>
1162 + <span class="spinner"></span>
868 1163 </label>
869 1164 </div>
870 1165 </fieldset>
871 1166 <?php
@@ -874,13 +1169,13 @@
874 1169
875 1170 /**
876 1171 * This function is use to map List table column name with excluded setting keys
877 1172 *
878 - * @param string $column List table column name
1173 + * @param string $column List table column name.
879 1174 *
880 1175 * @return string setting name for that column
881 1176 */
882 - function get_column_excluded_setting_key( $column ) {
1177 + public function get_column_excluded_setting_key( $column ) {
883 1178 switch ( $column ) {
884 1179 case 'connector':
885 1180 $output = 'connectors';
886 1181 break;
@@ -905,9 +1200,9 @@
905 1200
906 1201 /**
907 1202 * Get users as dropdown items
908 1203 *
909 - * @param array $users
1204 + * @param array $users Users.
910 1205 *
911 1206 * @return array
912 1207 */
913 1208 public function get_users_dropdown_items( $users ) {