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-list-table.php

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

882 lines 26.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 class WP_Stream_List_Table extends WP_List_Table {
4
5 function __construct( $args = array() ) {
6
7 $screen_id = isset( $args['screen'] ) ? $args['screen'] : null;
8 $screen_id = apply_filters( 'wp_stream_list_table_screen_id', $screen_id );
9
10 parent::__construct(
11 array(
12 'post_type' => 'stream',
13 'plural' => 'records',
14 'screen' => $screen_id,
15 )
16 );
17
18 add_screen_option(
19 'per_page',
20 array(
21 'default' => 20,
22 'label' => __( 'Records per page', 'stream' ),
23 'option' => 'edit_stream_per_page',
24 )
25 );
26
27 // Check for default hidden columns
28 $this->get_hidden_columns();
29
30 add_filter( 'screen_settings', array( $this, 'screen_controls' ), 10, 2 );
31 add_filter( 'set-screen-option', array( __CLASS__, 'set_screen_option' ), 10, 3 );
32
33 set_screen_options();
34 }
35
36 function extra_tablenav( $which ) {
37 if ( 'top' === $which ) {
38 echo $this->filters_form(); //xss ok
39 }
40 }
41
42 function no_items() {
43 $site = WP_Stream::$api->get_site();
44
45 if ( isset( $site->plan->type ) && 'free' === $site->plan->type && 0 !== $this->get_total_found_rows() ) {
46 ?>
47 <div class="stream-list-table-upgrade">
48 <p><?php printf( _n( 'Your free account is limited to viewing 24 hours of activity history.', 'Your free account is limited to viewing <strong>%d days</strong> of activity history.', $site->plan->retention, 'stream' ), absint( $site->plan->retention ) ) ?></p>
49 <p><a href="<?php echo esc_url( WP_Stream_Admin::account_url( sprintf( 'upgrade?site_uuid=%s', WP_Stream::$api->site_uuid ) ) ); ?>" class="button button-primary button-large"><?php _e( 'Upgrade to Pro', 'stream' ) ?></a></p>
50 </div>
51 <?php
52 } else {
53 _e( 'Sorry, no activity records were found.', 'stream' );
54 }
55 }
56
57 function get_columns(){
58 /**
59 * Allows devs to add new columns to table
60 *
61 * @param array default columns
62 *
63 * @return array updated list of columns
64 */
65 return apply_filters(
66 'wp_stream_list_table_columns',
67 array(
68 'date' => __( 'Date', 'stream' ),
69 'summary' => __( 'Summary', 'stream' ),
70 'author' => __( 'Author', 'stream' ),
71 'context' => __( 'Context', 'stream' ),
72 'action' => __( 'Action', 'stream' ),
73 'ip' => __( 'IP Address', 'stream' ),
74 )
75 );
76 }
77
78 function get_sortable_columns() {
79 return array(
80 'date' => array( 'date', false ),
81 );
82 }
83
84 function get_hidden_columns() {
85 if ( ! $user = wp_get_current_user() ) {
86 return array();
87 }
88
89 // Directly checking the user meta; to check whether user has changed screen option or not
90 $hidden = get_user_meta( $user->ID, 'manage' . $this->screen->id . 'columnshidden', true );
91
92 // If user meta is not found; add the default hidden column 'id'
93 if ( ! $hidden ) {
94 $hidden = array( 'id' );
95 update_user_meta( $user->ID, 'manage' . $this->screen->id . 'columnshidden', $hidden );
96 }
97
98 return $hidden;
99 }
100
101 function prepare_items() {
102 $columns = $this->get_columns();
103 $sortable = $this->get_sortable_columns();
104 $hidden = $this->get_hidden_columns();
105
106 $this->_column_headers = array( $columns, $hidden, $sortable );
107
108 $this->items = $this->get_records();
109
110 $total_items = $this->get_total_found_rows();
111
112 $this->set_pagination_args(
113 array(
114 'total_items' => $total_items,
115 'per_page' => $this->get_items_per_page( 'edit_stream_per_page', 20 ),
116 )
117 );
118 }
119
120 /**
121 * Render the checkbox column
122 *
123 * @param array $item Contains all the data for the checkbox column
124 *
125 * @return string Displays a checkbox
126 */
127 function column_cb( $item ) {
128 return sprintf(
129 '<input type="checkbox" name="%1$s[]" value="%2$s" />',
130 /*$1%s*/
131 'wp_stream_checkbox',
132 /*$2%s*/
133 $item->ID
134 );
135 }
136
137 function get_records() {
138 $args = array();
139
140 // Parse sorting params
141 if ( $order = wp_stream_filter_input( INPUT_GET, 'order' ) ) {
142 $args['order'] = $order;
143 }
144 if ( $orderby = wp_stream_filter_input( INPUT_GET, 'orderby' ) ) {
145 $args['orderby'] = $orderby;
146 }
147
148 // Filters
149 $params = array(
150 'search',
151 'date',
152 'date_from',
153 'date_to',
154 'record_after', // Deprecated, use date_after instead
155 'date_after',
156 'date_before',
157 );
158
159 foreach ( $params as $param ) {
160 $value = wp_stream_filter_input( INPUT_GET, $param );
161 if ( $value ) {
162 $args[ $param ] = $value;
163 }
164 }
165
166 // Additional filter properties
167 $properties = array(
168 'record',
169 'author',
170 'author_role',
171 'ip',
172 'object_id',
173 'site_id',
174 'blog_id',
175 'connector',
176 'context',
177 'action',
178 );
179
180 // Add property fields to defaults, including their __in/__not_in variations
181 foreach ( $properties as $property ) {
182 $value = wp_stream_filter_input( INPUT_GET, $property );
183 if ( $value ) {
184 $args[ $property ] = $value;
185 }
186
187 $value_in = wp_stream_filter_input( INPUT_GET, $property . '__in' );
188 if ( $value_in ) {
189 $args[ $property . '__in' ] = explode( ',', $value_in );
190 }
191
192 $value_not_in = wp_stream_filter_input( INPUT_GET, $property . '__not_in' );
193 if ( $value_not_in ) {
194 $args[ $property . '__not_in' ] = explode( ',', $value_not_in );
195 }
196 }
197
198 $args['paged'] = $this->get_pagenum();
199
200 if ( isset( $args['context'] ) && 0 === strpos( $args['context'], 'group-' ) ) {
201 $args['connector'] = str_replace( 'group-', '', $args['context'] );
202 $args['context'] = '';
203 }
204
205 if ( ! isset( $args['records_per_page'] ) ) {
206 $args['records_per_page'] = $this->get_items_per_page( 'edit_stream_per_page', 20 );
207 }
208
209 $args['aggregations'] = array( 'author', 'connector', 'context', 'action' );
210
211 $items = wp_stream_query( $args );
212
213 return $items;
214 }
215
216 /**
217 * Get last query found rows
218 *
219 * @return integer
220 */
221 function get_total_found_rows() {
222 return WP_Stream::$db->get_found_rows();
223 }
224
225 function column_default( $item, $column_name ) {
226 switch ( $column_name ) {
227 case 'date' :
228 $created = date( 'Y-m-d H:i:s', strtotime( $item->created ) );
229 $date_string = sprintf(
230 '<time datetime="%s" class="relative-time record-created">%s</time>',
231 wp_stream_get_iso_8601_extended_date( strtotime( $item->created ) ),
232 get_date_from_gmt( $created, 'Y/m/d' )
233 );
234 $out = $this->column_link( $date_string, 'date', get_date_from_gmt( $created, 'Y/m/d' ) );
235 $out .= '<br />';
236 $out .= get_date_from_gmt( $created, 'h:i:s A' );
237 break;
238
239 case 'summary' :
240 $out = $item->summary;
241 $object_title = wp_stream_get_object_title( $item );
242 $view_all_text = $object_title ? sprintf( __( 'View all activity for "%s"', 'stream' ), esc_attr( $object_title ) ) : __( 'View all activity for this object', 'stream' );
243 if ( $item->object_id ) {
244 $out .= $this->column_link(
245 '<span class="dashicons dashicons-search stream-filter-object-id"></span>',
246 array(
247 'object_id' => $item->object_id,
248 'context' => $item->context,
249 ),
250 null,
251 esc_attr( $view_all_text )
252 );
253 }
254 $out .= $this->get_action_links( $item );
255 break;
256
257 case 'author' :
258 $author = new WP_Stream_Author( (int) $item->author, (array) $item->author_meta );
259
260 $out = sprintf(
261 '<a href="%s">%s <span>%s</span></a>%s%s%s',
262 $author->get_records_page_url(),
263 $author->get_avatar_img( 80 ),
264 $author->get_display_name(),
265 $author->is_deleted() ? sprintf( '<br /><small class="deleted">%s</small>', esc_html__( 'Deleted User', 'stream' ) ) : '',
266 $author->get_role() ? sprintf( '<br /><small>%s</small>', $author->get_role() ) : '',
267 $author->get_agent() ? sprintf( '<br /><small>%s</small>', WP_Stream_Author::get_agent_label( $author->get_agent() ) ) : ''
268 );
269 break;
270
271 case 'context':
272 $connector_title = $this->get_term_title( $item->{'connector'}, 'connector' );
273 $context_title = $this->get_term_title( $item->{'context'}, 'context' );
274
275 $out = $this->column_link( $connector_title, 'connector', $item->{'connector'} );
276 $out .= '<br />&#8627;&nbsp;';
277 $out .= $this->column_link(
278 $context_title,
279 array(
280 'connector' => $item->{'connector'},
281 'context' => $item->{'context'},
282 )
283 );
284 break;
285
286 case 'action':
287 $out = $this->column_link( $this->get_term_title( $item->{$column_name}, $column_name ), $column_name, $item->{$column_name} );
288 break;
289
290 case 'ip' :
291 $out = $this->column_link( $item->{$column_name}, 'ip', $item->{$column_name} );
292 break;
293
294 case 'blog_id':
295 $blog = get_blog_details( $item->blog_id );
296 $out = sprintf(
297 '<a href="%s"><span>%s</span></a>',
298 add_query_arg( array( 'blog_id' => $blog->blog_id ), admin_url( 'admin.php?page=wp_stream' ) ),
299 esc_html( $blog->blogname )
300 );
301 break;
302
303 default :
304 /**
305 * Registers new Columns to be inserted into the table. The cell contents of this column is set
306 * below with 'wp_stream_inster_column_default-'
307 *
308 * @param array $new_columns Array of new column titles to add
309 */
310 $inserted_columns = apply_filters( 'wp_stream_register_column_defaults', $new_columns = array() );
311
312 if ( ! empty( $inserted_columns ) && is_array( $inserted_columns ) ) {
313 foreach ( $inserted_columns as $column_title ) {
314 /**
315 * If column title inserted via wp_stream_register_column_defaults ($column_title) exists
316 * among columns registered with get_columns ($column_name) and there is an action associated
317 * with this column, do the action
318 *
319 * Also, note that the action name must include the $column_title registered
320 * with wp_stream_register_column_defaults
321 */
322 if ( $column_title == $column_name && has_action( "wp_stream_insert_column_default-{$column_title}" ) ) {
323 /**
324 * Allows for the addition of content under a specified column.
325 *
326 * @since 1.0.0
327 *
328 * @param object $item Contents of the row
329 */
330 $out = do_action( "wp_stream_insert_column_default-{$column_title}", $item );
331 } else {
332 $out = $column_name;
333 }
334 }
335 } else {
336 $out = $column_name; // xss ok
337 }
338 }
339
340 echo $out; // xss ok
341 }
342
343 public static function get_action_links( $record ) {
344 $out = '';
345
346 /**
347 * Filter allows modification of action links for a specific connector
348 *
349 * @param string connector
350 * @param array array of action links for this connector
351 * @param obj record
352 *
353 * @return arrray action links for this connector
354 */
355 $action_links = apply_filters( 'wp_stream_action_links_' . $record->connector, array(), $record );
356
357 /**
358 * Filter allows addition of custom links for a specific connector
359 *
360 * @param string connector
361 * @param array array of custom links for this connector
362 * @param obj record
363 *
364 * @return arrray custom links for this connector
365 */
366 $custom_links = apply_filters( 'wp_stream_custom_action_links_' . $record->connector, array(), $record );
367
368 if ( $action_links || $custom_links ) {
369 $out .= '<div class="row-actions">';
370 }
371
372 $links = array();
373 if ( $action_links && is_array( $action_links ) ) {
374 foreach ( $action_links as $al_title => $al_href ) {
375 $links[] = sprintf(
376 '<span><a href="%s" class="action-link">%s</a></span>',
377 $al_href,
378 $al_title
379 );
380 }
381 }
382
383 if ( $custom_links && is_array( $custom_links ) ) {
384 foreach ( $custom_links as $key => $link ) {
385 $links[] = $link;
386 }
387 }
388
389 $out .= implode( ' | ', $links );
390
391 if ( $action_links || $custom_links ) {
392 $out .= '</div>';
393 }
394
395 return $out;
396 }
397
398 function column_link( $display, $key, $value = null, $title = null ) {
399 $url = add_query_arg(
400 array(
401 'page' => WP_Stream_Admin::RECORDS_PAGE_SLUG,
402 ),
403 self_admin_url( WP_Stream_Admin::ADMIN_PARENT_PAGE )
404 );
405
406 $args = ! is_array( $key ) ? array( $key => $value ) : $key;
407
408 foreach ( $args as $k => $v ) {
409 $url = add_query_arg( $k, $v, $url );
410 }
411
412 return sprintf(
413 '<a href="%s" title="%s">%s</a>',
414 esc_url( $url ),
415 esc_attr( $title ),
416 $display
417 );
418 }
419
420 public function get_term_title( $term, $type ) {
421 if ( isset( WP_Stream_Connectors::$term_labels[ "stream_$type" ][ $term ] ) ) {
422 return WP_Stream_Connectors::$term_labels[ "stream_$type" ][ $term ];
423 } else {
424 return $term;
425 }
426 }
427
428 /**
429 * Assembles records for display in search filters
430 *
431 * Gathers list of all authors/connectors, then compares it to
432 * results of existing records. All items that do not exist in records
433 * get assigned a disabled value of "true".
434 *
435 * @uses wp_stream_existing_records (see class-wp-stream-query.php)
436 * @since 1.0.4
437 *
438 * @param string Column requested
439 * @param string Table to be queried
440 *
441 * @return array options to be displayed in search filters
442 */
443 function assemble_records( $column ) {
444 $setting_key = self::get_column_excluded_setting_key( $column );
445
446 // @todo eliminate special condition for authors, especially using a WP_User object as the value; should use string or stringifiable object
447 if ( 'author' === $column ) {
448 $all_records = array();
449
450 // If the number of users exceeds the max authors constant value then return an empty array and use AJAX instead
451 $user_count = count_users();
452 $total_users = $user_count['total_users'];
453
454 if ( $total_users > WP_Stream_Admin::PRELOAD_AUTHORS_MAX ) {
455 return array();
456 }
457
458 $authors = array_map(
459 function ( $user_id ) {
460 return new WP_Stream_Author( $user_id );
461 },
462 get_users( array( 'fields' => 'ID' ) )
463 );
464
465 $authors[] = new WP_Stream_Author( 0, array( 'is_wp_cli' => true ) );
466
467 foreach ( $authors as $author ) {
468 $all_records[ $author->id ] = $author->get_display_name();
469 }
470 } else {
471 $prefixed_column = sprintf( 'stream_%s', $column );
472 $all_records = WP_Stream_Connectors::$term_labels[ $prefixed_column ];
473 }
474
475 $query_meta = WP_Stream::$db->get_query_meta();
476
477 $values = array();
478 $existing_records = array();
479
480 if ( isset( $query_meta->aggregations->$column->buckets ) ) {
481 foreach ( $query_meta->aggregations->$column->buckets as $field ) {
482 $values[ $field->key ] = $field->key;
483 }
484
485 if ( ! empty( $values ) ) {
486 $existing_records = array_combine( $values, $values );
487 }
488 }
489
490 $active_records = array();
491 $disabled_records = array();
492
493 foreach ( $all_records as $record => $label ) {
494 if ( array_key_exists( $record, $existing_records ) ) {
495 $active_records[ $record ] = array( 'label' => $label, 'disabled' => '' );
496 } else {
497 $disabled_records[ $record ] = array( 'label' => $label, 'disabled' => 'disabled="disabled"' );
498 }
499 }
500
501 // Remove WP-CLI pseudo user if no records with user=0 exist
502 if ( isset( $disabled_records[0] ) ) {
503 unset( $disabled_records[0] );
504 }
505
506 $sort = function ( $a, $b ) use ( $column ) {
507 $label_a = (string) $a['label'];
508 $label_b = (string) $b['label'];
509
510 if ( $label_a === $label_b ) {
511 return 0;
512 }
513
514 return ( strtolower( $label_a ) < strtolower( $label_b ) ) ? -1 : 1;
515 };
516
517 uasort( $active_records, $sort );
518 uasort( $disabled_records, $sort );
519
520 // Not using array_merge() in order to preserve the array index for the Authors dropdown which uses the user_id as the key
521 $all_records = $active_records + $disabled_records;
522
523 return $all_records;
524 }
525
526 public function get_filters() {
527 $filters = array();
528
529 $date_interval = new WP_Stream_Date_Interval();
530
531 $filters['date'] = array(
532 'title' => __( 'dates', 'stream' ),
533 'items' => $date_interval->intervals,
534 );
535
536 $authors_records = WP_Stream_Admin::get_authors_record_meta(
537 $this->assemble_records( 'author' )
538 );
539
540 $filters['author'] = array(
541 'title' => __( 'authors', 'stream' ),
542 'items' => $authors_records,
543 'ajax' => count( $authors_records ) <= 0,
544 );
545
546 $filters['context'] = array(
547 'title' => __( 'contexts', 'stream' ),
548 'items' => $this->assemble_records( 'context' ),
549 );
550
551 $filters['action'] = array(
552 'title' => __( 'actions', 'stream' ),
553 'items' => $this->assemble_records( 'action' ),
554 );
555
556 /**
557 * Filter allows additional filters in the list table dropdowns
558 * Note the format of the filters above, with they key and array
559 * containing a title and array of items.
560 *
561 * @param array Array of filters
562 *
563 * @return array Updated array of filters
564 */
565
566 return apply_filters( 'wp_stream_list_table_filters', $filters );
567 }
568
569 function filters_form() {
570 $user_id = get_current_user_id();
571 $filters = $this->get_filters();
572
573 $filters_string = sprintf( '<input type="hidden" name="page" value="%s" />', 'wp_stream' );
574 $filters_string .= sprintf( '<span class="filter_info hidden">%s</span>', esc_html__( 'Show filter controls via the screen options tab above.', 'stream' ) );
575
576 foreach ( $filters as $name => $data ) {
577 if ( 'date' === $name ) {
578 $filters_string .= $this->filter_date( $data['items'] );
579 } else {
580 if ( 'context' === $name ) {
581 // Add Connectors as parents, and apply the Contexts as children
582 $connectors = $this->assemble_records( 'connector' );
583
584 foreach ( $connectors as $connector => $item ) {
585 $context_items[ $connector ]['label'] = $item['label'];
586
587 foreach ( $data['items'] as $context_value => $context_item ) {
588 if ( isset( WP_Stream_Connectors::$contexts[ $connector ] ) && array_key_exists( $context_value, WP_Stream_Connectors::$contexts[ $connector ] ) ) {
589 $context_items[ $connector ]['children'][ $context_value ] = $context_item;
590 }
591 }
592 }
593
594 foreach ( $context_items as $context_value => $context_item ) {
595 if ( ! isset( $context_item['children'] ) || empty( $context_item['children'] ) ) {
596 unset( $context_items[ $context_value ] );
597 }
598 }
599
600 $data['items'] = $context_items;
601
602 ksort( $data['items'] );
603
604 // Ouput a hidden input to handle the connector value
605 $filters_string .= '<input type="hidden" name="connector" class="record-filter-connector" />';
606 }
607 $filters_string .= $this->filter_select( $name, $data['title'], $data['items'] );
608 }
609 }
610
611 $filters_string .= sprintf( '<input type="submit" id="record-query-submit" class="button" value="%s" />', __( 'Filter', 'stream' ) );
612
613 $url = self_admin_url( WP_Stream_Admin::ADMIN_PARENT_PAGE );
614
615 return sprintf( '<div class="alignleft actions">%s</div>', $filters_string ); // xss ok
616 }
617
618 function filter_select( $name, $title, $items, $ajax = false ) {
619 if ( $ajax ) {
620 $out = sprintf(
621 '<input type="hidden" name="%s" class="chosen-select" value="%s" data-placeholder="%s" />',
622 esc_attr( $name ),
623 esc_attr( wp_stream_filter_input( INPUT_GET, $name ) ),
624 esc_attr( $title )
625 );
626 } else {
627 $options = array( '<option value=""></option>' );
628 $selected = wp_stream_filter_input( INPUT_GET, $name );
629
630 foreach ( $items as $key => $item ) {
631 $value = isset( $item['children'] ) ? 'group-' . $key : $key;
632 $option_args = array(
633 'value' => $value,
634 'selected' => selected( $value, $selected, false ),
635 'disabled' => isset( $item['disabled'] ) ? $item['disabled'] : null,
636 'icon' => isset( $item['icon'] ) ? $item['icon'] : null,
637 'group' => isset( $item['children'] ) ? $key : null,
638 'tooltip' => isset( $item['tooltip'] ) ? $item['tooltip'] : null,
639 'class' => isset( $item['children'] ) ? 'level-1' : null,
640 'label' => isset( $item['label'] ) ? $item['label'] : null,
641 );
642 $options[] = $this->filter_option( $option_args );
643
644 if ( isset( $item['children'] ) ) {
645 foreach ( $item['children'] as $child_value => $child_item ) {
646 $option_args = array(
647 'value' => $child_value,
648 'selected' => selected( $child_value, $selected, false ),
649 'disabled' => isset( $child_item['disabled'] ) ? $child_item['disabled'] : null,
650 'icon' => isset( $child_item['icon'] ) ? $child_item['icon'] : null,
651 'group' => $key,
652 'tooltip' => isset( $child_item['tooltip'] ) ? $child_item['tooltip'] : null,
653 'class' => 'level-2',
654 'label' => isset( $child_item['label'] ) ? '- ' . $child_item['label'] : null,
655 );
656 $options[] = $this->filter_option( $option_args );
657 }
658 }
659 }
660 $out = sprintf(
661 '<select name="%s" class="chosen-select" data-placeholder="%s">%s</select>',
662 esc_attr( $name ),
663 sprintf( esc_attr__( 'Show all %s', 'stream' ), $title ),
664 implode( '', $options )
665 );
666 }
667
668 return $out;
669 }
670
671 function filter_option( $args ) {
672 $defaults = array(
673 'value' => null,
674 'selected' => null,
675 'disabled' => null,
676 'icon' => null,
677 'group' => null,
678 'tooltip' => null,
679 'class' => null,
680 'label' => null,
681 );
682 wp_parse_args( $args, $defaults );
683
684 return sprintf(
685 '<option value="%s" %s %s %s %s %s class="%s">%s</option>',
686 esc_attr( $args['value'] ),
687 $args['selected'],
688 $args['disabled'],
689 $args['icon'] ? sprintf( 'data-icon="%s"', esc_attr( $args['icon'] ) ) : null,
690 $args['group'] ? sprintf( 'data-group="%s"', esc_attr( $args['group'] ) ) : null,
691 $args['tooltip'] ? sprintf( 'title="%s"', esc_attr( $args['tooltip'] ) ) : null,
692 $args['class'] ? esc_attr( $args['class'] ) : null,
693 esc_html( $args['label'] )
694 );
695 }
696
697 function filter_search() {
698 $out = sprintf(
699 '<p class="search-box">
700 <label class="screen-reader-text" for="record-search-input">%1$s:</label>
701 <input type="search" id="record-search-input" name="search" value="%2$s" />
702 <input type="submit" name="" id="search-submit" class="button" value="%1$s" />
703 </p>',
704 esc_attr__( 'Search Records', 'stream' ),
705 isset( $_GET['search'] ) ? esc_attr( wp_unslash( $_GET['search'] ) ) : null
706 );
707
708 return $out;
709 }
710
711 function filter_date( $items ) {
712 wp_enqueue_style( 'jquery-ui' );
713 wp_enqueue_style( 'wp-stream-datepicker' );
714 wp_enqueue_script( 'jquery-ui-datepicker' );
715
716 $date_predefined = wp_stream_filter_input( INPUT_GET, 'date_predefined' );
717 $date_from = wp_stream_filter_input( INPUT_GET, 'date_from' );
718 $date_to = wp_stream_filter_input( INPUT_GET, 'date_to' );
719
720 ob_start();
721 ?>
722 <div class="date-interval">
723
724 <select class="field-predefined hide-if-no-js" name="date_predefined" data-placeholder="<?php _e( 'All Time', 'stream' ); ?>">
725 <option></option>
726 <option value="custom" <?php selected( 'custom' === $date_predefined ); ?>><?php esc_attr_e( 'Custom', 'stream' ) ?></option>
727 <?php
728 foreach ( $items as $key => $interval ) {
729 printf(
730 '<option value="%s" data-from="%s" data-to="%s" %s>%s</option>',
731 esc_attr( $key ),
732 esc_attr( $interval['start']->format( 'Y/m/d' ) ),
733 isset( $interval['end'] ) ? esc_attr( $interval['end']->format( 'Y/m/d' ) ) : '',
734 selected( $key === $date_predefined ),
735 esc_html( $interval['label'] )
736 ); // xss ok
737 }
738 ?>
739 </select>
740
741 <div class="date-inputs">
742 <div class="box">
743 <i class="date-remove dashicons"></i>
744 <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 ) ?>" />
745 </div>
746 <span class="connector dashicons"></span>
747
748 <div class="box">
749 <i class="date-remove dashicons"></i>
750 <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 ) ?>" />
751 </div>
752 </div>
753
754 </div>
755 <?php
756
757 return ob_get_clean();
758 }
759
760 function display() {
761 $url = self_admin_url( WP_Stream_Admin::ADMIN_PARENT_PAGE );
762
763 echo '<form method="get" action="' . esc_url( $url ) . '" id="record-filter-form">';
764 echo $this->filter_search(); // xss ok
765
766 parent::display();
767 echo '</form>';
768 }
769
770 function display_tablenav( $which ) {
771 if ( 'top' === $which ) : ?>
772 <div class="tablenav <?php echo esc_attr( $which ); ?>">
773 <?php
774 $this->pagination( $which );
775 $this->extra_tablenav( $which );
776 ?>
777
778 <br class="clear" />
779 </div>
780 <?php else : ?>
781 <div class="tablenav <?php echo esc_attr( $which ); ?>">
782 <?php
783 /**
784 * Fires after the list table is displayed.
785 *
786 * @since 1.0.0
787 */
788 do_action( 'wp_stream_after_list_table' );
789 $this->pagination( $which );
790 $this->extra_tablenav( $which );
791 ?>
792
793 <br class="clear" />
794 </div>
795 <?php
796 endif;
797 }
798
799 static function set_screen_option( $dummy, $option, $value ) {
800 if ( 'edit_stream_per_page' === $option ) {
801 return $value;
802 } else {
803 return $dummy;
804 }
805 }
806
807 static function set_live_update_option( $dummy, $option, $value ) {
808 if ( WP_Stream_Live_Update::USER_META_KEY === $option ) {
809 $value = $_POST[ WP_Stream_Live_Update::USER_META_KEY ];
810 return $value;
811 } else {
812 return $dummy;
813 }
814 }
815
816 public function screen_controls( $status, $args ) {
817 $user_id = get_current_user_id();
818 $option = get_user_meta( $user_id, WP_Stream_Live_Update::USER_META_KEY, true );
819 $heartbeat = wp_script_is( 'heartbeat', 'done' ) ? 'true' : 'false';
820
821 if ( 'on' === $option && 'false' === $heartbeat ) {
822 $option = 'off';
823
824 update_user_meta( $user_id, WP_Stream_Live_Update::USER_META_KEY, 'off' );
825 }
826
827 $nonce = wp_create_nonce( WP_Stream_Live_Update::USER_META_KEY . '_nonce' );
828
829 ob_start();
830 ?>
831 <fieldset>
832 <h5><?php esc_html_e( 'Live updates', 'stream' ) ?></h5>
833
834 <div>
835 <input type="hidden" name="stream_live_update_nonce" id="stream_live_update_nonce" value="<?php echo esc_attr( $nonce ) ?>" />
836 </div>
837 <div>
838 <input type="hidden" name="enable_live_update_user" id="enable_live_update_user" value="<?php echo absint( $user_id ) ?>" />
839 </div>
840 <div class="metabox-prefs stream-live-update-checkbox">
841 <label for="enable_live_update">
842 <input type="checkbox" value="on" name="enable_live_update" id="enable_live_update" data-heartbeat="<?php echo esc_attr( $heartbeat ) ?>" <?php checked( $option, 'on' ) ?> />
843 <?php esc_html_e( 'Enabled', 'stream' ) ?><span class="spinner"></span>
844 </label>
845 </div>
846 </fieldset>
847 <?php
848 return ob_get_clean();
849 }
850
851 /**
852 * This function is use to map List table column name with excluded setting keys
853 *
854 * @param $column string list table column name
855 *
856 * @return string setting name for that column
857 */
858 function get_column_excluded_setting_key( $column ) {
859 switch ( $column ) {
860 case 'connector':
861 $output = 'connectors';
862 break;
863 case 'context':
864 $output = 'contexts';
865 break;
866 case 'action':
867 $output = 'action';
868 break;
869 case 'ip':
870 $output = 'ip_addresses';
871 break;
872 case 'author':
873 $output = 'authors';
874 break;
875 default:
876 $output = false;
877 }
878
879 return $output;
880 }
881 }
882