Slimstat Analytics - Version 4.8.6

Version Description

  • [New] Slimstat can now track most WordPress redirects and mark them with the appropriate content type.
  • [Update] The GDPR compliance through third-party tools is now more flexible and allows admins to specify name/value pairs so that the cookie must CONTAIN the given string.
  • [Update] Simplified code that manages the sidebar menu.
  • [Update] Reorganized code that manages the plugin options.
  • [Update] Rewrote the portion of code that manages tracker errors, which are now saved in a separate field in the database.
  • [Update] Reintroduced feature to hide certain report pages when no reports are assigned to them.
  • [Update] Decrease the number of database requests needed to record a new pageview.
  • [Fix] Entries with a trailing slash and ones without were being listed as separate in Top Web Pages.
  • [Fix] Typo in one of the conditions definining the Top Bots report.
Download this release

Release Info

Developer coolmann
Plugin Icon 128x128 Slimstat Analytics
Version 4.8.6
Comparing to
See all releases

Code changes from version 4.8.5.1 to 4.8.6

CHANGELOG.md CHANGED
@@ -1,4 +1,15 @@
1
  ## Changelog ##
 
 
 
 
 
 
 
 
 
 
 
2
  ### 4.8.5.1 ###
3
  * [Fix] A bug was affecting the way shortcodes were being displayed on the website (thank you, [inndesign](https://wordpress.org/support/topic/crashes-avada-theme-in-chrome/)).
4
  * [Fix] Some icons in the Access Log were broken and not displayed as expected.
1
  ## Changelog ##
2
+ ### 4.8.6 ###
3
+ * [New] Slimstat can now track most WordPress redirects and mark them with the appropriate content type.
4
+ * [Update] The GDPR compliance through third-party tools is now more flexible and allows admins to specify name/value pairs so that the cookie must CONTAIN the given string.
5
+ * [Update] Simplified code that manages the sidebar menu.
6
+ * [Update] Reorganized code that manages the plugin options.
7
+ * [Update] Rewrote the portion of code that manages tracker errors, which are now saved in a separate field in the database.
8
+ * [Update] Reintroduced feature to hide certain report pages when no reports are assigned to them.
9
+ * [Update] Decrease the number of database requests needed to record a new pageview.
10
+ * [Fix] Entries with a trailing slash and ones without were being listed as separate in Top Web Pages.
11
+ * [Fix] Typo in one of the conditions definining the Top Bots report.
12
+
13
  ### 4.8.5.1 ###
14
  * [Fix] A bug was affecting the way shortcodes were being displayed on the website (thank you, [inndesign](https://wordpress.org/support/topic/crashes-avada-theme-in-chrome/)).
15
  * [Fix] Some icons in the Access Log were broken and not displayed as expected.
admin/config/index.php CHANGED
@@ -5,101 +5,9 @@ if ( !function_exists( 'add_action' ) ) {
5
  exit(0);
6
  }
7
 
 
8
  $current_tab = empty( $_GET[ 'tab' ] ) ? 1 : intval( $_GET[ 'tab' ] );
9
 
10
- // Some options require some extra processing
11
- if ( $current_tab == 6 && !empty( $_REQUEST[ 'options' ] ) ) {
12
- // DB Indexes
13
- if ( !empty( $_REQUEST[ 'options' ][ 'db_indexes' ] ) && wp_slimstat::$settings[ 'db_indexes' ] == 'no' ) {
14
- wp_slimstat::$wpdb->query( "ALTER TABLE {$GLOBALS[ 'wpdb' ]->prefix}slim_stats ADD INDEX {$GLOBALS[ 'wpdb' ]->prefix}stats_resource_idx( resource( 20 ) )" );
15
- wp_slimstat::$wpdb->query( "ALTER TABLE {$GLOBALS[ 'wpdb' ]->prefix}slim_stats ADD INDEX {$GLOBALS[ 'wpdb' ]->prefix}stats_browser_idx( browser( 10 ) )" );
16
- wp_slimstat::$wpdb->query( "ALTER TABLE {$GLOBALS[ 'wpdb' ]->prefix}slim_stats ADD INDEX {$GLOBALS[ 'wpdb' ]->prefix}stats_searchterms_idx( searchterms( 15 ) )" );
17
- wp_slimstat_admin::$faulty_fields[] = __( 'Congratulations! Slimstat Analytics is now optimized for <a href="https://www.youtube.com/watch?v=ygE01sOhzz0" target="_blank">ludicrous speed</a>.', 'wp-slimstat' );
18
- }
19
- else if ( empty( $_REQUEST[ 'options' ][ 'db_indexes' ] ) && wp_slimstat::$settings[ 'db_indexes' ] == 'on' ) {
20
- // An empty value means that the toggle has been switched to "Off"
21
- wp_slimstat::$wpdb->query( "ALTER TABLE {$GLOBALS[ 'wpdb' ]->prefix}slim_stats DROP INDEX {$GLOBALS[ 'wpdb' ]->prefix}stats_resource_idx" );
22
- wp_slimstat::$wpdb->query( "ALTER TABLE {$GLOBALS[ 'wpdb' ]->prefix}slim_stats DROP INDEX {$GLOBALS[ 'wpdb' ]->prefix}stats_browser_idx");
23
- wp_slimstat::$wpdb->query( "ALTER TABLE {$GLOBALS[ 'wpdb' ]->prefix}slim_stats DROP INDEX {$GLOBALS[ 'wpdb' ]->prefix}stats_searchterms_idx");
24
- wp_slimstat_admin::$faulty_fields[] = __( 'Table indexes have been disabled. Enjoy the extra database space!', 'wp-slimstat' );
25
- }
26
-
27
- // MaxMind Data File
28
- if ( !empty( $_REQUEST[ 'options' ][ 'enable_maxmind' ] ) && wp_slimstat::$settings[ 'enable_maxmind' ] == 'no' ) {
29
- $error = wp_slimstat::download_maxmind_database();
30
-
31
- if ( !empty( $error ) ) {
32
- wp_slimstat_admin::$faulty_fields[] = $error;
33
- }
34
- else {
35
- wp_slimstat_admin::$faulty_fields[] = __( 'The geolocation database has been installed on your server.', 'wp-slimstat' );
36
- }
37
- }
38
- else if ( empty( $_REQUEST[ 'options' ][ 'enable_maxmind' ] ) && wp_slimstat::$settings[ 'enable_maxmind' ] == 'on' ) {
39
- $is_deleted = @unlink( wp_slimstat::$maxmind_path );
40
-
41
- if ( $is_deleted ) {
42
- wp_slimstat_admin::$faulty_fields[] = __( 'The geolocation database has been uninstalled from your server.', 'wp-slimstat' );
43
- }
44
- else {
45
- // Some users have reported that a directory is created, instead of a file
46
- $is_deleted = @rmdir( wp_slimstat::$maxmind_path );
47
-
48
- if ( $is_deleted ) {
49
- wp_slimstat_admin::$faulty_fields[] = __( 'The geolocation database has been uninstalled from your server.', 'wp-slimstat' );
50
- }
51
- else {
52
- wp_slimstat_admin::$faulty_fields[] = __( "The geolocation database could not be uninstalled from your server. Please make sure Slimstat can save files in your <code>wp-content/uploads</code> folder.", 'wp-slimstat' );
53
- }
54
- }
55
- }
56
-
57
- // Browscap Library
58
- if ( !empty( $_REQUEST[ 'options' ][ 'enable_browscap' ] ) && wp_slimstat::$settings[ 'enable_browscap' ] == 'no' ) {
59
- $error = slim_browser::update_browscap_database( true );
60
-
61
- if ( is_array( $error ) ) {
62
- wp_slimstat_admin::$faulty_fields[] = $error[ 1 ];
63
- }
64
- }
65
- else if ( empty( $_REQUEST[ 'options' ][ 'enable_browscap' ] ) && wp_slimstat::$settings[ 'enable_browscap' ] == 'on' ) {
66
- WP_Filesystem();
67
-
68
- if ( $GLOBALS[ 'wp_filesystem' ]->rmdir( wp_slimstat::$upload_dir . '/browscap-db-master/', true ) ) {
69
- wp_slimstat_admin::$faulty_fields[] = __( 'The Browscap data file has been uninstalled from your server.', 'wp-slimstat' );
70
- }
71
- else {
72
- wp_slimstat_admin::$faulty_fields[] = __( 'There was an error deleting the Browscap data folder on your server. Please check your permissions.', 'wp-slimstat' );
73
- }
74
- }
75
- }
76
-
77
- if ( !empty( $_REQUEST[ 'action' ] ) ) {
78
- switch ( $_REQUEST[ 'action' ] ) {
79
- case 'reset-tracker-error-status':
80
- wp_slimstat::$settings[ 'last_tracker_error' ] = array();
81
- break;
82
-
83
- case 'truncate-table':
84
- wp_slimstat::$wpdb->query( "DELETE te FROM {$GLOBALS[ 'wpdb' ]->prefix}slim_events te" );
85
- wp_slimstat::$wpdb->query( "OPTIMIZE TABLE {$GLOBALS[ 'wpdb' ]->prefix}slim_events" );
86
- wp_slimstat::$wpdb->query( "DELETE t1 FROM {$GLOBALS[ 'wpdb' ]->prefix}slim_stats t1" );
87
- wp_slimstat::$wpdb->query( "OPTIMIZE TABLE {$GLOBALS[ 'wpdb' ]->prefix}slim_stats" );
88
- wp_slimstat_admin::show_message( __( 'All the records were successfully deleted.', 'wp-slimstat' ) );
89
- break;
90
-
91
- default:
92
- break;
93
- }
94
- }
95
-
96
- $maxmind_last_modified = '';
97
- if ( file_exists( wp_slimstat::$maxmind_path ) && false !== ( $file_stat = @stat( wp_slimstat::$maxmind_path ) ) ) {
98
- $maxmind_last_modified = date_i18n( get_option( 'date_format' ), $file_stat[ 'mtime' ] );
99
- }
100
-
101
- $index_enabled = wp_slimstat::$wpdb->get_results( "SHOW INDEX FROM {$GLOBALS[ 'wpdb' ]->prefix}slim_stats WHERE Key_name = '{$GLOBALS[ 'wpdb' ]->prefix}stats_resource_idx'" );
102
-
103
  // Define all the options
104
  $settings = array(
105
  1 => array(
@@ -206,12 +114,12 @@ $settings = array(
206
  'opt_out_cookie_names' => array(
207
  'title' => __( 'Opt-out Cookies', 'wp-slimstat' ),
208
  'type'=> 'textarea',
209
- 'description'=> __( "If you are already using another tool to monitor which users opt-out of tracking, and assuming that this tool sets its own cookie to remember their selection, you can enter the cookie names and values in this field to let Slimstat comply with their choice. Please use the following format: <code>cookie_name=value</code>. Slimstat will track any visitor who sends a cookie that <strong>does not</strong> have that value. Separate multiple duplets with commas.", 'wp-slimstat' )
210
  ),
211
  'opt_in_cookie_names' => array(
212
  'title' => __( 'Opt-in Cookies', 'wp-slimstat' ),
213
  'type'=> 'textarea',
214
- 'description'=> __( "Similarly to the option here above, you can configure Slimstat to work with an opt-in mechanism. Please use the following format: <code>cookie_name=value</code>. Slimstat will only track visitors who send a cookie that <strong>has</strong> that value. Separate multiple duplets with commas.", 'wp-slimstat' )
215
  ),
216
  'opt_out_message' => array(
217
  'title' => __( 'Opt-out Message', 'wp-slimstat' ),
@@ -607,7 +515,7 @@ var SlimStatParams = {
607
  'filters_users_header' => array(
608
  'title' => __( 'Tracker Error', 'wp-slimstat' ),
609
  'type'=> 'plain-text',
610
- 'after_input_field' => ( !empty( wp_slimstat::$settings[ 'last_tracker_error' ][ 1 ] ) && !empty( wp_slimstat::$settings[ 'last_tracker_error' ][ 2 ] ) ) ? '<strong>[' . date_i18n( get_option( 'date_format' ), wp_slimstat::$settings[ 'last_tracker_error' ][ 2 ], true ) . ' ' . date_i18n( get_option( 'time_format' ), wp_slimstat::$settings[ 'last_tracker_error' ][ 2 ], true ) . '] ' . wp_slimstat::$settings[ 'last_tracker_error' ][ 0 ] . ' ' . wp_slimstat::$settings[ 'last_tracker_error' ][ 1 ] . '</strong><a class="slimstat-font-cancel" title="' . htmlentities( __( 'Reset this error', 'wp-slimstat' ), ENT_QUOTES, 'UTF-8' ) . '" href="' . wp_slimstat_admin::$config_url.$current_tab . '&amp;action=reset-tracker-error-status"></a>' : __( 'So far so good.', 'wp-slimstat' ),
611
  'description'=> __( 'The information here above is useful to troubleshoot issues with the tracker. <strong>Errors</strong> are returned when the tracker could not record a page view for some reason, and are indicative of some kind of malfunction. Please include the message here above when sending a <a href="https://support.wp-slimstat.com" target="_blank">support request</a>.', 'wp-slimstat' )
612
  ),
613
  'show_sql_debug' => array(
@@ -618,7 +526,6 @@ var SlimStatParams = {
618
  'db_indexes' => array(
619
  'title' => __( 'Increase Performance', 'wp-slimstat' ),
620
  'type'=> 'toggle',
621
- 'default_value' => !empty( $index_enabled ) ? 'on' : 'no',
622
  'description'=> __( 'Enable this option to add column indexes to the main Slimstat table. This will make SQL queries faster and increase the size of the table by about 30%.', 'wp-slimstat' )
623
  ),
624
 
@@ -630,7 +537,6 @@ var SlimStatParams = {
630
  'enable_maxmind' => array(
631
  'title' => __( 'MaxMind Geolocation', 'wp-slimstat' ),
632
  'type'=> 'toggle',
633
- 'default_value' => ( file_exists( wp_slimstat::$maxmind_path ) && false !== ( $file_stat = @stat( wp_slimstat::$maxmind_path ) ) ) ? 'on' : 'no',
634
  'description'=> __( "The <a href='https://dev.maxmind.com/geoip/geoip2/geolite2/' target='_blank'>MaxMind GeoLite2 library</a>, which Slimstat uses to geolocate your visitors, is released under the Creative Commons BY-SA 4.0 license, and cannot be directly bundled with the plugin because of license incompatibility issues. If you're getting an error after enabling this option, please <a href='https://slimstat.freshdesk.com/solution/articles/12000039798-how-to-manually-install-the-maxmind-geolocation-data-file-' target='_blank'>take a look at our knowledge base</a> to learn how to install this file manually.", 'wp-slimstat' ) . ( !empty( $maxmind_last_modified ) ? ' ' . sprintf ( __( 'Your data file was last downloaded on <strong>%s</strong>', 'wp-slimstat' ), $maxmind_last_modified ) : '' )
635
  ),
636
 
@@ -658,32 +564,339 @@ if ( version_compare( PHP_VERSION, '7.1', '>=' ) ) {
658
  $enable_browscap = array( 'enable_browscap' => array(
659
  'title' => __( 'Browscap Library', 'wp-slimstat' ),
660
  'type'=> 'toggle',
661
- 'default_value' => ( file_exists( slim_browser::$browscap_autoload_path ) && false !== ( $file_stat = @stat( slim_browser::$browscap_autoload_path ) ) ) ? 'on' : 'no',
662
  'description'=> __( "We are contributing to the <a href='https://browscap.org/' target='_blank'>Browscap Capabilities Project</a>, which we use to decode your visitors' user agent string into browser name and operating system. We use an <a href='https://github.com/slimstat/browscap-db' target='_blank'>optimized version of their data structure</a>, for improved performance. When enabled, Slimstat uses this library in addition to the built-in heuristic function, to determine your visitors' browser information. Updates are downloaded automatically every two weeks, when available.", 'wp-slimstat' ) . ( !empty( slim_browser::$browscap_local_version ) ? ' ' . sprintf( __( 'You are currently using version %s.' ), '<strong>' . slim_browser::$browscap_local_version . '</strong>' ) : '' )
663
  ) );
664
 
665
  $settings[ 6 ][ 'rows' ] = array_slice( $settings[ 6 ][ 'rows' ], 0, 6, true) + $enable_browscap + array_slice($settings[ 6 ][ 'rows' ], 6, NULL, true );
666
  }
667
 
 
668
  $settings = apply_filters( 'slimstat_options_on_page', $settings );
669
 
670
- $tabs_html = '';
671
- foreach ( $settings as $a_tab_id => $a_tab_info ) {
672
- if ( !empty( $a_tab_info[ 'rows' ] ) || !empty( $a_tab_info[ 'include' ] ) ) {
673
- $tabs_html .= "<li class='nav-tab nav-tab".(($current_tab == $a_tab_id)?'-active':'-inactive')."'><a href='".wp_slimstat_admin::$config_url.$a_tab_id."'>{$a_tab_info[ 'title' ]}</a></li>";
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
674
  }
675
  }
676
 
677
- echo '<div class="wrap slimstat-config"><h2>'.__('Settings','wp-slimstat').'</h2><ul class="nav-tabs">'.$tabs_html.'</ul>';
678
- echo '<div class="notice slimstat-notice slimstat-tooltip-content" style="background-color:#ffa;border:0;padding:10px">' . __( '<strong>AdBlock browser extension detected</strong> - If you see this notice, it means that your browser is not loading our stylesheet and/or Javascript files correctly. This could be caused by an overzealous ad blocker feature enabled in your browser (AdBlock Plus and friends). <a href="https://slimstat.freshdesk.com/support/solutions/articles/12000000414-the-reports-are-not-being-rendered-correctly-or-buttons-do-not-work" target="_blank">Please make sure to add an exception</a> to your configuration and allow the browser to load these assets.', 'wp-slimstat' ) . '</div>';
 
 
 
 
 
 
679
 
680
- // The maintenance tab has its own separate file
681
- if ( !empty( $settings[ $current_tab ][ 'include' ] ) ) {
682
- include_once( $settings[ $current_tab ][ 'include' ] );
683
  }
684
- else if ( !empty( $settings[ $current_tab ][ 'rows' ] ) ) {
685
- wp_slimstat_admin::update_settings( $settings[ $current_tab ][ 'rows' ] );
686
- wp_slimstat_admin::display_settings( $settings[ $current_tab ][ 'rows' ], $current_tab );
 
 
 
687
  }
688
 
689
- echo '</div>';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5
  exit(0);
6
  }
7
 
8
+ // Determine what tab is currently being displayed
9
  $current_tab = empty( $_GET[ 'tab' ] ) ? 1 : intval( $_GET[ 'tab' ] );
10
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11
  // Define all the options
12
  $settings = array(
13
  1 => array(
114
  'opt_out_cookie_names' => array(
115
  'title' => __( 'Opt-out Cookies', 'wp-slimstat' ),
116
  'type'=> 'textarea',
117
+ 'description'=> __( "If you are already using another tool to monitor which users opt-out of tracking, and assuming that this tool sets its own cookie to remember their selection, you can enter the cookie names and values in this field to let Slimstat comply with their choice. Please use the following format: <code>cookie_name=value</code>. Slimstat will track any visitors who either don't send a cookie with that name, or send a cookie whose value <strong>does not CONTAIN</strong> the string you specified. If your tool uses structured values like JSON or similar encodings, find the substring related to tracking and enter that as the value here below. For example, <a href='https://wordpress.org/plugins/smart-cookie-kit/' target='_blank'>Smart Cookie Kit</a> uses something like <code>{\"settings\":{\"technical\":true,\"statistics\":false,\"profiling\":false},\"ver\":\"2.0.0\"}</code>, so your pair should look like: <code>CookiePreferences-your.website.here=\"statistics\":false</code>. Separate multiple pairs with commas.", 'wp-slimstat' )
118
  ),
119
  'opt_in_cookie_names' => array(
120
  'title' => __( 'Opt-in Cookies', 'wp-slimstat' ),
121
  'type'=> 'textarea',
122
+ 'description'=> __( "Similarly to the option here above, you can configure Slimstat to work with an opt-in mechanism. Please use the following format: <code>cookie_name=value</code>. Slimstat will only track visitors who send a cookie whose value <strong>CONTAINS</strong> the string you specified. Separate multiple pairs with commas.", 'wp-slimstat' )
123
  ),
124
  'opt_out_message' => array(
125
  'title' => __( 'Opt-out Message', 'wp-slimstat' ),
515
  'filters_users_header' => array(
516
  'title' => __( 'Tracker Error', 'wp-slimstat' ),
517
  'type'=> 'plain-text',
518
+ 'after_input_field' => !empty( $last_tracker_error ) ? '<strong>[' . date_i18n( get_option( 'date_format' ), $last_tracker_error[ 1 ], true ) . ' ' . date_i18n( get_option( 'time_format' ), $last_tracker_error[ 1 ], true ) . '] ' . $last_tracker_error[ 0 ] . ' ' . slim_i18n::get_string( 'e-' . $last_tracker_error[ 0 ] ) . '</strong><a class="slimstat-font-cancel" title="' . htmlentities( __( 'Reset this error', 'wp-slimstat' ), ENT_QUOTES, 'UTF-8' ) . '" href="' . wp_slimstat_admin::$config_url . $current_tab . '&amp;action=reset-tracker-error-status"></a>' : __( 'So far so good.', 'wp-slimstat' ),
519
  'description'=> __( 'The information here above is useful to troubleshoot issues with the tracker. <strong>Errors</strong> are returned when the tracker could not record a page view for some reason, and are indicative of some kind of malfunction. Please include the message here above when sending a <a href="https://support.wp-slimstat.com" target="_blank">support request</a>.', 'wp-slimstat' )
520
  ),
521
  'show_sql_debug' => array(
526
  'db_indexes' => array(
527
  'title' => __( 'Increase Performance', 'wp-slimstat' ),
528
  'type'=> 'toggle',
 
529
  'description'=> __( 'Enable this option to add column indexes to the main Slimstat table. This will make SQL queries faster and increase the size of the table by about 30%.', 'wp-slimstat' )
530
  ),
531
 
537
  'enable_maxmind' => array(
538
  'title' => __( 'MaxMind Geolocation', 'wp-slimstat' ),
539
  'type'=> 'toggle',
 
540
  'description'=> __( "The <a href='https://dev.maxmind.com/geoip/geoip2/geolite2/' target='_blank'>MaxMind GeoLite2 library</a>, which Slimstat uses to geolocate your visitors, is released under the Creative Commons BY-SA 4.0 license, and cannot be directly bundled with the plugin because of license incompatibility issues. If you're getting an error after enabling this option, please <a href='https://slimstat.freshdesk.com/solution/articles/12000039798-how-to-manually-install-the-maxmind-geolocation-data-file-' target='_blank'>take a look at our knowledge base</a> to learn how to install this file manually.", 'wp-slimstat' ) . ( !empty( $maxmind_last_modified ) ? ' ' . sprintf ( __( 'Your data file was last downloaded on <strong>%s</strong>', 'wp-slimstat' ), $maxmind_last_modified ) : '' )
541
  ),
542
 
564
  $enable_browscap = array( 'enable_browscap' => array(
565
  'title' => __( 'Browscap Library', 'wp-slimstat' ),
566
  'type'=> 'toggle',
 
567
  'description'=> __( "We are contributing to the <a href='https://browscap.org/' target='_blank'>Browscap Capabilities Project</a>, which we use to decode your visitors' user agent string into browser name and operating system. We use an <a href='https://github.com/slimstat/browscap-db' target='_blank'>optimized version of their data structure</a>, for improved performance. When enabled, Slimstat uses this library in addition to the built-in heuristic function, to determine your visitors' browser information. Updates are downloaded automatically every two weeks, when available.", 'wp-slimstat' ) . ( !empty( slim_browser::$browscap_local_version ) ? ' ' . sprintf( __( 'You are currently using version %s.' ), '<strong>' . slim_browser::$browscap_local_version . '</strong>' ) : '' )
568
  ) );
569
 
570
  $settings[ 6 ][ 'rows' ] = array_slice( $settings[ 6 ][ 'rows' ], 0, 6, true) + $enable_browscap + array_slice($settings[ 6 ][ 'rows' ], 6, NULL, true );
571
  }
572
 
573
+ // Allow third-party tools to add their own settings
574
  $settings = apply_filters( 'slimstat_options_on_page', $settings );
575
 
576
+ // Save options
577
+ $save_messages = array();
578
+ if ( !empty( $settings ) && !empty( $_POST[ 'slimstat_update_settings' ] ) && wp_verify_nonce( $_POST[ 'slimstat_update_settings' ], 'slimstat_update_settings' ) ) {
579
+
580
+ // Some of them require extra processing
581
+ if ( !empty( $_POST[ 'options' ] ) ) {
582
+ // DB Indexes
583
+ if ( !empty( $_POST[ 'options' ][ 'db_indexes' ] ) ) {
584
+ if ( $_POST[ 'options' ][ 'db_indexes' ] == 'on' && wp_slimstat::$settings[ 'db_indexes' ] == 'no' ) {
585
+ wp_slimstat::$wpdb->query( "ALTER TABLE {$GLOBALS[ 'wpdb' ]->prefix}slim_stats ADD INDEX {$GLOBALS[ 'wpdb' ]->prefix}stats_resource_idx( resource( 20 ) )" );
586
+ wp_slimstat::$wpdb->query( "ALTER TABLE {$GLOBALS[ 'wpdb' ]->prefix}slim_stats ADD INDEX {$GLOBALS[ 'wpdb' ]->prefix}stats_browser_idx( browser( 10 ) )" );
587
+ wp_slimstat::$wpdb->query( "ALTER TABLE {$GLOBALS[ 'wpdb' ]->prefix}slim_stats ADD INDEX {$GLOBALS[ 'wpdb' ]->prefix}stats_searchterms_idx( searchterms( 15 ) )" );
588
+ $save_messages[] = __( 'Congratulations! Slimstat Analytics is now optimized for <a href="https://www.youtube.com/watch?v=ygE01sOhzz0" target="_blank">ludicrous speed</a>.', 'wp-slimstat' );
589
+ wp_slimstat::$settings[ 'db_indexes' ] = 'on';
590
+ }
591
+ else if ( $_POST[ 'options' ][ 'db_indexes' ] == 'no' && wp_slimstat::$settings[ 'db_indexes' ] == 'on' ) {
592
+ // An empty value means that the toggle has been switched to "Off"
593
+ wp_slimstat::$wpdb->query( "ALTER TABLE {$GLOBALS[ 'wpdb' ]->prefix}slim_stats DROP INDEX {$GLOBALS[ 'wpdb' ]->prefix}stats_resource_idx" );
594
+ wp_slimstat::$wpdb->query( "ALTER TABLE {$GLOBALS[ 'wpdb' ]->prefix}slim_stats DROP INDEX {$GLOBALS[ 'wpdb' ]->prefix}stats_browser_idx");
595
+ wp_slimstat::$wpdb->query( "ALTER TABLE {$GLOBALS[ 'wpdb' ]->prefix}slim_stats DROP INDEX {$GLOBALS[ 'wpdb' ]->prefix}stats_searchterms_idx");
596
+ $save_messages[] = __( 'Table indexes have been disabled. Enjoy the extra database space!', 'wp-slimstat' );
597
+ wp_slimstat::$settings[ 'db_indexes' ] = 'no';
598
+ }
599
+ }
600
+
601
+ // MaxMind Data File
602
+ if ( !empty( $_POST[ 'options' ][ 'enable_maxmind' ] ) ) {
603
+ if ( $_POST[ 'options' ][ 'enable_maxmind' ] == 'on' && wp_slimstat::$settings[ 'enable_maxmind' ] == 'no' ) {
604
+ $error = wp_slimstat::download_maxmind_database();
605
+
606
+ if ( empty( $error ) ) {
607
+ $save_messages[] = __( 'The geolocation database has been installed on your server.', 'wp-slimstat' );
608
+ wp_slimstat::$settings[ 'enable_maxmind' ] = 'on';
609
+ }
610
+ else {
611
+ $save_messages[] = $error;
612
+ }
613
+ }
614
+ else if ( $_POST[ 'options' ][ 'enable_maxmind' ] == 'no' && wp_slimstat::$settings[ 'enable_maxmind' ] == 'on' ) {
615
+ $is_deleted = @unlink( wp_slimstat::$maxmind_path );
616
+
617
+ if ( $is_deleted ) {
618
+ $save_messages[] = __( 'The geolocation database has been uninstalled from your server.', 'wp-slimstat' );
619
+ wp_slimstat::$settings[ 'enable_maxmind' ] = 'no';
620
+ }
621
+ else {
622
+ // Some users have reported that a directory is created, instead of a file
623
+ $is_deleted = @rmdir( wp_slimstat::$maxmind_path );
624
+
625
+ if ( $is_deleted ) {
626
+ $save_messages[] = __( 'The geolocation database has been uninstalled from your server.', 'wp-slimstat' );
627
+ wp_slimstat::$settings[ 'enable_maxmind' ] = 'no';
628
+ }
629
+ else {
630
+ $save_messages[] = __( 'The geolocation database could not be uninstalled from your server. Please make sure Slimstat can save files in your <code>wp-content/uploads</code> folder.', 'wp-slimstat' );
631
+ }
632
+ }
633
+ }
634
+ }
635
+
636
+ // Browscap Library
637
+ if ( !empty( $_POST[ 'options' ][ 'enable_browscap' ] ) ) {
638
+ if ( $_POST[ 'options' ][ 'enable_browscap' ] == 'on' && wp_slimstat::$settings[ 'enable_browscap' ] == 'no' ) {
639
+ $error = slim_browser::update_browscap_database( true );
640
+
641
+ if ( !is_array( $error ) ) {
642
+ $save_messages[] = __( 'The Browscap library has been installed on your server.', 'wp-slimstat' );
643
+ wp_slimstat::$settings[ 'enable_browscap' ] = 'on';
644
+ }
645
+ else {
646
+ $save_messages[] = $error[ 1 ];
647
+ }
648
+ }
649
+ else if ( $_POST[ 'options' ][ 'enable_browscap' ] == 'no' && wp_slimstat::$settings[ 'enable_browscap' ] == 'on' ) {
650
+ WP_Filesystem();
651
+
652
+ if ( $GLOBALS[ 'wp_filesystem' ]->rmdir( wp_slimstat::$upload_dir . '/browscap-db-master/', true ) ) {
653
+ $save_messages[] = __( 'The Browscap data file has been uninstalled from your server.', 'wp-slimstat' );
654
+ wp_slimstat::$settings[ 'enable_browscap' ] = 'no';
655
+ }
656
+ else {
657
+ $save_messages[] = __( 'There was an error deleting the Browscap data folder on your server. Please check your permissions.', 'wp-slimstat' );
658
+ }
659
+ }
660
+ }
661
+ }
662
+
663
+ if ( !empty( $_GET[ 'action' ] ) ) {
664
+ switch ( $_GET[ 'action' ] ) {
665
+ case 'reset-tracker-error-status':
666
+ $last_tracker_error = array();
667
+ if ( !is_network_admin() ) {
668
+ update_option( 'slimstat_tracker_error', $last_tracker_error );
669
+ }
670
+ else {
671
+ update_site_option( 'slimstat_tracker_error', $last_tracker_error );
672
+ }
673
+ break;
674
+
675
+ case 'truncate-table':
676
+ wp_slimstat::$wpdb->query( "DELETE te FROM {$GLOBALS[ 'wpdb' ]->prefix}slim_events te" );
677
+ wp_slimstat::$wpdb->query( "OPTIMIZE TABLE {$GLOBALS[ 'wpdb' ]->prefix}slim_events" );
678
+ wp_slimstat::$wpdb->query( "DELETE t1 FROM {$GLOBALS[ 'wpdb' ]->prefix}slim_stats t1" );
679
+ wp_slimstat::$wpdb->query( "OPTIMIZE TABLE {$GLOBALS[ 'wpdb' ]->prefix}slim_stats" );
680
+ wp_slimstat_admin::show_message( __( 'All the records were successfully deleted.', 'wp-slimstat' ) );
681
+ break;
682
+
683
+ default:
684
+ break;
685
+ }
686
+ }
687
+
688
+ // All other options
689
+ foreach( $_POST[ 'options' ] as $a_post_slug => $a_post_value ) {
690
+ if ( empty( $settings[ $current_tab ][ 'rows' ][ $a_post_slug ] ) || in_array( $settings[ $current_tab ][ 'rows' ][ $a_post_slug ][ 'type' ], array( 'readonly', 'section_header', 'plain-text' ) ) ) {
691
+ continue;
692
+ }
693
+
694
+ // An empty toggle option is saved in the database as 'no'
695
+ if ( !empty( $a_post_value ) ) {
696
+ wp_slimstat::$settings[ $a_post_slug ] = !empty( $settings[ $current_tab ][ 'rows' ][ $a_post_slug ][ 'use_code_editor' ] ) ? $a_post_value : sanitize_text_field( $a_post_value );
697
+ }
698
+
699
+ // If the Network Settings add-on is enabled, there might be a switch to decide if this option needs to override what single sites have set
700
+ if ( is_network_admin() ) {
701
+ if ( !isset( $_POST[ 'options' ][ 'addon_network_settings_' . $a_post_slug ] ) || strtolower( $_POST[ 'options' ][ 'addon_network_settings_' . $a_post_slug ] != 'on' ) ) {
702
+ wp_slimstat::$settings[ 'addon_network_settings_' . $a_post_slug ] = 'no';
703
+ }
704
+ else {
705
+ wp_slimstat::$settings[ 'addon_network_settings_' . $a_post_slug ] = 'on';
706
+ }
707
+ }
708
+ else if ( isset( wp_slimstat::$settings[ 'addon_network_settings_' . $a_post_slug ] ) ) {
709
+ // Keep settings clean
710
+ unset( wp_slimstat::$settings[ 'addon_network_settings_' . $a_post_slug ] );
711
+ }
712
+ }
713
+
714
+ // Allow third-party functions to manipulate the options right before they are saved
715
+ wp_slimstat::$settings = apply_filters( 'slimstat_save_options', wp_slimstat::$settings );
716
+
717
+ if ( !is_network_admin() ) {
718
+ update_option( 'slimstat_options', wp_slimstat::$settings );
719
+ }
720
+ else {
721
+ update_site_option( 'slimstat_options', wp_slimstat::$settings );
722
+ }
723
+
724
+ if ( !empty( $save_messages ) ) {
725
+ wp_slimstat_admin::show_message( implode( ' ', $save_messages ), 'warning' );
726
+ }
727
+ else{
728
+ wp_slimstat_admin::show_message( __( 'Your new settings have been saved.', 'wp-slimstat' ), 'info' );
729
  }
730
  }
731
 
732
+ $maxmind_last_modified = '';
733
+ if ( file_exists( wp_slimstat::$maxmind_path ) && false !== ( $file_stat = @stat( wp_slimstat::$maxmind_path ) ) ) {
734
+ $maxmind_last_modified = date_i18n( get_option( 'date_format' ), $file_stat[ 'mtime' ] );
735
+ }
736
+
737
+ $index_enabled = wp_slimstat::$wpdb->get_results(
738
+ "SHOW INDEX FROM {$GLOBALS[ 'wpdb' ]->prefix}slim_stats WHERE Key_name = '{$GLOBALS[ 'wpdb' ]->prefix}stats_resource_idx'"
739
+ );
740
 
741
+ if ( !isset( $last_tracker_error ) ) {
742
+ $last_tracker_error = get_option( 'slimstat_tracker_error', array() );
 
743
  }
744
+
745
+ $tabs_html = '';
746
+ foreach ( $settings as $a_tab_id => $a_tab_info ) {
747
+ if ( !empty( $a_tab_info[ 'rows' ] ) ) {
748
+ $tabs_html .= "<li class='nav-tab nav-tab" . ( ( $current_tab == $a_tab_id ) ? '-active' : '-inactive' ) . "'><a href='" . wp_slimstat_admin::$config_url . $a_tab_id . "'>{$a_tab_info[ 'title' ]}</a></li>";
749
+ }
750
  }
751
 
752
+ ?>
753
+
754
+ <div class="wrap slimstat-config">
755
+ <h2><?php _e( 'Settings', 'wp-slimstat' ) ?></h2>
756
+ <ul class="nav-tabs">
757
+ <?php echo $tabs_html ?>
758
+ </ul>
759
+
760
+ <div class="notice slimstat-notice slimstat-tooltip-content" style="background-color:#ffa;border:0;padding:10px">
761
+ <?php _e( '<strong>AdBlock browser extension detected</strong> - If you see this notice, it means that your browser is not loading our stylesheet and/or Javascript files correctly. This could be caused by an overzealous ad blocker feature enabled in your browser (AdBlock Plus and friends). <a href="https://slimstat.freshdesk.com/support/solutions/articles/12000000414-the-reports-are-not-being-rendered-correctly-or-buttons-do-not-work" target="_blank">Please make sure to add an exception</a> to your configuration and allow the browser to load these assets.', 'wp-slimstat' ) ?>
762
+ </div>
763
+
764
+ <?php if ( !empty( $settings[ $current_tab ][ 'rows' ] ) ) : ?>
765
+
766
+ <form action="<?php echo wp_slimstat_admin::$config_url . $current_tab ?>" method="post" id="slimstat-options-<?php echo $current_tab ?>">
767
+ <?php wp_nonce_field( 'slimstat_update_settings', 'slimstat_update_settings' ); ?>
768
+ <table class="form-table widefat <?php echo $GLOBALS[ 'wp_locale' ]->text_direction ?>">
769
+ <tbody><?php
770
+ $i = 0;
771
+ foreach( $settings[ $current_tab ][ 'rows' ] as $a_setting_slug => $a_setting_info ) {
772
+ $i++;
773
+ $a_setting_info = array_merge( array(
774
+ 'title' =>'',
775
+ 'type' => '',
776
+ 'rows' => 4,
777
+ 'description' => '',
778
+ 'before_input_field' => '',
779
+ 'after_input_field' => '',
780
+ 'custom_label_yes' => '',
781
+ 'custom_label_no' => '',
782
+ 'use_tag_list' => true,
783
+ 'use_code_editor' => '',
784
+ 'select_values' => array()
785
+ ), $a_setting_info );
786
+
787
+ $is_readonly = ( $a_setting_info[ 'type' ] === 'readonly' ) ? ' readonly' : '';
788
+ $use_tag_list = ( empty( $is_readonly ) && !empty( $a_setting_info[ 'use_tag_list' ] ) && $a_setting_info[ 'use_tag_list' ] === true ) ? ' slimstat-taglist' : '';
789
+ $use_code_editor = ( empty( $is_readonly ) && !empty( $a_setting_info[ 'use_code_editor' ] ) ) ? ' data-code-editor="' . $a_setting_info[ 'use_code_editor' ] . '"': '';
790
+
791
+ $network_override_checkbox = is_network_admin() ? '
792
+ <input class="slimstat-checkbox-toggle"
793
+ type="checkbox"
794
+ name="options[addon_network_settings_' . $a_setting_slug . ']"' .
795
+ ( ( !empty( wp_slimstat::$settings[ 'addon_network_settings_' . $a_setting_slug ] ) && wp_slimstat::$settings[ 'addon_network_settings_' . $a_setting_slug ] == 'on' ) ? ' checked="checked"' : '' ) . '
796
+ id="addon_network_settings_' . $a_setting_slug . '"
797
+ data-size="mini" data-handle-width="50" data-on-color="warning" data-on-text="Network" data-off-text="Site">' : '';
798
+
799
+ echo '<tr' . ( $i % 2 == 0 ? ' class="alternate"' : '' ) . '>';
800
+ switch ( $a_setting_info[ 'type' ] ) {
801
+ case 'section_header':
802
+ echo '<td colspan="2" class="slimstat-options-section-header" id="wp-slimstat-' . sanitize_title( $a_setting_info[ 'title' ] ) . '">' . $a_setting_info[ 'title' ] . '</td>';
803
+ break;
804
+
805
+ case 'readonly':
806
+ echo '<td colspan="2">' . $a_setting_info[ 'title' ] . '<textarea rows="7" class="large-text code" readonly>' . $a_setting_info[ 'description' ] . '</textarea></td>';
807
+ break;
808
+
809
+ case 'toggle':
810
+ echo '<th scope="row"><label for="' . $a_setting_slug . '">' . $a_setting_info[ 'title' ] . '</label></th>
811
+ <td>
812
+ <input type="hidden" value="no" name="options[' . $a_setting_slug . ']" id="' . $a_setting_slug . '">
813
+ <span class="block-element">
814
+ <input class="slimstat-checkbox-toggle" type="checkbox"' . $is_readonly . '
815
+ name="options[' . $a_setting_slug . ']"
816
+ id="' . $a_setting_slug . '"
817
+ data-size="mini" data-handle-width="50" data-on-color="success"' .
818
+ ( ( wp_slimstat::$settings[ $a_setting_slug ] == 'on' ) ? ' checked="checked"' : '' ) . '
819
+ data-on-text="' . ( !empty( $a_setting_info[ 'custom_label_on' ] ) ? $a_setting_info[ 'custom_label_on' ] : __( 'On', 'wp-slimstat' ) ) . '"
820
+ data-off-text="' . ( !empty( $a_setting_info[ 'custom_label_off' ] ) ? $a_setting_info[ 'custom_label_off' ] : __( 'Off', 'wp-slimstat' ) ) . '">' .
821
+ $network_override_checkbox . '
822
+ </span>
823
+ <span class="description">' . $a_setting_info[ 'description' ] . '</span>
824
+ </td>';
825
+ // ( is_network_admin() ? ' data-indeterminate="true"' : '' ) . '>
826
+ break;
827
+
828
+ case 'select':
829
+ echo '<th scope="row"><label for="' . $a_setting_slug . '">' . $a_setting_info[ 'title' ] . '</label></th>
830
+ <td>
831
+ <span class="block-element">
832
+ <select' . $is_readonly .' name="options[' . $a_setting_slug . ']" id="' . $a_setting_slug .'">';
833
+ foreach ( $a_setting_info[ 'select_values' ] as $a_key => $a_value ) {
834
+ $is_selected = ( wp_slimstat::$settings[ $a_setting_slug ] == $a_key ) ? ' selected' : '';
835
+ echo '<option' . $is_selected . ' value="' . $a_key . '">' . $a_value . '</option>';
836
+ }
837
+ echo '</select>' .
838
+ $network_override_checkbox . '
839
+ </span>
840
+ <span class="description">' . $a_setting_info[ 'description' ] . '</span>
841
+ </td>';
842
+ break;
843
+
844
+ case 'text':
845
+ case 'integer':
846
+ $empty_value = ( $a_setting_info[ 'type' ] == 'text' ) ? '' : '0';
847
+ echo '<th scope="row"><label for="' . $a_setting_slug . '">' . $a_setting_info[ 'title' ] . '</label></th>
848
+ <td>
849
+ <span class="block-element"> ' .
850
+ $a_setting_info[ 'before_input_field' ] . '
851
+ <input class="' . ( ( $a_setting_info[ 'type' ] == 'integer' ) ? 'small-text' : 'regular-text' ) . '"' . $is_readonly . '
852
+ type="' . ( ( $a_setting_info[ 'type' ] == 'integer' ) ? 'number' : 'text' ) . '"
853
+ name="options[' . $a_setting_slug . ']"
854
+ id="' . $a_setting_slug . '"
855
+ value="' . ( !empty( wp_slimstat::$settings[ $a_setting_slug ] ) ? wp_slimstat::$settings[ $a_setting_slug ] : $empty_value ) . '"> ' . $a_setting_info[ 'after_input_field' ] .
856
+ $network_override_checkbox . '
857
+ </span>
858
+ <span class="description">' . $a_setting_info[ 'description' ] . '</span>
859
+ </td>';
860
+ break;
861
+
862
+ case 'textarea':
863
+ echo '
864
+ <td colspan="2">
865
+ <label for="' . $a_setting_slug . '">' . $a_setting_info[ 'title' ] . $network_override_checkbox . '</label>
866
+ <p class="description">' . $a_setting_info[ 'description' ] . '</p>
867
+ <p>
868
+ <textarea class="large-text code' . $use_tag_list . '"' . $is_readonly . $use_code_editor . '
869
+ id="' . $a_setting_slug . '"
870
+ rows="' . $a_setting_info[ 'rows' ] . '"
871
+ name="options[' . $a_setting_slug . ']">' . ( !empty( wp_slimstat::$settings[ $a_setting_slug ] ) ? stripslashes( wp_slimstat::$settings[ $a_setting_slug ] ) : '' ) . '</textarea>
872
+ <span class="description">' . $a_setting_info[ 'after_input_field' ] . '</span>
873
+ </p>
874
+ </td>';
875
+ break;
876
+
877
+ case 'plain-text':
878
+ echo '<th scope="row"><label for="' . $a_setting_slug . '">' . $a_setting_info[ 'title' ] . '</label></th>
879
+ <td>
880
+ <span class="block-element">' . $a_setting_info[ 'after_input_field' ] . '</span>
881
+ <span class="description">' . $a_setting_info[ 'description' ] . '</span>
882
+ </td>';
883
+ break;
884
+
885
+ case 'custom':
886
+ echo '<td colspan="2">' . $a_setting_info[ 'title' ] . '<br/><br/>' . $a_setting_info[ 'markup' ] . '</td>';
887
+ break;
888
+
889
+ default:
890
+ }
891
+ echo '</tr>';
892
+ }
893
+ ?></tbody>
894
+ </table>
895
+
896
+ <p class="submit">
897
+ <input type="submit" value="<?php _e( 'Save Changes', 'wp-slimstat' ) ?>" class="button-primary" name="Submit">
898
+ </p>
899
+ </form>
900
+
901
+ <?php endif ?>
902
+ </div>
admin/index.php CHANGED
@@ -4,8 +4,8 @@ class wp_slimstat_admin {
4
  public static $screens_info = array();
5
  public static $config_url = '';
6
  public static $current_screen = 'slimview1';
7
- public static $faulty_fields = array();
8
  public static $page_location = 'slimstat';
 
9
 
10
  protected static $admin_notice = '';
11
  protected static $data_for_column = array(
@@ -31,55 +31,77 @@ class wp_slimstat_admin {
31
  'is_report_group' => true,
32
  'show_in_sidebar' => true,
33
  'title' => __( 'Real-time', 'wp-slimstat' ),
 
34
  'callback' => array( __CLASS__, 'wp_slimstat_include_view' )
35
  ),
36
  'slimview2' => array(
37
  'is_report_group' => true,
38
  'show_in_sidebar' => true,
39
  'title' => __( 'Overview', 'wp-slimstat' ),
 
40
  'callback' => array( __CLASS__, 'wp_slimstat_include_view' )
41
  ),
42
  'slimview3' => array(
43
  'is_report_group' => true,
44
  'show_in_sidebar' => true,
45
  'title' => __( 'Audience', 'wp-slimstat' ),
 
46
  'callback' => array( __CLASS__, 'wp_slimstat_include_view' )
47
  ),
48
  'slimview4' => array(
49
  'is_report_group' => true,
50
  'show_in_sidebar' => true,
51
  'title' => __( 'Site Analysis', 'wp-slimstat' ),
 
52
  'callback' => array( __CLASS__, 'wp_slimstat_include_view' )
53
  ),
54
  'slimview5' => array(
55
  'is_report_group' => true,
56
  'show_in_sidebar' => true,
57
  'title' => __( 'Traffic Sources', 'wp-slimstat' ),
 
58
  'callback' => array( __CLASS__, 'wp_slimstat_include_view' )
59
  ),
 
 
 
 
 
 
 
 
 
 
 
 
 
 
60
  'slimaddons' => array(
61
  'is_report_group' => false,
62
  'show_in_sidebar' => current_user_can( 'manage_options' ),
63
  'title' => __( 'Add-ons', 'wp-slimstat' ),
 
64
  'callback' => array( __CLASS__, 'wp_slimstat_include_addons' )
65
  ),
66
  'dashboard' => array(
67
  'is_report_group' => true,
68
  'show_in_sidebar' => false,
69
  'title' => __( 'WordPress Dashboard', 'wp-slimstat' ),
70
- 'callback' => '' // No callback if show_in_sidebar is false
 
71
  ),
72
  'inactive' => array(
73
  'is_report_group' => true,
74
  'show_in_sidebar' => false,
75
  'title' => __( 'Inactive Reports' ),
76
- 'callback' => '' // No callback if show_in_sidebar is false
 
77
  )
78
  );
79
  self::$screens_info = apply_filters( 'slimstat_screens_info', self::$screens_info );
80
 
81
  // Settings URL
82
- self::$config_url = 'admin.php?page=slimconfig&amp;tab=';
83
 
84
  // Current Screen
85
  if ( !empty( $_REQUEST[ 'page' ] ) && array_key_exists( $_REQUEST[ 'page' ], self::$screens_info ) ) {
@@ -91,6 +113,20 @@ class wp_slimstat_admin {
91
  self::$page_location = 'admin';
92
  }
93
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
94
  // WPMU - New blog created
95
  $active_sitewide_plugins = get_site_option( 'active_sitewide_plugins' );
96
  if ( !empty( $active_sitewide_plugins[ 'wp-slimstat/wp-slimstat.php' ] ) ) {
@@ -116,16 +152,14 @@ class wp_slimstat_admin {
116
  add_action( 'transition_comment_status', array( __CLASS__, 'remove_spam' ), 15, 3 );
117
  }
118
 
119
- // Add a menu to the admin bar ( this function is declared here and not in wp_slimstat_admin because the latter is only initialized if is_admin(), and not in the front-end )
120
  if ( wp_slimstat::$settings[ 'use_separate_menu' ] != 'no' && is_admin_bar_showing() ) {
121
  add_action( 'admin_bar_menu', array( __CLASS__, 'add_menu_to_adminbar' ), 100 );
122
  }
123
 
124
  if ( function_exists( 'is_network_admin' ) && !is_network_admin() ) {
125
  // Add the appropriate entries to the admin menu, if this user can view/admin Slimstat
126
- add_action( 'admin_menu', array( __CLASS__, 'add_view_menu' ) );
127
- add_action( 'admin_menu', array( __CLASS__, 'add_customize_menu' ) );
128
- add_action( 'admin_menu', array( __CLASS__, 'add_config_menu' ) );
129
 
130
  // Display the column in the Edit Posts / Pages screen
131
  if ( wp_slimstat::$settings[ 'add_posts_column' ] == 'on' ) {
@@ -144,9 +178,6 @@ class wp_slimstat_admin {
144
  }
145
  }
146
 
147
- // Add some inline CSS to customize the icon associated to Slimstat in the sidebar
148
- add_action( 'admin_enqueue_scripts', array( __CLASS__, 'wp_slimstat_stylesheet_icon' ) );
149
-
150
  // Update the table structure and options, if needed
151
  if ( !empty( wp_slimstat::$settings[ 'version' ] ) && wp_slimstat::$settings[ 'version' ] != wp_slimstat::$version ) {
152
  add_action( 'admin_init', array(__CLASS__, 'update_tables_and_options' ) );
@@ -486,18 +517,6 @@ class wp_slimstat_admin {
486
  }
487
  // END: wp_slimstat_stylesheet
488
 
489
- /**
490
- * Customizes the icon associated to Slimstat in the sidebar
491
- */
492
- public static function wp_slimstat_stylesheet_icon(){
493
- if (!array_key_exists('dashicons', $GLOBALS['wp_styles']->registered)){
494
- return true;
495
- }
496
-
497
- wp_add_inline_style('dashicons', "#adminmenu #toplevel_page_slimview1 .wp-menu-image:before { content: '\\f239'; margin-top: -2px; }");
498
- }
499
- // END: wp_slimstat_stylesheet_icon
500
-
501
  /**
502
  * Loads user-defined stylesheet code
503
  */
@@ -534,7 +553,7 @@ class wp_slimstat_admin {
534
  /**
535
  * Adds a new entry in the admin menu, to view the stats
536
  */
537
- public static function add_view_menu( $_s = '' ) {
538
  // If this user is whitelisted, we use the minimum capability
539
  $minimum_capability = 'read';
540
  if ( is_network_admin() ) {
@@ -544,21 +563,50 @@ class wp_slimstat_admin {
544
  $minimum_capability = wp_slimstat::$settings[ 'capability_can_view' ];
545
  }
546
 
547
- // Get the current report assignments
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
548
  $new_entry = array();
549
  if ( wp_slimstat::$settings[ 'use_separate_menu' ] == 'no' || is_network_admin() ) {
550
- $parent = 'slimview1';
551
- $new_entry[] = add_menu_page( __( 'Slimstat', 'wp-slimstat' ), __( 'Slimstat', 'wp-slimstat' ), $minimum_capability, $parent, array( __CLASS__, 'wp_slimstat_include_view' ) );
552
  }
553
  else {
554
  $parent = 'admin.php';
555
  }
556
 
557
- $current_user = wp_get_current_user();
558
-
559
  foreach ( self::$screens_info as $a_screen_id => $a_screen_info ) {
 
 
 
 
 
 
 
 
 
560
  if ( $a_screen_info[ 'show_in_sidebar' ] ) {
561
- $new_entry[] = add_submenu_page( $parent, $a_screen_info[ 'title' ], $a_screen_info[ 'title' ], $minimum_capability, $a_screen_id, $a_screen_info[ 'callback' ] );
 
 
 
 
 
 
 
562
  }
563
  }
564
 
@@ -571,136 +619,69 @@ class wp_slimstat_admin {
571
 
572
  return $_s;
573
  }
574
- // END: add_view_menu
575
 
576
  /**
577
  * Adds a new entry in the WordPress Admin Bar
578
  */
579
  public static function add_menu_to_adminbar() {
580
  // If this user is whitelisted, we use the minimum capability
581
- $minimum_capability_view = 'read';
582
- if ( strpos( wp_slimstat::$settings[ 'can_view' ], $GLOBALS[ 'current_user' ]->user_login) === false && !empty( wp_slimstat::$settings[ 'capability_can_view' ] ) ) {
583
- $minimum_capability_view = wp_slimstat::$settings[ 'capability_can_view' ];
584
  }
585
-
586
- // If this user is whitelisted, we use the minimum capability
587
- $minimum_capability_customize = 'read';
588
- if ( strpos( wp_slimstat::$settings[ 'can_customize' ], $GLOBALS[ 'current_user' ]->user_login) === false && !empty( wp_slimstat::$settings[ 'capability_can_customize' ] ) ) {
589
- $minimum_capability_customize = wp_slimstat::$settings[ 'capability_can_customize' ];
590
  }
591
 
592
- // If this user is whitelisted, we use the minimum capability
593
- $minimum_capability_config = 'read';
594
- if ( ( strpos( wp_slimstat::$settings[ 'can_admin' ], $GLOBALS[ 'current_user' ]->user_login ) === false) && $GLOBALS[ 'current_user' ]->user_login != 'slimstatadmin' && !empty( wp_slimstat::$settings[ 'capability_can_admin' ] ) ) {
595
- $minimum_capability_config = wp_slimstat::$settings[ 'capability_can_admin' ];
596
- }
 
 
 
 
 
597
 
598
- if ( ( function_exists( 'is_network_admin' ) && is_network_admin() ) || !is_user_logged_in() || !current_user_can( $minimum_capability_view ) ) {
599
- return;
 
600
  }
601
 
602
- wp_slimstat::$settings[ 'capability_can_view' ] = empty( wp_slimstat::$settings[ 'capability_can_view' ] ) ? 'read' : wp_slimstat::$settings[ 'capability_can_view' ];
603
-
604
- if ( empty( wp_slimstat::$settings[ 'can_view' ]) || strpos( wp_slimstat::$settings[ 'can_view' ], $GLOBALS[ 'current_user' ]->user_login ) !== false || current_user_can( 'manage_options' ) ) {
605
- $slimstat_view_url = get_admin_url( $GLOBALS[ 'blog_id' ], "admin.php?page=" );
606
-
607
- $frontend_filter = '';
608
- if ( !is_admin() ) {
609
- $frontend_filter = '&amp;fs%5Bresource%5D=contains+' . urlencode( wp_slimstat::get_request_uri() );
610
- }
611
 
612
  $GLOBALS[ 'wp_admin_bar' ]->add_menu( array(
613
  'id' => 'slimstat-header',
614
- 'title' => __( 'Slimstat', 'wp-slimstat' ),
615
- 'href' => "{$slimstat_view_url}slimview1"
616
  ) );
617
 
618
  foreach ( self::$screens_info as $a_screen_id => $a_screen_info ) {
619
- if ( $a_screen_info[ 'show_in_sidebar' ] ) {
 
 
 
 
 
 
 
 
 
620
  $GLOBALS[ 'wp_admin_bar' ]->add_menu( array(
621
  'id' => $a_screen_id,
622
- 'href' => "{$slimstat_view_url}$a_screen_id" . ( ( $a_screen_info[ 'callback' ] == array( __CLASS__, 'wp_slimstat_include_view' ) ) ? $frontend_filter : '' ),
623
  'parent' => 'slimstat-header',
624
  'title' => $a_screen_info[ 'title' ]
625
  ) );
626
  }
627
  }
628
-
629
- if ( ( empty( wp_slimstat::$settings[ 'can_customize' ] ) || strpos( wp_slimstat::$settings[ 'can_customize' ], $GLOBALS[ 'current_user' ]->user_login ) !== false ) && current_user_can( $minimum_capability_customize ) ) {
630
- $GLOBALS[ 'wp_admin_bar' ]->add_menu( array(
631
- 'id' => 'slimstat-layout',
632
- 'href' => get_admin_url( $GLOBALS[ 'blog_id' ], "admin.php?page=slimlayout" ),
633
- 'parent' => 'slimstat-header',
634
- 'title' => __( 'Customize', 'wp-slimstat' ) )
635
- );
636
- }
637
-
638
- if ( ( empty( wp_slimstat::$settings[ 'can_admin' ] ) || strpos( wp_slimstat::$settings[ 'can_admin' ], $GLOBALS[ 'current_user' ]->user_login ) !== false || $GLOBALS[ 'current_user' ]->user_login == 'slimstatadmin' ) && current_user_can( $minimum_capability_config ) ) {
639
- $GLOBALS[ 'wp_admin_bar' ]->add_menu( array(
640
- 'id' => 'slimstat-config',
641
- 'href' => get_admin_url( $GLOBALS[ 'blog_id' ], "admin.php?page=slimconfig" ),
642
- 'parent' => 'slimstat-header',
643
- 'title' => __( 'Settings', 'wp-slimstat' ) )
644
- );
645
- }
646
  }
647
  }
648
  // END: add_menu_to_adminbar
649
 
650
- /**
651
- * Adds a new entry in the admin menu, to customize the reports layout
652
- */
653
- public static function add_customize_menu( $_s ) {
654
- wp_slimstat::$settings[ 'capability_can_customize' ] = empty( wp_slimstat::$settings[ 'capability_can_customize' ] ) ? 'manage_options' : wp_slimstat::$settings[ 'capability_can_customize' ];
655
-
656
- // If this user is whitelisted, we use the minimum capability
657
- $minimum_capability = 'read';
658
- if ( ( strpos( wp_slimstat::$settings[ 'can_customize' ], $GLOBALS[ 'current_user' ]->user_login ) === false ) && !empty( wp_slimstat::$settings[ 'capability_can_customize' ] ) ) {
659
- $minimum_capability = wp_slimstat::$settings[ 'capability_can_customize' ];
660
- }
661
-
662
- if ( wp_slimstat::$settings[ 'use_separate_menu' ] == 'no' ) {
663
- $new_entry = add_submenu_page( 'slimview1', __( 'Customize', 'wp-slimstat' ), __( 'Customize', 'wp-slimstat' ), $minimum_capability, 'slimlayout', array( __CLASS__, 'wp_slimstat_include_layout' ) );
664
- }
665
- else {
666
- $new_entry = add_submenu_page( null, __( 'Customize', 'wp-slimstat' ), __( 'Customize', 'wp-slimstat' ), $minimum_capability, 'slimlayout', array( __CLASS__, 'wp_slimstat_include_layout' ) );
667
- }
668
-
669
- // Load styles and Javascript needed to make the reports look nice and interactive
670
- add_action( 'load-' . $new_entry, array( __CLASS__, 'wp_slimstat_stylesheet' ) );
671
- add_action('load-'.$new_entry, array(__CLASS__, 'wp_slimstat_enqueue_scripts'));
672
-
673
- return $_s;
674
- }
675
- // END: add_customize_menu
676
-
677
- /**
678
- * Adds a new entry in the admin menu, to manage Slimstat options
679
- */
680
- public static function add_config_menu( $_s ) {
681
- wp_slimstat::$settings[ 'capability_can_admin' ] = empty( wp_slimstat::$settings[ 'capability_can_admin' ] ) ? 'manage_options' : wp_slimstat::$settings[ 'capability_can_admin' ];
682
-
683
- // If this user is whitelisted, we use the minimum capability
684
- $minimum_capability = 'read';
685
- if ( ( strpos( wp_slimstat::$settings[ 'can_admin' ], $GLOBALS[ 'current_user' ]->user_login ) === false ) && ( $GLOBALS[ 'current_user' ]->user_login != 'slimstatadmin' ) && !empty( wp_slimstat::$settings[ 'capability_can_admin' ] ) ) {
686
- $minimum_capability = wp_slimstat::$settings[ 'capability_can_admin' ];
687
- }
688
-
689
- if ( wp_slimstat::$settings[ 'use_separate_menu' ] == 'no' ) {
690
- $new_entry = add_submenu_page( 'slimview1', __( 'Settings', 'wp-slimstat' ), __( 'Settings', 'wp-slimstat' ), $minimum_capability, 'slimconfig', array( __CLASS__, 'wp_slimstat_include_config' ) );
691
- }
692
- else {
693
- $new_entry = add_submenu_page( null, __( 'Settings', 'wp-slimstat' ), __( 'Settings', 'wp-slimstat' ), $minimum_capability, 'slimconfig', array( __CLASS__, 'wp_slimstat_include_config' ) );
694
- }
695
-
696
- // Load styles and Javascript needed to make the reports look nice and interactive
697
- add_action( 'load-' . $new_entry, array( __CLASS__, 'wp_slimstat_stylesheet' ) );
698
- add_action('load-'.$new_entry, array(__CLASS__, 'wp_slimstat_enqueue_scripts'));
699
-
700
- return $_s;
701
- }
702
- // END: add_config_menu
703
-
704
  /**
705
  * Includes the appropriate panel to view the stats
706
  */
@@ -965,193 +946,11 @@ class wp_slimstat_admin {
965
  }
966
  // END: manage_filters
967
 
968
- /*
969
- * Displays the options
970
- */
971
- public static function display_settings( $_settings = array(), $_current_tab = 1 ) { ?>
972
- <form action="<?php echo self::$config_url . $_current_tab ?>" method="post" id="slimstat-options-<?php echo $_current_tab ?>">
973
- <?php wp_nonce_field( 'slimstat_update_settings', 'slimstat_update_settings' ); ?>
974
- <table class="form-table widefat <?php echo $GLOBALS[ 'wp_locale' ]->text_direction ?>">
975
- <tbody><?php
976
- $i = 0;
977
- foreach( $_settings as $_setting_slug => $_setting_info ) {
978
- $i++;
979
- $_setting_info = array_merge( array(
980
- 'title' =>'',
981
- 'type' => '',
982
- 'rows' => 4,
983
- 'description' => '',
984
- 'before_input_field' => '',
985
- 'after_input_field' => '',
986
- 'custom_label_yes' => '',
987
- 'custom_label_no' => '',
988
- 'use_tag_list' => true,
989
- 'use_code_editor' => '',
990
- 'select_values' => array(),
991
- 'default_value' => ''
992
- ), $_setting_info );
993
-
994
- $is_readonly = ( $_setting_info[ 'type' ] === 'readonly' ) ? ' readonly' : '';
995
- $use_tag_list = ( empty( $is_readonly ) && !empty( $_setting_info[ 'use_tag_list' ] ) && $_setting_info[ 'use_tag_list' ] === true ) ? ' slimstat-taglist' : '';
996
- $use_code_editor = ( empty( $is_readonly ) && !empty( $_setting_info[ 'use_code_editor' ] ) ) ? ' data-code-editor="' . $_setting_info[ 'use_code_editor' ] . '"': '';
997
-
998
- if ( empty( $_setting_info[ 'default_value' ] ) && isset( wp_slimstat::$settings[ $_setting_slug ] ) ) {
999
- $_setting_info[ 'default_value' ] = wp_slimstat::$settings[ $_setting_slug ];
1000
- }
1001
-
1002
- $network_override_checkbox = is_network_admin() ? '
1003
- <input class="slimstat-checkbox-toggle"
1004
- type="checkbox"
1005
- name="options[addon_network_settings_' . $_setting_slug . ']"' .
1006
- ( ( !empty( wp_slimstat::$settings[ 'addon_network_settings_' . $_setting_slug ] ) && wp_slimstat::$settings[ 'addon_network_settings_' . $_setting_slug ] == 'on' ) ? ' checked="checked"' : '' ) . '
1007
- id="addon_network_settings_' . $_setting_slug . '"
1008
- data-size="mini" data-handle-width="50" data-on-color="warning" data-on-text="Network" data-off-text="Site">' : '';
1009
-
1010
- echo '<tr' . ( $i % 2 == 0 ? ' class="alternate"' : '' ) . '>';
1011
- switch ( $_setting_info[ 'type' ] ) {
1012
- case 'section_header':
1013
- echo '<td colspan="2" class="slimstat-options-section-header" id="wp-slimstat-' . sanitize_title( $_setting_info[ 'title' ] ) . '">' . $_setting_info[ 'title' ] . '</td>';
1014
- break;
1015
-
1016
- case 'readonly':
1017
- echo '<td colspan="2">' . $_setting_info[ 'title' ] . '<textarea rows="7" class="large-text code" readonly>' . $_setting_info[ 'description' ] . '</textarea></td>';
1018
- break;
1019
-
1020
- case 'toggle':
1021
- echo '<th scope="row"><label for="' . $_setting_slug . '">' . $_setting_info[ 'title' ] . '</label></th>
1022
- <td>
1023
- <span class="block-element">
1024
- <input class="slimstat-checkbox-toggle" type="checkbox"' . $is_readonly . '
1025
- name="options[' . $_setting_slug . ']"
1026
- id="' . $_setting_slug . '"
1027
- data-size="mini" data-handle-width="50" data-on-color="success"' .
1028
- ( ( $_setting_info[ 'default_value' ] == 'on' ) ? ' checked="checked"' : '' ) . '
1029
- data-on-text="' . ( !empty( $_setting_info[ 'custom_label_on' ] ) ? $_setting_info[ 'custom_label_on' ] : __( 'On', 'wp-slimstat' ) ) . '"
1030
- data-off-text="' . ( !empty( $_setting_info[ 'custom_label_off' ] ) ? $_setting_info[ 'custom_label_off' ] : __( 'Off', 'wp-slimstat' ) ) . '">' .
1031
- $network_override_checkbox . '
1032
- </span>
1033
- <span class="description">' . $_setting_info[ 'description' ] . '</span>
1034
- </td>';
1035
- // ( is_network_admin() ? ' data-indeterminate="true"' : '' ) . '>
1036
- break;
1037
-
1038
- case 'select':
1039
- echo '<th scope="row"><label for="' . $_setting_slug . '">' . $_setting_info[ 'title' ] . '</label></th>
1040
- <td>
1041
- <span class="block-element">
1042
- <select' . $is_readonly .' name="options[' . $_setting_slug . ']" id="' . $_setting_slug .'">';
1043
- foreach ( $_setting_info[ 'select_values' ] as $a_key => $a_value ) {
1044
- $is_selected = ( $_setting_info[ 'default_value' ] == $a_key ) ? ' selected' : '';
1045
- echo '<option' . $is_selected . ' value="' . $a_key . '">' . $a_value . '</option>';
1046
- }
1047
- echo '</select>' .
1048
- $network_override_checkbox . '
1049
- </span>
1050
- <span class="description">' . $_setting_info[ 'description' ] . '</span>
1051
- </td>';
1052
- break;
1053
-
1054
- case 'text':
1055
- case 'integer':
1056
- $empty_value = ( $_setting_info[ 'type' ] == 'text' ) ? '' : '0';
1057
- echo '<th scope="row"><label for="' . $_setting_slug . '">' . $_setting_info[ 'title' ] . '</label></th>
1058
- <td>
1059
- <span class="block-element"> ' .
1060
- $_setting_info[ 'before_input_field' ] . '
1061
- <input class="' . ( ( $_setting_info[ 'type' ] == 'integer' ) ? 'small-text' : 'regular-text' ) . '"' . $is_readonly . '
1062
- type="' . ( ( $_setting_info[ 'type' ] == 'integer' ) ? 'number' : 'text' ) . '"
1063
- name="options[' . $_setting_slug . ']"
1064
- id="' . $_setting_slug . '"
1065
- value="' . ( !empty( $_setting_info[ 'default_value' ] ) ? $_setting_info[ 'default_value' ] : $empty_value ) . '"> ' . $_setting_info[ 'after_input_field' ] .
1066
- $network_override_checkbox . '
1067
- </span>
1068
- <span class="description">' . $_setting_info[ 'description' ] . '</span>
1069
- </td>';
1070
- break;
1071
-
1072
- case 'textarea':
1073
- echo '
1074
- <td colspan="2">
1075
- <label for="' . $_setting_slug . '">' . $_setting_info[ 'title' ] . $network_override_checkbox . '</label>
1076
- <p class="description">' . $_setting_info[ 'description' ] . '</p>
1077
- <p>
1078
- <textarea class="large-text code' . $use_tag_list . '"' . $is_readonly . $use_code_editor . '
1079
- id="' . $_setting_slug . '"
1080
- rows="' . $_setting_info[ 'rows' ] . '"
1081
- name="options[' . $_setting_slug . ']">' . ( !empty( $_setting_info[ 'default_value' ] ) ? stripslashes( $_setting_info[ 'default_value' ] ) : '' ) . '</textarea>
1082
- <span class="description">' . $_setting_info[ 'after_input_field' ] . '</span>
1083
- </p>
1084
- </td>';
1085
- break;
1086
-
1087
- case 'plain-text':
1088
- echo '<th scope="row"><label for="' . $_setting_slug . '">' . $_setting_info[ 'title' ] . '</label></th>
1089
- <td>
1090
- <span class="block-element">' . $_setting_info[ 'after_input_field' ] . '</span>
1091
- <span class="description">' . $_setting_info[ 'description' ] . '</span>
1092
- </td>';
1093
- break;
1094
-
1095
- case 'custom':
1096
- echo '<td colspan="2">' . $_setting_info[ 'title' ] . '<br/><br/>' . $_setting_info[ 'markup' ] . '</td>';
1097
- break;
1098
-
1099
- default:
1100
- }
1101
- echo '</tr>';
1102
- }
1103
- ?></tbody>
1104
- </table>
1105
- <input type="hidden" name="options[make_sure_post_is_not_empty]" id="make_sure_post_is_not_empty" value="make_sure_post_is_not_empty">
1106
- <?php if ( empty( $_settings[ $_current_tab ][ 'include' ] ) ): ?><p class="submit"><input type="submit" value="<?php _e( 'Save Changes', 'wp-slimstat' ) ?>" class="button-primary" name="Submit"></p><?php endif ?>
1107
- </form><?php
1108
- }
1109
- // END: display_settings
1110
-
1111
  /*
1112
  * Updates the options
1113
  */
1114
  public static function update_settings( $_settings = array() ) {
1115
- // Nothing to do, if there is no data to be parsed or the nonce is not valid
1116
- if ( !isset( $_POST[ 'options' ] ) || empty( $_settings ) || !isset( $_POST[ 'slimstat_update_settings' ] ) || !wp_verify_nonce( $_POST[ 'slimstat_update_settings' ], 'slimstat_update_settings' ) ) {
1117
- return true;
1118
- }
1119
-
1120
- foreach( $_settings as $_setting_slug => $_setting_info ) {
1121
- // Some options require a special treatment and are updated somewhere else
1122
- if ( $_setting_info[ 'type' ] == 'readonly' || $_setting_info[ 'type' ] == 'section_header' || $_setting_info[ 'type' ] == 'plain-text' ) {
1123
- continue;
1124
- }
1125
-
1126
- // An empty toggle option is saved in the database as 'no'
1127
- if ( $_setting_info[ 'type' ] == 'toggle' && ( !isset( $_POST[ 'options' ][ $_setting_slug ] ) || strtolower( $_POST[ 'options' ][ $_setting_slug ] != 'on' ) ) ) {
1128
- wp_slimstat::$settings[ $_setting_slug ] = 'no';
1129
- }
1130
- else if ( isset( $_POST[ 'options' ][ $_setting_slug ] ) ) {
1131
- wp_slimstat::$settings[ $_setting_slug ] = !empty( $_setting_info[ 'use_code_editor' ] ) ? $_POST[ 'options' ][ $_setting_slug ] : sanitize_text_field( $_POST[ 'options' ][ $_setting_slug ] );
1132
- }
1133
-
1134
- // If the Network Settings add-on is enabled, there might be a switch to decide if this option needs to override what single sites have set
1135
- if ( is_network_admin() ) {
1136
- if ( !isset( $_POST[ 'options' ][ 'addon_network_settings_' . $_setting_slug ] ) || strtolower( $_POST[ 'options' ][ 'addon_network_settings_' . $_setting_slug ] != 'on' ) ) {
1137
- wp_slimstat::$settings[ 'addon_network_settings_' . $_setting_slug ] = 'no';
1138
- }
1139
- else {
1140
- wp_slimstat::$settings[ 'addon_network_settings_' . $_setting_slug ] = 'on';
1141
- }
1142
- }
1143
- else if ( isset( wp_slimstat::$settings[ 'addon_network_settings_' . $_setting_slug ] ) ) {
1144
- // Keep settings clean
1145
- unset( wp_slimstat::$settings[ 'addon_network_settings_' . $_setting_slug ] );
1146
- }
1147
- }
1148
-
1149
- if ( !empty( self::$faulty_fields ) ) {
1150
- self::show_message( implode( ' ', self::$faulty_fields ), 'warning' );
1151
- }
1152
- else{
1153
- self::show_message( __( 'Your new settings have been saved.', 'wp-slimstat' ), 'info' );
1154
- }
1155
  }
1156
  // END: update_settings
1157
 
@@ -1245,4 +1044,613 @@ class wp_slimstat_admin {
1245
  }
1246
  // END: _create_table
1247
  }
1248
- // END: class declaration
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4
  public static $screens_info = array();
5
  public static $config_url = '';
6
  public static $current_screen = 'slimview1';
 
7
  public static $page_location = 'slimstat';
8
+ public static $meta_user_reports = array();
9
 
10
  protected static $admin_notice = '';
11
  protected static $data_for_column = array(
31
  'is_report_group' => true,
32
  'show_in_sidebar' => true,
33
  'title' => __( 'Real-time', 'wp-slimstat' ),
34
+ 'capability' => 'can_view',
35
  'callback' => array( __CLASS__, 'wp_slimstat_include_view' )
36
  ),
37
  'slimview2' => array(
38
  'is_report_group' => true,
39
  'show_in_sidebar' => true,
40
  'title' => __( 'Overview', 'wp-slimstat' ),
41
+ 'capability' => 'can_view',
42
  'callback' => array( __CLASS__, 'wp_slimstat_include_view' )
43
  ),
44
  'slimview3' => array(
45
  'is_report_group' => true,
46
  'show_in_sidebar' => true,
47
  'title' => __( 'Audience', 'wp-slimstat' ),
48
+ 'capability' => 'can_view',
49
  'callback' => array( __CLASS__, 'wp_slimstat_include_view' )
50
  ),
51
  'slimview4' => array(
52
  'is_report_group' => true,
53
  'show_in_sidebar' => true,
54
  'title' => __( 'Site Analysis', 'wp-slimstat' ),
55
+ 'capability' => 'can_view',
56
  'callback' => array( __CLASS__, 'wp_slimstat_include_view' )
57
  ),
58
  'slimview5' => array(
59
  'is_report_group' => true,
60
  'show_in_sidebar' => true,
61
  'title' => __( 'Traffic Sources', 'wp-slimstat' ),
62
+ 'capability' => 'can_view',
63
  'callback' => array( __CLASS__, 'wp_slimstat_include_view' )
64
  ),
65
+ 'slimlayout' => array(
66
+ 'is_report_group' => false,
67
+ 'show_in_sidebar' => true,
68
+ 'title' => __( 'Customize', 'wp-slimstat' ),
69
+ 'capability' => 'can_customize',
70
+ 'callback' => array( __CLASS__, 'wp_slimstat_include_layout' )
71
+ ),
72
+ 'slimconfig' => array(
73
+ 'is_report_group' => false,
74
+ 'show_in_sidebar' => true,
75
+ 'title' => __( 'Settings', 'wp-slimstat' ),
76
+ 'capability' => 'can_admin',
77
+ 'callback' => array( __CLASS__, 'wp_slimstat_include_config' )
78
+ ),
79
  'slimaddons' => array(
80
  'is_report_group' => false,
81
  'show_in_sidebar' => current_user_can( 'manage_options' ),
82
  'title' => __( 'Add-ons', 'wp-slimstat' ),
83
+ 'capability' => 'can_admin',
84
  'callback' => array( __CLASS__, 'wp_slimstat_include_addons' )
85
  ),
86
  'dashboard' => array(
87
  'is_report_group' => true,
88
  'show_in_sidebar' => false,
89
  'title' => __( 'WordPress Dashboard', 'wp-slimstat' ),
90
+ 'capability' => '',
91
+ 'callback' => '' // No callback and capabilities are needed if show_in_sidebar is false
92
  ),
93
  'inactive' => array(
94
  'is_report_group' => true,
95
  'show_in_sidebar' => false,
96
  'title' => __( 'Inactive Reports' ),
97
+ 'capability' => '',
98
+ 'callback' => '' // No callback and capabilities are needed if show_in_sidebar is false
99
  )
100
  );
101
  self::$screens_info = apply_filters( 'slimstat_screens_info', self::$screens_info );
102
 
103
  // Settings URL
104
+ self::$config_url = get_admin_url( $GLOBALS[ 'blog_id' ], 'admin.php?page=slimconfig&amp;tab=' );
105
 
106
  // Current Screen
107
  if ( !empty( $_REQUEST[ 'page' ] ) && array_key_exists( $_REQUEST[ 'page' ], self::$screens_info ) ) {
113
  self::$page_location = 'admin';
114
  }
115
 
116
+ // Is the menu position setting being updated?
117
+ if ( !empty( $_POST[ 'slimstat_update_settings' ] ) && wp_verify_nonce( $_POST[ 'slimstat_update_settings' ], 'slimstat_update_settings' ) && !empty( $_POST[ 'options' ][ 'use_separate_menu' ] ) ) {
118
+ wp_slimstat::$settings[ 'use_separate_menu' ] = ( $_POST[ 'options' ][ 'use_separate_menu' ] == 'on' ) ? 'on' : 'no';
119
+ }
120
+
121
+ // Retrieve this user's custom report assignment (Customizer)
122
+ // Superadmins can customize the layout at network level, to override per-site settings
123
+ self::$meta_user_reports = get_user_option( 'meta-box-order_' . wp_slimstat_admin::$page_location . '_page_slimlayout-network', 1 );
124
+
125
+ // No network-wide settings found
126
+ if ( empty( self::$meta_user_reports ) ) {
127
+ self::$meta_user_reports = get_user_option( 'meta-box-order_' . wp_slimstat_admin::$page_location . '_page_slimlayout', $GLOBALS[ 'current_user' ]->ID );
128
+ }
129
+
130
  // WPMU - New blog created
131
  $active_sitewide_plugins = get_site_option( 'active_sitewide_plugins' );
132
  if ( !empty( $active_sitewide_plugins[ 'wp-slimstat/wp-slimstat.php' ] ) ) {
152
  add_action( 'transition_comment_status', array( __CLASS__, 'remove_spam' ), 15, 3 );
153
  }
154
 
155
+ // Add a menu to the admin bar
156
  if ( wp_slimstat::$settings[ 'use_separate_menu' ] != 'no' && is_admin_bar_showing() ) {
157
  add_action( 'admin_bar_menu', array( __CLASS__, 'add_menu_to_adminbar' ), 100 );
158
  }
159
 
160
  if ( function_exists( 'is_network_admin' ) && !is_network_admin() ) {
161
  // Add the appropriate entries to the admin menu, if this user can view/admin Slimstat
162
+ add_action( 'admin_menu', array( __CLASS__, 'add_menus' ) );
 
 
163
 
164
  // Display the column in the Edit Posts / Pages screen
165
  if ( wp_slimstat::$settings[ 'add_posts_column' ] == 'on' ) {
178
  }
179
  }
180
 
 
 
 
181
  // Update the table structure and options, if needed
182
  if ( !empty( wp_slimstat::$settings[ 'version' ] ) && wp_slimstat::$settings[ 'version' ] != wp_slimstat::$version ) {
183
  add_action( 'admin_init', array(__CLASS__, 'update_tables_and_options' ) );
517
  }
518
  // END: wp_slimstat_stylesheet
519
 
 
 
 
 
 
 
 
 
 
 
 
 
520
  /**
521
  * Loads user-defined stylesheet code
522
  */
553
  /**
554
  * Adds a new entry in the admin menu, to view the stats
555
  */
556
+ public static function add_menus( $_s = '' ) {
557
  // If this user is whitelisted, we use the minimum capability
558
  $minimum_capability = 'read';
559
  if ( is_network_admin() ) {
563
  $minimum_capability = wp_slimstat::$settings[ 'capability_can_view' ];
564
  }
565
 
566
+ // Find the first available location (screens with no reports assigned to them are hidden from the nav)
567
+ $parent = 'slimview1';
568
+ if ( is_array( self::$meta_user_reports ) ) {
569
+ $parent = '';
570
+ foreach ( self::$screens_info as $a_screen_id => $a_screen_info ) {
571
+ if ( !empty( self::$meta_user_reports[ $a_screen_id ] ) && $a_screen_info[ 'show_in_sidebar' ] ) {
572
+ $parent = $a_screen_id;
573
+ break;
574
+ }
575
+ }
576
+
577
+ if ( empty( $parent ) ) {
578
+ $parent = 'slimlayout';
579
+ }
580
+ }
581
+
582
+ // Get the current menu position
583
  $new_entry = array();
584
  if ( wp_slimstat::$settings[ 'use_separate_menu' ] == 'no' || is_network_admin() ) {
585
+ $new_entry[] = add_menu_page( __( 'Slimstat', 'wp-slimstat' ), __( 'Slimstat', 'wp-slimstat' ), $minimum_capability, $parent, array( __CLASS__, 'wp_slimstat_include_view' ), 'dashicons-chart-area' );
 
586
  }
587
  else {
588
  $parent = 'admin.php';
589
  }
590
 
 
 
591
  foreach ( self::$screens_info as $a_screen_id => $a_screen_info ) {
592
+ if ( isset( self::$meta_user_reports[ $a_screen_id ] ) && empty( self::$meta_user_reports[ $a_screen_id ] ) ) {
593
+ continue;
594
+ }
595
+
596
+ $minimum_capability = 'read';
597
+ if ( !empty( $a_screen_info[ 'capability' ] ) && strpos( wp_slimstat::$settings[ $a_screen_info[ 'capability' ] ], $GLOBALS[ 'current_user' ]->user_login ) === false && !empty( wp_slimstat::$settings[ 'capability_' . $a_screen_info[ 'capability' ] ] ) ) {
598
+ $minimum_capability = wp_slimstat::$settings[ 'capability_' . $a_screen_info[ 'capability' ] ];
599
+ }
600
+
601
  if ( $a_screen_info[ 'show_in_sidebar' ] ) {
602
+ $new_entry[] = add_submenu_page(
603
+ $parent,
604
+ $a_screen_info[ 'title' ],
605
+ $a_screen_info[ 'title' ],
606
+ $minimum_capability,
607
+ $a_screen_id,
608
+ $a_screen_info[ 'callback' ]
609
+ );
610
  }
611
  }
612
 
619
 
620
  return $_s;
621
  }
622
+ // END: add_menus
623
 
624
  /**
625
  * Adds a new entry in the WordPress Admin Bar
626
  */
627
  public static function add_menu_to_adminbar() {
628
  // If this user is whitelisted, we use the minimum capability
629
+ $minimum_capability = 'read';
630
+ if ( is_network_admin() ) {
631
+ $minimum_capability = 'manage_network';
632
  }
633
+ else if ( strpos( wp_slimstat::$settings[ 'can_view' ], $GLOBALS[ 'current_user' ]->user_login ) === false && !empty( wp_slimstat::$settings[ 'capability_can_view' ] ) ) {
634
+ $minimum_capability = wp_slimstat::$settings[ 'capability_can_view' ];
 
 
 
635
  }
636
 
637
+ // Find the first available location (screens with no reports assigned to them are hidden from the nav)
638
+ $parent = 'slimview1';
639
+ if ( is_array( self::$meta_user_reports ) ) {
640
+ $parent = '';
641
+ foreach ( self::$screens_info as $a_screen_id => $a_screen_info ) {
642
+ if ( !empty( self::$meta_user_reports[ $a_screen_id ] ) && $a_screen_info[ 'show_in_sidebar' ] ) {
643
+ $parent = $a_screen_id;
644
+ break;
645
+ }
646
+ }
647
 
648
+ if ( empty( $parent ) ) {
649
+ $parent = 'slimlayout';
650
+ }
651
  }
652
 
653
+ if ( current_user_can( $minimum_capability ) ) {
654
+ $view_url = get_admin_url( $GLOBALS[ 'blog_id' ], 'admin.php?page=' );
 
 
 
 
 
 
 
655
 
656
  $GLOBALS[ 'wp_admin_bar' ]->add_menu( array(
657
  'id' => 'slimstat-header',
658
+ 'title' => '<span class="ab-icon dashicons dashicons-chart-area" style="font-size:1rem;margin-top:3px"></span>' . __( 'Slimstat', 'wp-slimstat' ),
659
+ 'href' => "{$view_url}{$parent}"
660
  ) );
661
 
662
  foreach ( self::$screens_info as $a_screen_id => $a_screen_info ) {
663
+ if ( isset( self::$meta_user_reports[ $a_screen_id ] ) && empty( self::$meta_user_reports[ $a_screen_id ] ) ) {
664
+ continue;
665
+ }
666
+
667
+ $minimum_capability = 'read';
668
+ if ( !empty( $a_screen_info[ 'capability' ] ) && strpos( wp_slimstat::$settings[ $a_screen_info[ 'capability' ] ], $GLOBALS[ 'current_user' ]->user_login ) === false && !empty( wp_slimstat::$settings[ 'capability_' . $a_screen_info[ 'capability' ] ] ) ) {
669
+ $minimum_capability = wp_slimstat::$settings[ 'capability_' . $a_screen_info[ 'capability' ] ];
670
+ }
671
+
672
+ if ( $a_screen_info[ 'show_in_sidebar' ] && current_user_can( $minimum_capability ) ) {
673
  $GLOBALS[ 'wp_admin_bar' ]->add_menu( array(
674
  'id' => $a_screen_id,
675
+ 'href' => "{$view_url}$a_screen_id",
676
  'parent' => 'slimstat-header',
677
  'title' => $a_screen_info[ 'title' ]
678
  ) );
679
  }
680
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
681
  }
682
  }
683
  // END: add_menu_to_adminbar
684
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
685
  /**
686
  * Includes the appropriate panel to view the stats
687
  */
946
  }
947
  // END: manage_filters
948
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
949
  /*
950
  * Updates the options
951
  */
952
  public static function update_settings( $_settings = array() ) {
953
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
954
  }
955
  // END: update_settings
956
 
1044
  }
1045
  // END: _create_table
1046
  }
1047
+ // END: class declaration
1048
+
1049
+ class slim_i18n {
1050
+ public static $dynamic_strings = array();
1051
+
1052
+ public static function init_dynamic_strings() {
1053
+ if ( false === ( self::$dynamic_strings = get_transient( 'slimstat_dynamic_strings' ) ) ) {
1054
+ self::$dynamic_strings = array(
1055
+ 'xx' => __( 'Unknown', 'wp-slimstat' ),
1056
+
1057
+ // Countries
1058
+ 'c-' => __( 'Unknown', 'wp-slimstat' ),
1059
+ 'c-xx' => __( 'Unknown', 'wp-slimstat' ),
1060
+ 'c-xy' => __( 'Local IP Address', 'wp-slimstat' ),
1061
+
1062
+ 'c-af' => __( 'Afghanistan', 'wp-slimstat' ),
1063
+ 'c-ax' => __( 'Aland Islands', 'wp-slimstat' ),
1064
+ 'c-al' => __( 'Albania', 'wp-slimstat' ),
1065
+ 'c-dz' => __( 'Algeria', 'wp-slimstat' ),
1066
+ 'c-ad' => __( 'Andorra', 'wp-slimstat' ),
1067
+ 'c-ao' => __( 'Angola', 'wp-slimstat' ),
1068
+ 'c-ai' => __( 'Anguilla', 'wp-slimstat' ),
1069
+ 'c-ag' => __( 'Antigua and Barbuda', 'wp-slimstat' ),
1070
+ 'c-ar' => __( 'Argentina', 'wp-slimstat' ),
1071
+ 'c-am' => __( 'Armenia', 'wp-slimstat' ),
1072
+ 'c-aw' => __( 'Aruba', 'wp-slimstat' ),
1073
+ 'c-au' => __( 'Australia', 'wp-slimstat' ),
1074
+ 'c-at' => __( 'Austria', 'wp-slimstat' ),
1075
+ 'c-az' => __( 'Azerbaijan', 'wp-slimstat' ),
1076
+ 'c-bs' => __( 'Bahamas', 'wp-slimstat' ),
1077
+ 'c-bh' => __( 'Bahrain', 'wp-slimstat' ),
1078
+ 'c-bd' => __( 'Bangladesh', 'wp-slimstat' ),
1079
+ 'c-bb' => __( 'Barbados', 'wp-slimstat' ),
1080
+ 'c-by' => __( 'Belarus', 'wp-slimstat' ),
1081
+ 'c-be' => __( 'Belgium', 'wp-slimstat' ),
1082
+ 'c-bz' => __( 'Belize', 'wp-slimstat' ),
1083
+ 'c-bj' => __( 'Benin', 'wp-slimstat' ),
1084
+ 'c-bm' => __( 'Bermuda', 'wp-slimstat' ),
1085
+ 'c-bt' => __( 'Bhutan', 'wp-slimstat' ),
1086
+ 'c-bo' => __( 'Bolivia', 'wp-slimstat' ),
1087
+ 'c-ba' => __( 'Bosnia and Herzegovina', 'wp-slimstat' ),
1088
+ 'c-bw' => __( 'Botswana', 'wp-slimstat' ),
1089
+ 'c-br' => __( 'Brazil', 'wp-slimstat' ),
1090
+ 'c-bn' => __( 'Brunei Darussalam', 'wp-slimstat' ),
1091
+ 'c-bg' => __( 'Bulgaria', 'wp-slimstat' ),
1092
+ 'c-bf' => __( 'Burkina Faso', 'wp-slimstat' ),
1093
+ 'c-bi' => __( 'Burundi', 'wp-slimstat' ),
1094
+ 'c-kh' => __( 'Cambodia', 'wp-slimstat' ),
1095
+ 'c-cm' => __( 'Cameroon', 'wp-slimstat' ),
1096
+ 'c-ca' => __( 'Canada', 'wp-slimstat' ),
1097
+ 'c-cv' => __( 'Cape Verde', 'wp-slimstat' ),
1098
+ 'c-ky' => __( 'Cayman Islands', 'wp-slimstat' ),
1099
+ 'c-cf' => __( 'Central African Republic', 'wp-slimstat' ),
1100
+ 'c-td' => __( 'Chad', 'wp-slimstat' ),
1101
+ 'c-cl' => __( 'Chile', 'wp-slimstat' ),
1102
+ 'c-cn' => __( 'China', 'wp-slimstat' ),
1103
+ 'c-co' => __( 'Colombia', 'wp-slimstat' ),
1104
+ 'c-km' => __( 'Comoros', 'wp-slimstat' ),
1105
+ 'c-cg' => __( 'Congo', 'wp-slimstat' ),
1106
+ 'c-cd' => __( 'The Democratic Republic of the Congo', 'wp-slimstat' ),
1107
+ 'c-cr' => __( 'Costa Rica', 'wp-slimstat' ),
1108
+ 'c-ci' => __( 'Côte d\'Ivoire', 'wp-slimstat' ),
1109
+ 'c-hr' => __( 'Croatia', 'wp-slimstat' ),
1110
+ 'c-cu' => __( 'Cuba', 'wp-slimstat' ),
1111
+ 'c-cy' => __( 'Cyprus', 'wp-slimstat' ),
1112
+ 'c-cz' => __( 'Czech Republic', 'wp-slimstat' ),
1113
+ 'c-dk' => __( 'Denmark', 'wp-slimstat' ),
1114
+ 'c-dj' => __( 'Djibouti', 'wp-slimstat' ),
1115
+ 'c-dm' => __( 'Dominica', 'wp-slimstat' ),
1116
+ 'c-do' => __( 'Dominican Republic', 'wp-slimstat' ),
1117
+ 'c-ec' => __( 'Ecuador', 'wp-slimstat' ),
1118
+ 'c-eg' => __( 'Egypt', 'wp-slimstat' ),
1119
+ 'c-sv' => __( 'El Salvador', 'wp-slimstat' ),
1120
+ 'c-gq' => __( 'Equatorial Guinea', 'wp-slimstat' ),
1121
+ 'c-er' => __( 'Eritrea', 'wp-slimstat' ),
1122
+ 'c-ee' => __( 'Estonia', 'wp-slimstat' ),
1123
+ 'c-et' => __( 'Ethiopia', 'wp-slimstat' ),
1124
+ 'c-fo' => __( 'Faroe Islands', 'wp-slimstat' ),
1125
+ 'c-fk' => __( 'Falkland Islands (Malvinas)', 'wp-slimstat' ),
1126
+ 'c-fj' => __( 'Fiji', 'wp-slimstat' ),
1127
+ 'c-fi' => __( 'Finland', 'wp-slimstat' ),
1128
+ 'c-fr' => __( 'France', 'wp-slimstat' ),
1129
+ 'c-gf' => __( 'French Guiana', 'wp-slimstat' ),
1130
+ 'c-ga' => __( 'Gabon', 'wp-slimstat' ),
1131
+ 'c-gm' => __( 'Gambia', 'wp-slimstat' ),
1132
+ 'c-ge' => __( 'Georgia', 'wp-slimstat' ),
1133
+ 'c-de' => __( 'Germany', 'wp-slimstat' ),
1134
+ 'c-gh' => __( 'Ghana', 'wp-slimstat' ),
1135
+ 'c-gr' => __( 'Greece', 'wp-slimstat' ),
1136
+ 'c-gl' => __( 'Greenland', 'wp-slimstat' ),
1137
+ 'c-gd' => __( 'Grenada', 'wp-slimstat' ),
1138
+ 'c-gp' => __( 'Guadeloupe', 'wp-slimstat' ),
1139
+ 'c-gt' => __( 'Guatemala', 'wp-slimstat' ),
1140
+ 'c-gn' => __( 'Guinea', 'wp-slimstat' ),
1141
+ 'c-gw' => __( 'Guinea-Bissau', 'wp-slimstat' ),
1142
+ 'c-gy' => __( 'Guyana', 'wp-slimstat' ),
1143
+ 'c-ht' => __( 'Haiti', 'wp-slimstat' ),
1144
+ 'c-hn' => __( 'Honduras', 'wp-slimstat' ),
1145
+ 'c-hk' => __( 'Hong Kong', 'wp-slimstat' ),
1146
+ 'c-hu' => __( 'Hungary', 'wp-slimstat' ),
1147
+ 'c-is' => __( 'Iceland', 'wp-slimstat' ),
1148
+ 'c-in' => __( 'India', 'wp-slimstat' ),
1149
+ 'c-id' => __( 'Indonesia', 'wp-slimstat' ),
1150
+ 'c-ir' => __( 'Islamic Republic of Iran', 'wp-slimstat' ),
1151
+ 'c-iq' => __( 'Iraq', 'wp-slimstat' ),
1152
+ 'c-ie' => __( 'Ireland', 'wp-slimstat' ),
1153
+ 'c-il' => __( 'Israel', 'wp-slimstat' ),
1154
+ 'c-it' => __( 'Italy', 'wp-slimstat' ),
1155
+ 'c-jm' => __( 'Jamaica', 'wp-slimstat' ),
1156
+ 'c-jp' => __( 'Japan', 'wp-slimstat' ),
1157
+ 'c-jo' => __( 'Jordan', 'wp-slimstat' ),
1158
+ 'c-kz' => __( 'Kazakhstan', 'wp-slimstat' ),
1159
+ 'c-ke' => __( 'Kenya', 'wp-slimstat' ),
1160
+ 'c-nr' => __( 'Nauru', 'wp-slimstat' ),
1161
+ 'c-kp' => __( 'Democratic People\'s Republic of Korea', 'wp-slimstat' ),
1162
+ 'c-kr' => __( 'Republic of Korea', 'wp-slimstat' ),
1163
+ 'c-kv' => __( 'Kosovo', 'wp-slimstat' ),
1164
+ 'c-kw' => __( 'Kuwait', 'wp-slimstat' ),
1165
+ 'c-kg' => __( 'Kyrgyzstan', 'wp-slimstat' ),
1166
+ 'c-la' => __( 'Lao People\'s Democratic Republic', 'wp-slimstat' ),
1167
+ 'c-lv' => __( 'Latvia', 'wp-slimstat' ),
1168
+ 'c-lb' => __( 'Lebanon', 'wp-slimstat' ),
1169
+ 'c-ls' => __( 'Lesotho', 'wp-slimstat' ),
1170
+ 'c-lr' => __( 'Liberia', 'wp-slimstat' ),
1171
+ 'c-ly' => __( 'Libyan Arab Jamahiriya', 'wp-slimstat' ),
1172
+ 'c-li' => __( 'Liechtenstein', 'wp-slimstat' ),
1173
+ 'c-lt' => __( 'Lithuania', 'wp-slimstat' ),
1174
+ 'c-lu' => __( 'Luxembourg', 'wp-slimstat' ),
1175
+ 'c-mk' => __( 'The Former Yugoslav Republic of Macedonia', 'wp-slimstat' ),
1176
+ 'c-mg' => __( 'Madagascar', 'wp-slimstat' ),
1177
+ 'c-mw' => __( 'Malawi', 'wp-slimstat' ),
1178
+ 'c-my' => __( 'Malaysia', 'wp-slimstat' ),
1179
+ 'c-ml' => __( 'Mali', 'wp-slimstat' ),
1180
+ 'c-mt' => __( 'Malta', 'wp-slimstat' ),
1181
+ 'c-mq' => __( 'Martinique', 'wp-slimstat' ),
1182
+ 'c-mr' => __( 'Mauritania', 'wp-slimstat' ),
1183
+ 'c-mu' => __( 'Mauritius', 'wp-slimstat' ),
1184
+ 'c-mx' => __( 'Mexico', 'wp-slimstat' ),
1185
+ 'c-md' => __( 'Moldova', 'wp-slimstat' ),
1186
+ 'c-mn' => __( 'Mongolia', 'wp-slimstat' ),
1187
+ 'c-me' => __( 'Montenegro', 'wp-slimstat' ),
1188
+ 'c-ms' => __( 'Montserrat', 'wp-slimstat' ),
1189
+ 'c-ma' => __( 'Morocco', 'wp-slimstat' ),
1190
+ 'c-mz' => __( 'Mozambique', 'wp-slimstat' ),
1191
+ 'c-mm' => __( 'Myanmar', 'wp-slimstat' ),
1192
+ 'c-na' => __( 'Namibia', 'wp-slimstat' ),
1193
+ 'c-np' => __( 'Nepal', 'wp-slimstat' ),
1194
+ 'c-nl' => __( 'Netherlands', 'wp-slimstat' ),
1195
+ 'c-nc' => __( 'New Caledonia', 'wp-slimstat' ),
1196
+ 'c-nz' => __( 'New Zealand', 'wp-slimstat' ),
1197
+ 'c-ni' => __( 'Nicaragua', 'wp-slimstat' ),
1198
+ 'c-ne' => __( 'Niger', 'wp-slimstat' ),
1199
+ 'c-ng' => __( 'Nigeria', 'wp-slimstat' ),
1200
+ 'c-no' => __( 'Norway', 'wp-slimstat' ),
1201
+ 'c-om' => __( 'Oman', 'wp-slimstat' ),
1202
+ 'c-pk' => __( 'Pakistan', 'wp-slimstat' ),
1203
+ 'c-pw' => __( 'Palau', 'wp-slimstat' ),
1204
+ 'c-ps' => __( 'Occupied Palestinian Territory', 'wp-slimstat' ),
1205
+ 'c-pa' => __( 'Panama', 'wp-slimstat' ),
1206
+ 'c-pg' => __( 'Papua New Guinea', 'wp-slimstat' ),
1207
+ 'c-py' => __( 'Paraguay', 'wp-slimstat' ),
1208
+ 'c-pe' => __( 'Peru', 'wp-slimstat' ),
1209
+ 'c-ph' => __( 'Philippines', 'wp-slimstat' ),
1210
+ 'c-pl' => __( 'Poland', 'wp-slimstat' ),
1211
+ 'c-pt' => __( 'Portugal', 'wp-slimstat' ),
1212
+ 'c-pr' => __( 'Puerto Rico', 'wp-slimstat' ),
1213
+ 'c-qa' => __( 'Qatar', 'wp-slimstat' ),
1214
+ 'c-re' => __( 'Réunion', 'wp-slimstat' ),
1215
+ 'c-ro' => __( 'Romania', 'wp-slimstat' ),
1216
+ 'c-ru' => __( 'Russian Federation', 'wp-slimstat' ),
1217
+ 'c-rw' => __( 'Rwanda', 'wp-slimstat' ),
1218
+ 'c-kn' => __( 'Saint Kitts and Nevis', 'wp-slimstat' ),
1219
+ 'c-lc' => __( 'Saint Lucia', 'wp-slimstat' ),
1220
+ 'c-mf' => __( 'Saint Martin', 'wp-slimstat' ),
1221
+ 'c-vc' => __( 'Saint Vincent and the Grenadines', 'wp-slimstat' ),
1222
+ 'c-ws' => __( 'Samoa', 'wp-slimstat' ),
1223
+ 'c-st' => __( 'Sao Tome and Principe', 'wp-slimstat' ),
1224
+ 'c-sa' => __( 'Saudi Arabia', 'wp-slimstat' ),
1225
+ 'c-sn' => __( 'Senegal', 'wp-slimstat' ),
1226
+ 'c-rs' => __( 'Serbia', 'wp-slimstat' ),
1227
+ 'c-sl' => __( 'Sierra Leone', 'wp-slimstat' ),
1228
+ 'c-sg' => __( 'Singapore', 'wp-slimstat' ),
1229
+ 'c-sk' => __( 'Slovakia', 'wp-slimstat' ),
1230
+ 'c-si' => __( 'Slovenia', 'wp-slimstat' ),
1231
+ 'c-sb' => __( 'Solomon Islands', 'wp-slimstat' ),
1232
+ 'c-so' => __( 'Somalia', 'wp-slimstat' ),
1233
+ 'c-za' => __( 'South Africa', 'wp-slimstat' ),
1234
+ 'c-gs' => __( 'South Georgia and the South Sandwich Islands', 'wp-slimstat' ),
1235
+ 'c-es' => __( 'Spain', 'wp-slimstat' ),
1236
+ 'c-lk' => __( 'Sri Lanka', 'wp-slimstat' ),
1237
+ 'c-sc' => __( 'Seychelles', 'wp-slimstat' ),
1238
+ 'c-sd' => __( 'Sudan', 'wp-slimstat' ),
1239
+ 'c-ss' => __( 'South Sudan', 'wp-slimstat' ),
1240
+ 'c-sr' => __( 'Suriname', 'wp-slimstat' ),
1241
+ 'c-sj' => __( 'Svalbard and Jan Mayen', 'wp-slimstat' ),
1242
+ 'c-sz' => __( 'Swaziland', 'wp-slimstat' ),
1243
+ 'c-se' => __( 'Sweden', 'wp-slimstat' ),
1244
+ 'c-ch' => __( 'Switzerland', 'wp-slimstat' ),
1245
+ 'c-sy' => __( 'Syrian Arab Republic', 'wp-slimstat' ),
1246
+ 'c-tw' => __( 'Taiwan', 'wp-slimstat' ),
1247
+ 'c-tj' => __( 'Tajikistan', 'wp-slimstat' ),
1248
+ 'c-tz' => __( 'United Republic of Tanzania', 'wp-slimstat' ),
1249
+ 'c-th' => __( 'Thailand', 'wp-slimstat' ),
1250
+ 'c-tl' => __( 'Timor-Leste', 'wp-slimstat' ),
1251
+ 'c-tg' => __( 'Togo', 'wp-slimstat' ),
1252
+ 'c-to' => __( 'Tonga', 'wp-slimstat' ),
1253
+ 'c-tt' => __( 'Trinidad and Tobago', 'wp-slimstat' ),
1254
+ 'c-tn' => __( 'Tunisia', 'wp-slimstat' ),
1255
+ 'c-tr' => __( 'Turkey', 'wp-slimstat' ),
1256
+ 'c-tm' => __( 'Turkmenistan', 'wp-slimstat' ),
1257
+ 'c-tc' => __( 'Turks and Caicos Islands', 'wp-slimstat' ),
1258
+ 'c-ug' => __( 'Uganda', 'wp-slimstat' ),
1259
+ 'c-ua' => __( 'Ukraine', 'wp-slimstat' ),
1260
+ 'c-ae' => __( 'United Arab Emirates', 'wp-slimstat' ),
1261
+ 'c-gb' => __( 'United Kingdom', 'wp-slimstat' ),
1262
+ 'c-us' => __( 'United States', 'wp-slimstat' ),
1263
+ 'c-uy' => __( 'Uruguay', 'wp-slimstat' ),
1264
+ 'c-uz' => __( 'Uzbekistan', 'wp-slimstat' ),
1265
+ 'c-vu' => __( 'Vanuatu', 'wp-slimstat' ),
1266
+ 'c-ve' => __( 'Venezuela', 'wp-slimstat' ),
1267
+ 'c-vn' => __( 'Viet Nam', 'wp-slimstat' ),
1268
+ 'c-vg' => __( 'British Virgin Islands', 'wp-slimstat' ),
1269
+ 'c-vi' => __( 'U.S. Virgin Islands', 'wp-slimstat' ),
1270
+ 'c-eh' => __( 'Western Sahara', 'wp-slimstat' ),
1271
+ 'c-ye' => __( 'Yemen', 'wp-slimstat' ),
1272
+ 'c-zm' => __( 'Zambia', 'wp-slimstat' ),
1273
+ 'c-zw' => __( 'Zimbabwe', 'wp-slimstat' ),
1274
+ 'c-gg' => __( 'Guernsey', 'wp-slimstat' ),
1275
+ 'c-je' => __( 'Jersey', 'wp-slimstat' ),
1276
+ 'c-im' => __( 'Isle of Man', 'wp-slimstat' ),
1277
+ 'c-mv' => __( 'Maldives', 'wp-slimstat' ),
1278
+ 'c-eu' => __( 'Europe', 'wp-slimstat' ),
1279
+
1280
+ // Languages
1281
+ 'l-' => __( 'Unknown', 'wp-slimstat' ),
1282
+ 'l-empty' => __( 'Unknown', 'wp-slimstat' ),
1283
+ 'l-xx' => __( 'Unknown', 'wp-slimstat' ),
1284
+
1285
+ 'l-af' => __( 'Afrikaans', 'wp-slimstat' ),
1286
+ 'l-af-za' => __( 'Afrikaans (South Africa)', 'wp-slimstat' ),
1287
+ 'l-ar' => __( 'Arabic', 'wp-slimstat' ),
1288
+ 'l-ar-ae' => __( 'Arabic (U.A.E.)', 'wp-slimstat' ),
1289
+ 'l-ar-bh' => __( 'Arabic (Bahrain)', 'wp-slimstat' ),
1290
+ 'l-ar-dz' => __( 'Arabic (Algeria)', 'wp-slimstat' ),
1291
+ 'l-ar-eg' => __( 'Arabic (Egypt)', 'wp-slimstat' ),
1292
+ 'l-ar-iq' => __( 'Arabic (Iraq)', 'wp-slimstat' ),
1293
+ 'l-ar-jo' => __( 'Arabic (Jordan)', 'wp-slimstat' ),
1294
+ 'l-ar-kw' => __( 'Arabic (Kuwait)', 'wp-slimstat' ),
1295
+ 'l-ar-lb' => __( 'Arabic (Lebanon)', 'wp-slimstat' ),
1296
+ 'l-ar-ly' => __( 'Arabic (Libya)', 'wp-slimstat' ),
1297
+ 'l-ar-ma' => __( 'Arabic (Morocco)', 'wp-slimstat' ),
1298
+ 'l-ar-om' => __( 'Arabic (Oman)', 'wp-slimstat' ),
1299
+ 'l-ar-qa' => __( 'Arabic (Qatar)', 'wp-slimstat' ),
1300
+ 'l-ar-sa' => __( 'Arabic (Saudi Arabia)', 'wp-slimstat' ),
1301
+ 'l-ar-sy' => __( 'Arabic (Syria)', 'wp-slimstat' ),
1302
+ 'l-ar-tn' => __( 'Arabic (Tunisia)', 'wp-slimstat' ),
1303
+ 'l-ar-ye' => __( 'Arabic (Yemen)', 'wp-slimstat' ),
1304
+ 'l-az' => __( 'Azeri (Latin)', 'wp-slimstat' ),
1305
+ 'l-az-az' => __( 'Azeri (Latin) (Azerbaijan)', 'wp-slimstat' ),
1306
+ 'l-be' => __( 'Belarusian', 'wp-slimstat' ),
1307
+ 'l-be-by' => __( 'Belarusian (Belarus)', 'wp-slimstat' ),
1308
+ 'l-bg' => __( 'Bulgarian', 'wp-slimstat' ),
1309
+ 'l-bg-bg' => __( 'Bulgarian (Bulgaria)', 'wp-slimstat' ),
1310
+ 'l-bs-ba' => __( 'Bosnian (Bosnia and Herzegovina)', 'wp-slimstat' ),
1311
+ 'l-ca' => __( 'Catalan', 'wp-slimstat' ),
1312
+ 'l-ca-es' => __( 'Catalan (Spain)', 'wp-slimstat' ),
1313
+ 'l-cs' => __( 'Czech', 'wp-slimstat' ),
1314
+ 'l-cs-cz' => __( 'Czech (Czech Republic)', 'wp-slimstat' ),
1315
+ 'l-cy' => __( 'Welsh', 'wp-slimstat' ),
1316
+ 'l-cy-gb' => __( 'Welsh (United Kingdom)', 'wp-slimstat' ),
1317
+ 'l-da' => __( 'Danish', 'wp-slimstat' ),
1318
+ 'l-da-dk' => __( 'Danish (Denmark)', 'wp-slimstat' ),
1319
+ 'l-de' => __( 'German', 'wp-slimstat' ),
1320
+ 'l-de-at' => __( 'German (Austria)', 'wp-slimstat' ),
1321
+ 'l-de-ch' => __( 'German (Switzerland)', 'wp-slimstat' ),
1322
+ 'l-de-de' => __( 'German (Germany)', 'wp-slimstat' ),
1323
+ 'l-de-li' => __( 'German (Liechtenstein)', 'wp-slimstat' ),
1324
+ 'l-de-lu' => __( 'German (Luxembourg)', 'wp-slimstat' ),
1325
+ 'l-dv' => __( 'Divehi', 'wp-slimstat' ),
1326
+ 'l-dv-mv' => __( 'Divehi (Maldives)', 'wp-slimstat' ),
1327
+ 'l-el' => __( 'Greek', 'wp-slimstat' ),
1328
+ 'l-el-gr' => __( 'Greek (Greece)', 'wp-slimstat' ),
1329
+ 'l-en' => __( 'English', 'wp-slimstat' ),
1330
+ 'l-en-au' => __( 'English (Australia)', 'wp-slimstat' ),
1331
+ 'l-en-bz' => __( 'English (Belize)', 'wp-slimstat' ),
1332
+ 'l-en-ca' => __( 'English (Canada)', 'wp-slimstat' ),
1333
+ 'l-en-cb' => __( 'English (Caribbean)', 'wp-slimstat' ),
1334
+ 'l-en-gb' => __( 'English (United Kingdom)', 'wp-slimstat' ),
1335
+ 'l-en-ie' => __( 'English (Ireland)', 'wp-slimstat' ),
1336
+ 'l-en-jm' => __( 'English (Jamaica)', 'wp-slimstat' ),
1337
+ 'l-en-nz' => __( 'English (New Zealand)', 'wp-slimstat' ),
1338
+ 'l-en-ph' => __( 'English (Republic of the Philippines)', 'wp-slimstat' ),
1339
+ 'l-en-tt' => __( 'English (Trinidad and Tobago)', 'wp-slimstat' ),
1340
+ 'l-en-us' => __( 'English (United States)', 'wp-slimstat' ),
1341
+ 'l-en-za' => __( 'English (South Africa)', 'wp-slimstat' ),
1342
+ 'l-en-zw' => __( 'English (Zimbabwe)', 'wp-slimstat' ),
1343
+ 'l-eo' => __( 'Esperanto', 'wp-slimstat' ),
1344
+ 'l-es' => __( 'Spanish', 'wp-slimstat' ),
1345
+ 'l-es-ar' => __( 'Spanish (Argentina)', 'wp-slimstat' ),
1346
+ 'l-es-bo' => __( 'Spanish (Bolivia)', 'wp-slimstat' ),
1347
+ 'l-es-cl' => __( 'Spanish (Chile)', 'wp-slimstat' ),
1348
+ 'l-es-co' => __( 'Spanish (Colombia)', 'wp-slimstat' ),
1349
+ 'l-es-cr' => __( 'Spanish (Costa Rica)', 'wp-slimstat' ),
1350
+ 'l-es-do' => __( 'Spanish (Dominican Republic)', 'wp-slimstat' ),
1351
+ 'l-es-ec' => __( 'Spanish (Ecuador)', 'wp-slimstat' ),
1352
+ 'l-es-es' => __( 'Spanish (Spain)', 'wp-slimstat' ),
1353
+ 'l-es-gt' => __( 'Spanish (Guatemala)', 'wp-slimstat' ),
1354
+ 'l-es-hn' => __( 'Spanish (Honduras)', 'wp-slimstat' ),
1355
+ 'l-es-mx' => __( 'Spanish (Mexico)', 'wp-slimstat' ),
1356
+ 'l-es-ni' => __( 'Spanish (Nicaragua)', 'wp-slimstat' ),
1357
+ 'l-es-pa' => __( 'Spanish (Panama)', 'wp-slimstat' ),
1358
+ 'l-es-pe' => __( 'Spanish (Peru)', 'wp-slimstat' ),
1359
+ 'l-es-pr' => __( 'Spanish (Puerto Rico)', 'wp-slimstat' ),
1360
+ 'l-es-py' => __( 'Spanish (Paraguay)', 'wp-slimstat' ),
1361
+ 'l-es-sv' => __( 'Spanish (El Salvador)', 'wp-slimstat' ),
1362
+ 'l-es-uy' => __( 'Spanish (Uruguay)', 'wp-slimstat' ),
1363
+ 'l-es-ve' => __( 'Spanish (Venezuela)', 'wp-slimstat' ),
1364
+ 'l-et' => __( 'Estonian', 'wp-slimstat' ),
1365
+ 'l-et-ee' => __( 'Estonian (Estonia)', 'wp-slimstat' ),
1366
+ 'l-eu' => __( 'Basque', 'wp-slimstat' ),
1367
+ 'l-eu-es' => __( 'Basque (Spain)', 'wp-slimstat' ),
1368
+ 'l-fa' => __( 'Farsi', 'wp-slimstat' ),
1369
+ 'l-fa-ir' => __( 'Farsi (Iran)', 'wp-slimstat' ),
1370
+ 'l-fi' => __( 'Finnish', 'wp-slimstat' ),
1371
+ 'l-fi-fi' => __( 'Finnish (Finland)', 'wp-slimstat' ),
1372
+ 'l-fo' => __( 'Faroese', 'wp-slimstat' ),
1373
+ 'l-fo-fo' => __( 'Faroese (Faroe Islands)', 'wp-slimstat' ),
1374
+ 'l-fr' => __( 'French', 'wp-slimstat' ),
1375
+ 'l-fr-be' => __( 'French (Belgium)', 'wp-slimstat' ),
1376
+ 'l-fr-ca' => __( 'French (Canada)', 'wp-slimstat' ),
1377
+ 'l-fr-ch' => __( 'French (Switzerland)', 'wp-slimstat' ),
1378
+ 'l-fr-fr' => __( 'French (France)', 'wp-slimstat' ),
1379
+ 'l-fr-lu' => __( 'French (Luxembourg)', 'wp-slimstat' ),
1380
+ 'l-fr-mc' => __( 'French (Principality of Monaco)', 'wp-slimstat' ),
1381
+ 'l-gl' => __( 'Galician', 'wp-slimstat' ),
1382
+ 'l-gl-es' => __( 'Galician (Spain)', 'wp-slimstat' ),
1383
+ 'l-gu' => __( 'Gujarati', 'wp-slimstat' ),
1384
+ 'l-gu-in' => __( 'Gujarati (India)', 'wp-slimstat' ),
1385
+ 'l-he' => __( 'Hebrew', 'wp-slimstat' ),
1386
+ 'l-he-il' => __( 'Hebrew (Israel)', 'wp-slimstat' ),
1387
+ 'l-hi' => __( 'Hindi', 'wp-slimstat' ),
1388
+ 'l-hi-in' => __( 'Hindi (India)', 'wp-slimstat' ),
1389
+ 'l-hr' => __( 'Croatian', 'wp-slimstat' ),
1390
+ 'l-hr-ba' => __( 'Croatian (Bosnia and Herzegovina)', 'wp-slimstat' ),
1391
+ 'l-hr-hr' => __( 'Croatian (Croatia)', 'wp-slimstat' ),
1392
+ 'l-hu' => __( 'Hungarian', 'wp-slimstat' ),
1393
+ 'l-hu-hu' => __( 'Hungarian (Hungary)', 'wp-slimstat' ),
1394
+ 'l-hy' => __( 'Armenian', 'wp-slimstat' ),
1395
+ 'l-hy-am' => __( 'Armenian (Armenia)', 'wp-slimstat' ),
1396
+ 'l-id' => __( 'Indonesian', 'wp-slimstat' ),
1397
+ 'l-id-id' => __( 'Indonesian (Indonesia)', 'wp-slimstat' ),
1398
+ 'l-is' => __( 'Icelandic', 'wp-slimstat' ),
1399
+ 'l-is-is' => __( 'Icelandic (Iceland)', 'wp-slimstat' ),
1400
+ 'l-it' => __( 'Italian', 'wp-slimstat' ),
1401
+ 'l-it-ch' => __( 'Italian (Switzerland)', 'wp-slimstat' ),
1402
+ 'l-it-it' => __( 'Italian (Italy)', 'wp-slimstat' ),
1403
+ 'l-ja' => __( 'Japanese', 'wp-slimstat' ),
1404
+ 'l-ja-jp' => __( 'Japanese (Japan)', 'wp-slimstat' ),
1405
+ 'l-ka' => __( 'Georgian', 'wp-slimstat' ),
1406
+ 'l-ka-ge' => __( 'Georgian (Georgia)', 'wp-slimstat' ),
1407
+ 'l-kk' => __( 'Kazakh', 'wp-slimstat' ),
1408
+ 'l-kk-kz' => __( 'Kazakh (Kazakhstan)', 'wp-slimstat' ),
1409
+ 'l-kn' => __( 'Kannada', 'wp-slimstat' ),
1410
+ 'l-kn-in' => __( 'Kannada (India)', 'wp-slimstat' ),
1411
+ 'l-ko' => __( 'Korean', 'wp-slimstat' ),
1412
+ 'l-ko-kr' => __( 'Korean (Korea)', 'wp-slimstat' ),
1413
+ 'l-kok' => __( 'Konkani', 'wp-slimstat' ),
1414
+ 'l-kok-in' => __( 'Konkani (India)', 'wp-slimstat' ),
1415
+ 'l-ky' => __( 'Kyrgyz', 'wp-slimstat' ),
1416
+ 'l-ky-kg' => __( 'Kyrgyz (Kyrgyzstan)', 'wp-slimstat' ),
1417
+ 'l-lt' => __( 'Lithuanian', 'wp-slimstat' ),
1418
+ 'l-lt-lt' => __( 'Lithuanian (Lithuania)', 'wp-slimstat' ),
1419
+ 'l-lv' => __( 'Latvian', 'wp-slimstat' ),
1420
+ 'l-lv-lv' => __( 'Latvian (Latvia)', 'wp-slimstat' ),
1421
+ 'l-mi' => __( 'Maori', 'wp-slimstat' ),
1422
+ 'l-mi-nz' => __( 'Maori (New Zealand)', 'wp-slimstat' ),
1423
+ 'l-mk' => __( 'FYRO Macedonian', 'wp-slimstat' ),
1424
+ 'l-mk-ml' => __( 'FYRO Macedonian (Former Yugoslav Republic of Macedonia)', 'wp-slimstat' ),
1425
+ 'l-mn' => __( 'Mongolian', 'wp-slimstat' ),
1426
+ 'l-mn-mn' => __( 'Mongolian (Mongolia)', 'wp-slimstat' ),
1427
+ 'l-mr' => __( 'Marathi', 'wp-slimstat' ),
1428
+ 'l-mr-in' => __( 'Marathi (India)', 'wp-slimstat' ),
1429
+ 'l-ms' => __( 'Malay', 'wp-slimstat' ),
1430
+ 'l-ms-bn' => __( 'Malay (Brunei Darussalam)', 'wp-slimstat' ),
1431
+ 'l-ms-my' => __( 'Malay (Malaysia)', 'wp-slimstat' ),
1432
+ 'l-mt' => __( 'Maltese', 'wp-slimstat' ),
1433
+ 'l-mt-mt' => __( 'Maltese (Malta)', 'wp-slimstat' ),
1434
+ 'l-nb' => __( 'Norwegian (Bokmål)', 'wp-slimstat' ),
1435
+ 'l-nb-no' => __( 'Norwegian (Bokmål) (Norway)', 'wp-slimstat' ),
1436
+ 'l-nl' => __( 'Dutch', 'wp-slimstat' ),
1437
+ 'l-nl-be' => __( 'Dutch (Belgium)', 'wp-slimstat' ),
1438
+ 'l-nl-nl' => __( 'Dutch (Netherlands)', 'wp-slimstat' ),
1439
+ 'l-nn-no' => __( 'Norwegian (Nynorsk) (Norway)', 'wp-slimstat' ),
1440
+ 'l-ns' => __( 'Northern Sotho', 'wp-slimstat' ),
1441
+ 'l-ns-za' => __( 'Northern Sotho (South Africa)', 'wp-slimstat' ),
1442
+ 'l-pa' => __( 'Punjabi', 'wp-slimstat' ),
1443
+ 'l-pa-in' => __( 'Punjabi (India)', 'wp-slimstat' ),
1444
+ 'l-pl' => __( 'Polish', 'wp-slimstat' ),
1445
+ 'l-pl-pl' => __( 'Polish (Poland)', 'wp-slimstat' ),
1446
+ 'l-ps' => __( 'Pashto', 'wp-slimstat' ),
1447
+ 'l-ps-ar' => __( 'Pashto (Afghanistan)', 'wp-slimstat' ),
1448
+ 'l-pt' => __( 'Portuguese', 'wp-slimstat' ),
1449
+ 'l-pt-br' => __( 'Portuguese (Brazil)', 'wp-slimstat' ),
1450
+ 'l-pt-pt' => __( 'Portuguese (Portugal)', 'wp-slimstat' ),
1451
+ 'l-qu' => __( 'Quechua', 'wp-slimstat' ),
1452
+ 'l-qu-bo' => __( 'Quechua (Bolivia)', 'wp-slimstat' ),
1453
+ 'l-qu-ec' => __( 'Quechua (Ecuador)', 'wp-slimstat' ),
1454
+ 'l-qu-pe' => __( 'Quechua (Peru)', 'wp-slimstat' ),
1455
+ 'l-ro' => __( 'Romanian', 'wp-slimstat' ),
1456
+ 'l-ro-ro' => __( 'Romanian (Romania)', 'wp-slimstat' ),
1457
+ 'l-ru' => __( 'Russian', 'wp-slimstat' ),
1458
+ 'l-ru-ru' => __( 'Russian (Russia)', 'wp-slimstat' ),
1459
+ 'l-sa' => __( 'Sanskrit', 'wp-slimstat' ),
1460
+ 'l-sa-in' => __( 'Sanskrit (India)', 'wp-slimstat' ),
1461
+ 'l-se' => __( 'Sami (Northern)', 'wp-slimstat' ),
1462
+ 'l-se-fi' => __( 'Sami (Northern) (Finland)', 'wp-slimstat' ),
1463
+ 'l-se-no' => __( 'Sami (Northern) (Norway)', 'wp-slimstat' ),
1464
+ 'l-se-se' => __( 'Sami (Northern) (Sweden)', 'wp-slimstat' ),
1465
+ 'l-sk' => __( 'Slovak', 'wp-slimstat' ),
1466
+ 'l-sk-sk' => __( 'Slovak (Slovakia)', 'wp-slimstat' ),
1467
+ 'l-sl' => __( 'Slovenian', 'wp-slimstat' ),
1468
+ 'l-sl-si' => __( 'Slovenian (Slovenia)', 'wp-slimstat' ),
1469
+ 'l-sq' => __( 'Albanian', 'wp-slimstat' ),
1470
+ 'l-sq-al' => __( 'Albanian (Albania)', 'wp-slimstat' ),
1471
+ 'l-sr-ba' => __( 'Serbian (Latin) (Bosnia and Herzegovina)', 'wp-slimstat' ),
1472
+ 'l-sr-rs' => __( 'Serbian (Serbia and Montenegro)', 'wp-slimstat' ),
1473
+ 'l-sr-sp' => __( 'Serbian (Latin) (Serbia and Montenegro)', 'wp-slimstat' ),
1474
+ 'l-sv' => __( 'Swedish', 'wp-slimstat' ),
1475
+ 'l-sv-fi' => __( 'Swedish (Finland)', 'wp-slimstat' ),
1476
+ 'l-sv-se' => __( 'Swedish (Sweden)', 'wp-slimstat' ),
1477
+ 'l-sw' => __( 'Swahili', 'wp-slimstat' ),
1478
+ 'l-sw-ke' => __( 'Swahili (Kenya)', 'wp-slimstat' ),
1479
+ 'l-ta' => __( 'Tamil', 'wp-slimstat' ),
1480
+ 'l-ta-in' => __( 'Tamil (India)', 'wp-slimstat' ),
1481
+ 'l-te' => __( 'Telugu', 'wp-slimstat' ),
1482
+ 'l-te-in' => __( 'Telugu (India)', 'wp-slimstat' ),
1483
+ 'l-th' => __( 'Thai', 'wp-slimstat' ),
1484
+ 'l-th-th' => __( 'Thai (Thailand)', 'wp-slimstat' ),
1485
+ 'l-tl' => __( 'Tagalog', 'wp-slimstat' ),
1486
+ 'l-tl-ph' => __( 'Tagalog (Philippines)', 'wp-slimstat' ),
1487
+ 'l-tn' => __( 'Tswana', 'wp-slimstat' ),
1488
+ 'l-tn-za' => __( 'Tswana (South Africa)', 'wp-slimstat' ),
1489
+ 'l-tr' => __( 'Turkish', 'wp-slimstat' ),
1490
+ 'l-tr-tr' => __( 'Turkish (Turkey)', 'wp-slimstat' ),
1491
+ 'l-tt' => __( 'Tatar', 'wp-slimstat' ),
1492
+ 'l-tt-ru' => __( 'Tatar (Russia)', 'wp-slimstat' ),
1493
+ 'l-ts' => __( 'Tsonga', 'wp-slimstat' ),
1494
+ 'l-uk' => __( 'Ukrainian', 'wp-slimstat' ),
1495
+ 'l-uk-ua' => __( 'Ukrainian (Ukraine)', 'wp-slimstat' ),
1496
+ 'l-ur' => __( 'Urdu', 'wp-slimstat' ),
1497
+ 'l-ur-pk' => __( 'Urdu (Islamic Republic of Pakistan)', 'wp-slimstat' ),
1498
+ 'l-uz' => __( 'Uzbek (Latin)', 'wp-slimstat' ),
1499
+ 'l-uz-uz' => __( 'Uzbek (Cyrillic) (Uzbekistan)', 'wp-slimstat' ),
1500
+ 'l-vi' => __( 'Vietnamese', 'wp-slimstat' ),
1501
+ 'l-vi-vn' => __( 'Vietnamese (Viet Nam)', 'wp-slimstat' ),
1502
+ 'l-xh' => __( 'Xhosa', 'wp-slimstat' ),
1503
+ 'l-xh-za' => __( 'Xhosa (South Africa)', 'wp-slimstat' ),
1504
+ 'l-zh' => __( 'Chinese', 'wp-slimstat' ),
1505
+ 'l-zh-cn' => __( 'Chinese (S)', 'wp-slimstat' ),
1506
+ 'l-zh-hk' => __( 'Chinese (Hong Kong)', 'wp-slimstat' ),
1507
+ 'l-zh-mo' => __( 'Chinese (Macau)', 'wp-slimstat' ),
1508
+ 'l-zh-sg' => __( 'Chinese (Singapore)', 'wp-slimstat' ),
1509
+ 'l-zh-tw' => __( 'Chinese (T)', 'wp-slimstat' ),
1510
+ 'l-zu' => __( 'Zulu', 'wp-slimstat' ),
1511
+ 'l-zu-za' => __( 'Zulu (South Africa)', 'wp-slimstat' ),
1512
+
1513
+ // Operating Systems
1514
+ 'aix' => __( 'IBM AIX', 'wp-slimstat' ),
1515
+ 'amiga' => __( 'Amiga', 'wp-slimstat' ),
1516
+ 'android' => __( 'Android', 'wp-slimstat' ),
1517
+ 'beos' => __( 'BeOS', 'wp-slimstat' ),
1518
+ 'blackberry os' => __( 'BlackBerry OS', 'wp-slimstat' ),
1519
+ 'centos' => __( 'CentOS', 'wp-slimstat' ),
1520
+ 'chromeos' => __( 'ChromeOS', 'wp-slimstat' ),
1521
+ 'commodore64' => __( 'Commodore 64', 'wp-slimstat' ),
1522
+ 'cygwin' => __( 'Cygwin', 'wp-slimstat' ),
1523
+ 'debian' => __( 'Debian', 'wp-slimstat' ),
1524
+ 'digital unix' => __( 'Digital Unix', 'wp-slimstat' ),
1525
+ 'fedora' => __( 'Fedora', 'wp-slimstat' ),
1526
+ 'firefoxos' => __( 'Firefox OS', 'wp-slimstat' ),
1527
+ 'freebsd' => __( 'FreeBSD', 'wp-slimstat' ),
1528
+ 'gentoo' => __( 'Gentoo', 'wp-slimstat' ),
1529
+ 'hp-ux' => __( 'HP-UX', 'wp-slimstat' ),
1530
+ 'ios' => __( 'iPhone OS', 'wp-slimstat' ),
1531
+ 'iphone os' => __( 'iPhone OS', 'wp-slimstat' ),
1532
+ 'iphone osx' => __( 'iPhone OS X', 'wp-slimstat' ),
1533
+ 'irix' => __( 'SGI / IRIX', 'wp-slimstat' ),
1534
+ 'java' => __( 'Java', 'wp-slimstat' ),
1535
+ 'kanotix' => __( 'Kanotix Linux', 'wp-slimstat' ),
1536
+ 'knoppix' => __( 'Knoppix Linux', 'wp-slimstat' ),
1537
+ 'linux' => __( 'Linux Generic', 'wp-slimstat' ),
1538
+ 'mac' => __( 'Mac', 'wp-slimstat' ),
1539
+ 'mac68k' => __( 'Mac 68k', 'wp-slimstat' ),
1540
+ 'macos' => __( 'Mac OS X', 'wp-slimstat' ),
1541
+ 'macosx' => __( 'Mac OS X', 'wp-slimstat' ),
1542
+ 'macppc' => __( 'Mac PowerPC', 'wp-slimstat' ),
1543
+ 'mandrake' => __( 'Mandrake Linux', 'wp-slimstat' ),
1544
+ 'mandriva' => __( 'MS-DOS', 'wp-slimstat' ),
1545
+ 'mepis' => __( 'MEPIS Linux', 'wp-slimstat' ),
1546
+ 'ms-dos' => __( 'MS-DOS', 'wp-slimstat' ),
1547
+ 'netbsd' => __( 'NetBSD', 'wp-slimstat' ),
1548
+ 'nintendo' => __( 'Nintendo', 'wp-slimstat' ),
1549
+ 'openbsd' => __( 'OpenBSD', 'wp-slimstat' ),
1550
+ 'openvms' => __( 'OpenVMS', 'wp-slimstat' ),
1551
+ 'os/2' => __( 'IBM OS/2', 'wp-slimstat' ),
1552
+ 'palm' => __( 'Palm OS', 'wp-slimstat' ),
1553
+ 'palmos' => __( 'Palm OS', 'wp-slimstat' ),
1554
+ 'pclinuxos' => __( 'PCLinux OS', 'wp-slimstat' ),
1555
+ 'playstation' => __( 'Playstation', 'wp-slimstat' ),
1556
+ 'powertv' => __( 'PowerTV', 'wp-slimstat' ),
1557
+ 'redhat' => __( 'RedHat Linux', 'wp-slimstat' ),
1558
+ 'rim os' => __( 'Blackberry', 'wp-slimstat' ),
1559
+ 'risc os' => __( 'Risc OS', 'wp-slimstat' ),
1560
+ 'slackware' => __( 'Slackware Linux', 'wp-slimstat' ),
1561
+ 'solaris' => __( 'Solaris', 'wp-slimstat' ),
1562
+ 'sunos' => __( 'Sun OS', 'wp-slimstat' ),
1563
+ 'suse' => __( 'SuSE Linux', 'wp-slimstat' ),
1564
+ 'symbianos' => __( 'Symbian OS', 'wp-slimstat' ),
1565
+ 'ubuntu' => __( 'Ubuntu', 'wp-slimstat' ),
1566
+ 'unix' => __( 'Unix', 'wp-slimstat' ),
1567
+ 'unknown' => __( 'Unknown', 'wp-slimstat' ),
1568
+ 'xandros' => __( 'Xandros Linux', 'wp-slimstat' ),
1569
+ 'wap' => __( 'WAP', 'wp-slimstat' ),
1570
+ 'webos' => __( 'WebOS', 'wp-slimstat' ),
1571
+ 'win10' => __( 'Windows 10', 'wp-slimstat' ),
1572
+ 'win16' => __( 'Windows 16-bit', 'wp-slimstat' ),
1573
+ 'win2000' => __( 'Windows 2000', 'wp-slimstat' ),
1574
+ 'win2003' => __( 'Windows 2003', 'wp-slimstat' ),
1575
+ 'win31' => __( 'Windows 3.1', 'wp-slimstat' ),
1576
+ 'win32' => __( 'Windows 32-bit', 'wp-slimstat' ),
1577
+ 'win7' => __( 'Windows 7', 'wp-slimstat' ),
1578
+ 'win7' => __( 'Windows 7', 'wp-slimstat' ),
1579
+ 'win8' => __( 'Windows 8', 'wp-slimstat' ),
1580
+ 'win8.1' => __( 'Windows 8.1', 'wp-slimstat' ),
1581
+ 'win95' => __( 'Windows 95', 'wp-slimstat' ),
1582
+ 'win98' => __( 'Windows 98', 'wp-slimstat' ),
1583
+ 'wince' => __( 'Windows CE', 'wp-slimstat' ),
1584
+ 'winme' => __( 'Windows ME', 'wp-slimstat' ),
1585
+ 'winnt' => __( 'Windows NT', 'wp-slimstat' ),
1586
+ 'winphone7' => __( 'Windows Phone', 'wp-slimstat' ),
1587
+ 'winphone7.5' => __( 'Windows Phone', 'wp-slimstat' ),
1588
+ 'winphone8' => __( 'Windows Phone', 'wp-slimstat' ),
1589
+ 'winphone8.1' => __( 'Windows RT / Runtime', 'wp-slimstat' ),
1590
+ 'winrt' => __( 'Windows Phone', 'wp-slimstat' ),
1591
+ 'winvista' => __( 'Windows Vista', 'wp-slimstat' ),
1592
+ 'winxp' => __( 'Windows XP', 'wp-slimstat' ),
1593
+ 'wyderos' => __( 'WyderOS', 'wp-slimstat' ),
1594
+ 'zaurus' => __( 'Zaurus WAP', 'wp-slimstat' ),
1595
+
1596
+ // Operating System Families
1597
+ 'p-unk' => __( 'Unknown', 'wp-slimstat' ),
1598
+ 'p-' => __( 'Unknown', 'wp-slimstat' ),
1599
+
1600
+ 'p-and' => __( 'Android', 'wp-slimstat' ),
1601
+ 'p-bla' => __( 'BlackBerry', 'wp-slimstat' ),
1602
+ 'p-chr' => __( 'Chrome OS', 'wp-slimstat' ),
1603
+ 'p-fir' => __( 'Fire OS', 'wp-slimstat' ),
1604
+ 'p-fre' => __( 'Linux FreeBSD', 'wp-slimstat' ),
1605
+ 'p-ios' => __( 'Apple iOS', 'wp-slimstat' ),
1606
+ 'p-jav' => __( 'Java-based OS', 'wp-slimstat' ),
1607
+ 'p-lin' => __( 'Linux', 'wp-slimstat' ),
1608
+ 'p-mac' => __( 'Apple', 'wp-slimstat' ),
1609
+ 'p-rim' => __( 'Blackberry', 'wp-slimstat' ),
1610
+ 'p-sym' => __( 'Symbian OS', 'wp-slimstat' ),
1611
+ 'p-ubu' => __( 'Linux', 'wp-slimstat' ),
1612
+ 'p-win' => __( 'Microsoft', 'wp-slimstat' ),
1613
+
1614
+ // Tracker Errors
1615
+ 'e-100' => __( 'Invalid payload string. Try clearing your WordPress cache.', 'wp-slimstat' ),
1616
+ 'e-101' => __( 'Invalid data signature. Try clearing your WordPress cache.', 'wp-slimstat' ),
1617
+ 'e-200' => __( 'Unspecified error while attempting to add a new record to the table', 'wp-slimstat' ),
1618
+ 'e-201' => __( 'Malformed referrer URL', 'wp-slimstat' ),
1619
+ 'e-202' => __( 'Pageview not tracked because the IP address format was invalid.', 'wp-slimstat' ),
1620
+ 'e-204' => __( 'Tracking is turned off, but it looks like the client-side code is still attached to your pages. Do you have a caching tool enabled?', 'wp-slimstat' ),
1621
+ 'e-314' => __( 'Invalid MaxMind data file. Please <a target="_blank" href="https://slimstat.freshdesk.com/support/solutions/articles/12000039798-how-to-manually-install-the-maxmind-geolocation-data-file-">follow these steps</a> to download it manually.', 'wp-slimstat' ),
1622
+
1623
+
1624
+ );
1625
+
1626
+ // set_transient( 'slimstat_dynamic_strings', self::$dynamic_strings, 86400 );
1627
+ }
1628
+ }
1629
+
1630
+ public static function get_country_codes() {
1631
+ if ( empty( self::$dynamic_strings ) ) {
1632
+ self::init_dynamic_strings();
1633
+ }
1634
+
1635
+ $country_codes = array();
1636
+ foreach ( array_keys( self::$dynamic_strings ) as $a_code ) {
1637
+ if ( strpos( $a_code, 'c-', 0 ) !== false && strlen( $a_code ) > 2 && $a_code != 'c-xx' && $a_code != 'c-xy' ) {
1638
+ $country_codes[ strtolower( str_replace( 'c-', '', $a_code ) ) ] = self::$dynamic_strings[ $a_code ];
1639
+ }
1640
+ }
1641
+
1642
+ return $country_codes;
1643
+ }
1644
+
1645
+ public static function get_string( $_code = '' ) {
1646
+ if ( empty( self::$dynamic_strings ) ) {
1647
+ self::init_dynamic_strings();
1648
+ }
1649
+
1650
+ if ( !isset( self::$dynamic_strings[ $_code ] ) ) {
1651
+ return $_code;
1652
+ }
1653
+
1654
+ return self::$dynamic_strings[ $_code ];
1655
+ }
1656
+ }
admin/view/index.php CHANGED
@@ -63,7 +63,7 @@
63
  <a class="slimstat-filter-link noslimstat" href="<?php echo wp_slimstat_reports::fs_url( 'strtotime equals today&&&interval equals -7' ) ?>"><?php _e( 'Last 7 Days', 'wp-slimstat' ) ?></a>
64
  <a class="slimstat-filter-link noslimstat" href="<?php echo wp_slimstat_reports::fs_url( 'strtotime equals today&&&interval equals -28' ) ?>"><?php _e( 'Last 4 weeks', 'wp-slimstat' ) ?></a>
65
  <a class="slimstat-filter-link noslimstat" href="<?php echo wp_slimstat_reports::fs_url( 'strtotime equals today&&&interval equals -84' ) ?>"><?php _e( 'Last 12 weeks', 'wp-slimstat' ) ?></a>
66
- <a class="slimstat-filter-link noslimstat" href="<?php echo wp_slimstat_reports::fs_url( 'strtotime equals today&&&interval equals -364' ) ?>"><?php _e( 'Last Year', 'wp-slimstat' ) ?></a>
67
  </div>
68
 
69
  <strong><?php _e( 'Date Range', 'wp-slimstat' ) ?></strong>
63
  <a class="slimstat-filter-link noslimstat" href="<?php echo wp_slimstat_reports::fs_url( 'strtotime equals today&&&interval equals -7' ) ?>"><?php _e( 'Last 7 Days', 'wp-slimstat' ) ?></a>
64
  <a class="slimstat-filter-link noslimstat" href="<?php echo wp_slimstat_reports::fs_url( 'strtotime equals today&&&interval equals -28' ) ?>"><?php _e( 'Last 4 weeks', 'wp-slimstat' ) ?></a>
65
  <a class="slimstat-filter-link noslimstat" href="<?php echo wp_slimstat_reports::fs_url( 'strtotime equals today&&&interval equals -84' ) ?>"><?php _e( 'Last 12 weeks', 'wp-slimstat' ) ?></a>
66
+ <a class="slimstat-filter-link noslimstat" href="<?php echo wp_slimstat_reports::fs_url( 'strtotime equals today&&&interval equals -364' ) ?>"><?php _e( 'Last 12 months', 'wp-slimstat' ) ?></a>
67
  </div>
68
 
69
  <strong><?php _e( 'Date Range', 'wp-slimstat' ) ?></strong>
admin/view/wp-slimstat-db.php CHANGED
@@ -855,47 +855,46 @@ class wp_slimstat_db {
855
  return $results;
856
  }
857
 
858
- public static function get_recent( $_dimension = 'id', $_where = '', $_having = '', $_use_date_filters = true, $_as_column = '', $_more_dimensions = '', $_order_by = 'dt DESC' ) {
859
  // This function can be passed individual arguments, or an array of arguments
860
- if ( is_array( $_dimension ) ) {
861
- $_where = !empty( $_dimension[ 'where' ] ) ? $_dimension[ 'where' ] : '';
862
- $_having = !empty( $_dimension[ 'having' ] ) ? $_dimension[ 'having' ] : '';
863
- $_use_date_filters = isset( $_dimension[ 'use_date_filters' ] ) ? $_dimension[ 'use_date_filters' ] : true;
864
- $_as_column = !empty( $_dimension[ 'as_column' ] ) ? $_dimension[ 'as_column' ] : '';
865
- $_more_dimensions = !empty( $_dimension[ 'more_columns' ] ) ? $_dimension[ 'more_columns' ] : '';
866
- $_order_by = !empty( $_dimension[ 'order_by' ] ) ? $_dimension[ 'order_by' ] : 'dt DESC';
867
- $_dimension = $_dimension[ 'columns' ];
868
  }
869
 
870
- $dimensions = $_dimension;
871
  if ( !empty( $_as_column ) ) {
872
- $dimensions = "$_column AS $_as_column";
873
  }
874
 
875
- if ( $_dimension != '*' ) {
876
- $dimensions .= ', ip, dt';
877
  }
878
  else {
879
- $dimensions = 'id, ip, other_ip, username, email, country, city, location, referer, resource, searchterms, notes, visit_id, server_latency, page_performance, browser, browser_version, browser_type, platform, language, fingerprint, user_agent, resolution, screen_width, screen_height, content_type, category, author, content_id, outbound_resource, tz_offset, dt_out, dt';
880
  }
881
 
882
- if ( !empty( $_more_dimensions ) ) {
883
- $dimensions .= ', ' . $_more_dimensions;
884
  }
885
 
886
- $_where = self::get_combined_where( $_where, $_dimension, $_use_date_filters );
887
 
888
  $results = self::get_results( "
889
- SELECT $dimensions
890
  FROM {$GLOBALS['wpdb']->prefix}slim_stats
891
  WHERE $_where
892
  ORDER BY $_order_by
893
  LIMIT 0, " . self::$filters_normalized[ 'misc' ][ 'limit_results' ],
894
- $dimensions,
895
  'dt DESC' );
896
 
897
- if ( $_dimension != '*' ) {
898
- $values = array_map( 'unserialize', array_unique( array_map( 'serialize', self::array_column( $results, explode( ',', $_dimension ) ) ) ) );
899
  $results = array_intersect_key( $results, $values );
900
  }
901
 
855
  return $results;
856
  }
857
 
858
+ public static function get_recent( $_column = 'id', $_where = '', $_having = '', $_use_date_filters = true, $_as_column = '', $_more_columns = '', $_order_by = 'dt DESC' ) {
859
  // This function can be passed individual arguments, or an array of arguments
860
+ if ( is_array( $_column ) ) {
861
+ $_where = !empty( $_column[ 'where' ] ) ? $_column[ 'where' ] : '';
862
+ $_having = !empty( $_column[ 'having' ] ) ? $_column[ 'having' ] : '';
863
+ $_use_date_filters = isset( $_column[ 'use_date_filters' ] ) ? $_column[ 'use_date_filters' ] : true;
864
+ $_as_column = !empty( $_column[ 'as_column' ] ) ? $_column[ 'as_column' ] : '';
865
+ $_more_columns = !empty( $_column[ 'more_columns' ] ) ? $_column[ 'more_columns' ] : '';
866
+ $_order_by = !empty( $_column[ 'order_by' ] ) ? $_column[ 'order_by' ] : 'dt DESC';
867
+ $_column = $_column[ 'columns' ];
868
  }
869
 
 
870
  if ( !empty( $_as_column ) ) {
871
+ $_column = "$_column AS $_as_column";
872
  }
873
 
874
+ if ( $_column != '*' ) {
875
+ $_column .= ', ip, dt';
876
  }
877
  else {
878
+ $_column = 'id, ip, other_ip, username, email, country, city, location, referer, resource, searchterms, notes, visit_id, server_latency, page_performance, browser, browser_version, browser_type, platform, language, fingerprint, user_agent, resolution, screen_width, screen_height, content_type, category, author, content_id, outbound_resource, tz_offset, dt_out, dt';
879
  }
880
 
881
+ if ( !empty( $_more_columns ) ) {
882
+ $_column .= ', ' . $_more_columns;
883
  }
884
 
885
+ $_where = self::get_combined_where( $_where, $_column, $_use_date_filters );
886
 
887
  $results = self::get_results( "
888
+ SELECT $_column
889
  FROM {$GLOBALS['wpdb']->prefix}slim_stats
890
  WHERE $_where
891
  ORDER BY $_order_by
892
  LIMIT 0, " . self::$filters_normalized[ 'misc' ][ 'limit_results' ],
893
+ $_column,
894
  'dt DESC' );
895
 
896
+ if ( $_column != '*' ) {
897
+ $values = array_map( 'unserialize', array_unique( array_map( 'serialize', self::array_column( $results, explode( ',', $_column ) ) ) ) );
898
  $results = array_intersect_key( $results, $values );
899
  }
900
 
admin/view/wp-slimstat-reports.php CHANGED
@@ -98,7 +98,7 @@ class wp_slimstat_reports {
98
  'callback' => array( __CLASS__, 'raw_results_to_html' ),
99
  'callback_args' => array(
100
  'type' => 'top',
101
- 'columns' => 'SUBSTRING_INDEX(resource, "' . ( !get_option( 'permalink_structure' ) ? '&' : '?' ) . '", 1)',
102
  'as_column' => 'resource_calculated',
103
  'filter_op' => 'contains',
104
  'raw' => array( 'wp_slimstat_db', 'get_top' )
@@ -472,7 +472,7 @@ class wp_slimstat_reports {
472
  'callback_args' => array(
473
  'type' => 'top',
474
  'columns' => 'browser, browser_version',
475
- 'where' => 'browser_type == 1',
476
  'raw' => array( 'wp_slimstat_db', 'get_top' )
477
  ),
478
  'classes' => array( 'normal' ),
@@ -551,7 +551,8 @@ class wp_slimstat_reports {
551
  'callback' => array( __CLASS__, 'raw_results_to_html' ),
552
  'callback_args' => array(
553
  'type' => 'recent',
554
- 'columns' => 'resource',
 
555
  'where' => 'content_type = "post"',
556
  'raw' => array( 'wp_slimstat_db', 'get_recent' )
557
  ),
@@ -674,7 +675,8 @@ class wp_slimstat_reports {
674
  'callback' => array( __CLASS__, 'raw_results_to_html' ),
675
  'callback_args' => array(
676
  'type' => 'recent',
677
- 'columns' => 'resource',
 
678
  'where' => '(content_type = "category" OR content_type = "tag")',
679
  'raw' => array( 'wp_slimstat_db', 'get_recent' )
680
  ),
@@ -755,7 +757,8 @@ class wp_slimstat_reports {
755
  'callback' => array( __CLASS__, 'raw_results_to_html' ),
756
  'callback_args' => array(
757
  'type' => 'top',
758
- 'columns' => 'resource',
 
759
  'where' => 'content_type <> "404"',
760
  'having' => 'HAVING COUNT(visit_id) = 1',
761
  'raw' => array( 'wp_slimstat_db', 'get_top' )
@@ -849,30 +852,13 @@ class wp_slimstat_reports {
849
  self::$reports = apply_filters( 'slimstat_reports_info', self::$reports );
850
  $merge_reports = array_keys( self::$reports );
851
 
852
- // Retrieve this user's custom report assignment (Customizer)
853
- $current_user = wp_get_current_user();
854
-
855
- // Page Location
856
- $page_location = 'slimstat';
857
- if ( wp_slimstat::$settings[ 'use_separate_menu' ] != 'no' ) {
858
- $page_location = 'admin';
859
- }
860
-
861
- // Superadmins can customize the layout at network level, to override per-site settings
862
- self::$user_reports = get_user_option( 'meta-box-order_' . $page_location . '_page_slimlayout-network', 1 );
863
-
864
- // No network-wide settings found
865
- if ( empty( self::$user_reports ) ) {
866
- self::$user_reports = get_user_option( 'meta-box-order_' . $page_location . '_page_slimlayout', $current_user->ID );
867
- }
868
-
869
  // Do we have any new reports not listed in this user's settings?
870
- if ( !empty( self::$user_reports ) && is_array( self::$user_reports ) ) {
871
- $flat_user_reports = array_filter( explode( ',', implode( ',', self::$user_reports ) ) );
872
  $merge_reports = array_diff( array_filter( array_keys( self::$reports ) ), $flat_user_reports );
873
 
874
  // Now let's explode all the lists
875
- foreach ( self::$user_reports as $a_location => $a_report_list ) {
876
  self::$user_reports[ $a_location ] = explode( ',', $a_report_list );
877
  }
878
  }
98
  'callback' => array( __CLASS__, 'raw_results_to_html' ),
99
  'callback_args' => array(
100
  'type' => 'top',
101
+ 'columns' => 'TRIM( TRAILING "/" FROM SUBSTRING_INDEX( resource, "' . ( !get_option( 'permalink_structure' ) ? '&' : '?' ) . '", 1 ) )',
102
  'as_column' => 'resource_calculated',
103
  'filter_op' => 'contains',
104
  'raw' => array( 'wp_slimstat_db', 'get_top' )
472
  'callback_args' => array(
473
  'type' => 'top',
474
  'columns' => 'browser, browser_version',
475
+ 'where' => 'browser_type = 1',
476
  'raw' => array( 'wp_slimstat_db', 'get_top' )
477
  ),
478
  'classes' => array( 'normal' ),
551
  'callback' => array( __CLASS__, 'raw_results_to_html' ),
552
  'callback_args' => array(
553
  'type' => 'recent',
554
+ 'columns' => 'TRIM( TRAILING "/" FROM resource )',
555
+ 'as_column' => 'resource_calculated',
556
  'where' => 'content_type = "post"',
557
  'raw' => array( 'wp_slimstat_db', 'get_recent' )
558
  ),
675
  'callback' => array( __CLASS__, 'raw_results_to_html' ),
676
  'callback_args' => array(
677
  'type' => 'recent',
678
+ 'columns' => 'TRIM( TRAILING "/" FROM resource )',
679
+ 'as_column' => 'resource_calculated',
680
  'where' => '(content_type = "category" OR content_type = "tag")',
681
  'raw' => array( 'wp_slimstat_db', 'get_recent' )
682
  ),
757
  'callback' => array( __CLASS__, 'raw_results_to_html' ),
758
  'callback_args' => array(
759
  'type' => 'top',
760
+ 'columns' => 'TRIM( TRAILING "/" FROM resource )',
761
+ 'as_column' => 'resource_calculated',
762
  'where' => 'content_type <> "404"',
763
  'having' => 'HAVING COUNT(visit_id) = 1',
764
  'raw' => array( 'wp_slimstat_db', 'get_top' )
852
  self::$reports = apply_filters( 'slimstat_reports_info', self::$reports );
853
  $merge_reports = array_keys( self::$reports );
854
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
855
  // Do we have any new reports not listed in this user's settings?
856
+ if ( !empty( wp_slimstat_admin::$meta_user_reports ) && is_array( wp_slimstat_admin::$meta_user_reports ) ) {
857
+ $flat_user_reports = array_filter( explode( ',', implode( ',', wp_slimstat_admin::$meta_user_reports ) ) );
858
  $merge_reports = array_diff( array_filter( array_keys( self::$reports ) ), $flat_user_reports );
859
 
860
  // Now let's explode all the lists
861
+ foreach ( wp_slimstat_admin::$meta_user_reports as $a_location => $a_report_list ) {
862
  self::$user_reports[ $a_location ] = explode( ',', $a_report_list );
863
  }
864
  }
readme.txt CHANGED
@@ -6,7 +6,7 @@ Text Domain: wp-slimstat
6
  Requires at least: 3.8
7
  Requires PHP: 5.2
8
  Tested up to: 5.2
9
- Stable tag: 4.8.5.1
10
 
11
  == Description ==
12
  The leading web analytics plugin for WordPress. Track returning customers and registered users, monitor Javascript events, detect intrusions, analyze email campaigns. Thousands of WordPress sites are already using it.
@@ -60,6 +60,17 @@ Our knowledge base is available on our [support center](https://docs.wp-slimstat
60
  5. **Responsive layout** - Keep an eye on your reports on the go
61
 
62
  == Changelog ==
 
 
 
 
 
 
 
 
 
 
 
63
  = 4.8.5.1 =
64
  * [Fix] A bug was affecting the way shortcodes were being displayed on the website (thank you, [inndesign](https://wordpress.org/support/topic/crashes-avada-theme-in-chrome/)).
65
  * [Fix] Some icons in the Access Log were broken and not displayed as expected.
6
  Requires at least: 3.8
7
  Requires PHP: 5.2
8
  Tested up to: 5.2
9
+ Stable tag: 4.8.6
10
 
11
  == Description ==
12
  The leading web analytics plugin for WordPress. Track returning customers and registered users, monitor Javascript events, detect intrusions, analyze email campaigns. Thousands of WordPress sites are already using it.
60
  5. **Responsive layout** - Keep an eye on your reports on the go
61
 
62
  == Changelog ==
63
+ = 4.8.6 =
64
+ * [New] Slimstat can now track most WordPress redirects and mark them with the appropriate content type.
65
+ * [Update] The GDPR compliance through third-party tools is now more flexible and allows admins to specify name/value pairs so that the cookie must CONTAIN the given string.
66
+ * [Update] Simplified code that manages the sidebar menu.
67
+ * [Update] Reorganized code that manages the plugin options.
68
+ * [Update] Rewrote the portion of code that manages tracker errors, which are now saved in a separate field in the database.
69
+ * [Update] Reintroduced feature to hide certain report pages when no reports are assigned to them.
70
+ * [Update] Decrease the number of database requests needed to record a new pageview.
71
+ * [Fix] Entries with a trailing slash and ones without were being listed as separate in Top Web Pages.
72
+ * [Fix] Typo in one of the conditions definining the Top Bots report.
73
+
74
  = 4.8.5.1 =
75
  * [Fix] A bug was affecting the way shortcodes were being displayed on the website (thank you, [inndesign](https://wordpress.org/support/topic/crashes-avada-theme-in-chrome/)).
76
  * [Fix] Some icons in the Access Log were broken and not displayed as expected.
uninstall.php CHANGED
@@ -48,6 +48,7 @@ function slimstat_uninstall($_wpdb = '', $_options = array()){
48
  delete_option( 'slimstat_options' );
49
  delete_option( 'slimstat_visit_id' );
50
  delete_option( 'slimstat_filters' );
 
51
 
52
  $GLOBALS[ 'wpdb' ]->query( "DELETE FROM {$GLOBALS[ 'wpdb' ]->prefix}usermeta WHERE meta_key LIKE '%meta-box-order_slimstat%'" );
53
  $GLOBALS[ 'wpdb' ]->query( "DELETE FROM {$GLOBALS[ 'wpdb' ]->prefix}usermeta WHERE meta_key LIKE '%metaboxhidden_slimstat%'" );
48
  delete_option( 'slimstat_options' );
49
  delete_option( 'slimstat_visit_id' );
50
  delete_option( 'slimstat_filters' );
51
+ delete_option( 'slimstat_tracker_error' );
52
 
53
  $GLOBALS[ 'wpdb' ]->query( "DELETE FROM {$GLOBALS[ 'wpdb' ]->prefix}usermeta WHERE meta_key LIKE '%meta-box-order_slimstat%'" );
54
  $GLOBALS[ 'wpdb' ]->query( "DELETE FROM {$GLOBALS[ 'wpdb' ]->prefix}usermeta WHERE meta_key LIKE '%metaboxhidden_slimstat%'" );
vendor/browscap.php CHANGED
@@ -22,7 +22,6 @@ class slim_browser {
22
  if ( file_exists( wp_slimstat::$upload_dir . '/browscap-db-master/version.txt' ) ) {
23
  self::$browscap_local_version = @file_get_contents( wp_slimstat::$upload_dir . '/browscap-db-master/version.txt' );
24
  if ( false === self::$browscap_local_version ) {
25
- wp_slimstat::slimstat_save_options();
26
  return array( 4, __( 'The Browscap Library could not be opened on your filesystem. Please check your server permissions and try again.', 'wp-slimstat' ) );
27
  }
28
  }
@@ -102,8 +101,6 @@ class slim_browser {
102
  if ( empty( wp_slimstat::$settings[ 'browscap_last_modified' ] ) ) {
103
  wp_slimstat::$settings[ 'browscap_last_modified' ] = $current_timestamp;
104
  }
105
-
106
- wp_slimstat::slimstat_save_options();
107
  }
108
 
109
  // Check for updates once a week ( 604800 seconds ), if $_force_download is not true
@@ -117,7 +114,6 @@ class slim_browser {
117
  // Now check the version number on the server
118
  $response = wp_remote_get( 'https://raw.githubusercontent.com/slimstat/browscap-db/master/version.txt' );
119
  if ( !is_array( $response ) || is_wp_error( $response ) || 200 != wp_remote_retrieve_response_code( $response ) ) {
120
- wp_slimstat::slimstat_save_options();
121
  return array( 5, __( 'There was an error checking the remote library version. Please try again later.', 'wp-slimstat' ) );
122
  }
123
 
@@ -135,14 +131,12 @@ class slim_browser {
135
 
136
  if ( !file_exists( $browscap_zip ) ) {
137
  wp_slimstat::$settings[ 'browscap_last_modified' ] = $current_timestamp;
138
- wp_slimstat::slimstat_save_options();
139
  return array( 6, __( 'There was an error saving the Browscap data file on your server. Please check your folder permissions.', 'wp-slimstat' ) );
140
  }
141
 
142
  if ( is_wp_error( $response ) || 200 != wp_remote_retrieve_response_code( $response ) ) {
143
  @unlink( $browscap_zip );
144
  wp_slimstat::$settings[ 'browscap_last_modified' ] = $current_timestamp;
145
- wp_slimstat::slimstat_save_options();
146
  return array( 7, __( 'There was an error downloading the Browscap data file from our server. Please try again later.', 'wp-slimstat' ) );
147
  }
148
 
@@ -151,7 +145,6 @@ class slim_browser {
151
  if ( !function_exists( 'wp_filesystem' ) ) {
152
  @unlink( $browscap_zip );
153
  wp_slimstat::$settings[ 'browscap_last_modified' ] = $current_timestamp;
154
- wp_slimstat::slimstat_save_options();
155
  return array( 8, __( 'Could not initialize the WP Filesystem API. Please check your folder permissions and PHP configuration.', 'wp-slimstat' ) );
156
  }
157
 
@@ -166,7 +159,6 @@ class slim_browser {
166
  if ( !$unzip_done || !file_exists( self::$browscap_autoload_path ) ) {
167
  $GLOBALS[ 'wp_filesystem' ]->rmdir( dirname( self::$browscap_autoload_path ) . '/', true );
168
  wp_slimstat::$settings[ 'browscap_last_modified' ] = $current_timestamp;
169
- wp_slimstat::slimstat_save_options();
170
  return array( 9, __( 'There was an error uncompressing the Browscap data file on your server. Please check your folder permissions and PHP configuration.', 'wp-slimstat' ) );
171
  }
172
 
22
  if ( file_exists( wp_slimstat::$upload_dir . '/browscap-db-master/version.txt' ) ) {
23
  self::$browscap_local_version = @file_get_contents( wp_slimstat::$upload_dir . '/browscap-db-master/version.txt' );
24
  if ( false === self::$browscap_local_version ) {
 
25
  return array( 4, __( 'The Browscap Library could not be opened on your filesystem. Please check your server permissions and try again.', 'wp-slimstat' ) );
26
  }
27
  }
101
  if ( empty( wp_slimstat::$settings[ 'browscap_last_modified' ] ) ) {
102
  wp_slimstat::$settings[ 'browscap_last_modified' ] = $current_timestamp;
103
  }
 
 
104
  }
105
 
106
  // Check for updates once a week ( 604800 seconds ), if $_force_download is not true
114
  // Now check the version number on the server
115
  $response = wp_remote_get( 'https://raw.githubusercontent.com/slimstat/browscap-db/master/version.txt' );
116
  if ( !is_array( $response ) || is_wp_error( $response ) || 200 != wp_remote_retrieve_response_code( $response ) ) {
 
117
  return array( 5, __( 'There was an error checking the remote library version. Please try again later.', 'wp-slimstat' ) );
118
  }
119
 
131
 
132
  if ( !file_exists( $browscap_zip ) ) {
133
  wp_slimstat::$settings[ 'browscap_last_modified' ] = $current_timestamp;
 
134
  return array( 6, __( 'There was an error saving the Browscap data file on your server. Please check your folder permissions.', 'wp-slimstat' ) );
135
  }
136
 
137
  if ( is_wp_error( $response ) || 200 != wp_remote_retrieve_response_code( $response ) ) {
138
  @unlink( $browscap_zip );
139
  wp_slimstat::$settings[ 'browscap_last_modified' ] = $current_timestamp;
 
140
  return array( 7, __( 'There was an error downloading the Browscap data file from our server. Please try again later.', 'wp-slimstat' ) );
141
  }
142
 
145
  if ( !function_exists( 'wp_filesystem' ) ) {
146
  @unlink( $browscap_zip );
147
  wp_slimstat::$settings[ 'browscap_last_modified' ] = $current_timestamp;
 
148
  return array( 8, __( 'Could not initialize the WP Filesystem API. Please check your folder permissions and PHP configuration.', 'wp-slimstat' ) );
149
  }
150
 
159
  if ( !$unzip_done || !file_exists( self::$browscap_autoload_path ) ) {
160
  $GLOBALS[ 'wp_filesystem' ]->rmdir( dirname( self::$browscap_autoload_path ) . '/', true );
161
  wp_slimstat::$settings[ 'browscap_last_modified' ] = $current_timestamp;
 
162
  return array( 9, __( 'There was an error uncompressing the Browscap data file on your server. Please check your folder permissions and PHP configuration.', 'wp-slimstat' ) );
163
  }
164
 
wp-slimstat.php CHANGED
@@ -3,7 +3,7 @@
3
  Plugin Name: Slimstat Analytics
4
  Plugin URI: https://wordpress.org/plugins/wp-slimstat/
5
  Description: The leading web analytics plugin for WordPress
6
- Version: 4.8.5.1
7
  Author: Jason Crouse
8
  Author URI: https://www.wp-slimstat.com/
9
  Text Domain: wp-slimstat
@@ -15,7 +15,7 @@ if ( !empty( wp_slimstat::$settings ) ) {
15
  }
16
 
17
  class wp_slimstat {
18
- public static $version = '4.8.5.1';
19
  public static $settings = array();
20
 
21
  public static $wpdb = '';
@@ -27,7 +27,6 @@ class wp_slimstat {
27
 
28
  protected static $data_js = array( 'id' => 0 );
29
  protected static $stat = array();
30
- protected static $settings_signature = '';
31
  protected static $browser = array();
32
  protected static $heuristic_key = 0;
33
  protected static $date_i18n_filters = array();
@@ -50,9 +49,6 @@ class wp_slimstat {
50
  // Allow third party tools to edit the options
51
  self::$settings = apply_filters( 'slimstat_init_options', self::$settings );
52
 
53
- // Determine the options' signature: if it hasn't changed, there's no need to update/save them in the database
54
- self::$settings_signature = md5( serialize( self::$settings ) );
55
-
56
  // Allow third-party tools to use a custom database for Slimstat
57
  self::$wpdb = apply_filters( 'slimstat_custom_wpdb', $GLOBALS[ 'wpdb' ] );
58
 
@@ -105,6 +101,9 @@ class wp_slimstat {
105
  add_action( 'wp_ajax_slimstat_optout_html', array( __CLASS__, 'get_optout_html' ) );
106
  add_action( 'wp_ajax_nopriv_slimstat_optout_html', array( __CLASS__, 'get_optout_html' ) );
107
 
 
 
 
108
  // Shortcodes
109
  add_shortcode( 'slimstat', array( __CLASS__, 'slimstat_shortcode' ), 15 );
110
 
@@ -115,9 +114,6 @@ class wp_slimstat {
115
  // If add-ons are installed, check for updates
116
  add_action( 'wp_loaded', array( __CLASS__, 'update_checker' ) );
117
 
118
- // Update the options before shutting down
119
- add_action( 'shutdown', array( __CLASS__, 'slimstat_save_options' ), 100 );
120
-
121
  // REST API Support
122
  add_action( 'rest_api_init', array( __CLASS__, 'register_rest_route' ) );
123
 
@@ -135,9 +131,7 @@ class wp_slimstat {
135
  public static function slimtrack_ajax() {
136
  // If the website is using a caching plugin, the tracking code might still be there, even if the user turned off tracking
137
  if ( self::$settings[ 'is_tracking' ] != 'on' ) {
138
- self::$stat[ 'id' ] = -204;
139
- self::_set_error_array( __( 'Tracking is turned off, but it looks like the client-side code is still attached to your pages. Do you have a caching tool enabled?', 'wp-slimstat' ) );
140
- self::slimstat_save_options();
141
  exit( self::_get_id_with_checksum( self::$stat[ 'id' ] ) );
142
  }
143
 
@@ -177,7 +171,7 @@ class wp_slimstat {
177
 
178
  // Visitor is still on this page, record the timestamp in the corresponding field
179
  self::toggle_date_i18n_filters( false );
180
- self::$stat['dt_out'] = date_i18n( 'U' );
181
  self::toggle_date_i18n_filters( true );
182
 
183
  // Are we tracking an outbound click?
@@ -230,8 +224,8 @@ class wp_slimstat {
230
  // Was this pageview tracked?
231
  if ( self::$stat[ 'id' ] <= 0 ) {
232
  $abs_error_code = abs( self::$stat[ 'id' ] );
 
233
  do_action( 'slimstat_track_exit_' . $abs_error_code, self::$stat );
234
- self::slimstat_save_options();
235
  exit( self::_get_id_with_checksum( self::$stat[ 'id' ] ) );
236
  }
237
 
@@ -248,8 +242,7 @@ class wp_slimstat {
248
  public static function slimtrack( $_argument = '' ) {
249
  // If the website is using a caching plugin, the tracking code might still be there, even if the user turned off tracking
250
  if ( self::$settings[ 'is_tracking' ] != 'on' ) {
251
- self::$stat[ 'id' ] = -204;
252
- self::_set_error_array( __( 'Tracking is turned off, but it looks like the client-side code is still attached to your pages. Do you have a caching tool enabled?', 'wp-slimstat' ) );
253
  return $_argument;
254
  }
255
 
@@ -275,16 +268,16 @@ class wp_slimstat {
275
  $opt_out_cookie_names = self::string_to_array( self::$settings[ 'opt_out_cookie_names' ] );
276
 
277
  foreach ( $opt_out_cookie_names as $a_cookie_pair ) {
278
- $pair = explode( '=', $a_cookie_pair );
279
 
280
- if ( !empty( $pair[ 0 ] ) && !empty( $pair[ 1 ] ) ) {
281
  $cookie_names[ $name ] = $value;
282
  }
283
  }
284
  }
285
 
286
  foreach ( $cookie_names as $a_name => $a_value ) {
287
- if ( isset( $_COOKIE[ $a_name ] ) && $_COOKIE[ $a_name ] == $a_value ) {
288
  self::$stat[ 'id' ] = -315;
289
  return $_argument;
290
  }
@@ -320,8 +313,7 @@ class wp_slimstat {
320
  list ( self::$stat[ 'ip' ], self::$stat[ 'other_ip' ] ) = self::_get_remote_ip();
321
 
322
  if ( empty( self::$stat[ 'ip' ] ) || self::$stat[ 'ip' ] == '0.0.0.0' ) {
323
- self::$stat[ 'id' ] = -202;
324
- self::_set_error_array( __( 'Pageview not tracked because the IP address format was invalid.', 'wp-slimstat' ) );
325
  return $_argument;
326
  }
327
 
@@ -338,13 +330,11 @@ class wp_slimstat {
338
  // Is this a 'seriously malformed' URL?
339
  $referer = parse_url( self::$stat[ 'referer' ] );
340
  if ( !$referer ) {
341
- self::_set_error_array( sprintf( __( 'Malformed referrer URL: %s (IP: %s)', 'wp-slimstat' ), self::$stat[ 'referer' ], self::$stat[ 'ip' ] ), 201 );
342
- self::$stat[ 'notes' ][] = sprintf( __( 'Malformed referrer URL: %s', 'wp-slimstat' ), self::$stat[ 'referer' ] );
343
- unset( self::$stat[ 'referer' ] );
344
  }
345
 
346
  if ( !empty( $referer[ 'scheme' ] ) && !in_array( strtolower( $referer[ 'scheme' ] ), array( 'http', 'https', 'android-app' ) ) ) {
347
- self::_set_error_array( sprintf( __( 'Attempted XSS Injection: %s (IP: %s)', 'wp-slimstat' ), self::$stat[ 'referer' ], self::$stat[ 'ip' ] ), 203 );
348
  self::$stat[ 'notes' ][] = sprintf( __( 'Attempted XSS Injection: %s', 'wp-slimstat' ), self::$stat[ 'referer' ] );
349
  unset( self::$stat[ 'referer' ] );
350
  }
@@ -374,7 +364,9 @@ class wp_slimstat {
374
  }
375
  }
376
 
377
- $content_info = self::_get_content_info();
 
 
378
 
379
  // Is this content type blacklisted?
380
  if ( !empty( self::$settings[ 'ignore_content_types' ] ) && self::_is_blacklisted( $content_info[ 'content_type' ], self::$settings[ 'ignore_content_types' ] ) ) {
@@ -547,8 +539,7 @@ class wp_slimstat {
547
  $geolocation_data = maxmind_geolite2_connector::get_geolocation_info( self::$stat[ 'ip' ] );
548
  }
549
  catch( Exception $e ) {
550
- self::$stat[ 'id' ] = -314;
551
- self::_set_error_array( __( 'Invalid MaxMind data file. Please <a target="_blank" href="https://slimstat.freshdesk.com/support/solutions/articles/12000039798-how-to-manually-install-the-maxmind-geolocation-data-file-">follow these steps</a> to download it manually.', 'wp-slimstat' ) );
552
  return $_argument;
553
  }
554
 
@@ -675,8 +666,7 @@ class wp_slimstat {
675
  self::$stat['id'] = self::insert_row(self::$stat, $GLOBALS['wpdb']->prefix.'slim_stats');
676
 
677
  if ( empty( self::$stat[ 'id' ] ) ) {
678
- self::$stat[ 'id' ] = -200;
679
- self::_set_error_array( self::$wpdb->last_error );
680
  return $_argument;
681
  }
682
  }
@@ -773,489 +763,144 @@ class wp_slimstat {
773
 
774
  return 0;
775
  }
 
776
 
777
  /**
778
- * Tries to find the user's REAL IP address
779
  */
780
- protected static function _get_remote_ip(){
781
- $ip_array = array( '', '' );
 
 
 
 
 
782
 
783
- if ( !empty( $_SERVER[ 'REMOTE_ADDR' ] ) && filter_var( $_SERVER[ 'REMOTE_ADDR' ], FILTER_VALIDATE_IP ) !== false ) {
784
- $ip_array[ 0 ] = $_SERVER[ 'REMOTE_ADDR' ];
 
785
  }
786
 
787
- $originating_ip_headers = array( 'X-Forwarded-For', 'HTTP_X_FORWARDED_FOR', 'CF-Connecting-IP', 'HTTP_CLIENT_IP', 'HTTP_X_REAL_IP', 'HTTP_FORWARDED', 'HTTP_X_FORWARDED' );
788
- foreach ( $originating_ip_headers as $a_header ) {
789
- if ( !empty( $_SERVER[ $a_header ] ) ) {
790
- foreach ( explode( ',', $_SERVER[ $a_header ] ) as $a_ip ) {
791
- if ( filter_var( $a_ip, FILTER_VALIDATE_IP ) !== false && $a_ip != $ip_array[ 0 ] ) {
792
- $ip_array[ 1 ] = $a_ip;
793
- break;
794
- }
795
- }
 
 
 
 
 
 
 
796
  }
797
  }
798
 
799
- return apply_filters( 'slimstat_filter_ip_address', $ip_array );
 
 
 
 
 
 
 
 
 
 
 
800
  }
801
- // end _get_remote_ip
802
 
803
  /**
804
- * Extracts the accepted language from browser headers
805
  */
806
- protected static function _get_language() {
807
- if ( isset( $_SERVER[ 'HTTP_ACCEPT_LANGUAGE' ] ) ) {
808
-
809
- // Capture up to the first delimiter (, found in Safari)
810
- preg_match( "/([^,;]*)/", $_SERVER[ 'HTTP_ACCEPT_LANGUAGE' ], $array_languages );
811
 
812
- // Fix some codes, the correct syntax is with minus (-) not underscore (_)
813
- return str_replace( '_', '-', strtolower( $array_languages[ 0 ] ) );
814
  }
815
- return ''; // Indeterminable language
 
816
  }
817
- // end _get_language
818
 
819
  /**
820
- * Sniffs out referrals from search engines and tries to determine the query string
821
  */
822
- protected static function _get_search_terms( $_url = array() ) {
823
- if ( empty( $_url ) || !isset( $_url[ 'host' ] ) ) {
824
- return '';
 
825
  }
826
 
827
- // Engines with different character encodings should always be listed here, regardless of their query string format
828
- $query_formats = array(
829
- 'baidu.com' => 'wd',
830
- 'bing' => 'q',
831
- 'dogpile.com' => 'q',
832
- 'duckduckgo' => 'q',
833
- 'eniro' => 'search_word',
834
- 'exalead.com' => 'q',
835
- 'excite' => 'q',
836
- 'gigablast' => 'q',
837
- 'google' => 'q',
838
- 'hotbot' => 'q',
839
- 'maktoob' => 'p',
840
- 'mamma' => 'q',
841
- 'naver' => 'query',
842
- 'qwant' => 'q',
843
- 'rambler' => 'query',
844
- 'seznam' => 'oq',
845
- 'soso.com' => 'query',
846
- 'virgilio' => 'qs',
847
- 'voila' => 'rdata',
848
- 'yahoo' => 'p',
849
- 'yam' => 'k',
850
- 'yandex' => 'text',
851
- 'yell' => 'keywords',
852
- 'yippy' => 'query',
853
- 'youdao' => 'q'
854
- );
855
-
856
- $charsets = array( 'baidu' => 'EUC-CN' );
857
- $regex_match = implode( '|', array_keys( $query_formats ) );
858
- $searchterms = '';
859
-
860
- if ( !empty( $_url[ 'query' ] ) ) {
861
- parse_str( $_url[ 'query' ], $query );
862
- }
863
 
864
- if ( !empty( $_url[ 'host' ] ) ) {
865
- preg_match( "~($regex_match).~i", $_url[ 'host' ], $matches );
 
866
  }
867
 
868
- if ( !empty( $matches[ 1 ] ) ) {
869
- // Let's remember that this is a search engine, regardless of the URL containing searchterms (thank you, NSA)
870
- $searchterms = '_';
871
- if ( !empty( $query[ $query_formats[ $matches[ 1 ] ] ] ) ) {
872
- $searchterms = str_replace( '\\', '', trim( urldecode( $query[ $query_formats[ $matches[ 1 ] ] ] ) ) );
873
- // Test for encodings different from UTF-8
874
- if ( function_exists( 'mb_check_encoding' ) && !mb_check_encoding( $query[ $query_formats[ $matches[ 1 ] ] ], 'UTF-8' ) && !empty( $charsets[ $matches[ 1 ] ] ) ) {
875
- $searchterms = mb_convert_encoding( urldecode( $query[ $query_formats[ $matches[ 1 ] ] ] ), 'UTF-8', $charsets[ $matches[ 1 ] ] );
876
- }
877
- }
878
  }
879
  else {
880
- // We weren't lucky, but there's still hope
881
- foreach( array( 'q','s','k','qt' ) as $a_format ) {
882
- if ( !empty( $query[ $a_format ] ) ) {
883
- $searchterms = str_replace( '\\', '', trim( urldecode( $query[ $a_format ] ) ) );
884
- break;
885
- }
886
- }
887
  }
888
 
889
- return $searchterms;
890
- }
891
- // end _get_search_terms
892
-
893
- /**
894
- * Returns details about the resource being accessed
895
- */
896
- protected static function _get_content_info(){
897
- $content_info = array( 'content_type' => '' );
898
-
899
- // Mark 404 pages
900
- if ( is_404() ) {
901
- $content_info[ 'content_type' ] = '404';
902
  }
903
 
904
- // Type
905
- else if ( is_single() ) {
906
- if ( ( $post_type = get_post_type() ) != 'post' ) {
907
- $post_type = 'cpt:' . $post_type;
908
- }
909
 
910
- $content_info[ 'content_type' ] = $post_type;
911
- $content_info_array = array();
912
- foreach ( get_object_taxonomies( $GLOBALS[ 'post' ] ) as $a_taxonomy ) {
913
- $terms = get_the_terms( $GLOBALS[ 'post' ]->ID, $a_taxonomy );
914
- if ( is_array( $terms ) ) {
915
- foreach ( $terms as $a_term ) {
916
- $content_info_array[] = $a_term->term_id;
917
- }
918
- $content_info[ 'category' ] = implode( ',', $content_info_array );
919
  }
920
  }
921
- $content_info[ 'content_id' ] = $GLOBALS[ 'post' ]->ID;
922
- }
923
- else if ( is_page() ) {
924
- $content_info[ 'content_type' ] = 'page';
925
- $content_info[ 'content_id' ] = $GLOBALS[ 'post' ]->ID;
926
- }
927
- elseif (is_attachment()){
928
- $content_info['content_type'] = 'attachment';
929
- }
930
- elseif (is_singular()){
931
- $content_info['content_type'] = 'singular';
932
- }
933
- elseif (is_post_type_archive()){
934
- $content_info['content_type'] = 'post_type_archive';
935
- }
936
- elseif (is_tag()){
937
- $content_info['content_type'] = 'tag';
938
- $list_tags = get_the_tags();
939
- if (is_array($list_tags)){
940
- $tag_info = array_pop($list_tags);
941
- if (!empty($tag_info)) $content_info['category'] = "$tag_info->term_id";
942
  }
943
  }
944
- elseif (is_tax()){
945
- $content_info['content_type'] = 'taxonomy';
946
- }
947
- elseif (is_category()){
948
- $content_info['content_type'] = 'category';
949
- $list_categories = get_the_category();
950
- if (is_array($list_categories)){
951
- $cat_info = array_pop($list_categories);
952
- if (!empty($cat_info)) $content_info['category'] = "$cat_info->term_id";
953
  }
954
  }
955
- else if (is_date()){
956
- $content_info['content_type']= 'date';
957
- }
958
- else if (is_author()){
959
- $content_info['content_type'] = 'author';
960
- }
961
- else if ( is_archive() ) {
962
- $content_info['content_type'] = 'archive';
963
- }
964
- else if ( is_search() ) {
965
- $content_info[ 'content_type' ] = 'search';
966
- }
967
- else if ( is_feed() ) {
968
- $content_info[ 'content_type' ] = 'feed';
969
- }
970
- else if ( is_home() || is_front_page() ) {
971
- $content_info['content_type'] = 'home';
972
- }
973
- else if ( !empty( $GLOBALS[ 'pagenow' ] ) && $GLOBALS[ 'pagenow' ] == 'wp-login.php' ) {
974
- $content_info[ 'content_type' ] = 'login';
975
- }
976
- else if ( !empty( $GLOBALS['pagenow'] ) && $GLOBALS['pagenow'] == 'wp-register.php' ) {
977
- $content_info[ 'content_type' ] = 'registration';
978
- }
979
- // WordPress sets is_admin() to true for all ajax requests ( front-end or admin-side )
980
- elseif ( is_admin() && ( !defined( 'DOING_AJAX' ) || !DOING_AJAX ) ) {
981
- $content_info[ 'content_type' ] = 'admin';
982
  }
983
 
984
- if (is_paged()){
985
- $content_info[ 'content_type' ] .= ',paged';
986
  }
987
 
988
- // Author
989
- if ( is_singular() ) {
990
- $author = get_the_author_meta( 'user_login', $GLOBALS[ 'post' ]->post_author );
991
- if ( !empty( $author ) ) {
992
- $content_info[ 'author' ] = $author;
993
- }
 
994
  }
995
 
996
- return $content_info;
997
- }
998
- // end _get_content_info
999
 
1000
- /**
1001
- * Reads the cookie to get the visit_id and sets the variable accordingly
1002
- */
1003
- protected static function _set_visit_id($_force_assign = false){
1004
- $is_new_session = true;
1005
- $identifier = 0;
1006
-
1007
- if ( isset( $_COOKIE[ 'slimstat_tracking_code' ] ) ) {
1008
- // Make sure only authorized information is recorded
1009
- $identifier = self::_separate_id_from_checksum( $_COOKIE[ 'slimstat_tracking_code' ] );
1010
- if ( $identifier === false ) {
1011
- return false;
1012
- }
1013
-
1014
- $is_new_session = ( strpos( $identifier, 'id' ) !== false );
1015
- $identifier = intval( $identifier );
1016
- }
1017
-
1018
- // User doesn't have an active session
1019
- if ( $is_new_session && ( $_force_assign || self::$settings[ 'javascript_mode' ] == 'on' ) ) {
1020
- if ( empty( self::$settings[ 'session_duration' ] ) ) {
1021
- self::$settings[ 'session_duration' ] = 1800;
1022
- }
1023
-
1024
- self::$stat[ 'visit_id' ] = get_transient( 'slimstat_visit_id' );
1025
- if ( self::$stat[ 'visit_id' ] === false ) {
1026
- self::$stat[ 'visit_id' ] = intval( self::$wpdb->get_var( "SELECT MAX( visit_id ) FROM {$GLOBALS[ 'wpdb' ]->prefix}slim_stats" ) );
1027
- }
1028
- self::$stat[ 'visit_id' ]++;
1029
- set_transient( 'slimstat_visit_id', self::$stat[ 'visit_id' ] );
1030
-
1031
- $set_cookie = apply_filters( 'slimstat_set_visit_cookie', ( !empty( self::$settings[ 'set_tracker_cookie' ] ) && self::$settings[ 'set_tracker_cookie' ] == 'on' ) );
1032
- if ( $set_cookie ) {
1033
- @setcookie(
1034
- 'slimstat_tracking_code',
1035
- self::_get_id_with_checksum( self::$stat[ 'visit_id' ] ),
1036
- time() + self::$settings[ 'session_duration' ],
1037
- COOKIEPATH
1038
- );
1039
- }
1040
-
1041
- }
1042
- elseif ( $identifier > 0 ) {
1043
- self::$stat[ 'visit_id' ] = $identifier;
1044
- }
1045
-
1046
- if ( $is_new_session && $identifier > 0 ) {
1047
- self::$wpdb->query( self::$wpdb->prepare( "
1048
- UPDATE {$GLOBALS['wpdb']->prefix}slim_stats
1049
- SET visit_id = %d
1050
- WHERE id = %d AND visit_id = 0", self::$stat[ 'visit_id' ], $identifier
1051
- ) );
1052
- }
1053
- return ( $is_new_session && ( $_force_assign || self::$settings[ 'javascript_mode' ] == 'on' ) );
1054
- }
1055
- // end _set_visit_id
1056
-
1057
- /**
1058
- * Makes sure that the data received from the client is well-formed (and that nobody is trying to do bad stuff)
1059
- */
1060
- protected static function _check_data_integrity( $_data = '' ) {
1061
- // Parse the information we received
1062
- self::$data_js = apply_filters( 'slimstat_filter_pageview_data_js', $_data );
1063
-
1064
- // Do we have an id for this request?
1065
- if ( empty( self::$data_js[ 'id' ] ) || empty( self::$data_js[ 'op' ] ) ) {
1066
- do_action( 'slimstat_track_exit_102' );
1067
- self::$stat[ 'id' ] = -100;
1068
- self::_set_error_array( __( 'Invalid payload string. Try clearing your WordPress cache.', 'wp-slimstat' ) );
1069
- self::slimstat_save_options();
1070
- exit( self::_get_id_with_checksum( self::$stat[ 'id' ] ) );
1071
- }
1072
-
1073
- // Make sure that the control code is valid
1074
- self::$data_js[ 'id' ] = self::_separate_id_from_checksum( self::$data_js[ 'id' ] );
1075
-
1076
- if ( self::$data_js['id'] === false ) {
1077
- do_action( 'slimstat_track_exit_103' );
1078
- self::$stat[ 'id' ] = -101;
1079
- self::_set_error_array( __( 'Invalid data signature. Try clearing your WordPress cache.', 'wp-slimstat' ) );
1080
- self::slimstat_save_options();
1081
- exit( self::_get_id_with_checksum( self::$stat[ 'id' ] ) );
1082
- }
1083
-
1084
- $intval_id = intval( self::$data_js[ 'id' ] );
1085
- if ( $intval_id < 0 ) {
1086
- do_action( 'slimstat_track_exit_' . abs( $intval_id ) );
1087
- self::$stat[ 'id' ] = $intval_id;
1088
- self::slimstat_save_options();
1089
- exit( self::_get_id_with_checksum( self::$stat[ 'id' ] ) );
1090
- }
1091
- }
1092
- // end _check_data_integrity
1093
-
1094
- protected static function _set_error_array( $_error_message = '', $_error_code = 0 ) {
1095
- $error_code = empty( $_error_code ) ? abs( self::$stat[ 'id' ] ) : $_error_code;
1096
-
1097
- self::toggle_date_i18n_filters( false );
1098
- self::$settings[ 'last_tracker_error' ] = array( $error_code, $_error_message, date_i18n( 'U' ) );
1099
- self::toggle_date_i18n_filters( true );
1100
- }
1101
-
1102
- protected static function _get_id_with_checksum( $_id = 0 ) {
1103
- return $_id . '.' . md5( $_id . self::$settings[ 'secret' ] );
1104
- }
1105
-
1106
- protected static function _separate_id_from_checksum( $_id_with_checksum = '' ) {
1107
- list( $id, $checksum ) = explode( '.', $_id_with_checksum );
1108
-
1109
- if ( $checksum === md5( $id . self::$settings[ 'secret' ] ) ) {
1110
- return $id;
1111
- }
1112
-
1113
- return false;
1114
- }
1115
-
1116
- protected static function _is_blacklisted( $_needles = array(), $_haystack_string = '' ) {
1117
- foreach ( self::string_to_array( $_haystack_string ) as $a_item ) {
1118
- $pattern = str_replace( array( '\*', '\!' ) , array( '(.*)', '.' ), preg_quote( $a_item, '@' ) );
1119
-
1120
- if ( !is_array( $_needles ) ) {
1121
- $_needles = array( $_needles );
1122
- }
1123
-
1124
- foreach ( $_needles as $a_needle ) {
1125
- if ( preg_match( "@^$pattern$@i", $a_needle ) ) {
1126
- return true;
1127
- }
1128
- }
1129
- }
1130
-
1131
- return false;
1132
- }
1133
-
1134
- public static function is_local_ip_address( $ip_address = '' ) {
1135
- if ( !filter_var( $ip_address, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE ) ) {
1136
- return true;
1137
- }
1138
-
1139
- return false;
1140
- }
1141
-
1142
- public static function dtr_pton( $ip ){
1143
- if ( filter_var( $ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 ) ) {
1144
- $unpacked = unpack( 'A4', inet_pton( $ip ) );
1145
- }
1146
- else if ( filter_var( $ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6 ) && defined( 'AF_INET6' ) ) {
1147
- $unpacked = unpack( 'A16', inet_pton( $ip ) );
1148
- }
1149
-
1150
- $binary_ip = '';
1151
- if ( !empty( $unpacked ) ) {
1152
- $unpacked = str_split( $unpacked[ 1 ] );
1153
- foreach ( $unpacked as $char ) {
1154
- $binary_ip .= str_pad( decbin( ord( $char ) ), 8, '0', STR_PAD_LEFT );
1155
- }
1156
- }
1157
-
1158
- return $binary_ip;
1159
- }
1160
-
1161
- public static function get_mask_length( $ip ){
1162
- if ( filter_var( $ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 ) ) {
1163
- return 32;
1164
- }
1165
- else if ( filter_var( $ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6 ) ) {
1166
- return 128;
1167
- }
1168
-
1169
- return false;
1170
- }
1171
-
1172
- /**
1173
- * Opens given domains during CORS requests to admin-ajax.php
1174
- */
1175
- public static function open_cors_admin_ajax( $_allowed_origins = array() ) {
1176
- $exploded_domains = self::string_to_array( self::$settings[ 'external_domains' ] );
1177
-
1178
- if ( !empty( $exploded_domains ) && !empty( $exploded_domains[ 0 ] ) ) {
1179
- $_allowed_origins = array_merge( $_allowed_origins, $exploded_domains );
1180
- }
1181
-
1182
- return $_allowed_origins;
1183
- }
1184
-
1185
- /**
1186
- * Downloads the MaxMind geolocation database from their repository
1187
- */
1188
- public static function download_maxmind_database() {
1189
- // Create the folder, if it doesn't exist
1190
- if ( !file_exists( dirname( self::$maxmind_path ) ) ) {
1191
- mkdir( dirname( self::$maxmind_path ) );
1192
- }
1193
-
1194
- if ( file_exists( self::$maxmind_path ) ) {
1195
- if ( is_file( self::$maxmind_path ) ) {
1196
- $is_deleted = @unlink( self::$maxmind_path );
1197
- }
1198
- else {
1199
- // This should not happen, but hey...
1200
- $is_deleted = @rmdir( self::$maxmind_path );
1201
- }
1202
-
1203
- if ( !$is_deleted ) {
1204
- return __( "The geolocation database cannot be updated. Please check your server's file permissions and try again.", 'wp-slimstat' );
1205
- }
1206
- }
1207
-
1208
- // Download the most recent database directly from MaxMind's repository
1209
- if ( self::$settings[ 'geolocation_country' ] == 'on' ) {
1210
- $maxmind_tmp = self::download_url( 'https://geolite.maxmind.com/download/geoip/database/GeoLite2-Country.mmdb.gz' );
1211
- }
1212
- else {
1213
- $maxmind_tmp = self::download_url( 'https://geolite.maxmind.com/download/geoip/database/GeoLite2-City.mmdb.gz' );
1214
- }
1215
-
1216
- if ( is_wp_error( $maxmind_tmp ) ) {
1217
- return __( 'There was an error downloading the MaxMind Geolite DB:', 'wp-slimstat' ) . ' ' . $maxmind_tmp->get_error_message();
1218
- }
1219
-
1220
- $zh = false;
1221
-
1222
- if ( !function_exists( 'gzopen' ) ) {
1223
- if ( function_exists( 'gzopen64' ) ) {
1224
- if ( false === ( $zh = gzopen64( $maxmind_tmp, 'rb' ) ) ) {
1225
- return __( "There was an error opening the zipped MaxMind Geolite DB. Please check your server's file permissions and try again.", 'wp-slimstat' );
1226
- }
1227
- }
1228
- else {
1229
- return __( 'Function <code>gzopen</code> is not defined in your environment. Please ask your server administrator to install the corresponding library.', 'wp-slimstat' );
1230
- }
1231
- }
1232
- else{
1233
- if ( false === ( $zh = gzopen( $maxmind_tmp, 'rb' ) ) ) {
1234
- return __( "There was an error opening the zipped MaxMind Geolite DB. Please check your server's file permissions and try again.", 'wp-slimstat' );
1235
- }
1236
- }
1237
-
1238
- if ( false === ( $fh = fopen( self::$maxmind_path, 'wb' ) ) ) {
1239
- return __( "There was an error opening the MaxMind Geolite DB. Please check your server's file permissions and try again.", 'wp-slimstat' );
1240
- }
1241
-
1242
- while ( ( $data = gzread( $zh, 4096 ) ) != false ) {
1243
- fwrite( $fh, $data );
1244
- }
1245
-
1246
- @gzclose( $zh );
1247
- @fclose( $fh );
1248
-
1249
- if ( !is_file( self::$maxmind_path ) ) {
1250
- // Something went wrong, maybe a folder was created instead of a regular file
1251
- @rmdir( self::$maxmind_path );
1252
- return __( 'There was an error creating the MaxMind Geolite DB.', 'wp-slimstat' );
1253
- }
1254
-
1255
- @unlink( $maxmind_tmp );
1256
-
1257
- return '';
1258
- }
1259
 
1260
  public static function download_url( $url ) {
1261
  // Include the FILE API, if it's not defined
@@ -1725,27 +1370,6 @@ class wp_slimstat {
1725
  }
1726
  // end init_options
1727
 
1728
- /**
1729
- * Saves the options in the database, if necessary
1730
- */
1731
- public static function slimstat_save_options() {
1732
- // Allow third-party functions to manipulate the options right before they are saved
1733
- self::$settings = apply_filters( 'slimstat_save_options', self::$settings );
1734
-
1735
- if ( self::$settings_signature === md5( serialize( self::$settings ) ) ) {
1736
- return true;
1737
- }
1738
-
1739
- if ( !is_network_admin() ) {
1740
- update_option( 'slimstat_options', self::$settings );
1741
- }
1742
- else {
1743
- update_site_option( 'slimstat_options', self::$settings );
1744
- }
1745
-
1746
- return true;
1747
- }
1748
-
1749
  /**
1750
  * Enqueue a javascript to track users' screen resolution and other browser-based information
1751
  */
@@ -1932,13 +1556,373 @@ class wp_slimstat {
1932
  public static function register_widget() {
1933
  return register_widget( "slimstat_widget" );
1934
  }
1935
- }
1936
- // end of class declaration
1937
-
1938
- class slimstat_widget extends WP_Widget {
1939
 
1940
  /**
1941
- * Sets up the widgets name etc
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1942
  */
1943
  public function __construct() {
1944
  parent::__construct( 'slimstat_widget', 'Slimstat', array(
@@ -2015,604 +1999,6 @@ class slimstat_widget extends WP_Widget {
2015
  }
2016
  }
2017
 
2018
- class slim_i18n {
2019
- public static $dynamic_strings = array();
2020
-
2021
- public static function init_dynamic_strings() {
2022
- if ( false === ( self::$dynamic_strings = get_transient( 'slimstat_dynamic_strings' ) ) ) {
2023
- self::$dynamic_strings = array(
2024
- 'xx' => __( 'Unknown', 'wp-slimstat' ),
2025
-
2026
- // Countries
2027
- 'c-' => __( 'Unknown', 'wp-slimstat' ),
2028
- 'c-xx' => __( 'Unknown', 'wp-slimstat' ),
2029
- 'c-xy' => __( 'Local IP Address', 'wp-slimstat' ),
2030
-
2031
- 'c-af' => __( 'Afghanistan', 'wp-slimstat' ),
2032
- 'c-ax' => __( 'Aland Islands', 'wp-slimstat' ),
2033
- 'c-al' => __( 'Albania', 'wp-slimstat' ),
2034
- 'c-dz' => __( 'Algeria', 'wp-slimstat' ),
2035
- 'c-ad' => __( 'Andorra', 'wp-slimstat' ),
2036
- 'c-ao' => __( 'Angola', 'wp-slimstat' ),
2037
- 'c-ai' => __( 'Anguilla', 'wp-slimstat' ),
2038
- 'c-ag' => __( 'Antigua and Barbuda', 'wp-slimstat' ),
2039
- 'c-ar' => __( 'Argentina', 'wp-slimstat' ),
2040
- 'c-am' => __( 'Armenia', 'wp-slimstat' ),
2041
- 'c-aw' => __( 'Aruba', 'wp-slimstat' ),
2042
- 'c-au' => __( 'Australia', 'wp-slimstat' ),
2043
- 'c-at' => __( 'Austria', 'wp-slimstat' ),
2044
- 'c-az' => __( 'Azerbaijan', 'wp-slimstat' ),
2045
- 'c-bs' => __( 'Bahamas', 'wp-slimstat' ),
2046
- 'c-bh' => __( 'Bahrain', 'wp-slimstat' ),
2047
- 'c-bd' => __( 'Bangladesh', 'wp-slimstat' ),
2048
- 'c-bb' => __( 'Barbados', 'wp-slimstat' ),
2049
- 'c-by' => __( 'Belarus', 'wp-slimstat' ),
2050
- 'c-be' => __( 'Belgium', 'wp-slimstat' ),
2051
- 'c-bz' => __( 'Belize', 'wp-slimstat' ),
2052
- 'c-bj' => __( 'Benin', 'wp-slimstat' ),
2053
- 'c-bm' => __( 'Bermuda', 'wp-slimstat' ),
2054
- 'c-bt' => __( 'Bhutan', 'wp-slimstat' ),
2055
- 'c-bo' => __( 'Bolivia', 'wp-slimstat' ),
2056
- 'c-ba' => __( 'Bosnia and Herzegovina', 'wp-slimstat' ),
2057
- 'c-bw' => __( 'Botswana', 'wp-slimstat' ),
2058
- 'c-br' => __( 'Brazil', 'wp-slimstat' ),
2059
- 'c-bn' => __( 'Brunei Darussalam', 'wp-slimstat' ),
2060
- 'c-bg' => __( 'Bulgaria', 'wp-slimstat' ),
2061
- 'c-bf' => __( 'Burkina Faso', 'wp-slimstat' ),
2062
- 'c-bi' => __( 'Burundi', 'wp-slimstat' ),
2063
- 'c-kh' => __( 'Cambodia', 'wp-slimstat' ),
2064
- 'c-cm' => __( 'Cameroon', 'wp-slimstat' ),
2065
- 'c-ca' => __( 'Canada', 'wp-slimstat' ),
2066
- 'c-cv' => __( 'Cape Verde', 'wp-slimstat' ),
2067
- 'c-ky' => __( 'Cayman Islands', 'wp-slimstat' ),
2068
- 'c-cf' => __( 'Central African Republic', 'wp-slimstat' ),
2069
- 'c-td' => __( 'Chad', 'wp-slimstat' ),
2070
- 'c-cl' => __( 'Chile', 'wp-slimstat' ),
2071
- 'c-cn' => __( 'China', 'wp-slimstat' ),
2072
- 'c-co' => __( 'Colombia', 'wp-slimstat' ),
2073
- 'c-km' => __( 'Comoros', 'wp-slimstat' ),
2074
- 'c-cg' => __( 'Congo', 'wp-slimstat' ),
2075
- 'c-cd' => __( 'The Democratic Republic of the Congo', 'wp-slimstat' ),
2076
- 'c-cr' => __( 'Costa Rica', 'wp-slimstat' ),
2077
- 'c-ci' => __( 'Côte d\'Ivoire', 'wp-slimstat' ),
2078
- 'c-hr' => __( 'Croatia', 'wp-slimstat' ),
2079
- 'c-cu' => __( 'Cuba', 'wp-slimstat' ),
2080
- 'c-cy' => __( 'Cyprus', 'wp-slimstat' ),
2081
- 'c-cz' => __( 'Czech Republic', 'wp-slimstat' ),
2082
- 'c-dk' => __( 'Denmark', 'wp-slimstat' ),
2083
- 'c-dj' => __( 'Djibouti', 'wp-slimstat' ),
2084
- 'c-dm' => __( 'Dominica', 'wp-slimstat' ),
2085
- 'c-do' => __( 'Dominican Republic', 'wp-slimstat' ),
2086
- 'c-ec' => __( 'Ecuador', 'wp-slimstat' ),
2087
- 'c-eg' => __( 'Egypt', 'wp-slimstat' ),
2088
- 'c-sv' => __( 'El Salvador', 'wp-slimstat' ),
2089
- 'c-gq' => __( 'Equatorial Guinea', 'wp-slimstat' ),
2090
- 'c-er' => __( 'Eritrea', 'wp-slimstat' ),
2091
- 'c-ee' => __( 'Estonia', 'wp-slimstat' ),
2092
- 'c-et' => __( 'Ethiopia', 'wp-slimstat' ),
2093
- 'c-fo' => __( 'Faroe Islands', 'wp-slimstat' ),
2094
- 'c-fk' => __( 'Falkland Islands (Malvinas)', 'wp-slimstat' ),
2095
- 'c-fj' => __( 'Fiji', 'wp-slimstat' ),
2096
- 'c-fi' => __( 'Finland', 'wp-slimstat' ),
2097
- 'c-fr' => __( 'France', 'wp-slimstat' ),
2098
- 'c-gf' => __( 'French Guiana', 'wp-slimstat' ),
2099
- 'c-ga' => __( 'Gabon', 'wp-slimstat' ),
2100
- 'c-gm' => __( 'Gambia', 'wp-slimstat' ),
2101
- 'c-ge' => __( 'Georgia', 'wp-slimstat' ),
2102
- 'c-de' => __( 'Germany', 'wp-slimstat' ),
2103
- 'c-gh' => __( 'Ghana', 'wp-slimstat' ),
2104
- 'c-gr' => __( 'Greece', 'wp-slimstat' ),
2105
- 'c-gl' => __( 'Greenland', 'wp-slimstat' ),
2106
- 'c-gd' => __( 'Grenada', 'wp-slimstat' ),
2107
- 'c-gp' => __( 'Guadeloupe', 'wp-slimstat' ),
2108
- 'c-gt' => __( 'Guatemala', 'wp-slimstat' ),
2109
- 'c-gn' => __( 'Guinea', 'wp-slimstat' ),
2110
- 'c-gw' => __( 'Guinea-Bissau', 'wp-slimstat' ),
2111
- 'c-gy' => __( 'Guyana', 'wp-slimstat' ),
2112
- 'c-ht' => __( 'Haiti', 'wp-slimstat' ),
2113
- 'c-hn' => __( 'Honduras', 'wp-slimstat' ),
2114
- 'c-hk' => __( 'Hong Kong', 'wp-slimstat' ),
2115
- 'c-hu' => __( 'Hungary', 'wp-slimstat' ),
2116
- 'c-is' => __( 'Iceland', 'wp-slimstat' ),
2117
- 'c-in' => __( 'India', 'wp-slimstat' ),
2118
- 'c-id' => __( 'Indonesia', 'wp-slimstat' ),
2119
- 'c-ir' => __( 'Islamic Republic of Iran', 'wp-slimstat' ),
2120
- 'c-iq' => __( 'Iraq', 'wp-slimstat' ),
2121
- 'c-ie' => __( 'Ireland', 'wp-slimstat' ),
2122
- 'c-il' => __( 'Israel', 'wp-slimstat' ),
2123
- 'c-it' => __( 'Italy', 'wp-slimstat' ),
2124
- 'c-jm' => __( 'Jamaica', 'wp-slimstat' ),
2125
- 'c-jp' => __( 'Japan', 'wp-slimstat' ),
2126
- 'c-jo' => __( 'Jordan', 'wp-slimstat' ),
2127
- 'c-kz' => __( 'Kazakhstan', 'wp-slimstat' ),
2128
- 'c-ke' => __( 'Kenya', 'wp-slimstat' ),
2129
- 'c-nr' => __( 'Nauru', 'wp-slimstat' ),
2130
- 'c-kp' => __( 'Democratic People\'s Republic of Korea', 'wp-slimstat' ),
2131
- 'c-kr' => __( 'Republic of Korea', 'wp-slimstat' ),
2132
- 'c-kv' => __( 'Kosovo', 'wp-slimstat' ),
2133
- 'c-kw' => __( 'Kuwait', 'wp-slimstat' ),
2134
- 'c-kg' => __( 'Kyrgyzstan', 'wp-slimstat' ),
2135
- 'c-la' => __( 'Lao People\'s Democratic Republic', 'wp-slimstat' ),
2136
- 'c-lv' => __( 'Latvia', 'wp-slimstat' ),
2137
- 'c-lb' => __( 'Lebanon', 'wp-slimstat' ),
2138
- 'c-ls' => __( 'Lesotho', 'wp-slimstat' ),
2139
- 'c-lr' => __( 'Liberia', 'wp-slimstat' ),
2140
- 'c-ly' => __( 'Libyan Arab Jamahiriya', 'wp-slimstat' ),
2141
- 'c-li' => __( 'Liechtenstein', 'wp-slimstat' ),
2142
- 'c-lt' => __( 'Lithuania', 'wp-slimstat' ),
2143
- 'c-lu' => __( 'Luxembourg', 'wp-slimstat' ),
2144
- 'c-mk' => __( 'The Former Yugoslav Republic of Macedonia', 'wp-slimstat' ),
2145
- 'c-mg' => __( 'Madagascar', 'wp-slimstat' ),
2146
- 'c-mw' => __( 'Malawi', 'wp-slimstat' ),
2147
- 'c-my' => __( 'Malaysia', 'wp-slimstat' ),
2148
- 'c-ml' => __( 'Mali', 'wp-slimstat' ),
2149
- 'c-mt' => __( 'Malta', 'wp-slimstat' ),
2150
- 'c-mq' => __( 'Martinique', 'wp-slimstat' ),
2151
- 'c-mr' => __( 'Mauritania', 'wp-slimstat' ),
2152
- 'c-mu' => __( 'Mauritius', 'wp-slimstat' ),
2153
- 'c-mx' => __( 'Mexico', 'wp-slimstat' ),
2154
- 'c-md' => __( 'Moldova', 'wp-slimstat' ),
2155
- 'c-mn' => __( 'Mongolia', 'wp-slimstat' ),
2156
- 'c-me' => __( 'Montenegro', 'wp-slimstat' ),
2157
- 'c-ms' => __( 'Montserrat', 'wp-slimstat' ),
2158
- 'c-ma' => __( 'Morocco', 'wp-slimstat' ),
2159
- 'c-mz' => __( 'Mozambique', 'wp-slimstat' ),
2160
- 'c-mm' => __( 'Myanmar', 'wp-slimstat' ),
2161
- 'c-na' => __( 'Namibia', 'wp-slimstat' ),
2162
- 'c-np' => __( 'Nepal', 'wp-slimstat' ),
2163
- 'c-nl' => __( 'Netherlands', 'wp-slimstat' ),
2164
- 'c-nc' => __( 'New Caledonia', 'wp-slimstat' ),
2165
- 'c-nz' => __( 'New Zealand', 'wp-slimstat' ),
2166
- 'c-ni' => __( 'Nicaragua', 'wp-slimstat' ),
2167
- 'c-ne' => __( 'Niger', 'wp-slimstat' ),
2168
- 'c-ng' => __( 'Nigeria', 'wp-slimstat' ),
2169
- 'c-no' => __( 'Norway', 'wp-slimstat' ),
2170
- 'c-om' => __( 'Oman', 'wp-slimstat' ),
2171
- 'c-pk' => __( 'Pakistan', 'wp-slimstat' ),
2172
- 'c-pw' => __( 'Palau', 'wp-slimstat' ),
2173
- 'c-ps' => __( 'Occupied Palestinian Territory', 'wp-slimstat' ),
2174
- 'c-pa' => __( 'Panama', 'wp-slimstat' ),
2175
- 'c-pg' => __( 'Papua New Guinea', 'wp-slimstat' ),
2176
- 'c-py' => __( 'Paraguay', 'wp-slimstat' ),
2177
- 'c-pe' => __( 'Peru', 'wp-slimstat' ),
2178
- 'c-ph' => __( 'Philippines', 'wp-slimstat' ),
2179
- 'c-pl' => __( 'Poland', 'wp-slimstat' ),
2180
- 'c-pt' => __( 'Portugal', 'wp-slimstat' ),
2181
- 'c-pr' => __( 'Puerto Rico', 'wp-slimstat' ),
2182
- 'c-qa' => __( 'Qatar', 'wp-slimstat' ),
2183
- 'c-re' => __( 'Réunion', 'wp-slimstat' ),
2184
- 'c-ro' => __( 'Romania', 'wp-slimstat' ),
2185
- 'c-ru' => __( 'Russian Federation', 'wp-slimstat' ),
2186
- 'c-rw' => __( 'Rwanda', 'wp-slimstat' ),
2187
- 'c-kn' => __( 'Saint Kitts and Nevis', 'wp-slimstat' ),
2188
- 'c-lc' => __( 'Saint Lucia', 'wp-slimstat' ),
2189
- 'c-mf' => __( 'Saint Martin', 'wp-slimstat' ),
2190
- 'c-vc' => __( 'Saint Vincent and the Grenadines', 'wp-slimstat' ),
2191
- 'c-ws' => __( 'Samoa', 'wp-slimstat' ),
2192
- 'c-st' => __( 'Sao Tome and Principe', 'wp-slimstat' ),
2193
- 'c-sa' => __( 'Saudi Arabia', 'wp-slimstat' ),
2194
- 'c-sn' => __( 'Senegal', 'wp-slimstat' ),
2195
- 'c-rs' => __( 'Serbia', 'wp-slimstat' ),
2196
- 'c-sl' => __( 'Sierra Leone', 'wp-slimstat' ),
2197
- 'c-sg' => __( 'Singapore', 'wp-slimstat' ),
2198
- 'c-sk' => __( 'Slovakia', 'wp-slimstat' ),
2199
- 'c-si' => __( 'Slovenia', 'wp-slimstat' ),
2200
- 'c-sb' => __( 'Solomon Islands', 'wp-slimstat' ),
2201
- 'c-so' => __( 'Somalia', 'wp-slimstat' ),
2202
- 'c-za' => __( 'South Africa', 'wp-slimstat' ),
2203
- 'c-gs' => __( 'South Georgia and the South Sandwich Islands', 'wp-slimstat' ),
2204
- 'c-es' => __( 'Spain', 'wp-slimstat' ),
2205
- 'c-lk' => __( 'Sri Lanka', 'wp-slimstat' ),
2206
- 'c-sc' => __( 'Seychelles', 'wp-slimstat' ),
2207
- 'c-sd' => __( 'Sudan', 'wp-slimstat' ),
2208
- 'c-ss' => __( 'South Sudan', 'wp-slimstat' ),
2209
- 'c-sr' => __( 'Suriname', 'wp-slimstat' ),
2210
- 'c-sj' => __( 'Svalbard and Jan Mayen', 'wp-slimstat' ),
2211
- 'c-sz' => __( 'Swaziland', 'wp-slimstat' ),
2212
- 'c-se' => __( 'Sweden', 'wp-slimstat' ),
2213
- 'c-ch' => __( 'Switzerland', 'wp-slimstat' ),
2214
- 'c-sy' => __( 'Syrian Arab Republic', 'wp-slimstat' ),
2215
- 'c-tw' => __( 'Taiwan', 'wp-slimstat' ),
2216
- 'c-tj' => __( 'Tajikistan', 'wp-slimstat' ),
2217
- 'c-tz' => __( 'United Republic of Tanzania', 'wp-slimstat' ),
2218
- 'c-th' => __( 'Thailand', 'wp-slimstat' ),
2219
- 'c-tl' => __( 'Timor-Leste', 'wp-slimstat' ),
2220
- 'c-tg' => __( 'Togo', 'wp-slimstat' ),
2221
- 'c-to' => __( 'Tonga', 'wp-slimstat' ),
2222
- 'c-tt' => __( 'Trinidad and Tobago', 'wp-slimstat' ),
2223
- 'c-tn' => __( 'Tunisia', 'wp-slimstat' ),
2224
- 'c-tr' => __( 'Turkey', 'wp-slimstat' ),
2225
- 'c-tm' => __( 'Turkmenistan', 'wp-slimstat' ),
2226
- 'c-tc' => __( 'Turks and Caicos Islands', 'wp-slimstat' ),
2227
- 'c-ug' => __( 'Uganda', 'wp-slimstat' ),
2228
- 'c-ua' => __( 'Ukraine', 'wp-slimstat' ),
2229
- 'c-ae' => __( 'United Arab Emirates', 'wp-slimstat' ),
2230
- 'c-gb' => __( 'United Kingdom', 'wp-slimstat' ),
2231
- 'c-us' => __( 'United States', 'wp-slimstat' ),
2232
- 'c-uy' => __( 'Uruguay', 'wp-slimstat' ),
2233
- 'c-uz' => __( 'Uzbekistan', 'wp-slimstat' ),
2234
- 'c-vu' => __( 'Vanuatu', 'wp-slimstat' ),
2235
- 'c-ve' => __( 'Venezuela', 'wp-slimstat' ),
2236
- 'c-vn' => __( 'Viet Nam', 'wp-slimstat' ),
2237
- 'c-vg' => __( 'British Virgin Islands', 'wp-slimstat' ),
2238
- 'c-vi' => __( 'U.S. Virgin Islands', 'wp-slimstat' ),
2239
- 'c-eh' => __( 'Western Sahara', 'wp-slimstat' ),
2240
- 'c-ye' => __( 'Yemen', 'wp-slimstat' ),
2241
- 'c-zm' => __( 'Zambia', 'wp-slimstat' ),
2242
- 'c-zw' => __( 'Zimbabwe', 'wp-slimstat' ),
2243
- 'c-gg' => __( 'Guernsey', 'wp-slimstat' ),
2244
- 'c-je' => __( 'Jersey', 'wp-slimstat' ),
2245
- 'c-im' => __( 'Isle of Man', 'wp-slimstat' ),
2246
- 'c-mv' => __( 'Maldives', 'wp-slimstat' ),
2247
- 'c-eu' => __( 'Europe', 'wp-slimstat' ),
2248
-
2249
- // Languages
2250
- 'l-' => __( 'Unknown', 'wp-slimstat' ),
2251
- 'l-empty' => __( 'Unknown', 'wp-slimstat' ),
2252
- 'l-xx' => __( 'Unknown', 'wp-slimstat' ),
2253
-
2254
- 'l-af' => __( 'Afrikaans', 'wp-slimstat' ),
2255
- 'l-af-za' => __( 'Afrikaans (South Africa)', 'wp-slimstat' ),
2256
- 'l-ar' => __( 'Arabic', 'wp-slimstat' ),
2257
- 'l-ar-ae' => __( 'Arabic (U.A.E.)', 'wp-slimstat' ),
2258
- 'l-ar-bh' => __( 'Arabic (Bahrain)', 'wp-slimstat' ),
2259
- 'l-ar-dz' => __( 'Arabic (Algeria)', 'wp-slimstat' ),
2260
- 'l-ar-eg' => __( 'Arabic (Egypt)', 'wp-slimstat' ),
2261
- 'l-ar-iq' => __( 'Arabic (Iraq)', 'wp-slimstat' ),
2262
- 'l-ar-jo' => __( 'Arabic (Jordan)', 'wp-slimstat' ),
2263
- 'l-ar-kw' => __( 'Arabic (Kuwait)', 'wp-slimstat' ),
2264
- 'l-ar-lb' => __( 'Arabic (Lebanon)', 'wp-slimstat' ),
2265
- 'l-ar-ly' => __( 'Arabic (Libya)', 'wp-slimstat' ),
2266
- 'l-ar-ma' => __( 'Arabic (Morocco)', 'wp-slimstat' ),
2267
- 'l-ar-om' => __( 'Arabic (Oman)', 'wp-slimstat' ),
2268
- 'l-ar-qa' => __( 'Arabic (Qatar)', 'wp-slimstat' ),
2269
- 'l-ar-sa' => __( 'Arabic (Saudi Arabia)', 'wp-slimstat' ),
2270
- 'l-ar-sy' => __( 'Arabic (Syria)', 'wp-slimstat' ),
2271
- 'l-ar-tn' => __( 'Arabic (Tunisia)', 'wp-slimstat' ),
2272
- 'l-ar-ye' => __( 'Arabic (Yemen)', 'wp-slimstat' ),
2273
- 'l-az' => __( 'Azeri (Latin)', 'wp-slimstat' ),
2274
- 'l-az-az' => __( 'Azeri (Latin) (Azerbaijan)', 'wp-slimstat' ),
2275
- 'l-be' => __( 'Belarusian', 'wp-slimstat' ),
2276
- 'l-be-by' => __( 'Belarusian (Belarus)', 'wp-slimstat' ),
2277
- 'l-bg' => __( 'Bulgarian', 'wp-slimstat' ),
2278
- 'l-bg-bg' => __( 'Bulgarian (Bulgaria)', 'wp-slimstat' ),
2279
- 'l-bs-ba' => __( 'Bosnian (Bosnia and Herzegovina)', 'wp-slimstat' ),
2280
- 'l-ca' => __( 'Catalan', 'wp-slimstat' ),
2281
- 'l-ca-es' => __( 'Catalan (Spain)', 'wp-slimstat' ),
2282
- 'l-cs' => __( 'Czech', 'wp-slimstat' ),
2283
- 'l-cs-cz' => __( 'Czech (Czech Republic)', 'wp-slimstat' ),
2284
- 'l-cy' => __( 'Welsh', 'wp-slimstat' ),
2285
- 'l-cy-gb' => __( 'Welsh (United Kingdom)', 'wp-slimstat' ),
2286
- 'l-da' => __( 'Danish', 'wp-slimstat' ),
2287
- 'l-da-dk' => __( 'Danish (Denmark)', 'wp-slimstat' ),
2288
- 'l-de' => __( 'German', 'wp-slimstat' ),
2289
- 'l-de-at' => __( 'German (Austria)', 'wp-slimstat' ),
2290
- 'l-de-ch' => __( 'German (Switzerland)', 'wp-slimstat' ),
2291
- 'l-de-de' => __( 'German (Germany)', 'wp-slimstat' ),
2292
- 'l-de-li' => __( 'German (Liechtenstein)', 'wp-slimstat' ),
2293
- 'l-de-lu' => __( 'German (Luxembourg)', 'wp-slimstat' ),
2294
- 'l-dv' => __( 'Divehi', 'wp-slimstat' ),
2295
- 'l-dv-mv' => __( 'Divehi (Maldives)', 'wp-slimstat' ),
2296
- 'l-el' => __( 'Greek', 'wp-slimstat' ),
2297
- 'l-el-gr' => __( 'Greek (Greece)', 'wp-slimstat' ),
2298
- 'l-en' => __( 'English', 'wp-slimstat' ),
2299
- 'l-en-au' => __( 'English (Australia)', 'wp-slimstat' ),
2300
- 'l-en-bz' => __( 'English (Belize)', 'wp-slimstat' ),
2301
- 'l-en-ca' => __( 'English (Canada)', 'wp-slimstat' ),
2302
- 'l-en-cb' => __( 'English (Caribbean)', 'wp-slimstat' ),
2303
- 'l-en-gb' => __( 'English (United Kingdom)', 'wp-slimstat' ),
2304
- 'l-en-ie' => __( 'English (Ireland)', 'wp-slimstat' ),
2305
- 'l-en-jm' => __( 'English (Jamaica)', 'wp-slimstat' ),
2306
- 'l-en-nz' => __( 'English (New Zealand)', 'wp-slimstat' ),
2307
- 'l-en-ph' => __( 'English (Republic of the Philippines)', 'wp-slimstat' ),
2308
- 'l-en-tt' => __( 'English (Trinidad and Tobago)', 'wp-slimstat' ),
2309
- 'l-en-us' => __( 'English (United States)', 'wp-slimstat' ),
2310
- 'l-en-za' => __( 'English (South Africa)', 'wp-slimstat' ),
2311
- 'l-en-zw' => __( 'English (Zimbabwe)', 'wp-slimstat' ),
2312
- 'l-eo' => __( 'Esperanto', 'wp-slimstat' ),
2313
- 'l-es' => __( 'Spanish', 'wp-slimstat' ),
2314
- 'l-es-ar' => __( 'Spanish (Argentina)', 'wp-slimstat' ),
2315
- 'l-es-bo' => __( 'Spanish (Bolivia)', 'wp-slimstat' ),
2316
- 'l-es-cl' => __( 'Spanish (Chile)', 'wp-slimstat' ),
2317
- 'l-es-co' => __( 'Spanish (Colombia)', 'wp-slimstat' ),
2318
- 'l-es-cr' => __( 'Spanish (Costa Rica)', 'wp-slimstat' ),
2319
- 'l-es-do' => __( 'Spanish (Dominican Republic)', 'wp-slimstat' ),
2320
- 'l-es-ec' => __( 'Spanish (Ecuador)', 'wp-slimstat' ),
2321
- 'l-es-es' => __( 'Spanish (Spain)', 'wp-slimstat' ),
2322
- 'l-es-gt' => __( 'Spanish (Guatemala)', 'wp-slimstat' ),
2323
- 'l-es-hn' => __( 'Spanish (Honduras)', 'wp-slimstat' ),
2324
- 'l-es-mx' => __( 'Spanish (Mexico)', 'wp-slimstat' ),
2325
- 'l-es-ni' => __( 'Spanish (Nicaragua)', 'wp-slimstat' ),
2326
- 'l-es-pa' => __( 'Spanish (Panama)', 'wp-slimstat' ),
2327
- 'l-es-pe' => __( 'Spanish (Peru)', 'wp-slimstat' ),
2328
- 'l-es-pr' => __( 'Spanish (Puerto Rico)', 'wp-slimstat' ),
2329
- 'l-es-py' => __( 'Spanish (Paraguay)', 'wp-slimstat' ),
2330
- 'l-es-sv' => __( 'Spanish (El Salvador)', 'wp-slimstat' ),
2331
- 'l-es-uy' => __( 'Spanish (Uruguay)', 'wp-slimstat' ),
2332
- 'l-es-ve' => __( 'Spanish (Venezuela)', 'wp-slimstat' ),
2333
- 'l-et' => __( 'Estonian', 'wp-slimstat' ),
2334
- 'l-et-ee' => __( 'Estonian (Estonia)', 'wp-slimstat' ),
2335
- 'l-eu' => __( 'Basque', 'wp-slimstat' ),
2336
- 'l-eu-es' => __( 'Basque (Spain)', 'wp-slimstat' ),
2337
- 'l-fa' => __( 'Farsi', 'wp-slimstat' ),
2338
- 'l-fa-ir' => __( 'Farsi (Iran)', 'wp-slimstat' ),
2339
- 'l-fi' => __( 'Finnish', 'wp-slimstat' ),
2340
- 'l-fi-fi' => __( 'Finnish (Finland)', 'wp-slimstat' ),
2341
- 'l-fo' => __( 'Faroese', 'wp-slimstat' ),
2342
- 'l-fo-fo' => __( 'Faroese (Faroe Islands)', 'wp-slimstat' ),
2343
- 'l-fr' => __( 'French', 'wp-slimstat' ),
2344
- 'l-fr-be' => __( 'French (Belgium)', 'wp-slimstat' ),
2345
- 'l-fr-ca' => __( 'French (Canada)', 'wp-slimstat' ),
2346
- 'l-fr-ch' => __( 'French (Switzerland)', 'wp-slimstat' ),
2347
- 'l-fr-fr' => __( 'French (France)', 'wp-slimstat' ),
2348
- 'l-fr-lu' => __( 'French (Luxembourg)', 'wp-slimstat' ),
2349
- 'l-fr-mc' => __( 'French (Principality of Monaco)', 'wp-slimstat' ),
2350
- 'l-gl' => __( 'Galician', 'wp-slimstat' ),
2351
- 'l-gl-es' => __( 'Galician (Spain)', 'wp-slimstat' ),
2352
- 'l-gu' => __( 'Gujarati', 'wp-slimstat' ),
2353
- 'l-gu-in' => __( 'Gujarati (India)', 'wp-slimstat' ),
2354
- 'l-he' => __( 'Hebrew', 'wp-slimstat' ),
2355
- 'l-he-il' => __( 'Hebrew (Israel)', 'wp-slimstat' ),
2356
- 'l-hi' => __( 'Hindi', 'wp-slimstat' ),
2357
- 'l-hi-in' => __( 'Hindi (India)', 'wp-slimstat' ),
2358
- 'l-hr' => __( 'Croatian', 'wp-slimstat' ),
2359
- 'l-hr-ba' => __( 'Croatian (Bosnia and Herzegovina)', 'wp-slimstat' ),
2360
- 'l-hr-hr' => __( 'Croatian (Croatia)', 'wp-slimstat' ),
2361
- 'l-hu' => __( 'Hungarian', 'wp-slimstat' ),
2362
- 'l-hu-hu' => __( 'Hungarian (Hungary)', 'wp-slimstat' ),
2363
- 'l-hy' => __( 'Armenian', 'wp-slimstat' ),
2364
- 'l-hy-am' => __( 'Armenian (Armenia)', 'wp-slimstat' ),
2365
- 'l-id' => __( 'Indonesian', 'wp-slimstat' ),
2366
- 'l-id-id' => __( 'Indonesian (Indonesia)', 'wp-slimstat' ),
2367
- 'l-is' => __( 'Icelandic', 'wp-slimstat' ),
2368
- 'l-is-is' => __( 'Icelandic (Iceland)', 'wp-slimstat' ),
2369
- 'l-it' => __( 'Italian', 'wp-slimstat' ),
2370
- 'l-it-ch' => __( 'Italian (Switzerland)', 'wp-slimstat' ),
2371
- 'l-it-it' => __( 'Italian (Italy)', 'wp-slimstat' ),
2372
- 'l-ja' => __( 'Japanese', 'wp-slimstat' ),
2373
- 'l-ja-jp' => __( 'Japanese (Japan)', 'wp-slimstat' ),
2374
- 'l-ka' => __( 'Georgian', 'wp-slimstat' ),
2375
- 'l-ka-ge' => __( 'Georgian (Georgia)', 'wp-slimstat' ),
2376
- 'l-kk' => __( 'Kazakh', 'wp-slimstat' ),
2377
- 'l-kk-kz' => __( 'Kazakh (Kazakhstan)', 'wp-slimstat' ),
2378
- 'l-kn' => __( 'Kannada', 'wp-slimstat' ),
2379
- 'l-kn-in' => __( 'Kannada (India)', 'wp-slimstat' ),
2380
- 'l-ko' => __( 'Korean', 'wp-slimstat' ),
2381
- 'l-ko-kr' => __( 'Korean (Korea)', 'wp-slimstat' ),
2382
- 'l-kok' => __( 'Konkani', 'wp-slimstat' ),
2383
- 'l-kok-in' => __( 'Konkani (India)', 'wp-slimstat' ),
2384
- 'l-ky' => __( 'Kyrgyz', 'wp-slimstat' ),
2385
- 'l-ky-kg' => __( 'Kyrgyz (Kyrgyzstan)', 'wp-slimstat' ),
2386
- 'l-lt' => __( 'Lithuanian', 'wp-slimstat' ),
2387
- 'l-lt-lt' => __( 'Lithuanian (Lithuania)', 'wp-slimstat' ),
2388
- 'l-lv' => __( 'Latvian', 'wp-slimstat' ),
2389
- 'l-lv-lv' => __( 'Latvian (Latvia)', 'wp-slimstat' ),
2390
- 'l-mi' => __( 'Maori', 'wp-slimstat' ),
2391
- 'l-mi-nz' => __( 'Maori (New Zealand)', 'wp-slimstat' ),
2392
- 'l-mk' => __( 'FYRO Macedonian', 'wp-slimstat' ),
2393
- 'l-mk-ml' => __( 'FYRO Macedonian (Former Yugoslav Republic of Macedonia)', 'wp-slimstat' ),
2394
- 'l-mn' => __( 'Mongolian', 'wp-slimstat' ),
2395
- 'l-mn-mn' => __( 'Mongolian (Mongolia)', 'wp-slimstat' ),
2396
- 'l-mr' => __( 'Marathi', 'wp-slimstat' ),
2397
- 'l-mr-in' => __( 'Marathi (India)', 'wp-slimstat' ),
2398
- 'l-ms' => __( 'Malay', 'wp-slimstat' ),
2399
- 'l-ms-bn' => __( 'Malay (Brunei Darussalam)', 'wp-slimstat' ),
2400
- 'l-ms-my' => __( 'Malay (Malaysia)', 'wp-slimstat' ),
2401
- 'l-mt' => __( 'Maltese', 'wp-slimstat' ),
2402
- 'l-mt-mt' => __( 'Maltese (Malta)', 'wp-slimstat' ),
2403
- 'l-nb' => __( 'Norwegian (Bokmål)', 'wp-slimstat' ),
2404
- 'l-nb-no' => __( 'Norwegian (Bokmål) (Norway)', 'wp-slimstat' ),
2405
- 'l-nl' => __( 'Dutch', 'wp-slimstat' ),
2406
- 'l-nl-be' => __( 'Dutch (Belgium)', 'wp-slimstat' ),
2407
- 'l-nl-nl' => __( 'Dutch (Netherlands)', 'wp-slimstat' ),
2408
- 'l-nn-no' => __( 'Norwegian (Nynorsk) (Norway)', 'wp-slimstat' ),
2409
- 'l-ns' => __( 'Northern Sotho', 'wp-slimstat' ),
2410
- 'l-ns-za' => __( 'Northern Sotho (South Africa)', 'wp-slimstat' ),
2411
- 'l-pa' => __( 'Punjabi', 'wp-slimstat' ),
2412
- 'l-pa-in' => __( 'Punjabi (India)', 'wp-slimstat' ),
2413
- 'l-pl' => __( 'Polish', 'wp-slimstat' ),
2414
- 'l-pl-pl' => __( 'Polish (Poland)', 'wp-slimstat' ),
2415
- 'l-ps' => __( 'Pashto', 'wp-slimstat' ),
2416
- 'l-ps-ar' => __( 'Pashto (Afghanistan)', 'wp-slimstat' ),
2417
- 'l-pt' => __( 'Portuguese', 'wp-slimstat' ),
2418
- 'l-pt-br' => __( 'Portuguese (Brazil)', 'wp-slimstat' ),
2419
- 'l-pt-pt' => __( 'Portuguese (Portugal)', 'wp-slimstat' ),
2420
- 'l-qu' => __( 'Quechua', 'wp-slimstat' ),
2421
- 'l-qu-bo' => __( 'Quechua (Bolivia)', 'wp-slimstat' ),
2422
- 'l-qu-ec' => __( 'Quechua (Ecuador)', 'wp-slimstat' ),
2423
- 'l-qu-pe' => __( 'Quechua (Peru)', 'wp-slimstat' ),
2424
- 'l-ro' => __( 'Romanian', 'wp-slimstat' ),
2425
- 'l-ro-ro' => __( 'Romanian (Romania)', 'wp-slimstat' ),
2426
- 'l-ru' => __( 'Russian', 'wp-slimstat' ),
2427
- 'l-ru-ru' => __( 'Russian (Russia)', 'wp-slimstat' ),
2428
- 'l-sa' => __( 'Sanskrit', 'wp-slimstat' ),
2429
- 'l-sa-in' => __( 'Sanskrit (India)', 'wp-slimstat' ),
2430
- 'l-se' => __( 'Sami (Northern)', 'wp-slimstat' ),
2431
- 'l-se-fi' => __( 'Sami (Northern) (Finland)', 'wp-slimstat' ),
2432
- 'l-se-no' => __( 'Sami (Northern) (Norway)', 'wp-slimstat' ),
2433
- 'l-se-se' => __( 'Sami (Northern) (Sweden)', 'wp-slimstat' ),
2434
- 'l-sk' => __( 'Slovak', 'wp-slimstat' ),
2435
- 'l-sk-sk' => __( 'Slovak (Slovakia)', 'wp-slimstat' ),
2436
- 'l-sl' => __( 'Slovenian', 'wp-slimstat' ),
2437
- 'l-sl-si' => __( 'Slovenian (Slovenia)', 'wp-slimstat' ),
2438
- 'l-sq' => __( 'Albanian', 'wp-slimstat' ),
2439
- 'l-sq-al' => __( 'Albanian (Albania)', 'wp-slimstat' ),
2440
- 'l-sr-ba' => __( 'Serbian (Latin) (Bosnia and Herzegovina)', 'wp-slimstat' ),
2441
- 'l-sr-rs' => __( 'Serbian (Serbia and Montenegro)', 'wp-slimstat' ),
2442
- 'l-sr-sp' => __( 'Serbian (Latin) (Serbia and Montenegro)', 'wp-slimstat' ),
2443
- 'l-sv' => __( 'Swedish', 'wp-slimstat' ),
2444
- 'l-sv-fi' => __( 'Swedish (Finland)', 'wp-slimstat' ),
2445
- 'l-sv-se' => __( 'Swedish (Sweden)', 'wp-slimstat' ),
2446
- 'l-sw' => __( 'Swahili', 'wp-slimstat' ),
2447
- 'l-sw-ke' => __( 'Swahili (Kenya)', 'wp-slimstat' ),
2448
- 'l-ta' => __( 'Tamil', 'wp-slimstat' ),
2449
- 'l-ta-in' => __( 'Tamil (India)', 'wp-slimstat' ),
2450
- 'l-te' => __( 'Telugu', 'wp-slimstat' ),
2451
- 'l-te-in' => __( 'Telugu (India)', 'wp-slimstat' ),
2452
- 'l-th' => __( 'Thai', 'wp-slimstat' ),
2453
- 'l-th-th' => __( 'Thai (Thailand)', 'wp-slimstat' ),
2454
- 'l-tl' => __( 'Tagalog', 'wp-slimstat' ),
2455
- 'l-tl-ph' => __( 'Tagalog (Philippines)', 'wp-slimstat' ),
2456
- 'l-tn' => __( 'Tswana', 'wp-slimstat' ),
2457
- 'l-tn-za' => __( 'Tswana (South Africa)', 'wp-slimstat' ),
2458
- 'l-tr' => __( 'Turkish', 'wp-slimstat' ),
2459
- 'l-tr-tr' => __( 'Turkish (Turkey)', 'wp-slimstat' ),
2460
- 'l-tt' => __( 'Tatar', 'wp-slimstat' ),
2461
- 'l-tt-ru' => __( 'Tatar (Russia)', 'wp-slimstat' ),
2462
- 'l-ts' => __( 'Tsonga', 'wp-slimstat' ),
2463
- 'l-uk' => __( 'Ukrainian', 'wp-slimstat' ),
2464
- 'l-uk-ua' => __( 'Ukrainian (Ukraine)', 'wp-slimstat' ),
2465
- 'l-ur' => __( 'Urdu', 'wp-slimstat' ),
2466
- 'l-ur-pk' => __( 'Urdu (Islamic Republic of Pakistan)', 'wp-slimstat' ),
2467
- 'l-uz' => __( 'Uzbek (Latin)', 'wp-slimstat' ),
2468
- 'l-uz-uz' => __( 'Uzbek (Cyrillic) (Uzbekistan)', 'wp-slimstat' ),
2469
- 'l-vi' => __( 'Vietnamese', 'wp-slimstat' ),
2470
- 'l-vi-vn' => __( 'Vietnamese (Viet Nam)', 'wp-slimstat' ),
2471
- 'l-xh' => __( 'Xhosa', 'wp-slimstat' ),
2472
- 'l-xh-za' => __( 'Xhosa (South Africa)', 'wp-slimstat' ),
2473
- 'l-zh' => __( 'Chinese', 'wp-slimstat' ),
2474
- 'l-zh-cn' => __( 'Chinese (S)', 'wp-slimstat' ),
2475
- 'l-zh-hk' => __( 'Chinese (Hong Kong)', 'wp-slimstat' ),
2476
- 'l-zh-mo' => __( 'Chinese (Macau)', 'wp-slimstat' ),
2477
- 'l-zh-sg' => __( 'Chinese (Singapore)', 'wp-slimstat' ),
2478
- 'l-zh-tw' => __( 'Chinese (T)', 'wp-slimstat' ),
2479
- 'l-zu' => __( 'Zulu', 'wp-slimstat' ),
2480
- 'l-zu-za' => __( 'Zulu (South Africa)', 'wp-slimstat' ),
2481
-
2482
- // Operating Systems
2483
- 'aix' => __( 'IBM AIX', 'wp-slimstat' ),
2484
- 'amiga' => __( 'Amiga', 'wp-slimstat' ),
2485
- 'android' => __( 'Android', 'wp-slimstat' ),
2486
- 'beos' => __( 'BeOS', 'wp-slimstat' ),
2487
- 'blackberry os' => __( 'BlackBerry OS', 'wp-slimstat' ),
2488
- 'centos' => __( 'CentOS', 'wp-slimstat' ),
2489
- 'chromeos' => __( 'ChromeOS', 'wp-slimstat' ),
2490
- 'commodore64' => __( 'Commodore 64', 'wp-slimstat' ),
2491
- 'cygwin' => __( 'Cygwin', 'wp-slimstat' ),
2492
- 'debian' => __( 'Debian', 'wp-slimstat' ),
2493
- 'digital unix' => __( 'Digital Unix', 'wp-slimstat' ),
2494
- 'fedora' => __( 'Fedora', 'wp-slimstat' ),
2495
- 'firefoxos' => __( 'Firefox OS', 'wp-slimstat' ),
2496
- 'freebsd' => __( 'FreeBSD', 'wp-slimstat' ),
2497
- 'gentoo' => __( 'Gentoo', 'wp-slimstat' ),
2498
- 'hp-ux' => __( 'HP-UX', 'wp-slimstat' ),
2499
- 'ios' => __( 'iPhone OS', 'wp-slimstat' ),
2500
- 'iphone os' => __( 'iPhone OS', 'wp-slimstat' ),
2501
- 'iphone osx' => __( 'iPhone OS X', 'wp-slimstat' ),
2502
- 'irix' => __( 'SGI / IRIX', 'wp-slimstat' ),
2503
- 'java' => __( 'Java', 'wp-slimstat' ),
2504
- 'kanotix' => __( 'Kanotix Linux', 'wp-slimstat' ),
2505
- 'knoppix' => __( 'Knoppix Linux', 'wp-slimstat' ),
2506
- 'linux' => __( 'Linux Generic', 'wp-slimstat' ),
2507
- 'mac' => __( 'Mac', 'wp-slimstat' ),
2508
- 'mac68k' => __( 'Mac 68k', 'wp-slimstat' ),
2509
- 'macos' => __( 'Mac OS X', 'wp-slimstat' ),
2510
- 'macosx' => __( 'Mac OS X', 'wp-slimstat' ),
2511
- 'macppc' => __( 'Mac PowerPC', 'wp-slimstat' ),
2512
- 'mandrake' => __( 'Mandrake Linux', 'wp-slimstat' ),
2513
- 'mandriva' => __( 'MS-DOS', 'wp-slimstat' ),
2514
- 'mepis' => __( 'MEPIS Linux', 'wp-slimstat' ),
2515
- 'ms-dos' => __( 'MS-DOS', 'wp-slimstat' ),
2516
- 'netbsd' => __( 'NetBSD', 'wp-slimstat' ),
2517
- 'nintendo' => __( 'Nintendo', 'wp-slimstat' ),
2518
- 'openbsd' => __( 'OpenBSD', 'wp-slimstat' ),
2519
- 'openvms' => __( 'OpenVMS', 'wp-slimstat' ),
2520
- 'os/2' => __( 'IBM OS/2', 'wp-slimstat' ),
2521
- 'palm' => __( 'Palm OS', 'wp-slimstat' ),
2522
- 'palmos' => __( 'Palm OS', 'wp-slimstat' ),
2523
- 'pclinuxos' => __( 'PCLinux OS', 'wp-slimstat' ),
2524
- 'playstation' => __( 'Playstation', 'wp-slimstat' ),
2525
- 'powertv' => __( 'PowerTV', 'wp-slimstat' ),
2526
- 'redhat' => __( 'RedHat Linux', 'wp-slimstat' ),
2527
- 'rim os' => __( 'Blackberry', 'wp-slimstat' ),
2528
- 'risc os' => __( 'Risc OS', 'wp-slimstat' ),
2529
- 'slackware' => __( 'Slackware Linux', 'wp-slimstat' ),
2530
- 'solaris' => __( 'Solaris', 'wp-slimstat' ),
2531
- 'sunos' => __( 'Sun OS', 'wp-slimstat' ),
2532
- 'suse' => __( 'SuSE Linux', 'wp-slimstat' ),
2533
- 'symbianos' => __( 'Symbian OS', 'wp-slimstat' ),
2534
- 'ubuntu' => __( 'Ubuntu', 'wp-slimstat' ),
2535
- 'unix' => __( 'Unix', 'wp-slimstat' ),
2536
- 'unknown' => __( 'Unknown', 'wp-slimstat' ),
2537
- 'xandros' => __( 'Xandros Linux', 'wp-slimstat' ),
2538
- 'wap' => __( 'WAP', 'wp-slimstat' ),
2539
- 'webos' => __( 'WebOS', 'wp-slimstat' ),
2540
- 'win10' => __( 'Windows 10', 'wp-slimstat' ),
2541
- 'win16' => __( 'Windows 16-bit', 'wp-slimstat' ),
2542
- 'win2000' => __( 'Windows 2000', 'wp-slimstat' ),
2543
- 'win2003' => __( 'Windows 2003', 'wp-slimstat' ),
2544
- 'win31' => __( 'Windows 3.1', 'wp-slimstat' ),
2545
- 'win32' => __( 'Windows 32-bit', 'wp-slimstat' ),
2546
- 'win7' => __( 'Windows 7', 'wp-slimstat' ),
2547
- 'win7' => __( 'Windows 7', 'wp-slimstat' ),
2548
- 'win8' => __( 'Windows 8', 'wp-slimstat' ),
2549
- 'win8.1' => __( 'Windows 8.1', 'wp-slimstat' ),
2550
- 'win95' => __( 'Windows 95', 'wp-slimstat' ),
2551
- 'win98' => __( 'Windows 98', 'wp-slimstat' ),
2552
- 'wince' => __( 'Windows CE', 'wp-slimstat' ),
2553
- 'winme' => __( 'Windows ME', 'wp-slimstat' ),
2554
- 'winnt' => __( 'Windows NT', 'wp-slimstat' ),
2555
- 'winphone7' => __( 'Windows Phone', 'wp-slimstat' ),
2556
- 'winphone7.5' => __( 'Windows Phone', 'wp-slimstat' ),
2557
- 'winphone8' => __( 'Windows Phone', 'wp-slimstat' ),
2558
- 'winphone8.1' => __( 'Windows RT / Runtime', 'wp-slimstat' ),
2559
- 'winrt' => __( 'Windows Phone', 'wp-slimstat' ),
2560
- 'winvista' => __( 'Windows Vista', 'wp-slimstat' ),
2561
- 'winxp' => __( 'Windows XP', 'wp-slimstat' ),
2562
- 'wyderos' => __( 'WyderOS', 'wp-slimstat' ),
2563
- 'zaurus' => __( 'Zaurus WAP', 'wp-slimstat' ),
2564
-
2565
- // Operating System Families
2566
- 'p-unk' => __( 'Unknown', 'wp-slimstat' ),
2567
- 'p-' => __( 'Unknown', 'wp-slimstat' ),
2568
-
2569
- 'p-and' => __( 'Android', 'wp-slimstat' ),
2570
- 'p-bla' => __( 'BlackBerry', 'wp-slimstat' ),
2571
- 'p-chr' => __( 'Chrome OS', 'wp-slimstat' ),
2572
- 'p-fir' => __( 'Fire OS', 'wp-slimstat' ),
2573
- 'p-fre' => __( 'Linux FreeBSD', 'wp-slimstat' ),
2574
- 'p-ios' => __( 'Apple iOS', 'wp-slimstat' ),
2575
- 'p-jav' => __( 'Java-based OS', 'wp-slimstat' ),
2576
- 'p-lin' => __( 'Linux', 'wp-slimstat' ),
2577
- 'p-mac' => __( 'Apple', 'wp-slimstat' ),
2578
- 'p-rim' => __( 'Blackberry', 'wp-slimstat' ),
2579
- 'p-sym' => __( 'Symbian OS', 'wp-slimstat' ),
2580
- 'p-ubu' => __( 'Linux', 'wp-slimstat' ),
2581
- 'p-win' => __( 'Microsoft', 'wp-slimstat' )
2582
- );
2583
-
2584
- // set_transient( 'slimstat_dynamic_strings', self::$dynamic_strings, 86400 );
2585
- }
2586
- }
2587
-
2588
- public static function get_country_codes() {
2589
- if ( empty( self::$dynamic_strings ) ) {
2590
- self::init_dynamic_strings();
2591
- }
2592
-
2593
- $country_codes = array();
2594
- foreach ( array_keys( self::$dynamic_strings ) as $a_code ) {
2595
- if ( strpos( $a_code, 'c-', 0 ) !== false && strlen( $a_code ) > 2 && $a_code != 'c-xx' && $a_code != 'c-xy' ) {
2596
- $country_codes[ strtolower( str_replace( 'c-', '', $a_code ) ) ] = self::$dynamic_strings[ $a_code ];
2597
- }
2598
- }
2599
-
2600
- return $country_codes;
2601
- }
2602
-
2603
- public static function get_string( $_code = '' ) {
2604
- if ( empty( self::$dynamic_strings ) ) {
2605
- self::init_dynamic_strings();
2606
- }
2607
-
2608
- if ( !isset( self::$dynamic_strings[ $_code ] ) ) {
2609
- return $_code;
2610
- }
2611
-
2612
- return self::$dynamic_strings[ $_code ];
2613
- }
2614
- }
2615
-
2616
  // Ok, let's go, Sparky!
2617
  if ( function_exists( 'add_action' ) ) {
2618
  // Since we use sendBeacon, this function sends raw POST data, which does not populate the $_POST variable automatically
3
  Plugin Name: Slimstat Analytics
4
  Plugin URI: https://wordpress.org/plugins/wp-slimstat/
5
  Description: The leading web analytics plugin for WordPress
6
+ Version: 4.8.6
7
  Author: Jason Crouse
8
  Author URI: https://www.wp-slimstat.com/
9
  Text Domain: wp-slimstat
15
  }
16
 
17
  class wp_slimstat {
18
+ public static $version = '4.8.6';
19
  public static $settings = array();
20
 
21
  public static $wpdb = '';
27
 
28
  protected static $data_js = array( 'id' => 0 );
29
  protected static $stat = array();
 
30
  protected static $browser = array();
31
  protected static $heuristic_key = 0;
32
  protected static $date_i18n_filters = array();
49
  // Allow third party tools to edit the options
50
  self::$settings = apply_filters( 'slimstat_init_options', self::$settings );
51
 
 
 
 
52
  // Allow third-party tools to use a custom database for Slimstat
53
  self::$wpdb = apply_filters( 'slimstat_custom_wpdb', $GLOBALS[ 'wpdb' ] );
54
 
101
  add_action( 'wp_ajax_slimstat_optout_html', array( __CLASS__, 'get_optout_html' ) );
102
  add_action( 'wp_ajax_nopriv_slimstat_optout_html', array( __CLASS__, 'get_optout_html' ) );
103
 
104
+ // If this request was a redirect, we should update the content type accordingly
105
+ add_filter( 'wp_redirect_status', array( __CLASS__, 'update_content_type' ), 10, 2 );
106
+
107
  // Shortcodes
108
  add_shortcode( 'slimstat', array( __CLASS__, 'slimstat_shortcode' ), 15 );
109
 
114
  // If add-ons are installed, check for updates
115
  add_action( 'wp_loaded', array( __CLASS__, 'update_checker' ) );
116
 
 
 
 
117
  // REST API Support
118
  add_action( 'rest_api_init', array( __CLASS__, 'register_rest_route' ) );
119
 
131
  public static function slimtrack_ajax() {
132
  // If the website is using a caching plugin, the tracking code might still be there, even if the user turned off tracking
133
  if ( self::$settings[ 'is_tracking' ] != 'on' ) {
134
+ self::_log_error( 204 );
 
 
135
  exit( self::_get_id_with_checksum( self::$stat[ 'id' ] ) );
136
  }
137
 
171
 
172
  // Visitor is still on this page, record the timestamp in the corresponding field
173
  self::toggle_date_i18n_filters( false );
174
+ self::$stat[ 'dt_out' ] = date_i18n( 'U' );
175
  self::toggle_date_i18n_filters( true );
176
 
177
  // Are we tracking an outbound click?
224
  // Was this pageview tracked?
225
  if ( self::$stat[ 'id' ] <= 0 ) {
226
  $abs_error_code = abs( self::$stat[ 'id' ] );
227
+ self::_log_error( $abs_error_code );
228
  do_action( 'slimstat_track_exit_' . $abs_error_code, self::$stat );
 
229
  exit( self::_get_id_with_checksum( self::$stat[ 'id' ] ) );
230
  }
231
 
242
  public static function slimtrack( $_argument = '' ) {
243
  // If the website is using a caching plugin, the tracking code might still be there, even if the user turned off tracking
244
  if ( self::$settings[ 'is_tracking' ] != 'on' ) {
245
+ self::_log_error( 204 );
 
246
  return $_argument;
247
  }
248
 
268
  $opt_out_cookie_names = self::string_to_array( self::$settings[ 'opt_out_cookie_names' ] );
269
 
270
  foreach ( $opt_out_cookie_names as $a_cookie_pair ) {
271
+ list( $name, $value ) = explode( '=', $a_cookie_pair );
272
 
273
+ if ( !empty( $name ) && !empty( $value ) ) {
274
  $cookie_names[ $name ] = $value;
275
  }
276
  }
277
  }
278
 
279
  foreach ( $cookie_names as $a_name => $a_value ) {
280
+ if ( isset( $_COOKIE[ $a_name ] ) && strpos( $_COOKIE[ $a_name ], $a_value ) !== false ) {
281
  self::$stat[ 'id' ] = -315;
282
  return $_argument;
283
  }
313
  list ( self::$stat[ 'ip' ], self::$stat[ 'other_ip' ] ) = self::_get_remote_ip();
314
 
315
  if ( empty( self::$stat[ 'ip' ] ) || self::$stat[ 'ip' ] == '0.0.0.0' ) {
316
+ self::_log_error( 202 );
 
317
  return $_argument;
318
  }
319
 
330
  // Is this a 'seriously malformed' URL?
331
  $referer = parse_url( self::$stat[ 'referer' ] );
332
  if ( !$referer ) {
333
+ self::_log_error( 201 );
334
+ return $_argument;
 
335
  }
336
 
337
  if ( !empty( $referer[ 'scheme' ] ) && !in_array( strtolower( $referer[ 'scheme' ] ), array( 'http', 'https', 'android-app' ) ) ) {
 
338
  self::$stat[ 'notes' ][] = sprintf( __( 'Attempted XSS Injection: %s', 'wp-slimstat' ), self::$stat[ 'referer' ] );
339
  unset( self::$stat[ 'referer' ] );
340
  }
364
  }
365
  }
366
 
367
+ if ( empty( self::$stat[ 'content_type' ] ) ) {
368
+ $content_info = self::_get_content_info();
369
+ }
370
 
371
  // Is this content type blacklisted?
372
  if ( !empty( self::$settings[ 'ignore_content_types' ] ) && self::_is_blacklisted( $content_info[ 'content_type' ], self::$settings[ 'ignore_content_types' ] ) ) {
539
  $geolocation_data = maxmind_geolite2_connector::get_geolocation_info( self::$stat[ 'ip' ] );
540
  }
541
  catch( Exception $e ) {
542
+ self::_log_error( 314 );
 
543
  return $_argument;
544
  }
545
 
666
  self::$stat['id'] = self::insert_row(self::$stat, $GLOBALS['wpdb']->prefix.'slim_stats');
667
 
668
  if ( empty( self::$stat[ 'id' ] ) ) {
669
+ self::_log_error( 200 );
 
670
  return $_argument;
671
  }
672
  }
763
 
764
  return 0;
765
  }
766
+ // end update_row
767
 
768
  /**
769
+ * Update content type as needed
770
  */
771
+ public static function update_content_type( $_status = 301, $_location = '' ) {
772
+ if ( $_status >= 300 && $_status < 400 ) {
773
+ self::$stat[ 'content_type' ] = 'redirect:' . intval( $_status );
774
+ self::update_row( self::$stat, $GLOBALS[ 'wpdb' ]->prefix . 'slim_stats' );
775
+ }
776
+ }
777
+ // end update_content_type
778
 
779
+ public static function is_local_ip_address( $ip_address = '' ) {
780
+ if ( !filter_var( $ip_address, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE ) ) {
781
+ return true;
782
  }
783
 
784
+ return false;
785
+ }
786
+
787
+ public static function dtr_pton( $ip ){
788
+ if ( filter_var( $ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 ) ) {
789
+ $unpacked = unpack( 'A4', inet_pton( $ip ) );
790
+ }
791
+ else if ( filter_var( $ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6 ) && defined( 'AF_INET6' ) ) {
792
+ $unpacked = unpack( 'A16', inet_pton( $ip ) );
793
+ }
794
+
795
+ $binary_ip = '';
796
+ if ( !empty( $unpacked ) ) {
797
+ $unpacked = str_split( $unpacked[ 1 ] );
798
+ foreach ( $unpacked as $char ) {
799
+ $binary_ip .= str_pad( decbin( ord( $char ) ), 8, '0', STR_PAD_LEFT );
800
  }
801
  }
802
 
803
+ return $binary_ip;
804
+ }
805
+
806
+ public static function get_mask_length( $ip ){
807
+ if ( filter_var( $ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 ) ) {
808
+ return 32;
809
+ }
810
+ else if ( filter_var( $ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6 ) ) {
811
+ return 128;
812
+ }
813
+
814
+ return false;
815
  }
 
816
 
817
  /**
818
+ * Opens given domains during CORS requests to admin-ajax.php
819
  */
820
+ public static function open_cors_admin_ajax( $_allowed_origins = array() ) {
821
+ $exploded_domains = self::string_to_array( self::$settings[ 'external_domains' ] );
 
 
 
822
 
823
+ if ( !empty( $exploded_domains ) && !empty( $exploded_domains[ 0 ] ) ) {
824
+ $_allowed_origins = array_merge( $_allowed_origins, $exploded_domains );
825
  }
826
+
827
+ return $_allowed_origins;
828
  }
 
829
 
830
  /**
831
+ * Downloads the MaxMind geolocation database from their repository
832
  */
833
+ public static function download_maxmind_database() {
834
+ // Create the folder, if it doesn't exist
835
+ if ( !file_exists( dirname( self::$maxmind_path ) ) ) {
836
+ mkdir( dirname( self::$maxmind_path ) );
837
  }
838
 
839
+ if ( file_exists( self::$maxmind_path ) ) {
840
+ if ( is_file( self::$maxmind_path ) ) {
841
+ $is_deleted = @unlink( self::$maxmind_path );
842
+ }
843
+ else {
844
+ // This should not happen, but hey...
845
+ $is_deleted = @rmdir( self::$maxmind_path );
846
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
847
 
848
+ if ( !$is_deleted ) {
849
+ return __( "The geolocation database cannot be updated. Please check your server's file permissions and try again.", 'wp-slimstat' );
850
+ }
851
  }
852
 
853
+ // Download the most recent database directly from MaxMind's repository
854
+ if ( self::$settings[ 'geolocation_country' ] == 'on' ) {
855
+ $maxmind_tmp = self::download_url( 'https://geolite.maxmind.com/download/geoip/database/GeoLite2-Country.mmdb.gz' );
 
 
 
 
 
 
 
856
  }
857
  else {
858
+ $maxmind_tmp = self::download_url( 'https://geolite.maxmind.com/download/geoip/database/GeoLite2-City.mmdb.gz' );
 
 
 
 
 
 
859
  }
860
 
861
+ if ( is_wp_error( $maxmind_tmp ) ) {
862
+ return __( 'There was an error downloading the MaxMind Geolite DB:', 'wp-slimstat' ) . ' ' . $maxmind_tmp->get_error_message();
 
 
 
 
 
 
 
 
 
 
 
863
  }
864
 
865
+ $zh = false;
 
 
 
 
866
 
867
+ if ( !function_exists( 'gzopen' ) ) {
868
+ if ( function_exists( 'gzopen64' ) ) {
869
+ if ( false === ( $zh = gzopen64( $maxmind_tmp, 'rb' ) ) ) {
870
+ return __( "There was an error opening the zipped MaxMind Geolite DB. Please check your server's file permissions and try again.", 'wp-slimstat' );
 
 
 
 
 
871
  }
872
  }
873
+ else {
874
+ return __( 'Function <code>gzopen</code> is not defined in your environment. Please ask your server administrator to install the corresponding library.', 'wp-slimstat' );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
875
  }
876
  }
877
+ else{
878
+ if ( false === ( $zh = gzopen( $maxmind_tmp, 'rb' ) ) ) {
879
+ return __( "There was an error opening the zipped MaxMind Geolite DB. Please check your server's file permissions and try again.", 'wp-slimstat' );
 
 
 
 
 
 
880
  }
881
  }
882
+
883
+ if ( false === ( $fh = fopen( self::$maxmind_path, 'wb' ) ) ) {
884
+ return __( "There was an error opening the MaxMind Geolite DB. Please check your server's file permissions and try again.", 'wp-slimstat' );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
885
  }
886
 
887
+ while ( ( $data = gzread( $zh, 4096 ) ) != false ) {
888
+ fwrite( $fh, $data );
889
  }
890
 
891
+ @gzclose( $zh );
892
+ @fclose( $fh );
893
+
894
+ if ( !is_file( self::$maxmind_path ) ) {
895
+ // Something went wrong, maybe a folder was created instead of a regular file
896
+ @rmdir( self::$maxmind_path );
897
+ return __( 'There was an error creating the MaxMind Geolite DB.', 'wp-slimstat' );
898
  }
899
 
900
+ @unlink( $maxmind_tmp );
 
 
901
 
902
+ return '';
903
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
904
 
905
  public static function download_url( $url ) {
906
  // Include the FILE API, if it's not defined
1370
  }
1371
  // end init_options
1372
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1373
  /**
1374
  * Enqueue a javascript to track users' screen resolution and other browser-based information
1375
  */
1556
  public static function register_widget() {
1557
  return register_widget( "slimstat_widget" );
1558
  }
 
 
 
 
1559
 
1560
  /**
1561
+ * Tries to find the user's REAL IP address
1562
+ */
1563
+ protected static function _get_remote_ip() {
1564
+ $ip_array = array( '', '' );
1565
+
1566
+ if ( !empty( $_SERVER[ 'REMOTE_ADDR' ] ) && filter_var( $_SERVER[ 'REMOTE_ADDR' ], FILTER_VALIDATE_IP ) !== false ) {
1567
+ $ip_array[ 0 ] = $_SERVER[ 'REMOTE_ADDR' ];
1568
+ }
1569
+
1570
+ $originating_ip_headers = array( 'X-Forwarded-For', 'HTTP_X_FORWARDED_FOR', 'CF-Connecting-IP', 'HTTP_CLIENT_IP', 'HTTP_X_REAL_IP', 'HTTP_FORWARDED', 'HTTP_X_FORWARDED' );
1571
+ foreach ( $originating_ip_headers as $a_header ) {
1572
+ if ( !empty( $_SERVER[ $a_header ] ) ) {
1573
+ foreach ( explode( ',', $_SERVER[ $a_header ] ) as $a_ip ) {
1574
+ if ( filter_var( $a_ip, FILTER_VALIDATE_IP ) !== false && $a_ip != $ip_array[ 0 ] ) {
1575
+ $ip_array[ 1 ] = $a_ip;
1576
+ break;
1577
+ }
1578
+ }
1579
+ }
1580
+ }
1581
+
1582
+ return apply_filters( 'slimstat_filter_ip_address', $ip_array );
1583
+ }
1584
+ // end _get_remote_ip
1585
+
1586
+ /**
1587
+ * Extracts the accepted language from browser headers
1588
+ */
1589
+ protected static function _get_language() {
1590
+ if ( isset( $_SERVER[ 'HTTP_ACCEPT_LANGUAGE' ] ) ) {
1591
+
1592
+ // Capture up to the first delimiter (, found in Safari)
1593
+ preg_match( "/([^,;]*)/", $_SERVER[ 'HTTP_ACCEPT_LANGUAGE' ], $array_languages );
1594
+
1595
+ // Fix some codes, the correct syntax is with minus (-) not underscore (_)
1596
+ return str_replace( '_', '-', strtolower( $array_languages[ 0 ] ) );
1597
+ }
1598
+ return ''; // Indeterminable language
1599
+ }
1600
+ // end _get_language
1601
+
1602
+ /**
1603
+ * Sniffs out referrals from search engines and tries to determine the query string
1604
+ */
1605
+ protected static function _get_search_terms( $_url = array() ) {
1606
+ if ( empty( $_url ) || !isset( $_url[ 'host' ] ) ) {
1607
+ return '';
1608
+ }
1609
+
1610
+ // Engines with different character encodings should always be listed here, regardless of their query string format
1611
+ $query_formats = array(
1612
+ 'baidu.com' => 'wd',
1613
+ 'bing' => 'q',
1614
+ 'dogpile.com' => 'q',
1615
+ 'duckduckgo' => 'q',
1616
+ 'eniro' => 'search_word',
1617
+ 'exalead.com' => 'q',
1618
+ 'excite' => 'q',
1619
+ 'gigablast' => 'q',
1620
+ 'google' => 'q',
1621
+ 'hotbot' => 'q',
1622
+ 'maktoob' => 'p',
1623
+ 'mamma' => 'q',
1624
+ 'naver' => 'query',
1625
+ 'qwant' => 'q',
1626
+ 'rambler' => 'query',
1627
+ 'seznam' => 'oq',
1628
+ 'soso.com' => 'query',
1629
+ 'virgilio' => 'qs',
1630
+ 'voila' => 'rdata',
1631
+ 'yahoo' => 'p',
1632
+ 'yam' => 'k',
1633
+ 'yandex' => 'text',
1634
+ 'yell' => 'keywords',
1635
+ 'yippy' => 'query',
1636
+ 'youdao' => 'q'
1637
+ );
1638
+
1639
+ $charsets = array( 'baidu' => 'EUC-CN' );
1640
+ $regex_match = implode( '|', array_keys( $query_formats ) );
1641
+ $searchterms = '';
1642
+
1643
+ if ( !empty( $_url[ 'query' ] ) ) {
1644
+ parse_str( $_url[ 'query' ], $query );
1645
+ }
1646
+
1647
+ if ( !empty( $_url[ 'host' ] ) ) {
1648
+ preg_match( "~($regex_match).~i", $_url[ 'host' ], $matches );
1649
+ }
1650
+
1651
+ if ( !empty( $matches[ 1 ] ) ) {
1652
+ // Let's remember that this is a search engine, regardless of the URL containing searchterms (thank you, NSA)
1653
+ $searchterms = '_';
1654
+ if ( !empty( $query[ $query_formats[ $matches[ 1 ] ] ] ) ) {
1655
+ $searchterms = str_replace( '\\', '', trim( urldecode( $query[ $query_formats[ $matches[ 1 ] ] ] ) ) );
1656
+ // Test for encodings different from UTF-8
1657
+ if ( function_exists( 'mb_check_encoding' ) && !mb_check_encoding( $query[ $query_formats[ $matches[ 1 ] ] ], 'UTF-8' ) && !empty( $charsets[ $matches[ 1 ] ] ) ) {
1658
+ $searchterms = mb_convert_encoding( urldecode( $query[ $query_formats[ $matches[ 1 ] ] ] ), 'UTF-8', $charsets[ $matches[ 1 ] ] );
1659
+ }
1660
+ }
1661
+ }
1662
+ else {
1663
+ // We weren't lucky, but there's still hope
1664
+ foreach( array( 'q','s','k','qt' ) as $a_format ) {
1665
+ if ( !empty( $query[ $a_format ] ) ) {
1666
+ $searchterms = str_replace( '\\', '', trim( urldecode( $query[ $a_format ] ) ) );
1667
+ break;
1668
+ }
1669
+ }
1670
+ }
1671
+
1672
+ return $searchterms;
1673
+ }
1674
+ // end _get_search_terms
1675
+
1676
+ /**
1677
+ * Returns details about the resource being accessed
1678
+ */
1679
+ protected static function _get_content_info() {
1680
+ $content_info = array( 'content_type' => '' );
1681
+
1682
+ // Mark 404 pages
1683
+ if ( is_404() ) {
1684
+ $content_info[ 'content_type' ] = '404';
1685
+ }
1686
+
1687
+ // Type
1688
+ else if ( is_single() ) {
1689
+ if ( ( $post_type = get_post_type() ) != 'post' ) {
1690
+ $post_type = 'cpt:' . $post_type;
1691
+ }
1692
+
1693
+ $content_info[ 'content_type' ] = $post_type;
1694
+ $content_info_array = array();
1695
+ foreach ( get_object_taxonomies( $GLOBALS[ 'post' ] ) as $a_taxonomy ) {
1696
+ $terms = get_the_terms( $GLOBALS[ 'post' ]->ID, $a_taxonomy );
1697
+ if ( is_array( $terms ) ) {
1698
+ foreach ( $terms as $a_term ) {
1699
+ $content_info_array[] = $a_term->term_id;
1700
+ }
1701
+ $content_info[ 'category' ] = implode( ',', $content_info_array );
1702
+ }
1703
+ }
1704
+ $content_info[ 'content_id' ] = $GLOBALS[ 'post' ]->ID;
1705
+ }
1706
+ else if ( is_page() ) {
1707
+ $content_info[ 'content_type' ] = 'page';
1708
+ $content_info[ 'content_id' ] = $GLOBALS[ 'post' ]->ID;
1709
+ }
1710
+ elseif ( is_attachment() ) {
1711
+ $content_info[ 'content_type' ] = 'attachment';
1712
+ }
1713
+ elseif ( is_singular() ) {
1714
+ $content_info[ 'content_type' ] = 'singular';
1715
+ }
1716
+ elseif ( is_post_type_archive() ) {
1717
+ $content_info[ 'content_type' ] = 'post_type_archive';
1718
+ }
1719
+ elseif ( is_tag() ) {
1720
+ $content_info[ 'content_type' ] = 'tag';
1721
+ $list_tags = get_the_tags();
1722
+ if ( is_array( $list_tags ) ) {
1723
+ $tag_info = array_pop( $list_tags );
1724
+ if ( !empty( $tag_info ) ) {
1725
+ $content_info[ 'category' ] = $tag_info->term_id;
1726
+ }
1727
+ }
1728
+ }
1729
+ elseif ( is_tax() ) {
1730
+ $content_info[ 'content_type' ] = 'taxonomy';
1731
+ }
1732
+ elseif ( is_category() ) {
1733
+ $content_info[ 'content_type' ] = 'category';
1734
+ $list_categories = get_the_category();
1735
+ if ( is_array( $list_categories ) ) {
1736
+ $cat_info = array_pop( $list_categories );
1737
+ if ( !empty( $cat_info ) ) {
1738
+ $content_info[ 'category' ] = $cat_info->term_id;
1739
+ }
1740
+ }
1741
+ }
1742
+ else if ( is_date() ) {
1743
+ $content_info[ 'content_type' ]= 'date';
1744
+ }
1745
+ else if ( is_author() ) {
1746
+ $content_info[ 'content_type' ] = 'author';
1747
+ }
1748
+ else if ( is_archive() ) {
1749
+ $content_info[ 'content_type' ] = 'archive';
1750
+ }
1751
+ else if ( is_search() ) {
1752
+ $content_info[ 'content_type' ] = 'search';
1753
+ }
1754
+ else if ( is_feed() ) {
1755
+ $content_info[ 'content_type' ] = 'feed';
1756
+ }
1757
+ else if ( is_home() || is_front_page() ) {
1758
+ $content_info[ 'content_type' ] = 'home';
1759
+ }
1760
+ else if ( !empty( $GLOBALS[ 'pagenow' ] ) && $GLOBALS[ 'pagenow' ] == 'wp-login.php' ) {
1761
+ $content_info[ 'content_type' ] = 'login';
1762
+ }
1763
+ else if ( !empty( $GLOBALS['pagenow'] ) && $GLOBALS['pagenow'] == 'wp-register.php' ) {
1764
+ $content_info[ 'content_type' ] = 'registration';
1765
+ }
1766
+ // WordPress sets is_admin() to true for all ajax requests ( front-end or admin-side )
1767
+ elseif ( is_admin() && ( !defined( 'DOING_AJAX' ) || !DOING_AJAX ) ) {
1768
+ $content_info[ 'content_type' ] = 'admin';
1769
+ }
1770
+
1771
+ if ( is_paged() ) {
1772
+ $content_info[ 'content_type' ] .= ':paged';
1773
+ }
1774
+
1775
+ // Author
1776
+ if ( is_singular() ) {
1777
+ $author = get_the_author_meta( 'user_login', $GLOBALS[ 'post' ]->post_author );
1778
+ if ( !empty( $author ) ) {
1779
+ $content_info[ 'author' ] = $author;
1780
+ }
1781
+ }
1782
+
1783
+ return $content_info;
1784
+ }
1785
+ // end _get_content_info
1786
+
1787
+ /**
1788
+ * Reads the cookie to get the visit_id and sets the variable accordingly
1789
+ */
1790
+ protected static function _set_visit_id( $_force_assign = false ) {
1791
+ $is_new_session = true;
1792
+ $identifier = 0;
1793
+
1794
+ if ( isset( $_COOKIE[ 'slimstat_tracking_code' ] ) ) {
1795
+ // Make sure only authorized information is recorded
1796
+ $identifier = self::_separate_id_from_checksum( $_COOKIE[ 'slimstat_tracking_code' ] );
1797
+ if ( $identifier === false ) {
1798
+ return false;
1799
+ }
1800
+
1801
+ $is_new_session = ( strpos( $identifier, 'id' ) !== false );
1802
+ $identifier = intval( $identifier );
1803
+ }
1804
+
1805
+ // User doesn't have an active session
1806
+ if ( $is_new_session && ( $_force_assign || self::$settings[ 'javascript_mode' ] == 'on' ) ) {
1807
+ if ( empty( self::$settings[ 'session_duration' ] ) ) {
1808
+ self::$settings[ 'session_duration' ] = 1800;
1809
+ }
1810
+
1811
+ self::$stat[ 'visit_id' ] = get_transient( 'slimstat_visit_id' );
1812
+ if ( self::$stat[ 'visit_id' ] === false ) {
1813
+ self::$stat[ 'visit_id' ] = intval( self::$wpdb->get_var( "SELECT MAX( visit_id ) FROM {$GLOBALS[ 'wpdb' ]->prefix}slim_stats" ) );
1814
+ }
1815
+ self::$stat[ 'visit_id' ]++;
1816
+ set_transient( 'slimstat_visit_id', self::$stat[ 'visit_id' ] );
1817
+
1818
+ $set_cookie = apply_filters( 'slimstat_set_visit_cookie', ( !empty( self::$settings[ 'set_tracker_cookie' ] ) && self::$settings[ 'set_tracker_cookie' ] == 'on' ) );
1819
+ if ( $set_cookie ) {
1820
+ @setcookie(
1821
+ 'slimstat_tracking_code',
1822
+ self::_get_id_with_checksum( self::$stat[ 'visit_id' ] ),
1823
+ time() + self::$settings[ 'session_duration' ],
1824
+ COOKIEPATH
1825
+ );
1826
+ }
1827
+
1828
+ }
1829
+ elseif ( $identifier > 0 ) {
1830
+ self::$stat[ 'visit_id' ] = $identifier;
1831
+ }
1832
+
1833
+ if ( $is_new_session && $identifier > 0 ) {
1834
+ self::$wpdb->query( self::$wpdb->prepare( "
1835
+ UPDATE {$GLOBALS['wpdb']->prefix}slim_stats
1836
+ SET visit_id = %d
1837
+ WHERE id = %d AND visit_id = 0", self::$stat[ 'visit_id' ], $identifier
1838
+ ) );
1839
+ }
1840
+ return ( $is_new_session && ( $_force_assign || self::$settings[ 'javascript_mode' ] == 'on' ) );
1841
+ }
1842
+ // end _set_visit_id
1843
+
1844
+ /**
1845
+ * Makes sure that the data received from the client is well-formed (and that nobody is trying to do bad stuff)
1846
+ */
1847
+ protected static function _check_data_integrity( $_data = '' ) {
1848
+ // Parse the information we received
1849
+ self::$data_js = apply_filters( 'slimstat_filter_pageview_data_js', $_data );
1850
+
1851
+ // Do we have an id for this request?
1852
+ if ( empty( self::$data_js[ 'id' ] ) || empty( self::$data_js[ 'op' ] ) ) {
1853
+ do_action( 'slimstat_track_exit_100' );
1854
+ self::_log_error( 100 );
1855
+ exit( self::_get_id_with_checksum( self::$stat[ 'id' ] ) );
1856
+ }
1857
+
1858
+ // Make sure that the control code is valid
1859
+ self::$data_js[ 'id' ] = self::_separate_id_from_checksum( self::$data_js[ 'id' ] );
1860
+
1861
+ if ( self::$data_js[ 'id' ] === false ) {
1862
+ do_action( 'slimstat_track_exit_101' );
1863
+ self::_log_error( 101 );
1864
+ exit( self::_get_id_with_checksum( self::$stat[ 'id' ] ) );
1865
+ }
1866
+
1867
+ $intval_id = intval( self::$data_js[ 'id' ] );
1868
+ if ( $intval_id < 0 ) {
1869
+ do_action( 'slimstat_track_exit_' . abs( $intval_id ) );
1870
+ exit( self::_get_id_with_checksum( self::$stat[ 'id' ] ) );
1871
+ }
1872
+ }
1873
+ // end _check_data_integrity
1874
+
1875
+ protected static function _log_error( $_error_code = 0 ) {
1876
+ self::toggle_date_i18n_filters( false );
1877
+ if ( !is_network_admin() ) {
1878
+ update_option( 'slimstat_tracker_error', array( $_error_code, date_i18n( 'U' ) ) );
1879
+ }
1880
+ else {
1881
+ update_site_option( 'slimstat_tracker_error', array( $_error_code, date_i18n( 'U' ) ) );
1882
+ }
1883
+ self::toggle_date_i18n_filters( true );
1884
+
1885
+ self::$stat[ 'id' ] = -$_error_code;
1886
+ }
1887
+
1888
+ protected static function _get_id_with_checksum( $_id = 0 ) {
1889
+ return $_id . '.' . md5( $_id . self::$settings[ 'secret' ] );
1890
+ }
1891
+
1892
+ protected static function _separate_id_from_checksum( $_id_with_checksum = '' ) {
1893
+ list( $id, $checksum ) = explode( '.', $_id_with_checksum );
1894
+
1895
+ if ( $checksum === md5( $id . self::$settings[ 'secret' ] ) ) {
1896
+ return $id;
1897
+ }
1898
+
1899
+ return false;
1900
+ }
1901
+
1902
+ protected static function _is_blacklisted( $_needles = array(), $_haystack_string = '' ) {
1903
+ foreach ( self::string_to_array( $_haystack_string ) as $a_item ) {
1904
+ $pattern = str_replace( array( '\*', '\!' ) , array( '(.*)', '.' ), preg_quote( $a_item, '@' ) );
1905
+
1906
+ if ( !is_array( $_needles ) ) {
1907
+ $_needles = array( $_needles );
1908
+ }
1909
+
1910
+ foreach ( $_needles as $a_needle ) {
1911
+ if ( preg_match( "@^$pattern$@i", $a_needle ) ) {
1912
+ return true;
1913
+ }
1914
+ }
1915
+ }
1916
+
1917
+ return false;
1918
+ }
1919
+ }
1920
+ // end of class declaration
1921
+
1922
+ class slimstat_widget extends WP_Widget {
1923
+
1924
+ /**
1925
+ * Sets up the widgets name etc
1926
  */
1927
  public function __construct() {
1928
  parent::__construct( 'slimstat_widget', 'Slimstat', array(
1999
  }
2000
  }
2001
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2002
  // Ok, let's go, Sparky!
2003
  if ( function_exists( 'add_action' ) ) {
2004
  // Since we use sendBeacon, this function sends raw POST data, which does not populate the $_POST variable automatically