├── .gitmodules
├── useronline.js
├── useronline.dev.js
├── deprecated.php
├── uninstall.php
├── wp-stats.php
├── widget.php
├── wp-useronline.php
├── bots.php
├── core.php
├── README.md
├── template-tags.php
└── admin.php
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "scb"]
2 | path = scb
3 | url = https://github.com/lesterchan/wp-scb-framework.git
4 |
--------------------------------------------------------------------------------
/useronline.js:
--------------------------------------------------------------------------------
1 | jQuery(document).ready(function(c){var b=parseInt(useronlineL10n.timeout);var a=function(e){var d={action:"useronline",mode:e,page_url:location.protocol+"//"+location.host+location.pathname+location.search,page_title:c("title").text()};c.post(useronlineL10n.ajax_url,d,function(f){c("#useronline-"+e).html(f)})};c.each(["count","browsing-site","browsing-page","details"],function(d,e){if(c("#useronline-"+e).length){setInterval(function(){a(e)},b)}})});
--------------------------------------------------------------------------------
/useronline.dev.js:
--------------------------------------------------------------------------------
1 | jQuery(document).ready(function($) {
2 | var timeout = parseInt(useronlineL10n.timeout);
3 |
4 | var get_data = function(mode) {
5 | var data = {
6 | 'action': 'useronline',
7 | 'mode': mode,
8 | 'page_url': location.protocol + '//' + location.host + location.pathname + location.search,
9 | 'page_title': $('title').text()
10 | };
11 |
12 | $.post(useronlineL10n.ajax_url, data, function(response) {
13 | $('#useronline-' + mode).html(response);
14 | });
15 | }
16 |
17 | $.each(['count', 'browsing-site', 'browsing-page', 'details'], function(i, mode) {
18 | if ( $('#useronline-' + mode).length )
19 | setInterval(function() { get_data(mode); }, timeout);
20 | });
21 | });
22 |
--------------------------------------------------------------------------------
/deprecated.php:
--------------------------------------------------------------------------------
1 | 0 ) {
22 | foreach( $option_names as $option_name ) {
23 | delete_option( $option_name );
24 | plugin_uninstalled();
25 | }
26 | }
27 | }
28 | }
29 |
30 | restore_current_blog();
31 | } else {
32 | if( sizeof( $option_names ) > 0 ) {
33 | foreach( $option_names as $option_name ) {
34 | delete_option( $option_name );
35 | plugin_uninstalled();
36 | }
37 | }
38 | }
39 |
40 | /**
41 | * Delete plugin table when uninstalled
42 | *
43 | * @access public
44 | * @return void
45 | */
46 | function plugin_uninstalled() {
47 | global $wpdb;
48 |
49 | $table_names = array( 'useronline' );
50 | if( sizeof( $table_names ) > 0 ) {
51 | foreach( $table_names as $table_name ) {
52 | $table = $wpdb->prefix . $table_name;
53 | $wpdb->query( "DROP TABLE IF EXISTS $table" );
54 | }
55 | }
56 | }
--------------------------------------------------------------------------------
/wp-stats.php:
--------------------------------------------------------------------------------
1 | '.__( 'WP-UserOnline', 'wp-useronline' ).' '."\n";
61 |
62 | return $content;
63 | }
64 |
65 | /**
66 | * Add WP-UserOnline General Stats To WP-Stats Page
67 | *
68 | * @param string $content
69 | *
70 | * @access public
71 | *
72 | * @return string
73 | */
74 | public function page_general_stats( $content ) {
75 | $stats_display = get_option( 'stats_display' );
76 |
77 | $str = _n(
78 | '%s user online now.',
79 | '%s users online now.',
80 | get_users_online_count(), 'wp-useronline'
81 | );
82 |
83 | if ( $stats_display['useronline'] === 1 )
84 | $content .=
85 | html( 'p', html( 'strong', __( 'WP-UserOnline', 'wp-useronline' ) ) )
86 | .html( 'ul',
87 | html( 'li', sprintf( $str, number_format_i18n( get_users_online_count() ) ) )
88 | .html( 'li', UserOnline_Template::format_most_users() )
89 | );
90 |
91 | return $content;
92 | }
93 | }
94 |
95 | UserOnline_WpStats::get_instance();
96 |
--------------------------------------------------------------------------------
/widget.php:
--------------------------------------------------------------------------------
1 | __( 'WP-UserOnline users online statistics', 'wp-useronline' ) );
6 | parent::__construct( 'useronline', __( 'UserOnline', 'wp-useronline' ), $widget_ops );
7 | }
8 |
9 | function content( $instance ) {
10 | if ( empty( $instance['type'] ) ) {
11 | return '';
12 | }
13 |
14 | $out = '';
15 |
16 | switch( $instance['type'] ) {
17 | case 'users_online':
18 | $out .= html( 'div id="useronline-count"', get_users_online() );
19 | break;
20 | case 'users_browsing_page':
21 | $out .= html( 'div id="useronline-browsing-page"', get_users_browsing_page() );
22 | break;
23 | case 'users_browsing_site':
24 | $out .= html( 'div id="useronline-browsing-site"', get_users_browsing_site() );
25 | break;
26 | case 'users_online_browsing_page':
27 | $out .= html( 'div id="useronline-count"', get_users_online() );
28 | $out .= html( 'div id="useronline-browsing-page"', get_users_browsing_page() );
29 | break;
30 | case 'users_online_browsing_site':
31 | $out .= html( 'div id="useronline-count"', get_users_online() );
32 | $out .= html( 'div id="useronline-browsing-site"', get_users_browsing_site() );
33 | break;
34 | }
35 |
36 | echo $out;
37 | }
38 |
39 | function update( $new_instance, $old_instance ) {
40 | if ( !isset( $new_instance['submit'] ) )
41 | return false;
42 |
43 | $instance = $old_instance;
44 | $instance['title'] = strip_tags( $new_instance['title'] );
45 | $instance['type'] = strip_tags( $new_instance['type'] );
46 |
47 | return $instance;
48 | }
49 |
50 | function form( $instance ) {
51 | global $wpdb;
52 | $instance = wp_parse_args( (array) $instance, array(
53 | 'title' => __( 'UserOnline', 'wp-useronline' ),
54 | 'type' => 'users_online'
55 | ) );
56 | $title = esc_attr( $instance['title'] );
57 | $type = esc_attr( $instance['type'] );
58 | ?>
59 |
60 |
61 |
62 |
63 |
64 |
65 | >
66 | >
67 | >
68 |
69 | >
70 | >
71 |
72 |
73 |
74 |
75 | 1,
36 | 'date' => current_time( 'timestamp' )
37 | ) );
38 |
39 | $options = new scbOptions( 'useronline', __FILE__, array(
40 | 'timeout' => 300,
41 | 'url' => trailingslashit( get_bloginfo( 'url' ) ) . 'useronline',
42 | 'names' => false,
43 |
44 | 'naming' => array(
45 | 'user' => __( '1 User', 'wp-useronline' ),
46 | 'users' => __( '%COUNT% Users', 'wp-useronline' ),
47 | 'member' => __( '1 Member', 'wp-useronline' ),
48 | 'members' => __( '%COUNT% Members', 'wp-useronline' ),
49 | 'guest' => __( '1 Guest', 'wp-useronline' ),
50 | 'guests' => __( '%COUNT% Guests', 'wp-useronline' ),
51 | 'bot' => __( '1 Bot', 'wp-useronline' ),
52 | 'bots' => __( '%COUNT% Bots', 'wp-useronline' )
53 | ),
54 |
55 | 'templates' => array(
56 | 'useronline' => '%USERS% '.__( 'Online', 'wp-useronline' ).' ',
57 |
58 | 'browsingsite' => array(
59 | 'separators' => array(
60 | 'members' => __( ',', 'wp-useronline' ).' ',
61 | 'guests' => __( ',', 'wp-useronline' ).' ',
62 | 'bots' => __( ',', 'wp-useronline' ).' ',
63 | ),
64 | 'text' => _x( 'Users', 'Template Element', 'wp-useronline' ).': %MEMBER_NAMES%%GUESTS_SEPARATOR%%GUESTS%%BOTS_SEPARATOR%%BOTS% '
65 | ),
66 |
67 | 'browsingpage' => array(
68 | 'separators' => array(
69 | 'members' => __( ',', 'wp-useronline' ).' ',
70 | 'guests' => __( ',', 'wp-useronline' ).' ',
71 | 'bots' => __( ',', 'wp-useronline' ).' ',
72 | ),
73 | 'text' => '%USERS% '.__( 'Browsing This Page.', 'wp-useronline' ).' '._x( 'Users', 'Template Element', 'wp-useronline' ).': %MEMBER_NAMES%%GUESTS_SEPARATOR%%GUESTS%%BOTS_SEPARATOR%%BOTS% '
74 | )
75 | )
76 | ) );
77 |
78 | UserOnline_Core::init( $options, $most );
79 |
80 | if ( is_admin() ) {
81 | require_once __DIR__ . '/admin.php';
82 | scbAdminPage::register( 'UserOnline_Admin_Integration', __FILE__ );
83 | scbAdminPage::register( 'UserOnline_Options', __FILE__, UserOnline_Core::$options );
84 | }
85 |
86 | if ( function_exists( 'stats_page' ) )
87 | require_once __DIR__ . '/wp-stats.php';
88 |
89 | # scbUtil::do_uninstall( __FILE__ );
90 | # scbUtil::do_activation( __FILE__ );
91 | }
92 | scb_init( '_useronline_init' );
93 |
94 | add_action( 'plugins_loaded', 'useronline_init_widget' );
95 | function useronline_init_widget() {
96 | if ( ! class_exists( 'scbWidget', false ) ) {
97 | require_once __DIR__ . '/scb/Widget.php';
98 | }
99 | require_once __DIR__ . '/widget.php';
100 | scbWidget::init( 'UserOnline_Widget', __FILE__, 'useronline' );
101 | }
--------------------------------------------------------------------------------
/bots.php:
--------------------------------------------------------------------------------
1 | '360spider',
6 | 'AddThis' => 'addthis',
7 | 'Adsbot' => 'Adsbot',
8 | 'AdScanner' => 'adscanner',
9 | 'AHC' => 'AHC',
10 | 'Ahrefs' => 'ahrefsbot',
11 | 'Alex' => 'ia_archiver',
12 | 'AllTheWeb' => 'fast-webcrawler',
13 | 'Altavista' => 'scooter',
14 | 'Amazon' => 'amazonaws.com',
15 | 'Anders Pink' => 'anderspinkbot',
16 | 'Apple' => 'applebot',
17 | 'Archive.org' => 'archive.org_bot',
18 | 'Ask Jeeves' => 'jeeves',
19 | 'Aspiegel' => 'AspiegelBot',
20 | 'Axios' => 'axios',
21 | 'Baidu' => 'baidu',
22 | 'Become.com' => 'become.com',
23 | 'Bing' => 'bingbot',
24 | 'Bing Preview' => 'bingpreview',
25 | 'Blackboard' => 'Blackboard',
26 | 'BLEXBot' => 'blexbot',
27 | 'Bloglines' => 'bloglines',
28 | 'Blog Search Engine' => 'blogsearch',
29 | 'BUbiNG' => 'bubing',
30 | 'Buck' => 'Buck',
31 | 'Bytespider' => 'Bytespider',
32 | 'CCBot' => 'ccbot',
33 | 'CFNetwork' => 'cfnetwork',
34 | 'ChatGPT' => 'ChatGPT',
35 | 'CheckMarkNetwork' => 'CheckMarkNetwork',
36 | 'ClaudeBot' => 'ClaudeBot',
37 | 'Cliqzbot' => 'cliqzbot',
38 | 'Coccoc' => 'coccocbot',
39 | 'Crawl' => 'crawl',
40 | 'Curl' => 'Curl',
41 | 'Cyotek' => 'Cyotek',
42 | 'Daum' => 'Daum',
43 | 'Dispatch' => 'Dispatch',
44 | 'DomainCrawler' => 'domaincrawler',
45 | 'DotBot' => 'dotbot',
46 | 'DuckDuckGo' => 'duckduckbot',
47 | 'EveryoneSocialBot' => 'everyonesocialbot',
48 | 'Exalead' => 'exabot',
49 | 'Facebook' => 'facebook',
50 | 'Facebook Preview' => 'facebookexternalhit',
51 | 'faceBot' => 'facebot',
52 | 'Feedfetcher' => 'Feedfetcher',
53 | 'Femtosearch' => 'FemtosearchBot',
54 | 'Findexa' => 'findexa',
55 | 'Flipboard Preview' => 'FlipboardProxy',
56 | 'Gais' => 'gaisbo',
57 | 'Gigabot' => 'gigabot',
58 | 'Gluten Free' => 'gluten free crawler',
59 | 'Go-http-client' => 'Go-http-client',
60 | 'Goforit' => 'GOFORITBOT',
61 | 'Google' => 'google',
62 | 'GPTBot' => 'GPTBot',
63 | 'Grid' => 'gridbot',
64 | 'GroupHigh' => 'grouphigh',
65 | 'Heritrix' => 'heritrix',
66 | 'IA Archiver' => 'ia_archiver',
67 | 'Inktomi' => 'slurp@inktomi',
68 | 'IPS Agent' => 'ips-agent',
69 | 'James' => 'james bot',
70 | 'Jobboerse' => 'Jobboerse',
71 | 'KomodiaBot' => 'komodiabot',
72 | 'Konqueror' => 'konqueror',
73 | 'Lindex' => 'linkdexbot',
74 | 'Linguee' => 'Linguee',
75 | 'Linkfluence' => 'linkfluence',
76 | 'Lycos' => 'lycos',
77 | 'Maui' => 'mauibot',
78 | 'Mediatoolkit' => 'mediatoolkitbot',
79 | 'MegaIndex' => 'MegaIndex',
80 | 'MetaFeedly' => 'MetaFeedly',
81 | 'MetaURI' => 'metauri',
82 | 'MJ12bot' => 'mj12bot',
83 | 'MojeekBot' => 'mojeekBot',
84 | 'Moreover' => 'moreover',
85 | 'MSN' => 'msnbot',
86 | 'NBot' => 'nbot',
87 | 'NextLinks' => 'findlinks',
88 | 'Node-Fetch' => 'node-fetch',
89 | 'oBot' => 'oBot',
90 | 'Omgili' => 'omgili',
91 | 'Panscient' => 'panscient.com',
92 | 'PaperLiBot' => 'paperliBot',
93 | 'PetalBot' => 'PetalBot',
94 | 'PhantomJS' => 'phantomjs',
95 | 'Picsearch' => 'picsearch',
96 | 'Pinterestbot' => 'Pinterestbot',
97 | 'Proximic' => 'proximic',
98 | 'PubSub' => 'pubsub',
99 | 'Python' => 'Python',
100 | 'Radian6' => 'radian6',
101 | 'RadioUserland' => 'userland',
102 | 'Re-re Studio' => 'Re-re Studio',
103 | 'RyteBot' => 'RyteBot',
104 | 'Moz' => 'rogerbot',
105 | 'Qwantify' => 'Qwantify',
106 | 'Scoutjet' => 'Scoutjet',
107 | 'Scrapy' => 'Scrapy',
108 | 'Screaming Frog SEO Spider' => 'Screaming Frog SEO Spider',
109 | 'SEOkicks' => 'seokicks-robot',
110 | 'Semanticbot' => 'Semanticbot',
111 | 'SemrushBot' => 'semrushbot',
112 | 'SerendeputyBot' => 'serendeputybot',
113 | 'Seznam' => 'seznam',
114 | 'SirdataBot ' => 'SirdataBot ',
115 | 'SiteExplorer' => 'siteexplorer',
116 | 'Sixtrix' => 'SIXTRIX',
117 | 'Slurp' => 'slurp',
118 | 'SMTBot' => 'SMTBot',
119 | 'Sogou' => 'Sogou',
120 | 'OpenLinkProfiler.org' => 'spbot',
121 | 'SurveyBot' => 'surveybot',
122 | 'Syndic8' => 'syndic8',
123 | 'Technorati' => 'technorati',
124 | 'TelegramBot' => 'telegrambot',
125 | 'Tiny Tiny RSS' => 'tt-rss',
126 | 'Thither' => 'thither',
127 | 'TraceMyFile' => 'tracemyfile',
128 | 'Trendsmap' => 'trendsmap',
129 | 'Turnitin.com' => 'turnitinbot',
130 | 'The Tweeted Times' => 'tweetedtimes',
131 | 'TweetmemeBot' => 'tweetmemeBot',
132 | 'Twingly' => 'twingly',
133 | 'X' => 'twitterbot',
134 | 'VoilaBot' => 'VoilaBot',
135 | 'Wget' => 'wget',
136 | 'WhatsApp' => 'whatsapp',
137 | 'WhoisSource' => 'surveybot',
138 | 'WiseNut' => 'zyborg',
139 | 'Wotbox' => 'wotbox',
140 | 'Xenu Link Sleuth' => 'xenu link sleuth',
141 | 'XoviBot' => 'xoviBot',
142 | 'Yahoo' => 'yahoo',
143 | 'Yandex' => 'yandex',
144 | 'Disqus' => 'disqus',
145 | 'YisouSpider' => 'yisouspider'
146 | );
147 |
148 | return apply_filters( 'useronline_bots', $bots );
149 | }
150 |
151 |
--------------------------------------------------------------------------------
/core.php:
--------------------------------------------------------------------------------
1 | get_var( "SELECT COUNT( * ) FROM $wpdb->useronline" ) );
17 |
18 | return self::$useronline;
19 | }
20 |
21 | static function init( $options, $most ) {
22 | self::$options = $options;
23 | self::$most = $most;
24 |
25 | add_action( 'plugins_loaded', array( __CLASS__, 'wp_stats_integration' ) );
26 |
27 | add_action( 'admin_head', array( __CLASS__, 'record' ) );
28 | add_action( 'wp_head', array( __CLASS__, 'record' ) );
29 |
30 | add_action( 'wp_footer', array( __CLASS__, 'scripts' ) );
31 |
32 | add_action( 'wp_ajax_useronline', array( __CLASS__, 'ajax' ) );
33 | add_action( 'wp_ajax_nopriv_useronline', array( __CLASS__, 'ajax' ) );
34 |
35 | add_shortcode( 'page_useronline', 'users_online_page' );
36 |
37 | if ( self::$options->names )
38 | add_filter( 'useronline_display_user', array( __CLASS__, 'linked_names' ), 10, 2 );
39 | }
40 |
41 | static function linked_names( $name, $user ) {
42 | if ( !$user->user_id )
43 | return $name;
44 |
45 | return html_link( get_author_posts_url( $user->user_id ), $name );
46 | }
47 |
48 | static function scripts() {
49 | if ( !self::$add_script )
50 | return;
51 |
52 | $js_dev = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '.dev' : '';
53 |
54 | wp_enqueue_script( 'wp-useronline', plugins_url( "useronline$js_dev.js", __FILE__ ), array( 'jquery' ), '2.80', true );
55 | wp_localize_script( 'wp-useronline', 'useronlineL10n', array(
56 | 'ajax_url' => admin_url( 'admin-ajax.php' ),
57 | 'timeout' => self::$options->timeout * 1000
58 | ) );
59 |
60 | scbUtil::do_scripts('wp-useronline');
61 | }
62 |
63 | static function record( $page_url = '', $page_title = '' ) {
64 | require_once dirname(__FILE__) . '/bots.php';
65 |
66 | global $wpdb;
67 |
68 | if ( empty( $page_url ) ) {
69 | $page_url = wp_strip_all_tags( $_SERVER['REQUEST_URI'] );
70 | }
71 |
72 | if ( empty( $page_title ) ) {
73 | $page_title = wp_strip_all_tags( self::get_title() );
74 | }
75 |
76 | if ( isset( $_SERVER['HTTP_REFERER'] ) ) {
77 | $referral = wp_strip_all_tags( $_SERVER['HTTP_REFERER'] );
78 | } else {
79 | $referral = '';
80 | }
81 |
82 | $user_ip = wp_strip_all_tags( self::get_ip() );
83 |
84 | if ( isset( $_SERVER['HTTP_USER_AGENT'] ) ) {
85 | $user_agent = wp_strip_all_tags( $_SERVER['HTTP_USER_AGENT'] );
86 | } else {
87 | $user_agent = '';
88 | }
89 |
90 | $current_user = wp_get_current_user();
91 |
92 | // Check For Bot
93 | $bots = useronline_get_bots();
94 |
95 | $bot_found = false;
96 | foreach ( $bots as $name => $lookfor ) {
97 | if ( stristr( $user_agent, $lookfor ) !== false ) {
98 | $user_id = 0;
99 | $user_name = $name;
100 | $username = $lookfor;
101 | $user_type = 'bot';
102 | $bot_found = true;
103 |
104 | break;
105 | }
106 | }
107 |
108 | // If No Bot Is Found, Then We Check Members And Guests
109 | if ( !$bot_found ) {
110 | if ( $current_user->ID ) {
111 | // Check For Member
112 | $user_id = $current_user->ID;
113 | $user_name = $current_user->display_name;
114 | $user_type = 'member';
115 | $where = $wpdb->prepare( "WHERE user_id = %d", $user_id );
116 | } elseif ( !empty( $_COOKIE['comment_author_'.COOKIEHASH] ) ) {
117 | // Check For Comment Author ( Guest )
118 | $user_id = 0;
119 | $user_name = trim( wp_strip_all_tags( $_COOKIE['comment_author_'.COOKIEHASH] ) );
120 | $user_type = 'guest';
121 | } else {
122 | // Check For Guest
123 | $user_id = 0;
124 | $user_name = __( 'Guest', 'wp-useronline' );
125 | $user_type = 'guest';
126 | }
127 | }
128 |
129 | // Current GMT Timestamp
130 | $timestamp = current_time( 'mysql' );
131 |
132 | // Purge table
133 | $wpdb->query( $wpdb->prepare( "DELETE FROM $wpdb->useronline WHERE (user_id <> 0 AND user_id = %d) OR (user_id = 0 AND user_agent = %s AND user_ip = %s) OR (timestamp < DATE_SUB(%s, INTERVAL %d SECOND))", $user_id, $user_agent, $user_ip, $timestamp, self::$options->timeout ) );
134 |
135 | // Insert Users
136 | $data = compact( 'timestamp', 'user_type', 'user_id', 'user_name', 'user_ip', 'user_agent', 'page_title', 'page_url', 'referral' );
137 | $data = stripslashes_deep( $data );
138 | $wpdb->replace( $wpdb->useronline, $data );
139 |
140 | // Count Users Online
141 | self::$useronline = intval( $wpdb->get_var( "SELECT COUNT( * ) FROM $wpdb->useronline" ) );
142 |
143 | // Maybe Update Most User Online
144 | if ( self::$useronline > self::$most->count ) {
145 | self::$most->update( array(
146 | 'count' => self::$useronline,
147 | 'date' => current_time( 'timestamp' )
148 | ) );
149 | }
150 | }
151 |
152 | private function clear_table() {
153 | global $wpdb;
154 |
155 | $wpdb->query( "DELETE FROM $wpdb->useronline" );
156 | }
157 |
158 | static function ajax() {
159 | $mode = trim( $_POST['mode'] );
160 |
161 | $page_title = strip_tags( $_POST['page_title'] );
162 |
163 | $page_url = str_replace( get_bloginfo( 'url' ), '', $_POST['page_url'] );
164 |
165 | if ( $page_url != $_POST['page_url'] )
166 | self::record( $page_url, $page_title );
167 |
168 | switch( $mode ) {
169 | case 'count':
170 | users_online();
171 | break;
172 | case 'browsing-site':
173 | users_browsing_site();
174 | break;
175 | case 'browsing-page':
176 | users_browsing_page($page_url);
177 | break;
178 | case 'details':
179 | echo users_online_page();
180 | break;
181 | }
182 |
183 | die;
184 | }
185 |
186 | static function wp_stats_integration() {
187 | if ( function_exists( 'stats_page' ) )
188 | require_once dirname( __FILE__ ) . '/wp-stats.php';
189 | }
190 |
191 | private static function get_title() {
192 | if ( is_admin() && function_exists( 'get_admin_page_title' ) ) {
193 | $page_title = ' » ' . __( 'Admin', 'wp-useronline' ) . ' » ' . get_admin_page_title();
194 | } else {
195 | $page_title = wp_title( '»', false );
196 | if ( empty( $page_title ) )
197 | $page_title = ' » ' . strip_tags( $_SERVER['REQUEST_URI'] );
198 | elseif ( is_singular() )
199 | $page_title = ' » ' . $page_title;
200 | }
201 | $page_title = get_bloginfo( 'name' ) . $page_title;
202 |
203 | return $page_title;
204 | }
205 |
206 | private static function get_ip() {
207 | if ( isset( $_SERVER["HTTP_X_FORWARDED_FOR"] ) )
208 | $ip_address = $_SERVER["HTTP_X_FORWARDED_FOR"];
209 | else
210 | $ip_address = $_SERVER["REMOTE_ADDR"];
211 |
212 | list( $ip_address ) = explode( ',', $ip_address );
213 |
214 | return $ip_address;
215 | }
216 | }
217 |
218 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # WP-UserOnline
2 | Contributors: GamerZ
3 | Donate link: https://lesterchan.net/site/donation/
4 | Tags: useronline, usersonline, wp-useronline, online, widget
5 | Requires at least: 4.6
6 | Tested up to: 6.7
7 | Stable tag: 2.88.9
8 | License: GPLv2 or later
9 | License URI: http://www.gnu.org/licenses/gpl-2.0.html
10 |
11 | Enable you to display how many users are online on your Wordpress blog with detailed statistics.
12 |
13 | ## Description
14 | This plugin enables you to display how many users are online on your Wordpress site, with detailed statistics of where they are and who they are (Members/Guests/Search Bots).
15 |
16 | ### Usage (With Widget)
17 | 1. Go to `WP-Admin -> Appearance -> Widgets`
18 | 1. The widget name is UserOnline .
19 | 1. Scroll down for instructions on how to create a *UserOnline Page*.
20 |
21 | ### Usage (Without Widget)
22 | * Open `wp-content/themes//sidebar.php` and add Anywhere:
23 |
24 | ```php
25 |
26 | Users online:
27 |
28 | ```
29 |
30 | ### Development
31 | [https://github.com/lesterchan/wp-useronline](https://github.com/lesterchan/wp-useronline "https://github.com/lesterchan/wp-useronline")
32 |
33 | ### Credits
34 | * Plugin icon by [Freepik](http://www.freepik.com) from [Flaticon](http://www.flaticon.com)
35 |
36 | ### Donations
37 | I spent most of my free time creating, updating, maintaining and supporting these plugins, if you really love my plugins and could spare me a couple of bucks, I will really appreciate it. If not feel free to use it without any obligations.
38 |
39 | ## Screenshots
40 |
41 | 1. Admin - Dashboard's Right Now
42 | 2. UserOnline Page
43 | 3. Admin - Settings Page
44 |
45 | ## Frequently Asked Questions
46 |
47 | ### Creating A UserOnline Page
48 | 1. Go to `WP-Admin -> Pages -> Add New`
49 | 1. Type any title you like in the post's title area
50 | 1. If you ARE using nice permalinks, after typing the title, WordPress will generate the permalink to the page. You will see an 'Edit' link just beside the permalink.
51 | 1. Click 'Edit' and type in `useronline` in the text field and click 'Save'.
52 | 1. Type `[page_useronline]` in the post's content area
53 | 1. Click 'Publish'
54 |
55 | If you ARE NOT using nice permalinks, you need to go to `WP-Admin -> Settings -> UserOnline` and under 'UserOnline URL', you need to fill in the URL to the UserOnline Page you created above.
56 |
57 | ### To Display Most Number Of Users Online
58 | * Use:
59 | ```php
60 |
61 | Most Users Ever Online Is On
62 |
63 | ```
64 |
65 | ### To Display Users Browsing Site
66 | * Use:
67 | ```php
68 |
69 |
70 |
71 | ```
72 |
73 | ### To Display Users Browsing A Page
74 | * Use:
75 | ```php
76 |
77 |
78 |
79 | ```
80 |
81 | ### Error on activation: "Parse error: syntax error, unexpected..."
82 |
83 | Make sure your host is running PHP 5. The only foolproof way to do this is to add this line to wp-config.php (after the opening `templates['useronline'];
10 | $template = str_ireplace( '%PAGE_URL%', UserOnline_Core::$options->url, $template );
11 | $template = str_ireplace( '%MOSTONLINE_COUNT%', get_most_users_online(), $template );
12 | $template = str_ireplace( '%MOSTONLINE_DATE%', get_most_users_online_date(), $template );
13 |
14 | return UserOnline_Template::format_count( get_users_online_count(), 'user', $template );
15 | }
16 |
17 | ### Function: Display UserOnline Count
18 | function users_online_count() {
19 | echo number_format_i18n( get_useronline_count() );
20 | }
21 |
22 | function get_users_online_count() {
23 | return UserOnline_Core::get_user_online_count();
24 | }
25 |
26 | ### Function: Display Max UserOnline
27 | function most_users_online() {
28 | echo number_format_i18n( get_most_users_online() );
29 | }
30 |
31 | function get_most_users_online() {
32 | return intval( UserOnline_Core::$most->count );
33 | }
34 |
35 | ### Function: Display Max UserOnline Date
36 | function most_users_online_date() {
37 | echo get_most_users_online_date();
38 | }
39 |
40 | function get_most_users_online_date() {
41 | return UserOnline_Template::format_date( UserOnline_Core::$most->date );
42 | }
43 |
44 | ### Function: Display Users Browsing The Site
45 | function users_browsing_site() {
46 | echo get_users_browsing_site();
47 | }
48 |
49 | function get_users_browsing_site() {
50 | return UserOnline_Template::compact_list( 'site' );
51 | }
52 |
53 | ### Function: Display Users Browsing The ( Current ) Page
54 | function users_browsing_page( $page_url = '' ) {
55 | echo get_users_browsing_page( $page_url );
56 | }
57 |
58 | function get_users_browsing_page( $page_url = '' ) {
59 | return UserOnline_Template::compact_list( 'page', 'html', $page_url );
60 | }
61 |
62 | ### Function: UserOnline Page
63 | function users_online_page() {
64 | global $wpdb;
65 |
66 | $usersonline = $wpdb->get_results( "SELECT * FROM $wpdb->useronline ORDER BY timestamp DESC" );
67 |
68 | $user_buckets = array();
69 | foreach ( $usersonline as $useronline )
70 | $user_buckets[$useronline->user_type][] = $useronline;
71 |
72 | $user_buckets = apply_filters( 'useronline_buckets', $user_buckets );
73 |
74 | $counts = UserOnline_Template::get_counts( $user_buckets );
75 |
76 | $nicetexts = array();
77 | foreach ( array( 'user', 'member', 'guest', 'bot' ) as $user_type )
78 | $nicetexts[$user_type] = UserOnline_Template::format_count( $counts[$user_type], $user_type );
79 |
80 | $text = _n(
81 | 'There is %s online now: %s , %s and %s .',
82 | 'There are a total of %s online now: %s , %s and %s .',
83 | $counts['user'], 'wp-useronline'
84 | );
85 |
86 | $output =
87 | html( 'div id="useronline-details"',
88 | html( 'p', vsprintf( $text, $nicetexts ) )
89 | .html( 'p', UserOnline_Template::format_most_users() )
90 | .UserOnline_Template::detailed_list( $counts, $user_buckets, $nicetexts )
91 | );
92 |
93 | return apply_filters( 'useronline_page', $output );
94 | }
95 |
96 | ### Function Check If User Is Online
97 | function is_user_online( $user_id ) {
98 | global $wpdb;
99 |
100 | return (bool) $wpdb->get_var( $wpdb->prepare( "SELECT COUNT( * ) FROM $wpdb->useronline WHERE user_id = %d LIMIT 1", $user_id ) );
101 | }
102 |
103 | function get_useronline_( $output, $type = 'site' ) {
104 | return UserOnline_Template::compact_list( $type, $output );
105 | }
106 |
107 | class UserOnline_Template {
108 |
109 | private static $cache = array();
110 |
111 | static function compact_list( $type, $output = 'html', $page_url = '') {
112 | UserOnline_Core::$add_script = true;
113 |
114 | if ( !isset( self::$cache[$type] ) ) {
115 | global $wpdb;
116 |
117 | if ( 'site' == $type ) {
118 | $where = '';
119 | } elseif ( 'page' == $type ) {
120 | if ( empty($page_url) )
121 | $page_url = $_SERVER['REQUEST_URI'];
122 | $where = $wpdb->prepare( 'WHERE page_url = %s', $page_url );
123 | }
124 |
125 | self::$cache[$type . $page_url] = $wpdb->get_results( "SELECT * FROM $wpdb->useronline $where ORDER BY timestamp DESC" );
126 | }
127 |
128 | $users = self::$cache[$type . $page_url];
129 |
130 | if ( 'list' == $output )
131 | return $users;
132 |
133 | $buckets = array();
134 | foreach ( $users as $user )
135 | $buckets[$user->user_type][] = $user;
136 |
137 | if ( 'buckets' == $output )
138 | return $buckets;
139 |
140 | $counts = self::get_counts( $buckets );
141 |
142 | if ( 'counts' == $output )
143 | return $counts;
144 |
145 | // Template - Naming Conventions
146 | $naming = UserOnline_Core::$options->naming;
147 |
148 | // Template - User(s) Browsing Site
149 | $template = UserOnline_Core::$options->templates["browsing$type"];
150 |
151 | // Nice Text For Users
152 | $output = self::format_count( $counts['user'], 'user', $template['text'] );
153 |
154 | // Print Member Name
155 | $temp_member = '';
156 | $members = @$buckets['member'];
157 | if ( $members ) {
158 | $temp_member = array();
159 | foreach ( $members as $member )
160 | $temp_member[] = self::format_name( $member );
161 | $temp_member = implode( $template['separators']['members'], $temp_member );
162 | }
163 | $output = str_ireplace( '%MEMBER_NAMES%', $temp_member, $output );
164 |
165 | // Counts
166 | foreach ( array( 'member', 'guest', 'bot' ) as $user_type ) {
167 | if ( $counts[$user_type] > 1 )
168 | $number = str_ireplace( '%COUNT%', number_format_i18n( $counts[$user_type] ), $naming[$user_type . 's'] );
169 | elseif ( $counts[$user_type] == 1 )
170 | $number = $naming[$user_type];
171 | else
172 | $number = '';
173 | $output = str_ireplace( "%{$user_type}S%", $number, $output );
174 | }
175 |
176 | // SEPARATORs
177 | $separator = ( $counts['member'] && $counts['guest'] ) ? $template['separators']['guests'] : '';
178 | $output = str_ireplace( '%GUESTS_SEPARATOR%', $separator, $output );
179 |
180 | $separator = ( ( $counts['guest'] || $counts['member'] ) && $counts['bot'] ) ? $template['separators']['bots'] : '';
181 | $output = str_ireplace( '%BOTS_SEPARATOR%', $separator, $output );
182 |
183 | return $output;
184 | }
185 |
186 | static function detailed_list( $counts, $user_buckets, $nicetexts ) {
187 | UserOnline_Core::$add_script = true;
188 |
189 | if ( $counts['user'] == 0 )
190 | return html( 'h2', __( 'No one is online now.', 'wp-useronline' ) );
191 |
192 | $_on = __( 'on', 'wp-useronline' );
193 | $_url = __( 'url', 'wp-useronline' );
194 | $_referral = __( 'referral', 'wp-useronline' );
195 |
196 | $output = '';
197 | foreach ( array( 'member', 'guest', 'bot' ) as $user_type ) {
198 | if ( !$counts[$user_type] )
199 | continue;
200 |
201 | $count = $counts[$user_type];
202 | $users = $user_buckets[$user_type];
203 | $nicetext = $nicetexts[$user_type];
204 |
205 | $output .= html( 'h2', $nicetext . ' ' . __( 'Online Now', 'wp-useronline' ) );
206 |
207 | $i=1;
208 | foreach ( $users as $user ) {
209 | $nr = number_format_i18n( $i++ );
210 | $name = self::format_name( $user );
211 | $user_ip = self::format_ip( $user );
212 | $date = self::format_date( $user->timestamp, true );
213 |
214 | if ( current_user_can( 'edit_users' ) || false === strpos( $user->page_url, 'wp-admin' ) ) {
215 | $page_title = esc_html( $user->page_title );
216 | $current_link = self::format_link( $user->page_url, $_url );
217 | $referral_link = self::format_link( $user->referral, $_referral );
218 | }
219 |
220 | $output .= apply_filters("useronline_custom_template", "#$nr - $name $user_ip $_on $date $page_title $current_link $referral_link
\n", $nr, $user);
221 | }
222 | }
223 |
224 | return $output;
225 | }
226 |
227 | static function format_link($url, $title) {
228 | if ( !empty($url) )
229 | return '[' . html_link( $url, $title ) . ']';
230 |
231 | return '';
232 | }
233 |
234 | static function format_ip( $user ) {
235 | $ip = esc_attr( $user->user_ip );
236 |
237 | if ( current_user_can( 'edit_users' ) && !empty( $ip ) && $ip != 'unknown' ) {
238 | return
239 | html( 'span', array('dir' => 'ltr'),
240 | html( 'a', array(
241 | 'href' => esc_url( 'http://whois.domaintools.com/' . $ip ),
242 | 'title' => esc_attr( $user->user_agent )
243 | ), $ip )
244 | );
245 | }
246 | }
247 |
248 | static function format_date( $date, $mysql = false ) {
249 | if ( $mysql )
250 | return mysql2date( sprintf( __( '%s @ %s', 'wp-useronline' ), get_option( 'date_format' ), get_option( 'time_format' ) ), $date, true );
251 |
252 | return date_i18n( sprintf( __( '%s @ %s', 'wp-useronline' ), get_option( 'date_format' ), get_option( 'time_format' ) ), $date );
253 | }
254 |
255 | static function format_name( $user ) {
256 | return apply_filters( 'useronline_display_user', esc_html( $user->user_name ), $user );
257 | }
258 |
259 | static function format_count( $count, $user_type, $template = false ) {
260 | $i = ( $count == 1 ) ? '' : 's';
261 | $string = UserOnline_Core::$options->naming[$user_type . $i];
262 |
263 | $output = str_ireplace( '%COUNT%', number_format_i18n( $count ), $string );
264 |
265 | if ( false === $template )
266 | return $output;
267 |
268 | return str_ireplace( '%USERS%', $output, $template );
269 | }
270 |
271 | static function format_most_users() {
272 | return sprintf( __( 'Most users ever online were %s , on %s ', 'wp-useronline' ),
273 | number_format_i18n( get_most_users_online() ),
274 | get_most_users_online_date()
275 | );
276 | }
277 |
278 | static function get_counts( $buckets ) {
279 | $counts = array();
280 | $total = 0;
281 | foreach ( array( 'member', 'guest', 'bot' ) as $user_type ) {
282 | $count = isset( $buckets[$user_type] ) ? count( @$buckets[$user_type] ) : 0;
283 | $total += $counts[$user_type] = $count;
284 | }
285 |
286 | $counts['user'] = $total;
287 |
288 | return $counts;
289 | }
290 | }
291 |
292 |
--------------------------------------------------------------------------------
/admin.php:
--------------------------------------------------------------------------------
1 | textdomain = 'wp-useronline';
7 |
8 | $this->args = array(
9 | 'page_title' => __( 'Users Online Now', $this->textdomain ),
10 | 'menu_title' => __( 'WP-UserOnline', $this->textdomain ),
11 | 'page_slug' => 'useronline',
12 | 'parent' => 'index.php',
13 | 'action_link' => false,
14 | 'capability' => 'list_users',
15 | );
16 |
17 | add_action( 'rightnow_end', array( $this, 'rightnow' ) );
18 | }
19 |
20 | function rightnow() {
21 | if ( !current_user_can( 'manage_options' ) )
22 | return;
23 |
24 | $total_users = get_users_online_count();
25 |
26 | $str = _n(
27 | "There is %s user online now.",
28 | "There are a total of %s users online now.",
29 | $total_users, 'wp-useronline'
30 | );
31 |
32 | $out = sprintf( $str, add_query_arg( 'page', $this->args['page_slug'], admin_url( 'index.php' ) ), number_format_i18n( $total_users ) );
33 | $out .= ' ';
34 |
35 | if ( $tmp = get_users_browsing_site() )
36 | $out .= $tmp . ' ';
37 |
38 | $out .= UserOnline_Template::format_most_users();
39 |
40 | echo html( 'p', $out );
41 | }
42 |
43 | function page_content() {
44 | echo users_online_page();
45 | }
46 | }
47 |
48 |
49 | class UserOnline_Options extends scbAdminPage {
50 |
51 | public function setup() {
52 | $this->textdomain = 'wp-useronline';
53 |
54 | $this->args = array(
55 | 'page_title' => __( 'UserOnline Options', $this->textdomain ),
56 | 'menu_title' => __( 'UserOnline', $this->textdomain ),
57 | 'page_slug' => 'useronline-settings',
58 | );
59 |
60 | $this->option_name = 'useronline';
61 | }
62 |
63 | public function validate( $options, $old_data = array() ) {
64 | $options['timeout'] = isset( $options['timeout'] ) ? absint( $options['timeout'] ) : 0;
65 | $options['url'] = ! empty( $options['url'] ) ? esc_url_raw( trim( $options['url'] ) ) : '';
66 | $options['names'] = ! empty( $options['names'] ) ? (int) $options['names'] : 0;
67 |
68 | foreach ( $options['naming'] as $key => $template ) {
69 | $options['naming'][$key] = wp_kses_post( trim( $template ) );
70 | }
71 | foreach ( $options['templates'] as $key => $template ) {
72 | if ( is_array( $template ) ) {
73 | $options['templates'][$key]['text'] = wp_kses_post( trim( $template['text'] ) );
74 | if ( ! empty( $template['separators'] ) && is_array( $template['separators'] ) ) {
75 | foreach( $template['separators'] as $seperator_key => $seperator_value ) {
76 | $options['templates'][$key]['separators'][$seperator_key] = wp_kses_post( trim( $seperator_value ) );
77 | }
78 | }
79 | } else {
80 | $options['templates'][$key] = wp_kses_post( trim( $template ) );
81 | }
82 | }
83 |
84 | return $options;
85 | }
86 |
87 | public function page_head() {
88 | ?>
89 |
95 |
96 |
109 | options->get();
114 | $defaults = $this->options->get_defaults();
115 |
116 | ?>
117 |
190 |
195 |
196 |
197 |
198 |
199 | - %COUNT%
200 |
201 |
202 |
203 |
227 |
228 |
229 |
230 |
235 |
236 |
237 |
238 |
239 | - %USERS%
240 | - %PAGE_URL%
241 | - %MOSTONLINE_COUNT%
242 | - %MOSTONLINE_DATE%
243 |
244 |
245 |
246 | input( array(
247 | 'type' => 'textarea',
248 | 'name' => array( 'templates', 'useronline' ),
249 | ), $data ); ?>
250 |
251 |
252 |
257 |
258 |
259 |
260 |
261 | - %USERS%
262 | - %MEMBERS%
263 | - %MEMBER_NAMES%
264 | - %GUESTS_SEPARATOR%
265 | - %GUESTS%
266 | - %BOTS_SEPARATOR%
267 | - %BOTS%
268 |
269 |
270 |
271 |
289 |
290 | input( array(
291 | 'type' => 'textarea',
292 | 'name' => array( 'templates', $option, 'text' )
293 | ), $data ); ?>
294 |
295 |
296 |