'true', 'action' => 'connect', 'home_url' => urlencode( $home_url ), 'plugin_url' => urlencode( add_query_arg( array( 'page' => self::RECORDS_PAGE_SLUG, 'nonce' => $connect_nonce, ), admin_url( self::ADMIN_PARENT_PAGE ) ) ), ), esc_url_raw( untrailingslashit( self::PUBLIC_URL ) . '/pricing/' ) ); $api_key = wp_stream_filter_input( INPUT_GET, 'api_key' ); $site_uuid = wp_stream_filter_input( INPUT_GET, 'site_uuid' ); // Connect if ( ! empty( $api_key ) && ! empty( $site_uuid ) ) { add_action( 'admin_init', array( __CLASS__, 'save_api_authentication' ) ); } // Disconnect if ( self::ACCOUNT_PAGE_SLUG === wp_stream_filter_input( INPUT_GET, 'page' ) && '1' === wp_stream_filter_input( INPUT_GET, 'disconnect' ) ) { add_action( 'admin_init', array( __CLASS__, 'remove_api_authentication' ) ); } self::$disable_access = apply_filters( 'wp_stream_disable_admin_access', false ); // Register settings page if ( ! self::$disable_access ) { add_action( 'admin_menu', array( __CLASS__, 'register_menu' ) ); } // Admin notices add_action( 'admin_notices', array( __CLASS__, 'admin_notices' ) ); // Show connect notice on dashboard and plugins pages add_action( 'load-index.php', array( __CLASS__, 'prepare_connect_notice' ) ); add_action( 'load-plugins.php', array( __CLASS__, 'prepare_connect_notice' ) ); // Add admin body class add_filter( 'admin_body_class', array( __CLASS__, 'admin_body_class' ) ); // Plugin action links add_filter( 'plugin_action_links', array( __CLASS__, 'plugin_action_links' ), 10, 2 ); // Load admin scripts and styles add_action( 'admin_enqueue_scripts', array( __CLASS__, 'admin_enqueue_scripts' ) ); add_action( 'admin_enqueue_scripts', array( __CLASS__, 'admin_menu_css' ) ); // Catch list table results add_filter( 'wp_stream_query_results', array( __CLASS__, 'mark_as_read' ), 10, 3 ); // Add user option for enabling unread counts add_action( 'show_user_profile', array( __CLASS__, 'unread_count_user_option' ) ); add_action( 'edit_user_profile', array( __CLASS__, 'unread_count_user_option' ) ); // Save unread counts user option add_action( 'personal_options_update', array( __CLASS__, 'save_unread_count_user_option' ) ); add_action( 'edit_user_profile_update', array( __CLASS__, 'save_unread_count_user_option' ) ); // Delete user-specific transient when user is deleted add_action( 'delete_user', array( __CLASS__, 'delete_unread_count_transient' ), 10, 1 ); // Reset Streams settings add_action( 'wp_ajax_wp_stream_defaults', array( __CLASS__, 'wp_ajax_defaults' ) ); // Ajax authors list add_action( 'wp_ajax_wp_stream_filters', array( __CLASS__, 'ajax_filters' ) ); // Ajax author's name by ID add_action( 'wp_ajax_wp_stream_get_filter_value_by_id', array( __CLASS__, 'get_filter_value_by_id' ) ); } /** * Prepare the Connect to Stream prompt * * @return void */ public static function prepare_connect_notice() { if ( ! WP_Stream::is_connected() && ! WP_Stream::is_development_mode() ) { wp_enqueue_style( 'wp-stream-connect', WP_STREAM_URL . 'ui/css/connect.css', array(), WP_Stream::VERSION ); wp_enqueue_script( 'wp-stream-connect', WP_STREAM_URL . 'ui/js/connect.js', array(), WP_Stream::VERSION ); add_action( 'admin_notices', array( __CLASS__, 'admin_connect_notice' ) ); } } /** * Prompt the user to connect to Stream * * @return void */ public static function admin_connect_notice() { if ( ! current_user_can( self::SETTINGS_CAP ) ) { return; } $dismiss_and_deactivate_url = wp_nonce_url( 'plugins.php?action=deactivate&plugin=' . WP_STREAM_PLUGIN, 'deactivate-plugin_' . WP_STREAM_PLUGIN ); ?>
%s', esc_html__( 'You have successfully connected to Stream!', 'stream' ), esc_html__( 'Check back here regularly to see a history of the changes being made to this site.', 'stream' ) ); } break; } if ( $notice ) { WP_Stream::notice( $notice, false ); } } /** * Return URL used for account level actions * * @return string */ public static function account_url( $path = '' ) { $account_url = add_query_arg( array( 'auth' => 'true', 'plugin_url' => urlencode( add_query_arg( array( 'page' => self::RECORDS_PAGE_SLUG, ), admin_url( self::ADMIN_PARENT_PAGE ) ) ), ), esc_url_raw( sprintf( '%s/dashboard/%s', untrailingslashit( self::PUBLIC_URL ), untrailingslashit( $path ) ) ) ); return $account_url; } /** * Register menu page * * @action admin_menu * @return bool|void */ public static function register_menu() { if ( WP_Stream::is_connected() || WP_Stream::is_development_mode() ) { $unread_count = self::get_unread_count(); $menu_title = __( 'Stream', 'stream' ); if ( self::unread_enabled_for_user() && ! empty( $unread_count ) ) { $formatted_count = ( $unread_count > 99 ) ? __( '99 +', 'stream' ) : absint( $unread_count ); $menu_title = sprintf( '%s %s', esc_html( $menu_title ), absint( $unread_count ), esc_html( $formatted_count ) ); } self::$screen_id['main'] = add_menu_page( __( 'Stream', 'stream' ), $menu_title, self::VIEW_CAP, self::RECORDS_PAGE_SLUG, array( __CLASS__, 'render_stream_page' ), 'div', apply_filters( 'wp_stream_menu_position', '2.999999' ) // Using longtail decimal string to reduce the chance of position conflicts, see Codex ); self::$screen_id['settings'] = add_submenu_page( self::RECORDS_PAGE_SLUG, __( 'Stream Settings', 'stream' ), __( 'Settings', 'stream' ), self::SETTINGS_CAP, self::SETTINGS_PAGE_SLUG, array( __CLASS__, 'render_settings_page' ) ); self::$screen_id['account'] = add_submenu_page( self::RECORDS_PAGE_SLUG, __( 'Stream Account', 'stream' ), __( 'Account', 'stream' ), self::SETTINGS_CAP, self::ACCOUNT_PAGE_SLUG, array( __CLASS__, 'render_account_page' ) ); } else { self::$screen_id['connect'] = add_menu_page( __( 'Connect to Stream', 'stream' ), __( 'Stream', 'stream' ), self::SETTINGS_CAP, self::RECORDS_PAGE_SLUG, array( __CLASS__, 'render_connect_page' ), 'div', apply_filters( 'wp_stream_menu_position', '2.999999' ) // Using longtail decimal string to reduce the chance of position conflicts, see Codex ); } if ( isset( self::$screen_id['main'] ) ) { /** * Fires just before the Stream list table is registered. * * @since 1.4.0 * * @return void */ do_action( 'wp_stream_admin_menu_screens' ); // Register the list table early, so it associates the column headers with 'Screen settings' add_action( 'load-' . self::$screen_id['main'], array( __CLASS__, 'register_list_table' ) ); } } /** * Enqueue scripts/styles for admin screen * * @action admin_enqueue_scripts * * @param $hook * * @return void */ public static function admin_enqueue_scripts( $hook ) { wp_register_script( 'select2', WP_STREAM_URL . 'ui/lib/select2/select2.js', array( 'jquery' ), '3.5.2', true ); wp_register_style( 'select2', WP_STREAM_URL . 'ui/lib/select2/select2.css', array(), '3.5.2' ); wp_register_script( 'timeago', WP_STREAM_URL . 'ui/lib/timeago/jquery.timeago.js', array(), '1.4.1', true ); $locale = strtolower( substr( get_locale(), 0, 2 ) ); $file_tmpl = 'ui/lib/timeago/locales/jquery.timeago.%s.js'; if ( file_exists( WP_STREAM_DIR . sprintf( $file_tmpl, $locale ) ) ) { wp_register_script( 'timeago-locale', WP_STREAM_URL . sprintf( $file_tmpl, $locale ), array( 'timeago' ), '1' ); } else { wp_register_script( 'timeago-locale', WP_STREAM_URL . sprintf( $file_tmpl, 'en' ), array( 'timeago' ), '1' ); } wp_enqueue_style( 'wp-stream-admin', WP_STREAM_URL . 'ui/css/admin.css', array(), WP_Stream::VERSION ); $script_screens = array( 'plugins.php', 'user-edit.php', 'user-new.php', 'profile.php' ); if ( 'index.php' === $hook ) { wp_enqueue_script( 'wp-stream-dashboard', WP_STREAM_URL . 'ui/js/dashboard.js', array( 'jquery' ), WP_Stream::VERSION ); wp_enqueue_script( 'wp-stream-live-updates', WP_STREAM_URL . 'ui/js/live-updates.js', array( 'jquery', 'heartbeat' ), WP_Stream::VERSION ); } elseif ( in_array( $hook, self::$screen_id ) || in_array( $hook, $script_screens ) ) { wp_enqueue_script( 'select2' ); wp_enqueue_style( 'select2' ); wp_enqueue_script( 'timeago' ); wp_enqueue_script( 'timeago-locale' ); wp_enqueue_script( 'wp-stream-admin', WP_STREAM_URL . 'ui/js/admin.js', array( 'jquery', 'select2' ), WP_Stream::VERSION ); wp_enqueue_script( 'wp-stream-live-updates', WP_STREAM_URL . 'ui/js/live-updates.js', array( 'jquery', 'heartbeat' ), WP_Stream::VERSION ); wp_localize_script( 'wp-stream-admin', 'wp_stream', array( 'i18n' => array( 'confirm_defaults' => __( 'Are you sure you want to reset all site settings to default? This cannot be undone.', 'stream' ), ), 'locale' => esc_js( $locale ), 'gmt_offset' => get_option( 'gmt_offset' ), ) ); } wp_localize_script( 'wp-stream-live-updates', 'wp_stream_live_updates', array( 'current_screen' => $hook, 'current_page' => isset( $_GET['paged'] ) ? esc_js( $_GET['paged'] ) : '1', 'current_order' => isset( $_GET['order'] ) ? esc_js( $_GET['order'] ) : 'desc', 'current_query' => json_encode( $_GET ), 'current_query_count' => count( $_GET ), ) ); if ( WP_Stream_Migrate::show_migrate_notice() ) { $limit = absint( WP_Stream_Migrate::$limit ); $record_count = absint( WP_Stream_Migrate::$record_count ); $estimated_time = ( $limit < $record_count ) ? round( ( ( $record_count / $limit ) * ( 0.04 * $limit ) ) / 60 ) : 0; $migrate_time_message = ( $estimated_time > 1 ) ? sprintf( __( 'This will take about %d minutes.', 'stream' ), absint( $estimated_time ) ) : __( 'This could take a few minutes.', 'stream' ); $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' ); wp_enqueue_script( 'wp-stream-migrate', WP_STREAM_URL . 'ui/js/migrate.js', array( 'jquery' ), WP_Stream::VERSION ); wp_localize_script( 'wp-stream-migrate', 'wp_stream_migrate', array( 'i18n' => array( 'migrate_process_title' => __( 'Migrating Stream Records', 'stream' ), 'delete_process_title' => __( 'Deleting Stream Records', 'stream' ), 'error_message' => __( 'An unknown error occurred during migration. Please try again later or contact support.', 'stream' ), 'migrate_process_message' => __( 'Please do not exit this page until the process has completed.', 'stream' ) . ' ' . esc_html( $migrate_time_message ), 'delete_process_message' => __( 'Please do not exit this page until the process has completed.', 'stream' ) . ' ' . esc_html( $delete_time_message ), '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' ), 'confirm_migrate_reminder' => __( 'Please note: Your existing records will not appear in Stream until you have migrated them to your account.', 'stream' ), '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' ) ), ), 'chunk_size' => absint( $limit ), 'record_count' => absint( $record_count ), 'nonce' => wp_create_nonce( 'wp_stream_migrate-' . absint( get_current_blog_id() ) . absint( get_current_user_id() ) ), ) ); } /** * The maximum number of items that can be updated in bulk without receiving a warning. * * Stream watches for bulk actions performed in the WordPress Admin (such as updating * many posts at once) and warns the user before proceeding if the number of items they * are attempting to update exceeds this threshold value. Since Stream will try to save * a log for each item, it will take longer than usual to complete the operation. * * The default threshold is 100 items. * * @return int */ $bulk_actions_threshold = apply_filters( 'wp_stream_bulk_actions_threshold', 100 ); wp_enqueue_script( 'wp-stream-global', WP_STREAM_URL . 'ui/js/global.js', array( 'jquery' ), WP_Stream::VERSION ); wp_localize_script( 'wp-stream-global', 'wp_stream_global', array( 'bulk_actions' => array( 'i18n' => array( '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 ) ) ), 'confirm_import' => __( 'The Stream plugin must be deactivated before you can bulk import content into WordPress.', 'stream' ), ), 'threshold' => absint( $bulk_actions_threshold ), ), 'plugins_screen_url' => self_admin_url( 'plugins.php#stream' ), ) ); } /** * Check whether or not the current admin screen belongs to Stream * * @return bool */ public static function is_stream_screen() { global $typenow; if ( is_admin() && ( false !== strpos( wp_stream_filter_input( INPUT_GET, 'page' ), self::RECORDS_PAGE_SLUG ) || WP_Stream_Notifications_Post_Type::POSTTYPE === $typenow ) ) { return true; } return false; } /** * Add a specific body class to all Stream admin screens * * @filter admin_body_class * * @param string $classes * * @return string $classes */ public static function admin_body_class( $classes ) { if ( self::is_stream_screen() ) { $classes .= sprintf( ' %s ', self::ADMIN_BODY_CLASS ); if ( WP_Stream::is_connected() || WP_Stream::is_development_mode() ) { $classes .= ' wp_stream_connected '; } else { $classes .= ' wp_stream_disconnected '; } if ( WP_Stream_API::is_restricted() ) { $classes .= ' wp_stream_restricted '; } } $settings_pages = array( self::SETTINGS_PAGE_SLUG ); if ( isset( $_GET['page'] ) && in_array( $_GET['page'], $settings_pages ) ) { $classes .= sprintf( ' %s ', self::SETTINGS_PAGE_SLUG ); } return $classes; } /** * Add menu styles for various WP Admin skins * * @uses wp_add_inline_style() * @action admin_enqueue_scripts * @return bool true on success false on failure */ public static function admin_menu_css() { wp_register_style( 'jquery-ui', '//ajax.googleapis.com/ajax/libs/jqueryui/1.10.1/themes/base/jquery-ui.css', array(), '1.10.1' ); wp_register_style( 'wp-stream-datepicker', WP_STREAM_URL . 'ui/css/datepicker.css', array( 'jquery-ui' ), WP_Stream::VERSION ); wp_register_style( 'wp-stream-icons', WP_STREAM_URL . 'ui/stream-icons/style.css', array(), WP_Stream::VERSION ); // Make sure we're working off a clean version include( ABSPATH . WPINC . '/version.php' ); $body_class = self::ADMIN_BODY_CLASS; $records_page = self::RECORDS_PAGE_SLUG; $stream_url = WP_STREAM_URL; if ( version_compare( $wp_version, '3.8-alpha', '>=' ) ) { wp_enqueue_style( 'wp-stream-icons' ); $css = " #toplevel_page_{$records_page} .wp-menu-image:before { font-family: 'WP Stream' !important; content: '\\73' !important; } #toplevel_page_{$records_page} .wp-menu-image { background-repeat: no-repeat; } #menu-posts-feedback .wp-menu-image:before { font-family: dashicons !important; content: '\\f175'; } #adminmenu #menu-posts-feedback div.wp-menu-image { background: none !important; background-repeat: no-repeat; } body.{$body_class} #wpbody-content .wrap h2:nth-child(1):before { font-family: 'WP Stream' !important; content: '\\73'; padding: 0 8px 0 0; } "; } else { $css = " #toplevel_page_{$records_page} .wp-menu-image { background: url( {$stream_url}ui/stream-icons/menuicon-sprite.png ) 0 90% no-repeat; } /* Retina Stream Menu Icon */ @media only screen and (-moz-min-device-pixel-ratio: 1.5), only screen and (-o-min-device-pixel-ratio: 3/2), only screen and (-webkit-min-device-pixel-ratio: 1.5), only screen and (min-device-pixel-ratio: 1.5) { #toplevel_page_{$records_page} .wp-menu-image { background: url( {$stream_url}ui/stream-icons/menuicon-sprite-2x.png ) 0 90% no-repeat; background-size:30px 64px; } } #toplevel_page_{$records_page}.current .wp-menu-image, #toplevel_page_{$records_page}.wp-has-current-submenu .wp-menu-image, #toplevel_page_{$records_page}:hover .wp-menu-image { background-position: top left; } "; } wp_add_inline_style( 'wp-admin', $css ); } /** * Check whether or not the current user should see the unread counter. * * Defaults to TRUE if user option does not exist. * * @param int $user_id (optional) * * @return bool */ public static function unread_enabled_for_user( $user_id = 0 ) { $user_id = empty( $user_id ) ? get_current_user_id() : $user_id; $enabled = get_user_meta( $user_id, self::UNREAD_COUNT_OPTION_KEY, true ); $enabled = ( 'off' !== $enabled ); return (bool) $enabled; } /** * Get the unread count for the current user. * * Results are cached in transient with a 5 min TTL. * * @return int */ public static function get_unread_count() { if ( ! self::unread_enabled_for_user() ) { return false; } $user_id = get_current_user_id(); $cache_key = sprintf( '%s_%d', self::UNREAD_COUNT_OPTION_KEY, $user_id ); if ( false === ( $count = get_transient( $cache_key ) ) ) { $count = 0; $last_read = get_user_meta( $user_id, self::LAST_READ_OPTION_KEY, true ); if ( ! empty( $last_read ) ) { $args = array( 'records_per_page' => 101, 'author__not_in' => array( $user_id ), // Ignore changes authored by the current user 'date_after' => date( 'c', strtotime( $last_read . ' + 1 second' ) ), // Bump time to bypass gte issue 'fields' => array( 'created' ), // We don't need the entire record ); $unread_records = wp_stream_query( $args ); $count = empty( $unread_records ) ? 0 : count( $unread_records ); } set_transient( $cache_key, $count, 5 * 60 ); // TTL 5 min } return absint( $count ); } /** * Mark records as read based on Records screen results * * @filter wp_stream_query_results * * @param array $results * @param array $query * @param array $fields * * @return array */ public static function mark_as_read( $results, $query, $fields ) { if ( ! is_admin() ) { return $results; } $screen = get_current_screen(); $is_list_table = ( isset( $screen->id ) && sprintf( 'toplevel_page_%s', self::RECORDS_PAGE_SLUG ) === $screen->id ); $is_first_page = empty( $query['from'] ); $is_date_desc = ( isset( $query['sort'][0]['created']['order'] ) && 'desc' === $query['sort'][0]['created']['order'] ); if ( $is_list_table && $is_first_page && $is_date_desc ) { $user_id = get_current_user_id(); $cache_key = sprintf( '%s_%d', self::UNREAD_COUNT_OPTION_KEY, $user_id ); if ( self::unread_enabled_for_user() && isset( $results[0]->created ) ) { update_user_meta( $user_id, self::LAST_READ_OPTION_KEY, date( 'c', strtotime( $results[0]->created ) ) ); } set_transient( $cache_key, 0 ); // No expiration } return $results; } /** * Output for Stream Unread Count field in user profiles. * * @action show_user_profile * @action edit_user_profile * * @param WP_User $user * * @return void */ public static function unread_count_user_option( $user ) { if ( ! array_intersect( $user->roles, WP_Stream_Settings::$options['general_role_access'] ) ) { return; } $unread_enabled = self::unread_enabled_for_user(); ?>
| created ) ) ); ?> | |
site_uuid ); ?>
|
|
api_key ); ?>
|