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-admin.php

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

1,295 lines 41.5 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_Admin {
4
5 /**
6 * Menu page screen id
7 *
8 * @var string
9 */
10 public static $screen_id = array();
11
12 /**
13 * List table object
14 *
15 * @var WP_Stream_List_Table
16 */
17 public static $list_table = null;
18
19 /**
20 * Option to disable access to Stream
21 *
22 * @var bool
23 */
24 public static $disable_access = false;
25
26 /**
27 * URL used for authenticating with Stream
28 *
29 * @var string
30 */
31 public static $connect_url;
32
33 const ADMIN_BODY_CLASS = 'wp_stream_screen';
34 const RECORDS_PAGE_SLUG = 'wp_stream';
35 const SETTINGS_PAGE_SLUG = 'wp_stream_settings';
36 const ACCOUNT_PAGE_SLUG = 'wp_stream_account';
37 const ADMIN_PARENT_PAGE = 'admin.php';
38 const VIEW_CAP = 'view_stream';
39 const SETTINGS_CAP = 'manage_options';
40 const UNREAD_COUNT_OPTION_KEY = 'stream_unread_count';
41 const LAST_READ_OPTION_KEY = 'stream_last_read';
42 const PRELOAD_AUTHORS_MAX = 50;
43 const PUBLIC_URL = 'https://wp-stream.com';
44
45 public static function load() {
46 // User and role caps
47 add_filter( 'user_has_cap', array( __CLASS__, '_filter_user_caps' ), 10, 4 );
48 add_filter( 'role_has_cap', array( __CLASS__, '_filter_role_caps' ), 10, 3 );
49
50 $home_url = str_ireplace( array( 'http://', 'https://' ), '', home_url() );
51 $connect_nonce = wp_create_nonce( 'stream_connect_site-' . sanitize_key( $home_url ) );
52
53 self::$connect_url = add_query_arg(
54 array(
55 'auth' => 'true',
56 'action' => 'connect',
57 'home_url' => urlencode( $home_url ),
58 'plugin_url' => urlencode(
59 add_query_arg(
60 array(
61 'page' => self::RECORDS_PAGE_SLUG,
62 'nonce' => $connect_nonce,
63 ),
64 admin_url( self::ADMIN_PARENT_PAGE )
65 )
66 ),
67 ),
68 esc_url_raw( untrailingslashit( self::PUBLIC_URL ) . '/pricing/' )
69 );
70
71 $api_key = wp_stream_filter_input( INPUT_GET, 'api_key' );
72 $site_uuid = wp_stream_filter_input( INPUT_GET, 'site_uuid' );
73
74 // Connect
75 if ( ! empty( $api_key ) && ! empty( $site_uuid ) ) {
76 add_action( 'admin_init', array( __CLASS__, 'save_api_authentication' ) );
77 }
78
79 // Disconnect
80 if ( self::ACCOUNT_PAGE_SLUG === wp_stream_filter_input( INPUT_GET, 'page' ) && '1' === wp_stream_filter_input( INPUT_GET, 'disconnect' ) ) {
81 add_action( 'admin_init', array( __CLASS__, 'remove_api_authentication' ) );
82 }
83
84 self::$disable_access = apply_filters( 'wp_stream_disable_admin_access', false );
85
86 // Register settings page
87 if ( ! self::$disable_access ) {
88 add_action( 'admin_menu', array( __CLASS__, 'register_menu' ) );
89 }
90
91 // Admin notices
92 add_action( 'admin_notices', array( __CLASS__, 'admin_notices' ) );
93
94 // Show connect notice on dashboard and plugins pages
95 add_action( 'load-index.php', array( __CLASS__, 'prepare_connect_notice' ) );
96 add_action( 'load-plugins.php', array( __CLASS__, 'prepare_connect_notice' ) );
97
98 // Add admin body class
99 add_filter( 'admin_body_class', array( __CLASS__, 'admin_body_class' ) );
100
101 // Plugin action links
102 add_filter( 'plugin_action_links', array( __CLASS__, 'plugin_action_links' ), 10, 2 );
103
104 // Load admin scripts and styles
105 add_action( 'admin_enqueue_scripts', array( __CLASS__, 'admin_enqueue_scripts' ) );
106 add_action( 'admin_enqueue_scripts', array( __CLASS__, 'admin_menu_css' ) );
107
108 // Catch list table results
109 add_filter( 'wp_stream_query_results', array( __CLASS__, 'mark_as_read' ), 10, 3 );
110
111 // Add user option for enabling unread counts
112 add_action( 'show_user_profile', array( __CLASS__, 'unread_count_user_option' ) );
113 add_action( 'edit_user_profile', array( __CLASS__, 'unread_count_user_option' ) );
114
115 // Save unread counts user option
116 add_action( 'personal_options_update', array( __CLASS__, 'save_unread_count_user_option' ) );
117 add_action( 'edit_user_profile_update', array( __CLASS__, 'save_unread_count_user_option' ) );
118
119 // Delete user-specific transient when user is deleted
120 add_action( 'delete_user', array( __CLASS__, 'delete_unread_count_transient' ), 10, 1 );
121
122 // Reset Streams settings
123 add_action( 'wp_ajax_wp_stream_defaults', array( __CLASS__, 'wp_ajax_defaults' ) );
124
125 // Ajax authors list
126 add_action( 'wp_ajax_wp_stream_filters', array( __CLASS__, 'ajax_filters' ) );
127
128 // Ajax author's name by ID
129 add_action( 'wp_ajax_wp_stream_get_filter_value_by_id', array( __CLASS__, 'get_filter_value_by_id' ) );
130 }
131
132 /**
133 * Prepare the Connect to Stream prompt
134 *
135 * @return void
136 */
137 public static function prepare_connect_notice() {
138 if ( ! WP_Stream::is_connected() && ! WP_Stream::is_development_mode() ) {
139 wp_enqueue_style( 'wp-stream-connect', WP_STREAM_URL . 'ui/css/connect.css', array(), WP_Stream::VERSION );
140 wp_enqueue_script( 'wp-stream-connect', WP_STREAM_URL . 'ui/js/connect.js', array(), WP_Stream::VERSION );
141 add_action( 'admin_notices', array( __CLASS__, 'admin_connect_notice' ) );
142 }
143 }
144
145 /**
146 * Prompt the user to connect to Stream
147 *
148 * @return void
149 */
150 public static function admin_connect_notice() {
151 if ( ! current_user_can( self::SETTINGS_CAP ) ) {
152 return;
153 }
154
155 $dismiss_and_deactivate_url = wp_nonce_url( 'plugins.php?action=deactivate&plugin=' . WP_STREAM_PLUGIN, 'deactivate-plugin_' . WP_STREAM_PLUGIN );
156 ?>
157 <div id="stream-message" class="updated stream-connect" style="display:block !important;">
158
159 <div class="stream-message-container">
160
161 <div class="stream-button-container">
162 <a href="<?php echo esc_url( self::$connect_url ) ?>" class="stream-button"><i class="stream-icon"></i><?php _e( 'Connect to Stream', 'stream' ) ?></a>
163 </div>
164
165 <div class="stream-message-text">
166 <h4><?php esc_html_e( 'Stream is almost ready!', 'stream' ) ?></h4>
167 <p>
168 <?php
169 $tooltip = sprintf(
170 esc_html__( 'Stream only uses your WordPress.com ID during sign up to authorize your account. You can sign up for free at %swordpress.com/signup%s.', 'stream' ),
171 '<a href="https://signup.wordpress.com/signup/?user=1" target="_blank">',
172 '</a>'
173 );
174 echo wp_kses_post(
175 sprintf(
176 esc_html__( 'Connect to Stream with your %sWordPress.com ID%s to see every change made to your site in beautifully organized detail.', 'stream' ),
177 '<span class="wp-stream-tooltip-text">',
178 '</span><span class="wp-stream-tooltip">' . $tooltip . '</span>' // xss ok
179 )
180 );
181 ?>
182 </p>
183 </div>
184
185 <div class="clear"></div>
186
187 </div>
188
189 </div>
190 <?php
191 }
192
193 /**
194 * Output specific update
195 *
196 * @action admin_notices
197 * @return string
198 */
199 public static function admin_notices() {
200 $message = wp_stream_filter_input( INPUT_GET, 'message' );
201 $notice = false;
202
203 switch ( $message ) {
204 case 'settings_reset':
205 $notice = esc_html__( 'All site settings have been successfully reset.', 'stream' );
206 break;
207 case 'connected':
208 if ( ! WP_Stream_Migrate::show_migrate_notice() ) {
209 $notice = sprintf(
210 '<strong>%s</strong></p><p>%s',
211 esc_html__( 'You have successfully connected to Stream!', 'stream' ),
212 esc_html__( 'Check back here regularly to see a history of the changes being made to this site.', 'stream' )
213 );
214 }
215 break;
216 }
217
218 if ( $notice ) {
219 WP_Stream::notice( $notice, false );
220 }
221 }
222
223 /**
224 * Return URL used for account level actions
225 *
226 * @return string
227 */
228 public static function account_url( $path = '' ) {
229 $account_url = add_query_arg(
230 array(
231 'auth' => 'true',
232 'plugin_url' => urlencode(
233 add_query_arg(
234 array(
235 'page' => self::RECORDS_PAGE_SLUG,
236 ),
237 admin_url( self::ADMIN_PARENT_PAGE )
238 )
239 ),
240 ),
241 esc_url_raw( sprintf( '%s/dashboard/%s', untrailingslashit( self::PUBLIC_URL ), untrailingslashit( $path ) ) )
242 );
243
244 return $account_url;
245 }
246
247 /**
248 * Register menu page
249 *
250 * @action admin_menu
251 * @return bool|void
252 */
253 public static function register_menu() {
254 if ( WP_Stream::is_connected() || WP_Stream::is_development_mode() ) {
255 $unread_count = self::get_unread_count();
256 $menu_title = __( 'Stream', 'stream' );
257
258 if ( self::unread_enabled_for_user() && ! empty( $unread_count ) ) {
259 $formatted_count = ( $unread_count > 99 ) ? __( '99 +', 'stream' ) : absint( $unread_count );
260 $menu_title = sprintf( '%s <span class="update-plugins count-%d"><span class="plugin-count">%s</span></span>', esc_html( $menu_title ), absint( $unread_count ), esc_html( $formatted_count ) );
261 }
262
263 self::$screen_id['main'] = add_menu_page(
264 __( 'Stream', 'stream' ),
265 $menu_title,
266 self::VIEW_CAP,
267 self::RECORDS_PAGE_SLUG,
268 array( __CLASS__, 'render_stream_page' ),
269 'div',
270 apply_filters( 'wp_stream_menu_position', '2.999999' ) // Using longtail decimal string to reduce the chance of position conflicts, see Codex
271 );
272
273 self::$screen_id['settings'] = add_submenu_page(
274 self::RECORDS_PAGE_SLUG,
275 __( 'Stream Settings', 'stream' ),
276 __( 'Settings', 'stream' ),
277 self::SETTINGS_CAP,
278 self::SETTINGS_PAGE_SLUG,
279 array( __CLASS__, 'render_settings_page' )
280 );
281
282 self::$screen_id['account'] = add_submenu_page(
283 self::RECORDS_PAGE_SLUG,
284 __( 'Stream Account', 'stream' ),
285 __( 'Account', 'stream' ),
286 self::SETTINGS_CAP,
287 self::ACCOUNT_PAGE_SLUG,
288 array( __CLASS__, 'render_account_page' )
289 );
290 } else {
291 self::$screen_id['connect'] = add_menu_page(
292 __( 'Connect to Stream', 'stream' ),
293 __( 'Stream', 'stream' ),
294 self::SETTINGS_CAP,
295 self::RECORDS_PAGE_SLUG,
296 array( __CLASS__, 'render_connect_page' ),
297 'div',
298 apply_filters( 'wp_stream_menu_position', '2.999999' ) // Using longtail decimal string to reduce the chance of position conflicts, see Codex
299 );
300 }
301
302 if ( isset( self::$screen_id['main'] ) ) {
303 /**
304 * Fires just before the Stream list table is registered.
305 *
306 * @since 1.4.0
307 *
308 * @return void
309 */
310 do_action( 'wp_stream_admin_menu_screens' );
311
312 // Register the list table early, so it associates the column headers with 'Screen settings'
313 add_action( 'load-' . self::$screen_id['main'], array( __CLASS__, 'register_list_table' ) );
314 }
315 }
316
317 /**
318 * Enqueue scripts/styles for admin screen
319 *
320 * @action admin_enqueue_scripts
321 *
322 * @param $hook
323 *
324 * @return void
325 */
326 public static function admin_enqueue_scripts( $hook ) {
327 wp_register_script( 'select2', WP_STREAM_URL . 'ui/lib/select2/select2.js', array( 'jquery' ), '3.5.2', true );
328 wp_register_style( 'select2', WP_STREAM_URL . 'ui/lib/select2/select2.css', array(), '3.5.2' );
329 wp_register_script( 'timeago', WP_STREAM_URL . 'ui/lib/timeago/jquery.timeago.js', array(), '1.4.1', true );
330
331 $locale = strtolower( substr( get_locale(), 0, 2 ) );
332 $file_tmpl = 'ui/lib/timeago/locales/jquery.timeago.%s.js';
333
334 if ( file_exists( WP_STREAM_DIR . sprintf( $file_tmpl, $locale ) ) ) {
335 wp_register_script( 'timeago-locale', WP_STREAM_URL . sprintf( $file_tmpl, $locale ), array( 'timeago' ), '1' );
336 } else {
337 wp_register_script( 'timeago-locale', WP_STREAM_URL . sprintf( $file_tmpl, 'en' ), array( 'timeago' ), '1' );
338 }
339
340 wp_enqueue_style( 'wp-stream-admin', WP_STREAM_URL . 'ui/css/admin.css', array(), WP_Stream::VERSION );
341
342 $script_screens = array( 'plugins.php', 'user-edit.php', 'user-new.php', 'profile.php' );
343
344 if ( 'index.php' === $hook ) {
345 wp_enqueue_script( 'wp-stream-dashboard', WP_STREAM_URL . 'ui/js/dashboard.js', array( 'jquery' ), WP_Stream::VERSION );
346 wp_enqueue_script( 'wp-stream-live-updates', WP_STREAM_URL . 'ui/js/live-updates.js', array( 'jquery', 'heartbeat' ), WP_Stream::VERSION );
347 } elseif ( in_array( $hook, self::$screen_id ) || in_array( $hook, $script_screens ) ) {
348 wp_enqueue_script( 'select2' );
349 wp_enqueue_style( 'select2' );
350
351 wp_enqueue_script( 'timeago' );
352 wp_enqueue_script( 'timeago-locale' );
353
354 wp_enqueue_script( 'wp-stream-admin', WP_STREAM_URL . 'ui/js/admin.js', array( 'jquery', 'select2' ), WP_Stream::VERSION );
355 wp_enqueue_script( 'wp-stream-live-updates', WP_STREAM_URL . 'ui/js/live-updates.js', array( 'jquery', 'heartbeat' ), WP_Stream::VERSION );
356
357 wp_localize_script(
358 'wp-stream-admin',
359 'wp_stream',
360 array(
361 'i18n' => array(
362 'confirm_defaults' => __( 'Are you sure you want to reset all site settings to default? This cannot be undone.', 'stream' ),
363 ),
364 'locale' => esc_js( $locale ),
365 'gmt_offset' => get_option( 'gmt_offset' ),
366 )
367 );
368 }
369
370 wp_localize_script(
371 'wp-stream-live-updates',
372 'wp_stream_live_updates',
373 array(
374 'current_screen' => $hook,
375 'current_page' => isset( $_GET['paged'] ) ? esc_js( $_GET['paged'] ) : '1',
376 'current_order' => isset( $_GET['order'] ) ? esc_js( $_GET['order'] ) : 'desc',
377 'current_query' => json_encode( $_GET ),
378 'current_query_count' => count( $_GET ),
379 )
380 );
381
382 if ( WP_Stream_Migrate::show_migrate_notice() ) {
383 $limit = absint( WP_Stream_Migrate::$limit );
384 $record_count = absint( WP_Stream_Migrate::$record_count );
385 $estimated_time = ( $limit < $record_count ) ? round( ( ( $record_count / $limit ) * ( 0.04 * $limit ) ) / 60 ) : 0;
386 $migrate_time_message = ( $estimated_time > 1 ) ? sprintf( __( 'This will take about %d minutes.', 'stream' ), absint( $estimated_time ) ) : __( 'This could take a few minutes.', 'stream' );
387 $delete_time_message = ( $estimated_time > 1 && is_multisite() ) ? sprintf( __( 'This will take about %d minutes.', 'stream' ), absint( $estimated_time ) ) : __( 'This could take a few minutes.', 'stream' );
388
389 wp_enqueue_script( 'wp-stream-migrate', WP_STREAM_URL . 'ui/js/migrate.js', array( 'jquery' ), WP_Stream::VERSION );
390 wp_localize_script(
391 'wp-stream-migrate',
392 'wp_stream_migrate',
393 array(
394 'i18n' => array(
395 'migrate_process_title' => __( 'Migrating Stream Records', 'stream' ),
396 'delete_process_title' => __( 'Deleting Stream Records', 'stream' ),
397 'error_message' => __( 'An unknown error occurred during migration. Please try again later or contact support.', 'stream' ),
398 'migrate_process_message' => __( 'Please do not exit this page until the process has completed.', 'stream' ) . ' ' . esc_html( $migrate_time_message ),
399 'delete_process_message' => __( 'Please do not exit this page until the process has completed.', 'stream' ) . ' ' . esc_html( $delete_time_message ),
400 'confirm_start_migrate' => ( $estimated_time > 1 ) ? sprintf( __( 'Please note: This process will take about %d minutes to complete.', 'stream' ), absint( $estimated_time ) ) : __( 'Please note: This process could take a few minutes to complete.', 'stream' ),
401 'confirm_migrate_reminder' => __( 'Please note: Your existing records will not appear in Stream until you have migrated them to your account.', 'stream' ),
402 'confirm_delete_records' => sprintf( __( 'Are you sure you want to delete all %s existing Stream records without migrating? This will take %s minutes and cannot be undone.', 'stream' ), number_format( WP_Stream_Migrate::$record_count ), ( $estimated_time > 1 && is_multisite() ) ? sprintf( __( 'about %d', 'stream' ), absint( $estimated_time ) ) : __( 'a few', 'stream' ) ),
403 ),
404 'chunk_size' => absint( $limit ),
405 'record_count' => absint( $record_count ),
406 'nonce' => wp_create_nonce( 'wp_stream_migrate-' . absint( get_current_blog_id() ) . absint( get_current_user_id() ) ),
407 )
408 );
409 }
410
411 /**
412 * The maximum number of items that can be updated in bulk without receiving a warning.
413 *
414 * Stream watches for bulk actions performed in the WordPress Admin (such as updating
415 * many posts at once) and warns the user before proceeding if the number of items they
416 * are attempting to update exceeds this threshold value. Since Stream will try to save
417 * a log for each item, it will take longer than usual to complete the operation.
418 *
419 * The default threshold is 100 items.
420 *
421 * @return int
422 */
423 $bulk_actions_threshold = apply_filters( 'wp_stream_bulk_actions_threshold', 100 );
424
425 wp_enqueue_script( 'wp-stream-global', WP_STREAM_URL . 'ui/js/global.js', array( 'jquery' ), WP_Stream::VERSION );
426 wp_localize_script(
427 'wp-stream-global',
428 'wp_stream_global',
429 array(
430 'bulk_actions' => array(
431 'i18n' => array(
432 'confirm_action' => sprintf( __( 'Are you sure you want to perform bulk actions on over %s items? This process could take a while to complete.', 'stream' ), number_format( absint( $bulk_actions_threshold ) ) ),
433 'confirm_import' => __( 'The Stream plugin must be deactivated before you can bulk import content into WordPress.', 'stream' ),
434 ),
435 'threshold' => absint( $bulk_actions_threshold ),
436 ),
437 'plugins_screen_url' => self_admin_url( 'plugins.php#stream' ),
438 )
439 );
440 }
441
442 /**
443 * Check whether or not the current admin screen belongs to Stream
444 *
445 * @return bool
446 */
447 public static function is_stream_screen() {
448 global $typenow;
449
450 if ( is_admin() && ( false !== strpos( wp_stream_filter_input( INPUT_GET, 'page' ), self::RECORDS_PAGE_SLUG ) || WP_Stream_Notifications_Post_Type::POSTTYPE === $typenow ) ) {
451 return true;
452 }
453
454 return false;
455 }
456
457 /**
458 * Add a specific body class to all Stream admin screens
459 *
460 * @filter admin_body_class
461 *
462 * @param string $classes
463 *
464 * @return string $classes
465 */
466 public static function admin_body_class( $classes ) {
467 if ( self::is_stream_screen() ) {
468 $classes .= sprintf( ' %s ', self::ADMIN_BODY_CLASS );
469
470 if ( WP_Stream::is_connected() || WP_Stream::is_development_mode() ) {
471 $classes .= ' wp_stream_connected ';
472 } else {
473 $classes .= ' wp_stream_disconnected ';
474 }
475
476 if ( WP_Stream_API::is_restricted() ) {
477 $classes .= ' wp_stream_restricted ';
478 }
479 }
480
481 $settings_pages = array( self::SETTINGS_PAGE_SLUG );
482
483 if ( isset( $_GET['page'] ) && in_array( $_GET['page'], $settings_pages ) ) {
484 $classes .= sprintf( ' %s ', self::SETTINGS_PAGE_SLUG );
485 }
486
487 return $classes;
488 }
489
490 /**
491 * Add menu styles for various WP Admin skins
492 *
493 * @uses wp_add_inline_style()
494 * @action admin_enqueue_scripts
495 * @return bool true on success false on failure
496 */
497 public static function admin_menu_css() {
498 wp_register_style( 'jquery-ui', '//ajax.googleapis.com/ajax/libs/jqueryui/1.10.1/themes/base/jquery-ui.css', array(), '1.10.1' );
499 wp_register_style( 'wp-stream-datepicker', WP_STREAM_URL . 'ui/css/datepicker.css', array( 'jquery-ui' ), WP_Stream::VERSION );
500 wp_register_style( 'wp-stream-icons', WP_STREAM_URL . 'ui/stream-icons/style.css', array(), WP_Stream::VERSION );
501
502 // Make sure we're working off a clean version
503 include( ABSPATH . WPINC . '/version.php' );
504
505 $body_class = self::ADMIN_BODY_CLASS;
506 $records_page = self::RECORDS_PAGE_SLUG;
507 $stream_url = WP_STREAM_URL;
508
509 if ( version_compare( $wp_version, '3.8-alpha', '>=' ) ) {
510 wp_enqueue_style( 'wp-stream-icons' );
511 $css = "
512 #toplevel_page_{$records_page} .wp-menu-image:before {
513 font-family: 'WP Stream' !important;
514 content: '\\73' !important;
515 }
516 #toplevel_page_{$records_page} .wp-menu-image {
517 background-repeat: no-repeat;
518 }
519 #menu-posts-feedback .wp-menu-image:before {
520 font-family: dashicons !important;
521 content: '\\f175';
522 }
523 #adminmenu #menu-posts-feedback div.wp-menu-image {
524 background: none !important;
525 background-repeat: no-repeat;
526 }
527 body.{$body_class} #wpbody-content .wrap h2:nth-child(1):before {
528 font-family: 'WP Stream' !important;
529 content: '\\73';
530 padding: 0 8px 0 0;
531 }
532 ";
533 } else {
534 $css = "
535 #toplevel_page_{$records_page} .wp-menu-image {
536 background: url( {$stream_url}ui/stream-icons/menuicon-sprite.png ) 0 90% no-repeat;
537 }
538 /* Retina Stream Menu Icon */
539 @media only screen and (-moz-min-device-pixel-ratio: 1.5),
540 only screen and (-o-min-device-pixel-ratio: 3/2),
541 only screen and (-webkit-min-device-pixel-ratio: 1.5),
542 only screen and (min-device-pixel-ratio: 1.5) {
543 #toplevel_page_{$records_page} .wp-menu-image {
544 background: url( {$stream_url}ui/stream-icons/menuicon-sprite-2x.png ) 0 90% no-repeat;
545 background-size:30px 64px;
546 }
547 }
548 #toplevel_page_{$records_page}.current .wp-menu-image,
549 #toplevel_page_{$records_page}.wp-has-current-submenu .wp-menu-image,
550 #toplevel_page_{$records_page}:hover .wp-menu-image {
551 background-position: top left;
552 }
553 ";
554 }
555
556 wp_add_inline_style( 'wp-admin', $css );
557 }
558
559 /**
560 * Check whether or not the current user should see the unread counter.
561 *
562 * Defaults to TRUE if user option does not exist.
563 *
564 * @param int $user_id (optional)
565 *
566 * @return bool
567 */
568 public static function unread_enabled_for_user( $user_id = 0 ) {
569 $user_id = empty( $user_id ) ? get_current_user_id() : $user_id;
570 $enabled = get_user_meta( $user_id, self::UNREAD_COUNT_OPTION_KEY, true );
571 $enabled = ( 'off' !== $enabled );
572
573 return (bool) $enabled;
574 }
575
576 /**
577 * Get the unread count for the current user.
578 *
579 * Results are cached in transient with a 5 min TTL.
580 *
581 * @return int
582 */
583 public static function get_unread_count() {
584 if ( ! self::unread_enabled_for_user() ) {
585 return false;
586 }
587
588 $user_id = get_current_user_id();
589 $cache_key = sprintf( '%s_%d', self::UNREAD_COUNT_OPTION_KEY, $user_id );
590
591 if ( false === ( $count = get_transient( $cache_key ) ) ) {
592 $count = 0;
593 $last_read = get_user_meta( $user_id, self::LAST_READ_OPTION_KEY, true );
594
595 if ( ! empty( $last_read ) ) {
596 $args = array(
597 'records_per_page' => 101,
598 'author__not_in' => array( $user_id ), // Ignore changes authored by the current user
599 'date_after' => date( 'c', strtotime( $last_read . ' + 1 second' ) ), // Bump time to bypass gte issue
600 'fields' => array( 'created' ), // We don't need the entire record
601 );
602
603 $unread_records = wp_stream_query( $args );
604
605 $count = empty( $unread_records ) ? 0 : count( $unread_records );
606 }
607
608 set_transient( $cache_key, $count, 5 * 60 ); // TTL 5 min
609 }
610
611 return absint( $count );
612 }
613
614 /**
615 * Mark records as read based on Records screen results
616 *
617 * @filter wp_stream_query_results
618 *
619 * @param array $results
620 * @param array $query
621 * @param array $fields
622 *
623 * @return array
624 */
625 public static function mark_as_read( $results, $query, $fields ) {
626 if ( ! is_admin() ) {
627 return $results;
628 }
629
630 $screen = get_current_screen();
631 $is_list_table = ( isset( $screen->id ) && sprintf( 'toplevel_page_%s', self::RECORDS_PAGE_SLUG ) === $screen->id );
632 $is_first_page = empty( $query['from'] );
633 $is_date_desc = ( isset( $query['sort'][0]['created']['order'] ) && 'desc' === $query['sort'][0]['created']['order'] );
634
635 if ( $is_list_table && $is_first_page && $is_date_desc ) {
636 $user_id = get_current_user_id();
637 $cache_key = sprintf( '%s_%d', self::UNREAD_COUNT_OPTION_KEY, $user_id );
638
639 if ( self::unread_enabled_for_user() && isset( $results[0]->created ) ) {
640 update_user_meta( $user_id, self::LAST_READ_OPTION_KEY, date( 'c', strtotime( $results[0]->created ) ) );
641 }
642
643 set_transient( $cache_key, 0 ); // No expiration
644 }
645
646 return $results;
647 }
648
649 /**
650 * Output for Stream Unread Count field in user profiles.
651 *
652 * @action show_user_profile
653 * @action edit_user_profile
654 *
655 * @param WP_User $user
656 *
657 * @return void
658 */
659 public static function unread_count_user_option( $user ) {
660 if ( ! array_intersect( $user->roles, WP_Stream_Settings::$options['general_role_access'] ) ) {
661 return;
662 }
663
664 $unread_enabled = self::unread_enabled_for_user();
665 ?>
666 <table class="form-table">
667 <tr>
668 <th scope="row">
669 <label for="<?php echo esc_attr( self::UNREAD_COUNT_OPTION_KEY ) ?>">
670 <?php esc_html_e( 'Stream Unread Count', 'stream' ) ?>
671 </label>
672 </th>
673 <td>
674 <label for="<?php echo esc_attr( self::UNREAD_COUNT_OPTION_KEY ) ?>">
675 <input type="checkbox" name="<?php echo esc_attr( self::UNREAD_COUNT_OPTION_KEY ) ?>" id="<?php echo esc_attr( self::UNREAD_COUNT_OPTION_KEY ) ?>" value="1" <?php checked( $unread_enabled ) ?>>
676 <?php esc_html_e( 'Enabled', 'stream' ) ?>
677 </label>
678 </td>
679 </tr>
680 </table>
681 <?php
682 }
683
684 /**
685 * Saves unread count user meta option in profiles.
686 *
687 * @action personal_options_update
688 * @action edit_user_profile_update
689 *
690 * @param $user_id
691 *
692 * @return void
693 */
694 public static function save_unread_count_user_option( $user_id ) {
695 $enabled = wp_stream_filter_input( INPUT_POST, self::UNREAD_COUNT_OPTION_KEY );
696 $enabled = ( '1' === $enabled ) ? 'on' : 'off';
697
698 update_user_meta( $user_id, self::UNREAD_COUNT_OPTION_KEY, $enabled );
699 }
700
701 /**
702 * Delete user-specific transient when a user is deleted
703 *
704 * @action delete_user
705 *
706 * @param int $user_id
707 *
708 * @return void
709 */
710 public static function delete_unread_count_transient( $user_id ) {
711 $cache_key = sprintf( '%s_%d', self::UNREAD_COUNT_OPTION_KEY, $user_id );
712
713 delete_transient( $cache_key );
714 }
715
716 /**
717 * @filter plugin_action_links
718 */
719 public static function plugin_action_links( $links, $file ) {
720 if ( plugin_basename( WP_STREAM_DIR . 'stream.php' ) === $file ) {
721 $admin_page_url = add_query_arg( array( 'page' => self::SETTINGS_PAGE_SLUG ), admin_url( self::ADMIN_PARENT_PAGE ) );
722
723 $links[] = sprintf( '<a href="%s">%s</a>', esc_url( $admin_page_url ), esc_html__( 'Settings', 'stream' ) );
724 }
725
726 return $links;
727 }
728
729 public static function save_api_authentication() {
730 $home_url = str_ireplace( array( 'http://', 'https://' ), '', home_url() );
731 $connect_nonce_name = 'stream_connect_site-' . sanitize_key( $home_url );
732
733 if ( ! isset( $_GET['api_key'] ) || ! isset( $_GET['site_uuid'] ) ) {
734 wp_die( 'There was a problem connecting to Stream. Please try again later.', 'stream' );
735 }
736
737 if ( ! isset( $_GET['nonce'] ) || ! wp_verify_nonce( $_GET['nonce'], $connect_nonce_name ) ) {
738 wp_die( 'Doing it wrong.', 'stream' );
739 }
740
741 WP_Stream::$api->site_uuid = wp_stream_filter_input( INPUT_GET, 'site_uuid' );
742 WP_Stream::$api->api_key = wp_stream_filter_input( INPUT_GET, 'api_key' );
743
744 // Verify the API Key and Site UUID
745 $site = WP_Stream::$api->get_site();
746
747 WP_Stream_API::$restricted = ( ! isset( $site->plan->type ) || 'free' === $site->plan->type ) ? 1 : 0;
748
749 if ( ! isset( $site->site_id ) ) {
750 wp_die( 'There was a problem verifying your site with Stream. Please try again later.', 'stream' );
751 }
752
753 if ( ! WP_Stream_API::$restricted ) {
754 WP_Stream_Notifications::$instance->on_activation();
755 }
756
757 update_option( WP_Stream_API::SITE_UUID_OPTION_KEY, WP_Stream::$api->site_uuid );
758 update_option( WP_Stream_API::API_KEY_OPTION_KEY, WP_Stream::$api->api_key );
759 update_option( WP_Stream_API::RESTRICTED_OPTION_KEY, WP_Stream_API::$restricted );
760
761 do_action( 'wp_stream_site_connected', WP_Stream::$api->site_uuid, WP_Stream::$api->api_key, get_current_blog_id() );
762
763 $redirect_url = add_query_arg(
764 array(
765 'page' => self::RECORDS_PAGE_SLUG,
766 'message' => 'connected',
767 ),
768 admin_url( self::ADMIN_PARENT_PAGE )
769 );
770
771 wp_redirect( $redirect_url );
772 exit;
773 }
774
775 public static function remove_api_authentication() {
776 delete_option( WP_Stream_API::SITE_UUID_OPTION_KEY );
777 delete_option( WP_Stream_API::API_KEY_OPTION_KEY );
778
779 do_action( 'wp_stream_site_disconnected', WP_Stream::$api->site_uuid, WP_Stream::$api->api_key, get_current_blog_id() );
780
781 WP_Stream::$api->site_uuid = false;
782 WP_Stream::$api->api_key = false;
783
784 if ( '1' !== wp_stream_filter_input( INPUT_GET, 'disconnect' ) ) {
785 return;
786 }
787
788 $redirect_url = add_query_arg(
789 array(
790 'page' => self::RECORDS_PAGE_SLUG,
791 ),
792 admin_url( self::ADMIN_PARENT_PAGE )
793 );
794
795 wp_redirect( $redirect_url );
796 exit;
797 }
798
799 public static function get_testimonials() {
800 $testimonials = get_site_transient( 'wp_stream_testimonials' );
801
802 if ( false !== $testimonials ) {
803 return $testimonials;
804 }
805
806 $url = sprintf( '%s/wp-content/themes/wp-stream.com/assets/testimonials.json', untrailingslashit( self::PUBLIC_URL ) );
807 $request = wp_remote_request( esc_url_raw( $url ), array( 'sslverify' => false ) );
808
809 if ( ! is_wp_error( $request ) && $request['response']['code'] === 200 ) {
810 $testimonials = json_decode( $request['body'], true );
811 } else {
812 $testimonials = false;
813 }
814
815 // Cache failed attempts as zero, to distinguish them from expired transients
816 if ( ! $testimonials ) {
817 $testimonials = 0;
818 }
819
820 set_site_transient( 'wp_stream_testimonials', $testimonials, WEEK_IN_SECONDS );
821
822 return $testimonials;
823 }
824
825 /**
826 * Render settings page
827 *
828 * @return void
829 */
830 public static function render_settings_page() {
831
832 $option_key = WP_Stream_Settings::$option_key;
833 $form_action = apply_filters( 'wp_stream_settings_form_action', admin_url( 'options.php' ) );
834
835 $page_title = apply_filters( 'wp_stream_settings_form_title', get_admin_page_title() );
836 $page_description = apply_filters( 'wp_stream_settings_form_description', '' );
837
838 $sections = WP_Stream_Settings::get_fields();
839 $active_tab = wp_stream_filter_input( INPUT_GET, 'tab' );
840
841 wp_enqueue_script(
842 'stream-settings',
843 plugins_url( '../ui/js/settings.js', __FILE__ ),
844 array( 'jquery' ),
845 WP_Stream::VERSION,
846 true
847 );
848 ?>
849 <div class="wrap">
850 <h2><?php echo esc_html( $page_title ) ?></h2>
851
852 <?php if ( ! empty( $page_description ) ) : ?>
853 <p><?php echo esc_html( $page_description ) ?></p>
854 <?php endif; ?>
855
856 <?php settings_errors() ?>
857
858 <?php if ( count( $sections ) > 1 ) : ?>
859 <h2 class="nav-tab-wrapper">
860 <?php $i = 0 ?>
861 <?php foreach ( $sections as $section => $data ) : ?>
862 <?php $i ++ ?>
863 <?php $is_active = ( ( 1 === $i && ! $active_tab ) || $active_tab === $section ) ?>
864 <a href="<?php echo esc_url( add_query_arg( 'tab', $section ) ) ?>" class="nav-tab<?php if ( $is_active ) { echo esc_attr( ' nav-tab-active' ); } ?>">
865 <?php echo esc_html( $data['title'] ) ?>
866 </a>
867 <?php endforeach; ?>
868 </h2>
869 <?php endif; ?>
870
871 <div class="nav-tab-content" id="tab-content-settings">
872 <form method="post" action="<?php echo esc_attr( $form_action ) ?>" enctype="multipart/form-data">
873 <div class="settings-sections">
874 <?php
875 $i = 0;
876 foreach ( $sections as $section => $data ) {
877 $i++;
878 $is_active = ( ( 1 === $i && ! $active_tab ) || $active_tab === $section );
879 if ( $is_active ) {
880 settings_fields( $option_key );
881 do_settings_sections( $option_key );
882 }
883 }
884 ?>
885 </div>
886 <?php submit_button() ?>
887 </form>
888 </div>
889 </div>
890 <?php
891 }
892
893 /**
894 * Render account page
895 *
896 * @return void
897 */
898 public static function render_account_page() {
899 $page_title = apply_filters( 'wp_stream_account_page_title', get_admin_page_title() );
900 $date_format = get_option( 'date_format' );
901 $site_details = WP_Stream::$api->get_site();
902 ?>
903 <div class="wrap">
904 <h2><?php echo esc_html( $page_title ) ?></h2>
905 <div class="postbox">
906 <?php
907 if ( ! $site_details ) {
908 ?>
909 <h3><?php esc_html_e( 'Error retrieving account details.' ); ?></h3>
910 <div class="plan-details">
911 <p><?php esc_html_e( 'If this problem persists, please disconnect from Stream and try connecting again.', 'stream' ); ?></p>
912 </div>
913 <div class="plan-actions submitbox">
914 <a class="submitdelete disconnect" href="<?php echo esc_url( add_query_arg( 'disconnect', '1' ) ); ?>">Disconnect</a>
915 </div>
916 <?php
917 } else {
918 $plan_label = __( 'Free', 'stream' );
919
920 if ( isset( $site_details->plan ) ) {
921 if ( 0 === strpos( $site_details->plan->type, 'pro' ) ) {
922 $plan_label = __( 'Pro', 'stream' );
923 } elseif ( 0 === strpos( $site_details->plan->type, 'standard' ) ) {
924 $plan_label = __( 'Standard', 'stream' );
925 }
926 }
927
928 if ( 'free' !== $site_details->plan->type ) {
929 $next_billing_label = sprintf(
930 _x( '$%1$s on %2$s', '1: Price, 2: Renewal date', 'stream' ),
931 isset( $site_details->plan->amount ) ? $site_details->plan->amount : 0,
932 isset( $site_details->expiry->date ) ? date_i18n( $date_format, strtotime( $site_details->expiry->date ) ) : __( 'N/A', 'stream' )
933 );
934 }
935
936 $retention_label = '';
937
938 if ( 0 == $site_details->plan->retention ) { // Loose comparison needed
939 $retention_label = __( 'Unlimited', 'stream' );
940 } else {
941 $retention_label = sprintf(
942 _n( '1 Day', '%s Days', $site_details->plan->retention, 'stream' ),
943 $site_details->plan->retention
944 );
945 }
946 ?>
947 <h3><?php echo esc_html( $site_details->site_url ); ?></h3>
948 <div class="plan-details">
949 <table class="form-table">
950 <tbody>
951 <tr>
952 <th><?php _e( 'Plan', 'stream' ); ?></th>
953 <td><?php echo esc_html( $plan_label ); ?></td>
954 </tr>
955 <tr>
956 <th><?php _e( 'Activity History', 'stream' ); ?></th>
957 <td><?php echo esc_html( $retention_label ); ?></td>
958 </tr>
959 <?php if ( 'free' !== $site_details->plan->type ) : ?>
960 <tr>
961 <th><?php _e( 'Next Billing', 'stream' ); ?></th>
962 <td><?php echo esc_html( $next_billing_label ); ?></td>
963 </tr>
964 <?php endif; ?>
965 <tr>
966 <th><?php _e( 'Created', 'stream' ); ?></th>
967 <td><?php echo esc_html( date_i18n( $date_format, strtotime( $site_details->created ) ) ); ?></td>
968 </tr>
969 <tr>
970 <th><?php _e( 'Site ID', 'stream' ); ?></th>
971 <td>
972 <code class="site-uuid"><?php echo esc_html( WP_Stream::$api->site_uuid ); ?></code>
973 </td>
974 </tr>
975 <tr>
976 <th><?php _e( 'API Key', 'stream' ); ?></th>
977 <td>
978 <code class="api-key"><?php echo esc_html( WP_Stream::$api->api_key ); ?></code>
979 </td>
980 </tr>
981 </tbody>
982 </table>
983 </div>
984 <div class="plan-actions submitbox">
985 <?php if ( 'free' === $site_details->plan->type ) : ?>
986 <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>
987 <?php else : ?>
988 <a href="<?php echo esc_url( sprintf( '%s/dashboard/?site_uuid=%s', self::PUBLIC_URL, WP_Stream::$api->site_uuid ) ); ?>" class="button button-primary button-large" target="_blank"><?php _e( 'Modify This Plan', 'stream' ) ?></a>
989 <?php endif; ?>
990 <a class="submitdelete disconnect" href="<?php echo esc_url( add_query_arg( 'disconnect', '1' ) ); ?>">Disconnect</a>
991 </div>
992 <?php
993 }
994 ?>
995 </div>
996 </div>
997 <?php
998 }
999
1000 /**
1001 * Render connect page
1002 *
1003 * @return void
1004 */
1005 public static function render_connect_page() {
1006 $page_title = apply_filters( 'wp_stream_connect_page_title', get_admin_page_title() );
1007
1008 if ( $testimonials = self::get_testimonials() ) {
1009 $testimonial = $testimonials[ array_rand( $testimonials ) ];
1010 }
1011
1012 wp_enqueue_style( 'wp-stream-connect', WP_STREAM_URL . 'ui/css/connect.css', array(), WP_Stream::VERSION );
1013 wp_enqueue_script( 'wp-stream-connect', WP_STREAM_URL . 'ui/js/connect.js', array(), WP_Stream::VERSION );
1014 ?>
1015 <div id="wp-stream-connect">
1016
1017 <div class="wrap">
1018
1019 <div class="stream-connect-container">
1020 <a href="<?php echo esc_url( self::$connect_url ) ?>" class="stream-button"><i class="stream-icon"></i><?php _e( 'Connect to Stream', 'stream' ) ?></a>
1021 <p>
1022 <?php
1023 $tooltip = sprintf(
1024 esc_html__( 'Stream only uses your WordPress.com ID during sign up to authorize your account. You can sign up for free at %swordpress.com/signup%s.', 'stream' ),
1025 '<a href="https://signup.wordpress.com/signup/?user=1" target="_blank">',
1026 '</a>'
1027 );
1028 wp_kses_post(
1029 printf(
1030 esc_html__( 'with your %sWordPress.com ID%s', 'stream' ),
1031 '<span class="wp-stream-tooltip-text">',
1032 '</span><span class="wp-stream-tooltip">' . $tooltip . '</span>' // xss ok
1033 )
1034 );
1035 ?>
1036 </p>
1037 </div>
1038
1039 <?php if ( isset( $testimonial ) ) : ?>
1040 <div class="stream-quotes-container">
1041 <p class="stream-quote">&ldquo;<?php echo esc_html( $testimonial['quote'] ) ?>&rdquo;</p>
1042 <p class="stream-quote-author">&dash; <?php echo esc_html( $testimonial['author'] ) ?>, <a class="stream-quote-organization" href="<?php echo esc_url( $testimonial['link'] ) ?>"><?php echo esc_html( $testimonial['organization'] ) ?></a></p>
1043 </div>
1044 <?php endif; ?>
1045
1046 <div class="stream-haiku">
1047 <p>
1048 <?php echo esc_html( _x( 'A transformation', 'Haiku line 1', 'stream' ) ) ?><br />
1049 <?php echo esc_html( _x( 'Like brook, to river, to sea', 'Haiku line 2', 'stream' ) ) ?><br />
1050 <?php
1051 $love_letter_url = add_query_arg(
1052 array(
1053 'site-name' => urlencode( get_bloginfo( 'name' ) ),
1054 ),
1055 self::PUBLIC_URL . '/love-letter/'
1056 );
1057 ?>
1058 <a href="<?php echo esc_url( $love_letter_url ) ?>" target="_blank">
1059 <?php echo esc_html( _x( 'I have a secret', 'Haiku line 3', 'stream' ) ) ?>
1060 </a>
1061 </p>
1062 </div>
1063
1064 </div>
1065
1066 </div>
1067 <?php
1068 }
1069
1070 public static function register_list_table() {
1071 self::$list_table = new WP_Stream_List_Table( array( 'screen' => self::$screen_id['main'] ) );
1072 }
1073
1074 public static function render_stream_page() {
1075 $page_title = __( 'Stream Records', 'stream' );
1076
1077 self::$list_table->prepare_items();
1078
1079 echo '<div class="wrap">';
1080
1081 printf( '<h2>%s</h2>', __( 'Stream Records', 'stream' ) ); // xss ok
1082
1083 self::$list_table->display();
1084
1085 echo '</div>';
1086 }
1087
1088 public static function wp_ajax_defaults() {
1089 check_ajax_referer( 'stream_nonce', 'wp_stream_nonce' );
1090
1091 if ( current_user_can( self::SETTINGS_CAP ) ) {
1092 self::reset_stream_settings();
1093 wp_redirect(
1094 add_query_arg(
1095 array(
1096 'page' => 'wp_stream_settings',
1097 'message' => 'settings_reset',
1098 ),
1099 admin_url( self::ADMIN_PARENT_PAGE )
1100 )
1101 );
1102 exit;
1103 } else {
1104 wp_die( "You don't have sufficient privileges to do this action." );
1105 }
1106 }
1107
1108 private static function reset_stream_settings() {
1109 global $wpdb;
1110
1111 $blogs = wp_get_sites();
1112
1113 if ( $blogs ) {
1114 foreach ( $blogs as $blog ) {
1115 switch_to_blog( $blog['blog_id'] );
1116 delete_option( WP_Stream_Settings::OPTION_KEY );
1117 }
1118 restore_current_blog();
1119 }
1120 }
1121
1122 private static function _role_can_view_stream( $role ) {
1123 if ( in_array( $role, WP_Stream_Settings::$options['general_role_access'] ) ) {
1124 return true;
1125 }
1126
1127 return false;
1128 }
1129
1130 /**
1131 * Filter user caps to dynamically grant our view cap based on allowed roles
1132 *
1133 * @filter user_has_cap
1134 *
1135 * @param $allcaps
1136 * @param $caps
1137 * @param $args
1138 * @param $user
1139 *
1140 * @return array
1141 */
1142 public static function _filter_user_caps( $allcaps, $caps, $args, $user = null ) {
1143 global $wp_roles;
1144
1145 $_wp_roles = isset( $wp_roles ) ? $wp_roles : new WP_Roles();
1146
1147 $user = is_a( $user, 'WP_User' ) ? $user : wp_get_current_user();
1148
1149 // @see
1150 // https://github.com/WordPress/WordPress/blob/c67c9565f1495255807069fdb39dac914046b1a0/wp-includes/capabilities.php#L758
1151 $roles = array_unique(
1152 array_merge(
1153 $user->roles,
1154 array_filter(
1155 array_keys( $user->caps ),
1156 array( $_wp_roles, 'is_role' )
1157 )
1158 )
1159 );
1160
1161 $stream_view_caps = array(
1162 self::VIEW_CAP,
1163 WP_Stream_Notifications::VIEW_CAP,
1164 WP_Stream_Reports::VIEW_CAP,
1165 );
1166
1167 foreach ( $caps as $cap ) {
1168 if ( in_array( $cap, $stream_view_caps ) ) {
1169 foreach ( $roles as $role ) {
1170 if ( self::_role_can_view_stream( $role ) ) {
1171 $allcaps[ $cap ] = true;
1172 break 2;
1173 }
1174 }
1175 }
1176 }
1177
1178 return $allcaps;
1179 }
1180
1181 /**
1182 * Filter role caps to dynamically grant our view cap based on allowed roles
1183 *
1184 * @filter role_has_cap
1185 *
1186 * @param $allcaps
1187 * @param $cap
1188 * @param $role
1189 *
1190 * @return array
1191 */
1192 public static function _filter_role_caps( $allcaps, $cap, $role ) {
1193 $stream_view_caps = array(
1194 self::VIEW_CAP,
1195 WP_Stream_Notifications::VIEW_CAP,
1196 WP_Stream_Reports::VIEW_CAP,
1197 );
1198
1199 if ( in_array( $cap, $stream_view_caps ) && self::_role_can_view_stream( $role ) ) {
1200 $allcaps[ $cap ] = true;
1201 }
1202
1203 return $allcaps;
1204 }
1205
1206 /**
1207 * @action wp_ajax_wp_stream_filters
1208 */
1209 public static function ajax_filters() {
1210 switch ( wp_stream_filter_input( INPUT_GET, 'filter' ) ) {
1211 case 'author':
1212 $users = array_merge(
1213 array( 0 => (object) array( 'display_name' => 'WP-CLI' ) ),
1214 get_users()
1215 );
1216
1217 // `search` arg for get_users() is not enough
1218 $users = array_filter(
1219 $users,
1220 function ( $user ) {
1221 return false !== mb_strpos( mb_strtolower( $user->display_name ), mb_strtolower( wp_stream_filter_input( INPUT_GET, 'q' ) ) );
1222 }
1223 );
1224
1225 if ( count( $users ) > self::PRELOAD_AUTHORS_MAX ) {
1226 $users = array_slice( $users, 0, self::PRELOAD_AUTHORS_MAX );
1227 // @todo $extra is not used
1228 $extra = array(
1229 'id' => 0,
1230 'disabled' => true,
1231 'text' => sprintf( _n( 'One more result...', '%d more results...', $results_count - self::PRELOAD_AUTHORS_MAX, 'stream' ), $results_count - self::PRELOAD_AUTHORS_MAX ),
1232 );
1233 }
1234
1235 // Get gravatar / roles for final result set
1236 $results = self::get_authors_record_meta( $users );
1237
1238 break;
1239 }
1240 if ( isset( $results ) ) {
1241 echo json_encode( array_values( $results ) );
1242 }
1243 die();
1244 }
1245
1246 /**
1247 * @action wp_ajax_wp_stream_get_filter_value_by_id
1248 */
1249 public static function get_filter_value_by_id() {
1250 $filter = wp_stream_filter_input( INPUT_POST, 'filter' );
1251
1252 switch ( $filter ) {
1253 case 'author':
1254 $id = wp_stream_filter_input( INPUT_POST, 'id' );
1255 if ( '0' === $id ) {
1256 $value = 'WP-CLI';
1257 break;
1258 }
1259 $user = get_userdata( $id );
1260 if ( ! $user || is_wp_error( $user ) ) {
1261 $value = '';
1262 } else {
1263 $value = $user->display_name;
1264 }
1265 break;
1266 default:
1267 $value = '';
1268 }
1269
1270 echo json_encode( $value );
1271
1272 wp_die();
1273 }
1274
1275 public static function get_authors_record_meta( $authors ) {
1276 $authors_records = array();
1277
1278 foreach ( $authors as $user_id => $args ) {
1279 $author = new WP_Stream_Author( $user_id );
1280 $disabled = isset( $args['disabled'] ) ? $args['disabled'] : null;
1281
1282 $authors_records[ $user_id ] = array(
1283 'text' => $author->get_display_name(),
1284 'id' => $user_id,
1285 'label' => $author->get_display_name(),
1286 'icon' => $author->get_avatar_src( 32 ),
1287 'title' => '',
1288 'disabled' => $disabled,
1289 );
1290 }
1291
1292 return $authors_records;
1293 }
1294 }
1295